jamdesk 1.0.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 (435) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +323 -0
  3. package/bin/jamdesk.js +76 -0
  4. package/dist/__tests__/integration/deprecated-components.integration.test.d.ts +8 -0
  5. package/dist/__tests__/integration/deprecated-components.integration.test.d.ts.map +1 -0
  6. package/dist/__tests__/integration/deprecated-components.integration.test.js +165 -0
  7. package/dist/__tests__/integration/deprecated-components.integration.test.js.map +1 -0
  8. package/dist/__tests__/integration/migrate.integration.test.d.ts +2 -0
  9. package/dist/__tests__/integration/migrate.integration.test.d.ts.map +1 -0
  10. package/dist/__tests__/integration/migrate.integration.test.js +64 -0
  11. package/dist/__tests__/integration/migrate.integration.test.js.map +1 -0
  12. package/dist/__tests__/integration/prepublish.integration.test.d.ts +2 -0
  13. package/dist/__tests__/integration/prepublish.integration.test.d.ts.map +1 -0
  14. package/dist/__tests__/integration/prepublish.integration.test.js +27 -0
  15. package/dist/__tests__/integration/prepublish.integration.test.js.map +1 -0
  16. package/dist/__tests__/integration/validate.integration.test.d.ts +2 -0
  17. package/dist/__tests__/integration/validate.integration.test.d.ts.map +1 -0
  18. package/dist/__tests__/integration/validate.integration.test.js +56 -0
  19. package/dist/__tests__/integration/validate.integration.test.js.map +1 -0
  20. package/dist/__tests__/unit/deploy-templates.test.d.ts +2 -0
  21. package/dist/__tests__/unit/deploy-templates.test.d.ts.map +1 -0
  22. package/dist/__tests__/unit/deploy-templates.test.js +124 -0
  23. package/dist/__tests__/unit/deploy-templates.test.js.map +1 -0
  24. package/dist/__tests__/unit/deprecated-components-sync.test.d.ts +2 -0
  25. package/dist/__tests__/unit/deprecated-components-sync.test.d.ts.map +1 -0
  26. package/dist/__tests__/unit/deprecated-components-sync.test.js +69 -0
  27. package/dist/__tests__/unit/deprecated-components-sync.test.js.map +1 -0
  28. package/dist/__tests__/unit/deps-sync.test.d.ts +14 -0
  29. package/dist/__tests__/unit/deps-sync.test.d.ts.map +1 -0
  30. package/dist/__tests__/unit/deps-sync.test.js +166 -0
  31. package/dist/__tests__/unit/deps-sync.test.js.map +1 -0
  32. package/dist/__tests__/unit/docs-config.test.d.ts +2 -0
  33. package/dist/__tests__/unit/docs-config.test.d.ts.map +1 -0
  34. package/dist/__tests__/unit/docs-config.test.js +288 -0
  35. package/dist/__tests__/unit/docs-config.test.js.map +1 -0
  36. package/dist/__tests__/unit/errors.test.d.ts +2 -0
  37. package/dist/__tests__/unit/errors.test.d.ts.map +1 -0
  38. package/dist/__tests__/unit/errors.test.js +27 -0
  39. package/dist/__tests__/unit/errors.test.js.map +1 -0
  40. package/dist/__tests__/unit/extract-hooks.test.d.ts +5 -0
  41. package/dist/__tests__/unit/extract-hooks.test.d.ts.map +1 -0
  42. package/dist/__tests__/unit/extract-hooks.test.js +205 -0
  43. package/dist/__tests__/unit/extract-hooks.test.js.map +1 -0
  44. package/dist/__tests__/unit/frontmatter-sync.test.d.ts +8 -0
  45. package/dist/__tests__/unit/frontmatter-sync.test.d.ts.map +1 -0
  46. package/dist/__tests__/unit/frontmatter-sync.test.js +26 -0
  47. package/dist/__tests__/unit/frontmatter-sync.test.js.map +1 -0
  48. package/dist/__tests__/unit/mdx-validator.test.d.ts +2 -0
  49. package/dist/__tests__/unit/mdx-validator.test.d.ts.map +1 -0
  50. package/dist/__tests__/unit/mdx-validator.test.js +264 -0
  51. package/dist/__tests__/unit/mdx-validator.test.js.map +1 -0
  52. package/dist/__tests__/unit/migrate-convert.test.d.ts +2 -0
  53. package/dist/__tests__/unit/migrate-convert.test.d.ts.map +1 -0
  54. package/dist/__tests__/unit/migrate-convert.test.js +297 -0
  55. package/dist/__tests__/unit/migrate-convert.test.js.map +1 -0
  56. package/dist/__tests__/unit/migrate-detect.test.d.ts +2 -0
  57. package/dist/__tests__/unit/migrate-detect.test.d.ts.map +1 -0
  58. package/dist/__tests__/unit/migrate-detect.test.js +35 -0
  59. package/dist/__tests__/unit/migrate-detect.test.js.map +1 -0
  60. package/dist/__tests__/unit/migrate-mdx.test.d.ts +2 -0
  61. package/dist/__tests__/unit/migrate-mdx.test.d.ts.map +1 -0
  62. package/dist/__tests__/unit/migrate-mdx.test.js +158 -0
  63. package/dist/__tests__/unit/migrate-mdx.test.js.map +1 -0
  64. package/dist/__tests__/unit/openapi.test.d.ts +2 -0
  65. package/dist/__tests__/unit/openapi.test.d.ts.map +1 -0
  66. package/dist/__tests__/unit/openapi.test.js +52 -0
  67. package/dist/__tests__/unit/openapi.test.js.map +1 -0
  68. package/dist/__tests__/unit/package-config.test.d.ts +2 -0
  69. package/dist/__tests__/unit/package-config.test.d.ts.map +1 -0
  70. package/dist/__tests__/unit/package-config.test.js +63 -0
  71. package/dist/__tests__/unit/package-config.test.js.map +1 -0
  72. package/dist/__tests__/unit/port.test.d.ts +2 -0
  73. package/dist/__tests__/unit/port.test.d.ts.map +1 -0
  74. package/dist/__tests__/unit/port.test.js +20 -0
  75. package/dist/__tests__/unit/port.test.js.map +1 -0
  76. package/dist/__tests__/unit/vendored-sync.test.d.ts +14 -0
  77. package/dist/__tests__/unit/vendored-sync.test.d.ts.map +1 -0
  78. package/dist/__tests__/unit/vendored-sync.test.js +90 -0
  79. package/dist/__tests__/unit/vendored-sync.test.js.map +1 -0
  80. package/dist/commands/broken-links.d.ts +11 -0
  81. package/dist/commands/broken-links.d.ts.map +1 -0
  82. package/dist/commands/broken-links.js +95 -0
  83. package/dist/commands/broken-links.js.map +1 -0
  84. package/dist/commands/clean.d.ts +7 -0
  85. package/dist/commands/clean.d.ts.map +1 -0
  86. package/dist/commands/clean.js +59 -0
  87. package/dist/commands/clean.js.map +1 -0
  88. package/dist/commands/deploy/cloudflare.d.ts +12 -0
  89. package/dist/commands/deploy/cloudflare.d.ts.map +1 -0
  90. package/dist/commands/deploy/cloudflare.js +409 -0
  91. package/dist/commands/deploy/cloudflare.js.map +1 -0
  92. package/dist/commands/deploy/templates.d.ts +23 -0
  93. package/dist/commands/deploy/templates.d.ts.map +1 -0
  94. package/dist/commands/deploy/templates.js +179 -0
  95. package/dist/commands/deploy/templates.js.map +1 -0
  96. package/dist/commands/deploy/types.d.ts +19 -0
  97. package/dist/commands/deploy/types.d.ts.map +1 -0
  98. package/dist/commands/deploy/types.js +5 -0
  99. package/dist/commands/deploy/types.js.map +1 -0
  100. package/dist/commands/dev.d.ts +14 -0
  101. package/dist/commands/dev.d.ts.map +1 -0
  102. package/dist/commands/dev.js +817 -0
  103. package/dist/commands/dev.js.map +1 -0
  104. package/dist/commands/doctor.d.ts +7 -0
  105. package/dist/commands/doctor.d.ts.map +1 -0
  106. package/dist/commands/doctor.js +159 -0
  107. package/dist/commands/doctor.js.map +1 -0
  108. package/dist/commands/init.d.ts +7 -0
  109. package/dist/commands/init.d.ts.map +1 -0
  110. package/dist/commands/init.js +96 -0
  111. package/dist/commands/init.js.map +1 -0
  112. package/dist/commands/migrate/convert-mdx.d.ts +50 -0
  113. package/dist/commands/migrate/convert-mdx.d.ts.map +1 -0
  114. package/dist/commands/migrate/convert-mdx.js +108 -0
  115. package/dist/commands/migrate/convert-mdx.js.map +1 -0
  116. package/dist/commands/migrate/convert.d.ts +80 -0
  117. package/dist/commands/migrate/convert.d.ts.map +1 -0
  118. package/dist/commands/migrate/convert.js +158 -0
  119. package/dist/commands/migrate/convert.js.map +1 -0
  120. package/dist/commands/migrate/detect.d.ts +31 -0
  121. package/dist/commands/migrate/detect.d.ts.map +1 -0
  122. package/dist/commands/migrate/detect.js +62 -0
  123. package/dist/commands/migrate/detect.js.map +1 -0
  124. package/dist/commands/migrate/extract-hooks.d.ts +71 -0
  125. package/dist/commands/migrate/extract-hooks.d.ts.map +1 -0
  126. package/dist/commands/migrate/extract-hooks.js +473 -0
  127. package/dist/commands/migrate/extract-hooks.js.map +1 -0
  128. package/dist/commands/migrate/index.d.ts +17 -0
  129. package/dist/commands/migrate/index.d.ts.map +1 -0
  130. package/dist/commands/migrate/index.js +282 -0
  131. package/dist/commands/migrate/index.js.map +1 -0
  132. package/dist/commands/migrate/prompts.d.ts +22 -0
  133. package/dist/commands/migrate/prompts.d.ts.map +1 -0
  134. package/dist/commands/migrate/prompts.js +67 -0
  135. package/dist/commands/migrate/prompts.js.map +1 -0
  136. package/dist/commands/migrate/types.d.ts +22 -0
  137. package/dist/commands/migrate/types.d.ts.map +1 -0
  138. package/dist/commands/migrate/types.js +26 -0
  139. package/dist/commands/migrate/types.js.map +1 -0
  140. package/dist/commands/openapi-check.d.ts +11 -0
  141. package/dist/commands/openapi-check.d.ts.map +1 -0
  142. package/dist/commands/openapi-check.js +88 -0
  143. package/dist/commands/openapi-check.js.map +1 -0
  144. package/dist/commands/rename.d.ts +10 -0
  145. package/dist/commands/rename.d.ts.map +1 -0
  146. package/dist/commands/rename.js +125 -0
  147. package/dist/commands/rename.js.map +1 -0
  148. package/dist/commands/update.d.ts +10 -0
  149. package/dist/commands/update.d.ts.map +1 -0
  150. package/dist/commands/update.js +57 -0
  151. package/dist/commands/update.js.map +1 -0
  152. package/dist/commands/validate.d.ts +12 -0
  153. package/dist/commands/validate.d.ts.map +1 -0
  154. package/dist/commands/validate.js +163 -0
  155. package/dist/commands/validate.js.map +1 -0
  156. package/dist/index.d.ts +9 -0
  157. package/dist/index.d.ts.map +1 -0
  158. package/dist/index.js +334 -0
  159. package/dist/index.js.map +1 -0
  160. package/dist/lib/config.d.ts +7 -0
  161. package/dist/lib/config.d.ts.map +1 -0
  162. package/dist/lib/config.js +18 -0
  163. package/dist/lib/config.js.map +1 -0
  164. package/dist/lib/deprecated-components.d.ts +72 -0
  165. package/dist/lib/deprecated-components.d.ts.map +1 -0
  166. package/dist/lib/deprecated-components.js +138 -0
  167. package/dist/lib/deprecated-components.js.map +1 -0
  168. package/dist/lib/deps.d.ts +17 -0
  169. package/dist/lib/deps.d.ts.map +1 -0
  170. package/dist/lib/deps.js +186 -0
  171. package/dist/lib/deps.js.map +1 -0
  172. package/dist/lib/docs-config.d.ts +67 -0
  173. package/dist/lib/docs-config.d.ts.map +1 -0
  174. package/dist/lib/docs-config.js +294 -0
  175. package/dist/lib/docs-config.js.map +1 -0
  176. package/dist/lib/errors.d.ts +23 -0
  177. package/dist/lib/errors.d.ts.map +1 -0
  178. package/dist/lib/errors.js +32 -0
  179. package/dist/lib/errors.js.map +1 -0
  180. package/dist/lib/frontmatter-utils.d.ts +25 -0
  181. package/dist/lib/frontmatter-utils.d.ts.map +1 -0
  182. package/dist/lib/frontmatter-utils.js +64 -0
  183. package/dist/lib/frontmatter-utils.js.map +1 -0
  184. package/dist/lib/mdx-validator.d.ts +27 -0
  185. package/dist/lib/mdx-validator.d.ts.map +1 -0
  186. package/dist/lib/mdx-validator.js +148 -0
  187. package/dist/lib/mdx-validator.js.map +1 -0
  188. package/dist/lib/navigation-validator.d.ts +31 -0
  189. package/dist/lib/navigation-validator.d.ts.map +1 -0
  190. package/dist/lib/navigation-validator.js +75 -0
  191. package/dist/lib/navigation-validator.js.map +1 -0
  192. package/dist/lib/normalize-config.d.ts +57 -0
  193. package/dist/lib/normalize-config.d.ts.map +1 -0
  194. package/dist/lib/normalize-config.js +63 -0
  195. package/dist/lib/normalize-config.js.map +1 -0
  196. package/dist/lib/openapi/cache.d.ts +40 -0
  197. package/dist/lib/openapi/cache.d.ts.map +1 -0
  198. package/dist/lib/openapi/cache.js +76 -0
  199. package/dist/lib/openapi/cache.js.map +1 -0
  200. package/dist/lib/openapi/errors.d.ts +36 -0
  201. package/dist/lib/openapi/errors.d.ts.map +1 -0
  202. package/dist/lib/openapi/errors.js +162 -0
  203. package/dist/lib/openapi/errors.js.map +1 -0
  204. package/dist/lib/openapi/index.d.ts +10 -0
  205. package/dist/lib/openapi/index.d.ts.map +1 -0
  206. package/dist/lib/openapi/index.js +12 -0
  207. package/dist/lib/openapi/index.js.map +1 -0
  208. package/dist/lib/openapi/types.d.ts +198 -0
  209. package/dist/lib/openapi/types.d.ts.map +1 -0
  210. package/dist/lib/openapi/types.js +8 -0
  211. package/dist/lib/openapi/types.js.map +1 -0
  212. package/dist/lib/openapi/validator.d.ts +45 -0
  213. package/dist/lib/openapi/validator.d.ts.map +1 -0
  214. package/dist/lib/openapi/validator.js +128 -0
  215. package/dist/lib/openapi/validator.js.map +1 -0
  216. package/dist/lib/openapi.d.ts +7 -0
  217. package/dist/lib/openapi.d.ts.map +1 -0
  218. package/dist/lib/openapi.js +7 -0
  219. package/dist/lib/openapi.js.map +1 -0
  220. package/dist/lib/output.d.ts +14 -0
  221. package/dist/lib/output.d.ts.map +1 -0
  222. package/dist/lib/output.js +19 -0
  223. package/dist/lib/output.js.map +1 -0
  224. package/dist/lib/path-security.d.ts +23 -0
  225. package/dist/lib/path-security.d.ts.map +1 -0
  226. package/dist/lib/path-security.js +35 -0
  227. package/dist/lib/path-security.js.map +1 -0
  228. package/dist/lib/port.d.ts +18 -0
  229. package/dist/lib/port.d.ts.map +1 -0
  230. package/dist/lib/port.js +65 -0
  231. package/dist/lib/port.js.map +1 -0
  232. package/dist/lib/spinner.d.ts +4 -0
  233. package/dist/lib/spinner.d.ts.map +1 -0
  234. package/dist/lib/spinner.js +16 -0
  235. package/dist/lib/spinner.js.map +1 -0
  236. package/dist/lib/version.d.ts +2 -0
  237. package/dist/lib/version.d.ts.map +1 -0
  238. package/dist/lib/version.js +49 -0
  239. package/dist/lib/version.js.map +1 -0
  240. package/dist/utils/update-checker.d.ts +34 -0
  241. package/dist/utils/update-checker.d.ts.map +1 -0
  242. package/dist/utils/update-checker.js +142 -0
  243. package/dist/utils/update-checker.js.map +1 -0
  244. package/package.json +125 -0
  245. package/templates/docs.json +11 -0
  246. package/templates/introduction.mdx +19 -0
  247. package/templates/quickstart.mdx +20 -0
  248. package/vendored/app/[[...slug]]/error.tsx +103 -0
  249. package/vendored/app/[[...slug]]/page.tsx +690 -0
  250. package/vendored/app/api/assets/[...path]/route.ts +78 -0
  251. package/vendored/app/api/ev/route.ts +61 -0
  252. package/vendored/app/api/isr-health/route.ts +66 -0
  253. package/vendored/app/api/mcp/[project]/route.ts +435 -0
  254. package/vendored/app/api/og/route.tsx +167 -0
  255. package/vendored/app/api/r2/[project]/[...path]/route.ts +214 -0
  256. package/vendored/app/api/revalidate/route.ts +76 -0
  257. package/vendored/app/globals.css +37 -0
  258. package/vendored/app/layout.tsx +571 -0
  259. package/vendored/app/not-found.tsx +47 -0
  260. package/vendored/components/CodeBlockCopyButton.tsx +146 -0
  261. package/vendored/components/HeaderLinkCopy.tsx +135 -0
  262. package/vendored/components/errors/NotFoundContent.tsx +147 -0
  263. package/vendored/components/layout/LayoutWrapper.tsx +128 -0
  264. package/vendored/components/mdx/Accordion.tsx +91 -0
  265. package/vendored/components/mdx/ApiCodePanel.tsx +51 -0
  266. package/vendored/components/mdx/ApiEndpoint.tsx +104 -0
  267. package/vendored/components/mdx/ApiPage.tsx +379 -0
  268. package/vendored/components/mdx/Badge.tsx +169 -0
  269. package/vendored/components/mdx/Callouts.tsx +140 -0
  270. package/vendored/components/mdx/Card.tsx +214 -0
  271. package/vendored/components/mdx/CodeGroup.tsx +136 -0
  272. package/vendored/components/mdx/Color.tsx +244 -0
  273. package/vendored/components/mdx/Columns.tsx +37 -0
  274. package/vendored/components/mdx/Expandable.tsx +37 -0
  275. package/vendored/components/mdx/Frame.tsx +51 -0
  276. package/vendored/components/mdx/Icon.tsx +132 -0
  277. package/vendored/components/mdx/Latex.tsx +75 -0
  278. package/vendored/components/mdx/MDXComponents.tsx +414 -0
  279. package/vendored/components/mdx/Mermaid.tsx +35 -0
  280. package/vendored/components/mdx/MermaidInner.tsx +342 -0
  281. package/vendored/components/mdx/OpenApiEndpoint.tsx +971 -0
  282. package/vendored/components/mdx/Panel.tsx +26 -0
  283. package/vendored/components/mdx/PanelWrapper.tsx +100 -0
  284. package/vendored/components/mdx/ParamField.tsx +75 -0
  285. package/vendored/components/mdx/RequestExample.tsx +91 -0
  286. package/vendored/components/mdx/ResponseExample.tsx +145 -0
  287. package/vendored/components/mdx/ResponseField.tsx +109 -0
  288. package/vendored/components/mdx/Steps.tsx +173 -0
  289. package/vendored/components/mdx/Table.tsx +352 -0
  290. package/vendored/components/mdx/Tabs.tsx +147 -0
  291. package/vendored/components/mdx/Tile.tsx +127 -0
  292. package/vendored/components/mdx/Tooltip.tsx +111 -0
  293. package/vendored/components/mdx/Tree.tsx +484 -0
  294. package/vendored/components/mdx/Update.tsx +90 -0
  295. package/vendored/components/mdx/View.tsx +354 -0
  296. package/vendored/components/mdx/YouTube.tsx +35 -0
  297. package/vendored/components/mdx/ZoomableImage.tsx +83 -0
  298. package/vendored/components/navigation/Breadcrumb.tsx +241 -0
  299. package/vendored/components/navigation/DefaultLogo.tsx +81 -0
  300. package/vendored/components/navigation/Header.tsx +512 -0
  301. package/vendored/components/navigation/LanguageSelector.tsx +249 -0
  302. package/vendored/components/navigation/PageNavigation.tsx +174 -0
  303. package/vendored/components/navigation/Sidebar.tsx +713 -0
  304. package/vendored/components/navigation/SocialFooter.tsx +186 -0
  305. package/vendored/components/navigation/TableOfContents.tsx +435 -0
  306. package/vendored/components/navigation/TabsNav.tsx +182 -0
  307. package/vendored/components/search/LazySearchModal.tsx +19 -0
  308. package/vendored/components/search/SearchModal.tsx +573 -0
  309. package/vendored/components/snippets/ProjectSnippets.tsx +4 -0
  310. package/vendored/components/theme/ThemeProvider.tsx +31 -0
  311. package/vendored/components/theme/ThemeToggle.tsx +134 -0
  312. package/vendored/components/ui/CodePanel.tsx +517 -0
  313. package/vendored/components/ui/CodePanelModal.tsx +342 -0
  314. package/vendored/contexts/TabSyncContext.tsx +30 -0
  315. package/vendored/hooks/useFocusTrap.ts +42 -0
  316. package/vendored/hooks/useHashNavigation.ts +39 -0
  317. package/vendored/hooks/useShikiHighlight.ts +101 -0
  318. package/vendored/lib/analytics-client.ts +77 -0
  319. package/vendored/lib/build/cache.ts +138 -0
  320. package/vendored/lib/build/error-parser.ts +690 -0
  321. package/vendored/lib/build/estimation.ts +113 -0
  322. package/vendored/lib/build/index.ts +17 -0
  323. package/vendored/lib/build/page-file-map.ts +48 -0
  324. package/vendored/lib/build/r2-upload.ts +179 -0
  325. package/vendored/lib/cache-keys.ts +117 -0
  326. package/vendored/lib/code-utils.ts +42 -0
  327. package/vendored/lib/content-loader.ts +176 -0
  328. package/vendored/lib/deprecated-components.ts +185 -0
  329. package/vendored/lib/docs-isr.ts +180 -0
  330. package/vendored/lib/docs-types.ts +874 -0
  331. package/vendored/lib/docs.ts +203 -0
  332. package/vendored/lib/domain-helpers.ts +107 -0
  333. package/vendored/lib/email-notifier.ts +102 -0
  334. package/vendored/lib/email-templates/build-failure.tsx +193 -0
  335. package/vendored/lib/email-templates/components/base-layout.tsx +150 -0
  336. package/vendored/lib/email-templates/components/error-box.tsx +88 -0
  337. package/vendored/lib/email-templates/components/info-row.tsx +63 -0
  338. package/vendored/lib/email-templates/index.ts +13 -0
  339. package/vendored/lib/empty-polyfill.js +3 -0
  340. package/vendored/lib/extract-highlights.ts +124 -0
  341. package/vendored/lib/fonts.ts +227 -0
  342. package/vendored/lib/frontmatter-utils.ts +77 -0
  343. package/vendored/lib/fs-utils.ts +20 -0
  344. package/vendored/lib/git-utils.ts +87 -0
  345. package/vendored/lib/health-checks.ts +224 -0
  346. package/vendored/lib/icon-utils.ts +492 -0
  347. package/vendored/lib/infer-page-type.ts +14 -0
  348. package/vendored/lib/isr-build-executor.ts +185 -0
  349. package/vendored/lib/language-icons.ts +152 -0
  350. package/vendored/lib/language-utils.ts +338 -0
  351. package/vendored/lib/latex-config.ts +64 -0
  352. package/vendored/lib/link-prefix-context.tsx +32 -0
  353. package/vendored/lib/logger.ts +63 -0
  354. package/vendored/lib/mcp-search.ts +255 -0
  355. package/vendored/lib/mdx-inline-components.ts +155 -0
  356. package/vendored/lib/mdx.ts +100 -0
  357. package/vendored/lib/middleware-helpers.ts +519 -0
  358. package/vendored/lib/navigation-resolver.ts +621 -0
  359. package/vendored/lib/navigation-utils.ts +103 -0
  360. package/vendored/lib/normalize-config.ts +94 -0
  361. package/vendored/lib/openapi/cache.ts +92 -0
  362. package/vendored/lib/openapi/code-examples.ts +389 -0
  363. package/vendored/lib/openapi/errors.ts +253 -0
  364. package/vendored/lib/openapi/generator.ts +230 -0
  365. package/vendored/lib/openapi/index.ts +84 -0
  366. package/vendored/lib/openapi/parser.ts +474 -0
  367. package/vendored/lib/openapi/types.ts +232 -0
  368. package/vendored/lib/openapi/validator.ts +156 -0
  369. package/vendored/lib/openapi-isr.ts +121 -0
  370. package/vendored/lib/page-isr-helpers.ts +137 -0
  371. package/vendored/lib/path-safety.ts +130 -0
  372. package/vendored/lib/paths.ts +35 -0
  373. package/vendored/lib/preprocess-mdx.ts +951 -0
  374. package/vendored/lib/process-mdx-with-exports.ts +75 -0
  375. package/vendored/lib/project-resolver.ts +165 -0
  376. package/vendored/lib/r2-content.ts +60 -0
  377. package/vendored/lib/r2-manifest.ts +84 -0
  378. package/vendored/lib/recent-searches.ts +41 -0
  379. package/vendored/lib/recma-compound-components.ts +84 -0
  380. package/vendored/lib/redirect-compiler.ts +160 -0
  381. package/vendored/lib/redirect-matcher.ts +296 -0
  382. package/vendored/lib/redis.ts +23 -0
  383. package/vendored/lib/rehype-class-to-classname.ts +31 -0
  384. package/vendored/lib/rehype-code-meta.ts +275 -0
  385. package/vendored/lib/rehype-nozoom-to-data.ts +45 -0
  386. package/vendored/lib/remark-extract-exports.ts +104 -0
  387. package/vendored/lib/resilience.ts +260 -0
  388. package/vendored/lib/revalidation-helpers.ts +200 -0
  389. package/vendored/lib/revalidation-trigger.ts +150 -0
  390. package/vendored/lib/screenshot-capture.ts +229 -0
  391. package/vendored/lib/search-client.ts +91 -0
  392. package/vendored/lib/search-suggestions.ts +38 -0
  393. package/vendored/lib/search.ts +158 -0
  394. package/vendored/lib/seo.ts +264 -0
  395. package/vendored/lib/shiki-client.ts +131 -0
  396. package/vendored/lib/shiki-config.ts +289 -0
  397. package/vendored/lib/shiki-css-theme.ts +46 -0
  398. package/vendored/lib/shiki-highlighter.ts +62 -0
  399. package/vendored/lib/shiki-transformers.ts +337 -0
  400. package/vendored/lib/slack-notifier.ts +248 -0
  401. package/vendored/lib/snippet-compiler-isr.ts +114 -0
  402. package/vendored/lib/snippet-loader-isr.ts +276 -0
  403. package/vendored/lib/static-artifacts.ts +375 -0
  404. package/vendored/lib/static-file-route.ts +72 -0
  405. package/vendored/lib/tracking-script.ts +19 -0
  406. package/vendored/lib/typography-config.ts +42 -0
  407. package/vendored/lib/validate-config.ts +268 -0
  408. package/vendored/next.config.js +45 -0
  409. package/vendored/postcss.config.js +6 -0
  410. package/vendored/schema/README.md +28 -0
  411. package/vendored/schema/docs-schema.json +4631 -0
  412. package/vendored/scripts/build-project.cjs +174 -0
  413. package/vendored/scripts/build-search-index.cjs +347 -0
  414. package/vendored/scripts/compile-snippets.cjs +488 -0
  415. package/vendored/scripts/copy-files.cjs +295 -0
  416. package/vendored/scripts/dev-project.cjs +534 -0
  417. package/vendored/scripts/enhance-navigation.cjs +354 -0
  418. package/vendored/scripts/validate-links.cjs +423 -0
  419. package/vendored/shared/constants.ts +6 -0
  420. package/vendored/shared/index.ts +19 -0
  421. package/vendored/shared/logger.ts +62 -0
  422. package/vendored/shared/memory-monitor.ts +190 -0
  423. package/vendored/shared/navigation-validator.ts +101 -0
  424. package/vendored/shared/path-security.ts +39 -0
  425. package/vendored/shared/status-reporter.ts +199 -0
  426. package/vendored/shared/timer.ts +51 -0
  427. package/vendored/shared/types.ts +102 -0
  428. package/vendored/tailwind.config.ts +39 -0
  429. package/vendored/themes/base.css +1311 -0
  430. package/vendored/themes/index.ts +119 -0
  431. package/vendored/themes/jam/variables.css +835 -0
  432. package/vendored/themes/nebula/variables.css +282 -0
  433. package/vendored/themes/pulsar/variables.css +1009 -0
  434. package/vendored/themes/types.ts +89 -0
  435. package/vendored/tsconfig.json +48 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * SEO Metadata Builder
3
+ *
4
+ * Builds Next.js Metadata objects from docs.json config and page frontmatter.
5
+ * Supports 19+ meta tags with per-page overrides.
6
+ *
7
+ * Priority order: Page frontmatter > Global config > Auto-generated
8
+ */
9
+
10
+ import type { Metadata } from 'next';
11
+ import type { DocsConfig, Logo, LogoConfig, LanguageConfig, LanguageCode } from './docs-types';
12
+ import { transformLanguagePath, extractLanguageFromPath, isValidLanguageCode } from './language-utils';
13
+
14
+ /**
15
+ * Build the OG image URL for a page using the proxy's /api/og endpoint.
16
+ * Returns undefined if og:image is explicitly set in metatags.
17
+ */
18
+ function buildOgImageUrl(
19
+ baseUrl: string,
20
+ title: string,
21
+ siteName: string,
22
+ options?: {
23
+ description?: string;
24
+ section?: string;
25
+ logo?: Logo;
26
+ theme?: 'light' | 'dark';
27
+ }
28
+ ): string {
29
+ const params = new URLSearchParams();
30
+ params.set('title', title);
31
+ params.set('siteName', siteName);
32
+
33
+ if (options?.description) {
34
+ params.set('description', options.description);
35
+ }
36
+ if (options?.section) {
37
+ params.set('section', options.section);
38
+ }
39
+ if (options?.theme) {
40
+ params.set('theme', options.theme);
41
+ }
42
+
43
+ // Get root URL (strip /docs path if present, since API endpoints are at domain root)
44
+ const rootUrl = baseUrl.replace(/\/docs$/, '');
45
+
46
+ // Handle logo - prefer dark variant for OG images (dark background)
47
+ if (options?.logo) {
48
+ let logoPath: string;
49
+ if (typeof options.logo === 'string') {
50
+ logoPath = options.logo;
51
+ } else {
52
+ logoPath = (options.logo as LogoConfig).dark || (options.logo as LogoConfig).light;
53
+ }
54
+ // Make logo URL absolute (use root URL since assets are at domain root)
55
+ if (logoPath && !logoPath.startsWith('http')) {
56
+ logoPath = `${rootUrl}${logoPath.startsWith('/') ? '' : '/'}${logoPath}`;
57
+ }
58
+ if (logoPath) {
59
+ params.set('logo', logoPath);
60
+ }
61
+ }
62
+
63
+ return `${rootUrl}/api/og?${params.toString()}`;
64
+ }
65
+
66
+ export interface PageFrontmatter {
67
+ title?: string;
68
+ description?: string;
69
+ noindex?: boolean;
70
+ hidden?: boolean;
71
+ /** Section/group name for OG image (optional) */
72
+ section?: string;
73
+ seo?: {
74
+ noindex?: boolean;
75
+ canonical?: string;
76
+ [key: string]: unknown;
77
+ };
78
+ }
79
+
80
+ /**
81
+ * Build hreflang alternate links for multi-language pages.
82
+ * Generates links for each language version of the page, plus x-default.
83
+ *
84
+ * @param baseUrl - The base URL (e.g., "https://docs.example.com")
85
+ * @param pagePath - The current page path (e.g., "es/getting-started")
86
+ * @param languages - Array of language configurations from docs.json
87
+ * @returns Record of language code to URL for alternates.languages
88
+ */
89
+ function buildHreflangAlternates(
90
+ baseUrl: string,
91
+ pagePath: string,
92
+ languages: LanguageConfig[]
93
+ ): Record<string, string> | undefined {
94
+ // Only generate hreflang if there are multiple languages
95
+ if (!languages || languages.length <= 1) {
96
+ return undefined;
97
+ }
98
+
99
+ // Find the default language
100
+ const defaultLang = languages.find((l) => l.default)?.language || languages[0]?.language || 'en';
101
+
102
+ // Detect current language from path
103
+ const currentLang = extractLanguageFromPath(pagePath) || defaultLang;
104
+
105
+ // Build alternates for each language
106
+ const alternates: Record<string, string> = {};
107
+
108
+ for (const langConfig of languages) {
109
+ const lang = langConfig.language;
110
+ // Transform current path to this language's version
111
+ // transformLanguagePath returns paths relative to app root (e.g., '/es/intro' or '/intro')
112
+ const langPath = transformLanguagePath(pagePath, currentLang, lang, defaultLang);
113
+ const cleanPath = langPath.replace(/^\//, ''); // Remove leading slash for URL building
114
+ alternates[lang] = cleanPath ? `${baseUrl}/${cleanPath}` : baseUrl;
115
+ }
116
+
117
+ // Add x-default pointing to the default language version
118
+ const defaultPath = transformLanguagePath(pagePath, currentLang, defaultLang, defaultLang);
119
+ const cleanDefaultPath = defaultPath.replace(/^\//, '');
120
+ alternates['x-default'] = cleanDefaultPath ? `${baseUrl}/${cleanDefaultPath}` : baseUrl;
121
+
122
+ return alternates;
123
+ }
124
+
125
+ /**
126
+ * Build SEO metadata for a documentation page.
127
+ *
128
+ * @param config - The docs.json configuration
129
+ * @param frontmatter - Page frontmatter data
130
+ * @param pagePath - The page path (e.g., "getting-started/installation")
131
+ * @param baseUrl - The base URL (e.g., "https://docs.example.com")
132
+ * @param languages - Optional array of language configurations for hreflang tags
133
+ * @returns Partial<Metadata> to spread into generateMetadata return
134
+ */
135
+ export function buildSeoMetadata(
136
+ config: DocsConfig,
137
+ frontmatter: PageFrontmatter,
138
+ pagePath: string,
139
+ baseUrl: string,
140
+ languages?: LanguageConfig[]
141
+ ): Partial<Metadata> {
142
+ const globalMeta = config.seo?.metatags || {};
143
+ const pageMeta = (frontmatter.seo as Record<string, string>) || {};
144
+ // Merge: page overrides global
145
+ const metatags: Record<string, string> = { ...globalMeta, ...pageMeta };
146
+ const metadata: Partial<Metadata> = {};
147
+
148
+ // 1. Generator - always add
149
+ metadata.generator = 'Jamdesk';
150
+
151
+ // 2. Robots (priority: page > global)
152
+ // Page noindex can be set via frontmatter.noindex or frontmatter.seo.noindex
153
+ const pageNoindex = frontmatter.noindex ?? frontmatter.seo?.noindex;
154
+ if (pageNoindex === true) {
155
+ // noindex does NOT imply nofollow - use follow: true
156
+ metadata.robots = { index: false, follow: true };
157
+ } else if (pageNoindex !== false && metatags.robots) {
158
+ // Page didn't explicitly set noindex: false, so use global robots
159
+ metadata.robots = metatags.robots;
160
+ }
161
+ // If pageNoindex === false, it overrides any global noindex (no robots meta = index)
162
+
163
+ // 3. Googlebot (separate from robots)
164
+ if (metatags.googlebot) {
165
+ // Merge googlebot with existing robots config
166
+ const existingRobots = typeof metadata.robots === 'object' ? metadata.robots : {};
167
+ metadata.robots = {
168
+ ...existingRobots,
169
+ googleBot: metatags.googlebot,
170
+ };
171
+ }
172
+
173
+ // 4. Google site verification
174
+ if (metatags['google-site-verification']) {
175
+ metadata.verification = { google: metatags['google-site-verification'] };
176
+ }
177
+
178
+ // 5. Keywords
179
+ if (metatags.keywords) {
180
+ metadata.keywords = metatags.keywords.split(',').map((k) => k.trim());
181
+ }
182
+
183
+ // 6. Description (global fallback only - page description handled separately)
184
+ if (!frontmatter.description && metatags.description) {
185
+ metadata.description = metatags.description;
186
+ }
187
+
188
+ // 7. Canonical (auto-generate if not specified)
189
+ const cleanPath = pagePath.replace(/^\/+|\/+$/g, ''); // Remove leading/trailing slashes
190
+ const pageUrl = cleanPath ? `${baseUrl}/${cleanPath}` : baseUrl;
191
+ const canonical = pageMeta.canonical || metatags.canonical || pageUrl;
192
+
193
+ // 7b. Hreflang alternates for multi-language support
194
+ const hreflangLanguages = buildHreflangAlternates(baseUrl, pagePath, languages || []);
195
+
196
+ metadata.alternates = {
197
+ canonical,
198
+ ...(hreflangLanguages && { languages: hreflangLanguages }),
199
+ };
200
+
201
+ // 8. Open Graph
202
+ const hasOgTags = Object.keys(metatags).some((k) => k.startsWith('og:'));
203
+ if (hasOgTags || frontmatter.title) {
204
+ // Auto-generate OG image URL if not explicitly set
205
+ const ogImageUrl = metatags['og:image'] || buildOgImageUrl(
206
+ baseUrl,
207
+ frontmatter.title || 'Documentation',
208
+ config.name,
209
+ {
210
+ description: frontmatter.description,
211
+ section: frontmatter.section,
212
+ logo: config.logo,
213
+ theme: 'dark', // Dark theme looks better for OG images
214
+ }
215
+ );
216
+
217
+ metadata.openGraph = {
218
+ title: metatags['og:title'] || frontmatter.title,
219
+ description: metatags['og:description'] || frontmatter.description,
220
+ url: metatags['og:url'] || pageUrl,
221
+ siteName: metatags['og:site_name'] || config.name,
222
+ type: (metatags['og:type'] as 'website' | 'article') || 'website',
223
+ images: [ogImageUrl],
224
+ };
225
+ }
226
+
227
+ // 9. Twitter Cards
228
+ // Auto-generate Twitter card with OG image
229
+ const twitterImageUrl = metatags['twitter:image'] || (metadata.openGraph as { images?: string[] })?.images?.[0];
230
+ metadata.twitter = {
231
+ card: (metatags['twitter:card'] as 'summary' | 'summary_large_image') || 'summary_large_image',
232
+ site: metatags['twitter:site'],
233
+ title: metatags['twitter:title'] || frontmatter.title,
234
+ description: metatags['twitter:description'] || frontmatter.description,
235
+ ...(twitterImageUrl && { images: [twitterImageUrl] }),
236
+ };
237
+
238
+ // 10. Theme color
239
+ if (metatags['theme-color']) {
240
+ metadata.themeColor = metatags['theme-color'];
241
+ }
242
+
243
+ // 11. Authors
244
+ if (metatags.author) {
245
+ metadata.authors = [{ name: metatags.author }];
246
+ }
247
+
248
+ // 12. Other tags (google, copyright, etc.)
249
+ const other: Record<string, string> = {};
250
+ if (metatags.google) other.google = metatags.google;
251
+ if (metatags.copyright) other.copyright = metatags.copyright;
252
+
253
+ // 13. Build metadata - commit SHA helps identify which version created this page
254
+ // Note: We use commit SHA (not unique build ID) to ensure identical content = identical HTML
255
+ if (process.env.BUILD_ID) {
256
+ other['jamdesk:build-id'] = process.env.BUILD_ID;
257
+ }
258
+
259
+ if (Object.keys(other).length > 0) {
260
+ metadata.other = other;
261
+ }
262
+
263
+ return metadata;
264
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Client-side Shiki syntax highlighting utility
3
+ * Used for dynamic code highlighting (e.g., OpenAPI code examples)
4
+ */
5
+ 'use client';
6
+
7
+ import type { Highlighter, BundledLanguage, BundledTheme } from 'shiki';
8
+
9
+ let highlighter: Highlighter | null = null;
10
+
11
+ // Languages needed for API code examples
12
+ const CLIENT_LANGUAGES: BundledLanguage[] = [
13
+ 'javascript',
14
+ 'typescript',
15
+ 'python',
16
+ 'bash',
17
+ 'json',
18
+ 'shell',
19
+ ];
20
+
21
+ // Dual themes for light/dark mode support
22
+ const THEMES = {
23
+ light: 'github-light-default' as BundledTheme,
24
+ dark: 'github-dark-default' as BundledTheme,
25
+ };
26
+
27
+ /**
28
+ * Get or initialize the Shiki highlighter for client-side use
29
+ */
30
+ async function getHighlighter(): Promise<Highlighter> {
31
+ if (!highlighter) {
32
+ const { createHighlighter } = await import('shiki');
33
+
34
+ highlighter = await createHighlighter({
35
+ themes: [THEMES.dark, THEMES.light],
36
+ langs: CLIENT_LANGUAGES,
37
+ });
38
+ }
39
+ return highlighter;
40
+ }
41
+
42
+ /**
43
+ * Escape HTML entities for fallback rendering
44
+ */
45
+ function escapeHtml(text: string): string {
46
+ return text
47
+ .replace(/&/g, '&amp;')
48
+ .replace(/</g, '&lt;')
49
+ .replace(/>/g, '&gt;')
50
+ .replace(/"/g, '&quot;')
51
+ .replace(/'/g, '&#039;');
52
+ }
53
+
54
+ /**
55
+ * Highlight code synchronously if highlighter is ready, otherwise return escaped code
56
+ * This is useful for initial render - the component can re-render when highlighting is done
57
+ */
58
+ export function highlightCodeSync(code: string, language: string): string {
59
+ if (!highlighter) {
60
+ // Return escaped code if highlighter not ready yet
61
+ return escapeHtml(code);
62
+ }
63
+
64
+ try {
65
+ const lang = normalizeLanguage(language);
66
+ return highlighter.codeToHtml(code, {
67
+ lang,
68
+ themes: THEMES,
69
+ defaultColor: 'dark',
70
+ });
71
+ } catch {
72
+ return escapeHtml(code);
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Highlight code asynchronously
78
+ * Returns full HTML with pre.shiki element for proper theme background support
79
+ */
80
+ export async function highlightCode(
81
+ code: string,
82
+ language: string
83
+ ): Promise<string> {
84
+ try {
85
+ const shiki = await getHighlighter();
86
+ const lang = normalizeLanguage(language);
87
+
88
+ // Return full HTML - the pre.shiki element contains background styles
89
+ // that switch via CSS variables in light mode
90
+ return shiki.codeToHtml(code, {
91
+ lang,
92
+ themes: THEMES,
93
+ defaultColor: 'dark',
94
+ });
95
+ } catch {
96
+ return escapeHtml(code);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Preload the highlighter (call early to reduce latency)
102
+ */
103
+ export async function preloadHighlighter(): Promise<void> {
104
+ await getHighlighter();
105
+ }
106
+
107
+ /**
108
+ * Normalize language aliases
109
+ */
110
+ function normalizeLanguage(lang: string): BundledLanguage {
111
+ const normalized = lang.toLowerCase().trim();
112
+
113
+ const aliases: Record<string, BundledLanguage> = {
114
+ js: 'javascript',
115
+ ts: 'typescript',
116
+ sh: 'bash',
117
+ curl: 'bash',
118
+ py: 'python',
119
+ };
120
+
121
+ if (normalized in aliases) {
122
+ return aliases[normalized];
123
+ }
124
+
125
+ if (CLIENT_LANGUAGES.includes(normalized as BundledLanguage)) {
126
+ return normalized as BundledLanguage;
127
+ }
128
+
129
+ // Default to text-like rendering
130
+ return 'bash';
131
+ }
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Shiki syntax highlighting configuration
3
+ * Reads theme settings from docs.json and provides rehype plugin options
4
+ */
5
+
6
+ import type { RehypeShikiOptions } from '@shikijs/rehype';
7
+ import rehypeShikiFromHighlighter, { type RehypeShikiCoreOptions } from '@shikijs/rehype/core';
8
+ import type { BuiltinLanguage, Highlighter, ThemeRegistration } from 'shiki';
9
+ import type { Pluggable } from 'unified';
10
+ import type { DocsConfig, StylingConfig } from './docs-types';
11
+ import { transformerLineFeatures } from './shiki-transformers';
12
+ import { JAMDESK_CSS_THEME } from './shiki-css-theme';
13
+
14
+ /**
15
+ * Preloaded languages for faster static generation.
16
+ * These are loaded upfront when the highlighter initializes,
17
+ * avoiding I/O during page rendering.
18
+ *
19
+ * ## What happens if a language is NOT in this list?
20
+ * - The code block renders WITHOUT syntax highlighting (plain monospace text)
21
+ * - A warning is logged during build: "[shiki] Unknown language: <lang>"
22
+ * - The build continues successfully (no errors)
23
+ *
24
+ * ## How to add a new language:
25
+ * 1. Find the language ID from Shiki's bundled languages:
26
+ * https://shiki.style/languages
27
+ * 2. Add it to this array (must match the exact Shiki language ID)
28
+ * 3. Deploy to Cloud Run and rebuild affected projects
29
+ *
30
+ * Each language adds ~100-500KB to highlighter init time.
31
+ * Keep this list focused on commonly-used documentation languages.
32
+ */
33
+ export const PRELOADED_LANGUAGES: BuiltinLanguage[] = [
34
+ // Web fundamentals
35
+ 'javascript',
36
+ 'typescript',
37
+ 'js', // Alias for javascript
38
+ 'ts', // Alias for typescript
39
+ 'jsx',
40
+ 'tsx',
41
+ 'html',
42
+ 'css',
43
+ 'json',
44
+ 'yaml',
45
+ // Shell/scripting
46
+ 'bash',
47
+ 'shell', // Alias for shellscript, commonly used in markdown
48
+ 'shellscript',
49
+ 'powershell',
50
+ // Backend languages
51
+ 'python',
52
+ 'ruby',
53
+ 'go',
54
+ 'rust',
55
+ 'java',
56
+ 'kotlin',
57
+ 'swift',
58
+ 'php',
59
+ 'csharp',
60
+ 'c',
61
+ 'cpp',
62
+ 'clojure',
63
+ // Data/query
64
+ 'sql',
65
+ 'graphql',
66
+ // Config/markup
67
+ 'xml',
68
+ 'toml',
69
+ 'markdown',
70
+ 'md', // Alias for markdown - some docs use ```md instead of ```markdown
71
+ 'mdx',
72
+ // DevOps
73
+ 'dockerfile',
74
+ // Utility
75
+ 'diff',
76
+ 'log', // Log files
77
+ 'http', // HTTP requests (GET https://api.example.com)
78
+ // Note: 'text' and 'plaintext' are NOT valid Shiki languages.
79
+ // Code blocks with these will render without highlighting (which is correct).
80
+ ];
81
+
82
+ // Set for O(1) language lookups in the unknown language warning transformer
83
+ const PRELOADED_LANGUAGES_SET = new Set<string>(PRELOADED_LANGUAGES);
84
+
85
+ /**
86
+ * Languages that intentionally don't have syntax highlighting.
87
+ * Adding them here prevents the "Unknown language" warning during build.
88
+ *
89
+ * Note: 'mermaid' is included because it's rendered client-side by the Mermaid
90
+ * component. The data-language attribute is still set by Shiki's transformer,
91
+ * which MDXComponents.tsx uses to route to the Mermaid component.
92
+ */
93
+ const NO_HIGHLIGHT_LANGS = new Set(['text', 'plaintext', 'plain', 'txt', 'raw', 'mermaid']);
94
+
95
+ // Curated list of supported themes (reduces bundle size vs bundling all ~50)
96
+ export const SUPPORTED_THEMES = [
97
+ // GitHub family (default themes - matching marketing)
98
+ 'github-dark',
99
+ 'github-light',
100
+ 'github-dark-default',
101
+ 'github-light-default',
102
+ // Popular dark themes
103
+ 'tokyo-night',
104
+ 'one-dark-pro',
105
+ 'dracula',
106
+ 'nord',
107
+ 'vitesse-dark',
108
+ // Popular light themes
109
+ 'vitesse-light',
110
+ 'min-light',
111
+ // Catppuccin variants
112
+ 'catppuccin-mocha',
113
+ 'catppuccin-latte',
114
+ // Custom CSS styling
115
+ 'css-variables',
116
+ ] as const;
117
+
118
+ export type SupportedTheme = (typeof SUPPORTED_THEMES)[number];
119
+
120
+ // Default themes - github-dark-default has the darker #0d1117 background
121
+ const DEFAULT_DARK_THEME: SupportedTheme = 'github-dark-default';
122
+ const DEFAULT_LIGHT_THEME: SupportedTheme = 'github-light-default';
123
+
124
+ // Type for theme values (can be string or ThemeRegistration for css-variables)
125
+ type ThemeValue = SupportedTheme | ThemeRegistration;
126
+
127
+ /**
128
+ * Parse codeblocks config from docs.json styling section
129
+ */
130
+ function parseCodeblocksConfig(styling?: StylingConfig): {
131
+ darkTheme: ThemeValue;
132
+ lightTheme: ThemeValue;
133
+ } {
134
+ const codeblocks = styling?.codeblocks;
135
+
136
+ // Default: use github themes
137
+ if (!codeblocks || codeblocks === 'system') {
138
+ return { darkTheme: DEFAULT_DARK_THEME, lightTheme: DEFAULT_LIGHT_THEME };
139
+ }
140
+
141
+ // 'dark' mode only
142
+ if (codeblocks === 'dark') {
143
+ return { darkTheme: DEFAULT_DARK_THEME, lightTheme: DEFAULT_DARK_THEME };
144
+ }
145
+
146
+ // Object config with theme property
147
+ const themeConfig = codeblocks.theme;
148
+
149
+ if (!themeConfig) {
150
+ return { darkTheme: DEFAULT_DARK_THEME, lightTheme: DEFAULT_LIGHT_THEME };
151
+ }
152
+
153
+ // Single theme string - use for both
154
+ if (typeof themeConfig === 'string') {
155
+ const theme = validateTheme(themeConfig);
156
+ return { darkTheme: theme, lightTheme: theme };
157
+ }
158
+
159
+ // Light/dark theme pair
160
+ return {
161
+ darkTheme: validateTheme(themeConfig.dark),
162
+ lightTheme: validateTheme(themeConfig.light),
163
+ };
164
+ }
165
+
166
+ /**
167
+ * Validate a theme name against supported themes
168
+ * Returns ThemeRegistration object for css-variables, string for built-in themes
169
+ */
170
+ function validateTheme(theme: string | undefined): ThemeValue {
171
+ if (!theme) return DEFAULT_DARK_THEME;
172
+
173
+ // Special handling for css-variables theme
174
+ if (theme === 'css-variables') {
175
+ return JAMDESK_CSS_THEME;
176
+ }
177
+
178
+ if (SUPPORTED_THEMES.includes(theme as SupportedTheme)) {
179
+ return theme as SupportedTheme;
180
+ }
181
+
182
+ console.warn(
183
+ `[shiki-config] Unsupported theme "${theme}", falling back to "${DEFAULT_DARK_THEME}". ` +
184
+ `Supported themes: ${SUPPORTED_THEMES.join(', ')}`
185
+ );
186
+ return DEFAULT_DARK_THEME;
187
+ }
188
+
189
+ /**
190
+ * Get Shiki rehype plugin options based on docs.json config
191
+ */
192
+ export function getShikiOptions(config?: DocsConfig): Partial<RehypeShikiOptions> {
193
+ const { darkTheme, lightTheme } = parseCodeblocksConfig(config?.styling);
194
+
195
+ // Use dual themes for light/dark mode support
196
+ // The 'themes' option enables CSS variable-based theme switching
197
+ return {
198
+ themes: {
199
+ light: lightTheme,
200
+ dark: darkTheme,
201
+ },
202
+ // Preload common languages for faster static generation
203
+ // Unknown languages fall back to plaintext (no highlighting)
204
+ langs: PRELOADED_LANGUAGES,
205
+ // Default color mode (used when no preference is specified)
206
+ defaultColor: 'dark',
207
+ // Safety: skip highlighting lines >1000 chars to prevent OOM on minified code
208
+ // Lines exceeding this limit render without syntax highlighting
209
+ tokenizeMaxLineLength: 1000,
210
+ // Add transformers for language/meta attributes and line features
211
+ // Performance note: Order matters - cheaper transformers first, lazy notation last
212
+ transformers: [
213
+ {
214
+ name: 'log-unknown-languages',
215
+ preprocess(code: string, options: { lang?: string }) {
216
+ // Log warning for unknown languages so we know to add them
217
+ const lang = options.lang;
218
+ // Skip warning for intentionally unhighlighted languages
219
+ if (
220
+ lang &&
221
+ !PRELOADED_LANGUAGES_SET.has(lang) && // O(1) Set lookup instead of O(n) array
222
+ !NO_HIGHLIGHT_LANGS.has(lang) // O(1) Set lookup
223
+ ) {
224
+ console.warn(
225
+ `[shiki] Unknown language: "${lang}" - code block will render without highlighting. ` +
226
+ `To add support, add "${lang}" to PRELOADED_LANGUAGES in lib/shiki-config.ts`
227
+ );
228
+ }
229
+ return code;
230
+ },
231
+ },
232
+ {
233
+ name: 'add-data-attributes',
234
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
235
+ pre(this: any, node: any) {
236
+ // Add data-language attribute to pre element for tab label extraction
237
+ if (this.options.lang) {
238
+ node.properties['data-language'] = this.options.lang;
239
+ }
240
+ // Add data-meta attribute to pre element
241
+ // This preserves the raw meta string from code fences (e.g., "Header" from ```json Header)
242
+ // A post-Shiki rehype plugin (rehypeRestoreDataTitle) converts this to data-title
243
+ if (this.options.meta?.__raw) {
244
+ node.properties['data-meta'] = this.options.meta.__raw;
245
+ }
246
+ },
247
+ },
248
+ // Add line highlighting ({1,3-5} syntax) and line numbers support
249
+ // Note: This handles all meta string parsing with caching for performance
250
+ transformerLineFeatures(),
251
+ // NOTE: Notation transformers ([!code highlight], [!code focus], [!code ++/--])
252
+ // were removed for performance. Use {1,3-5} meta syntax for line highlighting.
253
+ // If notation support is needed, add createLazyNotationTransformer() here.
254
+ ],
255
+ };
256
+ }
257
+
258
+ /**
259
+ * Create a rehype plugin that uses a pre-existing Shiki highlighter.
260
+ * This is more efficient than the default rehypeShiki plugin which
261
+ * creates a new highlighter for each page render.
262
+ *
263
+ * @param highlighter - Pre-created highlighter from getHighlighter()
264
+ * @param config - Docs configuration for theme selection
265
+ * @returns A rehype plugin that can be used in MDXRemote options
266
+ */
267
+ export function createShikiRehypePlugin(
268
+ highlighter: Highlighter,
269
+ config?: DocsConfig
270
+ ): Pluggable {
271
+ const options = getShikiOptions(config) as RehypeShikiCoreOptions;
272
+ // Return a plugin function that creates the transformer
273
+ // This matches unified's expected plugin signature
274
+ return () => rehypeShikiFromHighlighter(highlighter, options);
275
+ }
276
+
277
+ /**
278
+ * Get themes array for preloading (excludes css-variables which is a ThemeRegistration)
279
+ */
280
+ export function getThemesToLoad(config?: DocsConfig): SupportedTheme[] {
281
+ const { darkTheme, lightTheme } = parseCodeblocksConfig(config?.styling);
282
+ const themes = new Set<SupportedTheme>();
283
+
284
+ // Only add string themes (not ThemeRegistration objects like css-variables)
285
+ if (typeof darkTheme === 'string') themes.add(darkTheme);
286
+ if (typeof lightTheme === 'string') themes.add(lightTheme);
287
+
288
+ return Array.from(themes);
289
+ }