@wrikka/create-docs 0.1.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 (380) hide show
  1. package/README.md +137 -0
  2. package/bin/cli.js +408 -0
  3. package/dist/index.cjs +20 -0
  4. package/dist/index.d.cts +475 -0
  5. package/dist/index.d.ts +475 -0
  6. package/dist/index.js +20 -0
  7. package/docs/_dir.yml +2 -0
  8. package/docs/config.md +75 -0
  9. package/docs/data-sources.md +88 -0
  10. package/docs/deploy.md +38 -0
  11. package/docs/features.md +51 -0
  12. package/docs/getting-started.md +42 -0
  13. package/docs/index.md +34 -0
  14. package/docs/markdown.md +154 -0
  15. package/docs/theming.md +53 -0
  16. package/package.json +142 -0
  17. package/scripts/generate-docs-index.ts +111 -0
  18. package/scripts/github-pull.ts +124 -0
  19. package/src/adapters/config/index.ts +1 -0
  20. package/src/adapters/config/node-config-loader.ts +36 -0
  21. package/src/adapters/fs/fs-docs-loader.ts +31 -0
  22. package/src/adapters/fs/index.ts +12 -0
  23. package/src/adapters/fs/memory-fs.ts +60 -0
  24. package/src/adapters/fs/node-fs.ts +116 -0
  25. package/src/adapters/git/index.ts +164 -0
  26. package/src/adapters/github/github-pull.ts +340 -0
  27. package/src/adapters/index.ts +6 -0
  28. package/src/adapters/velite.ts +112 -0
  29. package/src/adapters/vite/docs-watcher.ts +36 -0
  30. package/src/adapters/vite/index.ts +2 -0
  31. package/src/adapters/vite/polling-watcher.ts +89 -0
  32. package/src/code-block-enhancements/index.ts +3 -0
  33. package/src/config/index.ts +15 -0
  34. package/src/content/index.ts +11 -0
  35. package/src/content-validation/index.ts +5 -0
  36. package/src/index.ts +174 -0
  37. package/src/live-editor/index.ts +7 -0
  38. package/src/modules/analytics/application/plausible-adapter.ts +103 -0
  39. package/src/modules/analytics/application/umami-adapter.ts +109 -0
  40. package/src/modules/analytics/domain/events/index.ts +37 -0
  41. package/src/modules/analytics/domain/models/index.ts +35 -0
  42. package/src/modules/analytics/domain/operations/analytics-operations.ts +67 -0
  43. package/src/modules/analytics/domain/validators/index.ts +50 -0
  44. package/src/modules/analytics/index.ts +9 -0
  45. package/src/modules/analytics/ports/analytics-port.ts +17 -0
  46. package/src/modules/analytics/types/analytics.ts +16 -0
  47. package/src/modules/api-docs/application/type-docs-adapter.ts +34 -0
  48. package/src/modules/api-docs/domain/events/index.ts +42 -0
  49. package/src/modules/api-docs/domain/models/index.ts +40 -0
  50. package/src/modules/api-docs/domain/operations/api-docs-operations.ts +59 -0
  51. package/src/modules/api-docs/domain/validators/index.ts +56 -0
  52. package/src/modules/api-docs/index.ts +8 -0
  53. package/src/modules/api-docs/ports/api-docs-port.ts +21 -0
  54. package/src/modules/api-docs/types/api-docs.ts +15 -0
  55. package/src/modules/api-reference/openapi.ts +166 -0
  56. package/src/modules/api-reference/orpc.ts +94 -0
  57. package/src/modules/code-block-enhancements/application/usecases/index.ts +39 -0
  58. package/src/modules/code-block-enhancements/domain/code-operations.ts +72 -0
  59. package/src/modules/code-block-enhancements/domain/events/index.ts +58 -0
  60. package/src/modules/code-block-enhancements/domain/index.ts +11 -0
  61. package/src/modules/code-block-enhancements/domain/models/index.ts +36 -0
  62. package/src/modules/code-block-enhancements/domain/validators/index.ts +50 -0
  63. package/src/modules/code-block-enhancements/index.ts +10 -0
  64. package/src/modules/code-block-enhancements/ports/index.ts +18 -0
  65. package/src/modules/code-block-enhancements/types/index.ts +37 -0
  66. package/src/modules/code-execution/application/sandbox-adapter.ts +44 -0
  67. package/src/modules/code-execution/domain/events/index.ts +58 -0
  68. package/src/modules/code-execution/domain/models/index.ts +33 -0
  69. package/src/modules/code-execution/domain/operations/execution-operations.ts +60 -0
  70. package/src/modules/code-execution/domain/validators/index.ts +50 -0
  71. package/src/modules/code-execution/index.ts +8 -0
  72. package/src/modules/code-execution/ports/execution-port.ts +15 -0
  73. package/src/modules/code-execution/types/execution.ts +15 -0
  74. package/src/modules/comments/application/giscus-adapter.ts +55 -0
  75. package/src/modules/comments/domain/events/index.ts +55 -0
  76. package/src/modules/comments/domain/models/index.ts +30 -0
  77. package/src/modules/comments/domain/operations/comment-operations.ts +46 -0
  78. package/src/modules/comments/domain/validators/index.ts +50 -0
  79. package/src/modules/comments/index.ts +8 -0
  80. package/src/modules/comments/ports/comment-port.ts +18 -0
  81. package/src/modules/comments/types/comments.ts +19 -0
  82. package/src/modules/config/application/usecases/index.ts +1 -0
  83. package/src/modules/config/application/usecases/loadConfig.ts +38 -0
  84. package/src/modules/config/application/workflows/index.ts +1 -0
  85. package/src/modules/config/application/workflows/validateConfig.ts +14 -0
  86. package/src/modules/config/domain/events/index.ts +50 -0
  87. package/src/modules/config/domain/models/index.ts +9 -0
  88. package/src/modules/config/domain/operations/defaults.ts +74 -0
  89. package/src/modules/config/domain/operations/index.ts +2 -0
  90. package/src/modules/config/domain/operations/resolve.ts +40 -0
  91. package/src/modules/config/domain/validators/index.ts +152 -0
  92. package/src/modules/config/index.ts +23 -0
  93. package/src/modules/config/ports/index.ts +15 -0
  94. package/src/modules/config/types/index.ts +113 -0
  95. package/src/modules/config/types/public.ts +19 -0
  96. package/src/modules/content/application/cache/index.ts +6 -0
  97. package/src/modules/content/application/cache/parse-cache.ts +6 -0
  98. package/src/modules/content/application/cache/parseCache.ts +56 -0
  99. package/src/modules/content/application/usecases/index.ts +2 -0
  100. package/src/modules/content/application/usecases/load-doc-page.ts +1 -0
  101. package/src/modules/content/application/usecases/loadDocPage.ts +111 -0
  102. package/src/modules/content/application/usecases/scanDocsDir.ts +105 -0
  103. package/src/modules/content/application/workflows/index.ts +1 -0
  104. package/src/modules/content/application/workflows/processDocs.ts +51 -0
  105. package/src/modules/content/domain/events/index.ts +61 -0
  106. package/src/modules/content/domain/models/index.ts +13 -0
  107. package/src/modules/content/domain/operations/build-page.ts +146 -0
  108. package/src/modules/content/domain/operations/buildPage.ts +93 -0
  109. package/src/modules/content/domain/operations/index.ts +17 -0
  110. package/src/modules/content/domain/operations/parse.ts +241 -0
  111. package/src/modules/content/domain/validators/frontmatter.ts +82 -0
  112. package/src/modules/content/domain/validators/index.ts +6 -0
  113. package/src/modules/content/index.ts +27 -0
  114. package/src/modules/content/ports/index.ts +45 -0
  115. package/src/modules/content/ports/velite.ts +134 -0
  116. package/src/modules/content/types/index.ts +76 -0
  117. package/src/modules/content/types/public.ts +1 -0
  118. package/src/modules/content-linting/application/builtin-linting-adapter.ts +82 -0
  119. package/src/modules/content-linting/domain/events/index.ts +58 -0
  120. package/src/modules/content-linting/domain/models/index.ts +46 -0
  121. package/src/modules/content-linting/domain/operations/linting-operations.ts +82 -0
  122. package/src/modules/content-linting/domain/validators/index.ts +50 -0
  123. package/src/modules/content-linting/index.ts +8 -0
  124. package/src/modules/content-linting/ports/linting-port.ts +21 -0
  125. package/src/modules/content-linting/types/linting.ts +18 -0
  126. package/src/modules/content-validation/application/usecases/index.ts +18 -0
  127. package/src/modules/content-validation/domain/events/index.ts +7 -0
  128. package/src/modules/content-validation/domain/index.ts +16 -0
  129. package/src/modules/content-validation/domain/models/index.ts +33 -0
  130. package/src/modules/content-validation/domain/operations/index.ts +157 -0
  131. package/src/modules/content-validation/domain/types/index.ts +17 -0
  132. package/src/modules/content-validation/domain/validators/index.ts +8 -0
  133. package/src/modules/content-validation/index.ts +9 -0
  134. package/src/modules/content-validation/ports/index.ts +15 -0
  135. package/src/modules/content-validation/types/index.ts +5 -0
  136. package/src/modules/export/application/puppeteer-export-adapter.ts +63 -0
  137. package/src/modules/export/domain/events/index.ts +55 -0
  138. package/src/modules/export/domain/models/index.ts +38 -0
  139. package/src/modules/export/domain/operations/export-operations.ts +56 -0
  140. package/src/modules/export/domain/validators/index.ts +52 -0
  141. package/src/modules/export/index.ts +8 -0
  142. package/src/modules/export/ports/export-port.ts +15 -0
  143. package/src/modules/export/types/export.ts +15 -0
  144. package/src/modules/external-search/application/algolia-adapter.ts +182 -0
  145. package/src/modules/external-search/application/meilisearch-adapter.ts +161 -0
  146. package/src/modules/external-search/domain/events/index.ts +42 -0
  147. package/src/modules/external-search/domain/models/index.ts +42 -0
  148. package/src/modules/external-search/domain/operations/search-operations.ts +53 -0
  149. package/src/modules/external-search/domain/validators/index.ts +55 -0
  150. package/src/modules/external-search/index.ts +9 -0
  151. package/src/modules/external-search/ports/external-search-port.ts +23 -0
  152. package/src/modules/external-search/types/search.ts +19 -0
  153. package/src/modules/git-history/application/simple-git-adapter.ts +46 -0
  154. package/src/modules/git-history/domain/events/index.ts +34 -0
  155. package/src/modules/git-history/domain/models/index.ts +25 -0
  156. package/src/modules/git-history/domain/operations/git-history-operations.ts +56 -0
  157. package/src/modules/git-history/domain/validators/index.ts +52 -0
  158. package/src/modules/git-history/index.ts +8 -0
  159. package/src/modules/git-history/ports/git-history-port.ts +21 -0
  160. package/src/modules/git-history/types/git-history.ts +15 -0
  161. package/src/modules/i18n/application/fs-locale-loader.ts +39 -0
  162. package/src/modules/i18n/domain/events/index.ts +34 -0
  163. package/src/modules/i18n/domain/models/index.ts +34 -0
  164. package/src/modules/i18n/domain/operations/locale-operations.ts +74 -0
  165. package/src/modules/i18n/domain/validators/index.ts +52 -0
  166. package/src/modules/i18n/index.ts +8 -0
  167. package/src/modules/i18n/ports/locale-loader-port.ts +18 -0
  168. package/src/modules/i18n/types/locale.ts +17 -0
  169. package/src/modules/image-optimization/application/sharp-adapter.ts +58 -0
  170. package/src/modules/image-optimization/domain/events/index.ts +39 -0
  171. package/src/modules/image-optimization/domain/models/index.ts +27 -0
  172. package/src/modules/image-optimization/domain/operations/image-operations.ts +65 -0
  173. package/src/modules/image-optimization/domain/validators/index.ts +52 -0
  174. package/src/modules/image-optimization/index.ts +8 -0
  175. package/src/modules/image-optimization/ports/image-optimizer-port.ts +15 -0
  176. package/src/modules/image-optimization/types/image.ts +17 -0
  177. package/src/modules/live-editor/application/usecases/index.ts +60 -0
  178. package/src/modules/live-editor/domain/events/index.ts +37 -0
  179. package/src/modules/live-editor/domain/gitOperations.ts +110 -0
  180. package/src/modules/live-editor/domain/index.ts +15 -0
  181. package/src/modules/live-editor/domain/models/index.ts +21 -0
  182. package/src/modules/live-editor/domain/validators/index.ts +55 -0
  183. package/src/modules/live-editor/index.ts +14 -0
  184. package/src/modules/live-editor/ports/index.ts +49 -0
  185. package/src/modules/live-editor/types/index.ts +80 -0
  186. package/src/modules/live-preview/application/vite-preview-adapter.ts +20 -0
  187. package/src/modules/live-preview/domain/operations/preview-operations.ts +56 -0
  188. package/src/modules/live-preview/index.ts +8 -0
  189. package/src/modules/live-preview/ports/preview-port.ts +20 -0
  190. package/src/modules/live-preview/types/preview.ts +16 -0
  191. package/src/modules/mdx/application/mdx-js-adapter.ts +38 -0
  192. package/src/modules/mdx/domain/operations/parse-mdx.ts +43 -0
  193. package/src/modules/mdx/index.ts +8 -0
  194. package/src/modules/mdx/ports/mdx-parser-port.ts +15 -0
  195. package/src/modules/mdx/types/mdx.ts +14 -0
  196. package/src/modules/navigation/application/usecases/buildNav.ts +15 -0
  197. package/src/modules/navigation/application/usecases/buildSidebar.ts +45 -0
  198. package/src/modules/navigation/application/usecases/index.ts +2 -0
  199. package/src/modules/navigation/domain/events/index.ts +30 -0
  200. package/src/modules/navigation/domain/models/index.ts +7 -0
  201. package/src/modules/navigation/domain/operations/group.ts +79 -0
  202. package/src/modules/navigation/domain/operations/index.ts +10 -0
  203. package/src/modules/navigation/domain/operations/sort.ts +27 -0
  204. package/src/modules/navigation/domain/shared/utils/array.ts +39 -0
  205. package/src/modules/navigation/domain/validators/index.ts +88 -0
  206. package/src/modules/navigation/index.ts +15 -0
  207. package/src/modules/navigation/ports/index.ts +9 -0
  208. package/src/modules/navigation/types/index.ts +38 -0
  209. package/src/modules/navigation/types/public.ts +9 -0
  210. package/src/modules/openapi/application/swagger-parser-adapter.ts +178 -0
  211. package/src/modules/openapi/domain/operations/parse-openapi.ts +46 -0
  212. package/src/modules/openapi/index.ts +8 -0
  213. package/src/modules/openapi/ports/openapi-parser-port.ts +15 -0
  214. package/src/modules/openapi/types/openapi.ts +37 -0
  215. package/src/modules/plugin/application/usecases/build-virtual-modules.ts +53 -0
  216. package/src/modules/plugin/application/usecases/index.ts +1 -0
  217. package/src/modules/plugin/application/workflows/build-docs.ts +79 -0
  218. package/src/modules/plugin/application/workflows/index.ts +1 -0
  219. package/src/modules/plugin/domain/events/index.ts +62 -0
  220. package/src/modules/plugin/domain/models/index.ts +1 -0
  221. package/src/modules/plugin/domain/operations/build-virtual.ts +76 -0
  222. package/src/modules/plugin/domain/operations/index.ts +11 -0
  223. package/src/modules/plugin/domain/validators/index.ts +30 -0
  224. package/src/modules/plugin/index.ts +14 -0
  225. package/src/modules/plugin/ports/index.ts +21 -0
  226. package/src/modules/plugin/types/index.ts +27 -0
  227. package/src/modules/plugin/types/public.ts +1 -0
  228. package/src/modules/search/application/usecases/index.ts +1 -0
  229. package/src/modules/search/application/usecases/indexPages.ts +15 -0
  230. package/src/modules/search/domain/events/index.ts +32 -0
  231. package/src/modules/search/domain/models/index.ts +1 -0
  232. package/src/modules/search/domain/operations/build-index.ts +6 -0
  233. package/src/modules/search/domain/operations/buildIndex.ts +70 -0
  234. package/src/modules/search/domain/operations/index.ts +7 -0
  235. package/src/modules/search/domain/operations/query.ts +186 -0
  236. package/src/modules/search/domain/validators/index.ts +32 -0
  237. package/src/modules/search/index.ts +9 -0
  238. package/src/modules/search/types/index.ts +22 -0
  239. package/src/modules/search/types/public.ts +1 -0
  240. package/src/modules/search-analytics/application/local-storage-adapter.ts +68 -0
  241. package/src/modules/search-analytics/domain/operations/search-analytics-operations.ts +74 -0
  242. package/src/modules/search-analytics/index.ts +8 -0
  243. package/src/modules/search-analytics/ports/search-analytics-port.ts +20 -0
  244. package/src/modules/search-analytics/types/search-analytics.ts +16 -0
  245. package/src/modules/search-highlighting/application/dom-highlighting-adapter.ts +36 -0
  246. package/src/modules/search-highlighting/domain/operations/highlighting-operations.ts +72 -0
  247. package/src/modules/search-highlighting/index.ts +8 -0
  248. package/src/modules/search-highlighting/ports/highlighting-port.ts +14 -0
  249. package/src/modules/search-highlighting/types/highlighting.ts +15 -0
  250. package/src/modules/seo-optimization/application/usecases/index.ts +18 -0
  251. package/src/modules/seo-optimization/domain/index.ts +12 -0
  252. package/src/modules/seo-optimization/domain/seoOperations.ts +92 -0
  253. package/src/modules/seo-optimization/index.ts +8 -0
  254. package/src/modules/seo-optimization/ports/index.ts +18 -0
  255. package/src/modules/seo-optimization/types/index.ts +41 -0
  256. package/src/modules/theme/application/css-theme-adapter.ts +50 -0
  257. package/src/modules/theme/domain/operations/theme-operations.ts +68 -0
  258. package/src/modules/theme/index.ts +8 -0
  259. package/src/modules/theme/ports/theme-port.ts +8 -0
  260. package/src/modules/theme/types/theme.ts +12 -0
  261. package/src/modules/toc/application/markdown-toc-adapter.ts +106 -0
  262. package/src/modules/toc/domain/operations/toc-operations.ts +92 -0
  263. package/src/modules/toc/index.ts +8 -0
  264. package/src/modules/toc/ports/toc-port.ts +21 -0
  265. package/src/modules/toc/types/toc.ts +17 -0
  266. package/src/modules/toc-generator/application/usecases/index.ts +30 -0
  267. package/src/modules/toc-generator/domain/index.ts +12 -0
  268. package/src/modules/toc-generator/domain/tocOperations.ts +104 -0
  269. package/src/modules/toc-generator/index.ts +9 -0
  270. package/src/modules/toc-generator/ports/index.ts +20 -0
  271. package/src/modules/toc-generator/types/index.ts +50 -0
  272. package/src/modules/version-control/domain/events/index.ts +39 -0
  273. package/src/modules/version-control/domain/models/index.ts +25 -0
  274. package/src/modules/version-control/domain/validators/index.ts +50 -0
  275. package/src/modules/versioning/application/fs-version-loader.ts +44 -0
  276. package/src/modules/versioning/domain/operations/versioning-operations.ts +80 -0
  277. package/src/modules/versioning/index.ts +8 -0
  278. package/src/modules/versioning/ports/version-loader-port.ts +18 -0
  279. package/src/modules/versioning/types/versioning.ts +17 -0
  280. package/src/modules/workflow/domain/events/index.ts +55 -0
  281. package/src/modules/workflow/domain/models/index.ts +40 -0
  282. package/src/modules/workflow/domain/validators/index.ts +50 -0
  283. package/src/modules/yaml-parser/application/js-yaml-adapter.ts +34 -0
  284. package/src/modules/yaml-parser/domain/operations/parse-yaml.ts +58 -0
  285. package/src/modules/yaml-parser/index.ts +7 -0
  286. package/src/modules/yaml-parser/ports/yaml-parser-port.ts +18 -0
  287. package/src/navigation/index.ts +9 -0
  288. package/src/plugin/index.ts +4 -0
  289. package/src/presentation/index.ts +1 -0
  290. package/src/presentation/live-editor/index.ts +22 -0
  291. package/src/presentation/live-editor/live-editor-component.ts +219 -0
  292. package/src/presentation/live-editor/virtual-module.ts +16 -0
  293. package/src/presentation/solid/CodeBlock.tsx +120 -0
  294. package/src/presentation/solid/Toc.tsx +58 -0
  295. package/src/presentation/solid/index.ts +11 -0
  296. package/src/presentation/vite-plugin/docs-plugin.ts +212 -0
  297. package/src/presentation/vite-plugin/index.ts +9 -0
  298. package/src/presentation/vite-plugin/transform-markdown.ts +26 -0
  299. package/src/runtime/analytics.ts +59 -0
  300. package/src/runtime/api-diff.ts +115 -0
  301. package/src/runtime/app.tsx +32 -0
  302. package/src/runtime/components/AccentPicker.tsx +114 -0
  303. package/src/runtime/components/ApiPlayground.tsx +332 -0
  304. package/src/runtime/components/AskAiDialog.tsx +127 -0
  305. package/src/runtime/components/BackToTop.tsx +38 -0
  306. package/src/runtime/components/Banner.tsx +75 -0
  307. package/src/runtime/components/Breadcrumbs.tsx +42 -0
  308. package/src/runtime/components/CollectionDropdown.tsx +85 -0
  309. package/src/runtime/components/CustomizeDrawer.tsx +195 -0
  310. package/src/runtime/components/DocMarkdown.tsx +579 -0
  311. package/src/runtime/components/DocPrevNext.tsx +54 -0
  312. package/src/runtime/components/DocToc.tsx +147 -0
  313. package/src/runtime/components/DocsDropdown.tsx +184 -0
  314. package/src/runtime/components/Footer.tsx +52 -0
  315. package/src/runtime/components/GitHubAuth.tsx +82 -0
  316. package/src/runtime/components/GitHubStats.tsx +73 -0
  317. package/src/runtime/components/Head.tsx +225 -0
  318. package/src/runtime/components/LocaleDropdown.tsx +75 -0
  319. package/src/runtime/components/MobileBottomNav.tsx +111 -0
  320. package/src/runtime/components/NotFound.tsx +139 -0
  321. package/src/runtime/components/PageActions.tsx +144 -0
  322. package/src/runtime/components/RelatedDocs.tsx +50 -0
  323. package/src/runtime/components/ScrollProgress.tsx +32 -0
  324. package/src/runtime/components/SearchPalette.tsx +333 -0
  325. package/src/runtime/components/ShowcaseCard.tsx +87 -0
  326. package/src/runtime/components/SidebarNav.tsx +237 -0
  327. package/src/runtime/components/Skeleton.tsx +39 -0
  328. package/src/runtime/components/ThemeToggle.tsx +26 -0
  329. package/src/runtime/components/TopNav.tsx +270 -0
  330. package/src/runtime/components/VersionDropdown.tsx +189 -0
  331. package/src/runtime/components/markdown/components.ts +280 -0
  332. package/src/runtime/config.ts +225 -0
  333. package/src/runtime/content.ts +451 -0
  334. package/src/runtime/context.tsx +30 -0
  335. package/src/runtime/data.ts +93 -0
  336. package/src/runtime/github.ts +226 -0
  337. package/src/runtime/icons.ts +32 -0
  338. package/src/runtime/index.ts +153 -0
  339. package/src/runtime/layouts/DocsLayout.tsx +144 -0
  340. package/src/runtime/markdown-content.css +996 -0
  341. package/src/runtime/pages/AbTestPage.tsx +88 -0
  342. package/src/runtime/pages/AnalyticsPage.tsx +90 -0
  343. package/src/runtime/pages/ApiDiffPage.tsx +86 -0
  344. package/src/runtime/pages/ApiEndpointPage.tsx +248 -0
  345. package/src/runtime/pages/BuilderPage.tsx +150 -0
  346. package/src/runtime/pages/ChangelogPage.tsx +210 -0
  347. package/src/runtime/pages/CollectionPage.tsx +140 -0
  348. package/src/runtime/pages/CommunityPage.tsx +384 -0
  349. package/src/runtime/pages/CreatePage.tsx +448 -0
  350. package/src/runtime/pages/DocPage.tsx +193 -0
  351. package/src/runtime/pages/EditPage.tsx +201 -0
  352. package/src/runtime/pages/HomePage.tsx +187 -0
  353. package/src/runtime/pages/IssuesPage.tsx +140 -0
  354. package/src/runtime/pages/OAuthCallbackPage.tsx +80 -0
  355. package/src/runtime/pages/PluginsPage.tsx +249 -0
  356. package/src/runtime/pages/ShowcasePage.tsx +202 -0
  357. package/src/runtime/pwa.ts +39 -0
  358. package/src/runtime/router.tsx +192 -0
  359. package/src/runtime/seo.ts +192 -0
  360. package/src/runtime/theme.css +175 -0
  361. package/src/runtime/theme.ts +224 -0
  362. package/src/runtime/types.ts +217 -0
  363. package/src/search/index.ts +6 -0
  364. package/src/seo-optimization/index.ts +4 -0
  365. package/src/shared/constants/index.ts +26 -0
  366. package/src/shared/errors/index.ts +195 -0
  367. package/src/shared/index.ts +27 -0
  368. package/src/shared/types/brand.ts +14 -0
  369. package/src/shared/types/client.d.ts +45 -0
  370. package/src/shared/types/either.ts +38 -0
  371. package/src/shared/types/index.ts +42 -0
  372. package/src/shared/types/option.ts +52 -0
  373. package/src/shared/types/result.ts +81 -0
  374. package/src/shared/utils/array.ts +97 -0
  375. package/src/shared/utils/index.ts +46 -0
  376. package/src/shared/utils/object.ts +47 -0
  377. package/src/shared/utils/string.ts +74 -0
  378. package/src/toc-generator/index.ts +1 -0
  379. package/src/types/js-yaml.d.ts +42 -0
  380. package/src/worker.ts +462 -0
@@ -0,0 +1,448 @@
1
+ import { createSignal, For, onMount, Show } from "solid-js";
2
+ import {
3
+ clearGitHubToken,
4
+ GitHubAuthButton,
5
+ getGitHubToken,
6
+ } from "../components/GitHubAuth";
7
+
8
+ interface Template {
9
+ id: string;
10
+ name: string;
11
+ description: string;
12
+ icon: string;
13
+ tags: string[];
14
+ }
15
+
16
+ const templates: Template[] = [
17
+ {
18
+ id: "docs",
19
+ name: "Documentation site",
20
+ description: "VitePress-style docs, changelog, and API references.",
21
+ icon: "i-mdi:book-open-page-variant",
22
+ tags: ["Markdown", "API", "Search"],
23
+ },
24
+ {
25
+ id: "api",
26
+ name: "API reference",
27
+ description: "Scalar-like API playground with OpenAPI / oRPC / Elysia.",
28
+ icon: "i-mdi:api",
29
+ tags: ["OpenAPI", "oRPC", "Playground"],
30
+ },
31
+ {
32
+ id: "showcase",
33
+ name: "Showcase",
34
+ description: "A grid of project or product cards with previews.",
35
+ icon: "i-mdi:view-dashboard",
36
+ tags: ["Cards", "Portfolio"],
37
+ },
38
+ ];
39
+
40
+ export function CreatePage() {
41
+ const [step, setStep] = createSignal<
42
+ "template" | "github" | "deploy" | "done"
43
+ >("template");
44
+ const [selected, setSelected] = createSignal<string>("docs");
45
+ const [repo, setRepo] = createSignal("");
46
+ const [repoUrl, setRepoUrl] = createSignal("");
47
+ const [token, setToken] = createSignal(getGitHubToken() ?? "");
48
+ const [showManual, setShowManual] = createSignal(!getGitHubToken());
49
+ const [cfToken, setCfToken] = createSignal("");
50
+ const [cfAccountId, setCfAccountId] = createSignal("");
51
+ const [deployUrl, setDeployUrl] = createSignal("");
52
+ const [loading, setLoading] = createSignal(false);
53
+ const [error, setError] = createSignal("");
54
+
55
+ onMount(() => {
56
+ const t = getGitHubToken();
57
+ if (t) setToken(t);
58
+ });
59
+
60
+ const pick = (id: string) => {
61
+ setSelected(id);
62
+ setStep("github");
63
+ };
64
+
65
+ const onAuth = (t: string) => {
66
+ setToken(t);
67
+ setShowManual(false);
68
+ };
69
+
70
+ const createRepo = async () => {
71
+ if (!repo() || !token()) {
72
+ setError("Please enter a repository name and authorize with GitHub.");
73
+ return;
74
+ }
75
+ setLoading(true);
76
+ setError("");
77
+ try {
78
+ const res = await fetch("/api/github/user/repos", {
79
+ method: "POST",
80
+ headers: {
81
+ Authorization: `Bearer ${token()}`,
82
+ Accept: "application/vnd.github+json",
83
+ "X-GitHub-Api-Version": "2022-11-28",
84
+ "Content-Type": "application/json",
85
+ },
86
+ body: JSON.stringify({
87
+ name: repo(),
88
+ private: false,
89
+ auto_init: true,
90
+ }),
91
+ });
92
+ const data = (await res.json().catch(() => ({}))) as {
93
+ html_url?: string;
94
+ message?: string;
95
+ };
96
+ if (!res.ok) {
97
+ throw new Error(data.message ?? `GitHub error ${res.status}`);
98
+ }
99
+ if (data.html_url) setRepoUrl(data.html_url);
100
+ setStep("deploy");
101
+ } catch (e) {
102
+ setError(e instanceof Error ? e.message : "Failed to create repository.");
103
+ } finally {
104
+ setLoading(false);
105
+ }
106
+ };
107
+
108
+ const deploy = async () => {
109
+ if (!cfToken() || !cfAccountId()) {
110
+ setError("Please enter a Cloudflare API token and account ID.");
111
+ return;
112
+ }
113
+ setLoading(true);
114
+ setError("");
115
+ try {
116
+ const repoInfo = parseRepoUrl(repoUrl());
117
+ const res = await fetch("/api/deploy", {
118
+ method: "POST",
119
+ headers: {
120
+ Authorization: `Bearer ${cfToken()}`,
121
+ "Content-Type": "application/json",
122
+ },
123
+ body: JSON.stringify({
124
+ accountId: cfAccountId(),
125
+ projectName: repo() || "my-docs",
126
+ owner: repoInfo?.owner,
127
+ repo: repoInfo?.repo,
128
+ productionBranch: "main",
129
+ }),
130
+ });
131
+ const data = (await res.json().catch(() => ({}))) as {
132
+ ok?: boolean;
133
+ url?: string;
134
+ error?: string;
135
+ };
136
+ if (!res.ok || data.error) {
137
+ throw new Error(data.error ?? `Deploy failed (${res.status})`);
138
+ }
139
+ if (data.url) setDeployUrl(data.url);
140
+ setStep("done");
141
+ } catch (e) {
142
+ setError(e instanceof Error ? e.message : "Deploy failed.");
143
+ } finally {
144
+ setLoading(false);
145
+ }
146
+ };
147
+
148
+ return (
149
+ <div class="max-w-3xl mx-auto px-6 py-10">
150
+ <h1 class="text-3xl md:text-4xl font-bold text-center mb-2">
151
+ Create your docs site
152
+ </h1>
153
+ <p class="text-muted text-center mb-10 max-w-xl mx-auto">
154
+ Pick a template, connect GitHub, and deploy to Cloudflare in one flow.
155
+ </p>
156
+
157
+ <div class="flex items-center justify-center gap-2 mb-8">
158
+ <For each={["template", "github", "deploy"] as const}>
159
+ {(s, i) => (
160
+ <div class="flex items-center gap-2">
161
+ <div
162
+ class={`w-8 h-8 rounded-full flex items-center justify-center text-xs font-medium ${
163
+ step() === s
164
+ ? "bg-primary text-primary-foreground"
165
+ : stepOrder(step()) > stepOrder(s)
166
+ ? "bg-surface text-foreground border border-border"
167
+ : "bg-background text-muted border border-border"
168
+ }`}
169
+ >
170
+ {i() + 1}
171
+ </div>
172
+ <Show when={i() < 2}>
173
+ <div class="w-8 h-px bg-border" />
174
+ </Show>
175
+ </div>
176
+ )}
177
+ </For>
178
+ </div>
179
+
180
+ <Show when={step() === "template"}>
181
+ <div class="grid sm:grid-cols-3 gap-4 mb-6">
182
+ <For each={templates}>
183
+ {(t) => (
184
+ <button
185
+ type="button"
186
+ onClick={() => pick(t.id)}
187
+ class={`text-left p-5 rounded-xl border transition-all no-underline group ${
188
+ selected() === t.id
189
+ ? "border-primary bg-primary/5"
190
+ : "border-border bg-surface hover:border-focus"
191
+ }`}
192
+ >
193
+ <span
194
+ class={`${t.icon} text-3xl mb-3 block text-primary`}
195
+ aria-hidden="true"
196
+ />
197
+ <h2 class="font-semibold mb-1">{t.name}</h2>
198
+ <p class="text-sm text-muted mb-3 leading-relaxed">
199
+ {t.description}
200
+ </p>
201
+ <div class="flex flex-wrap gap-1">
202
+ <For each={t.tags}>
203
+ {(tag) => (
204
+ <span class="text-[10px] px-1.5 py-0.5 rounded bg-background border border-border text-muted">
205
+ {tag}
206
+ </span>
207
+ )}
208
+ </For>
209
+ </div>
210
+ </button>
211
+ )}
212
+ </For>
213
+ </div>
214
+ <p class="text-xs text-center text-muted">
215
+ The template only sets the initial files — you can customize
216
+ everything after creation.
217
+ </p>
218
+ </Show>
219
+
220
+ <Show when={step() === "github"}>
221
+ <form
222
+ class="border border-border rounded-xl p-6 bg-surface mb-4"
223
+ onSubmit={(e) => {
224
+ e.preventDefault();
225
+ createRepo();
226
+ }}
227
+ >
228
+ <h2 class="font-semibold mb-4 flex items-center gap-2">
229
+ <span class="i-mdi:github" aria-hidden="true" />
230
+ Connect GitHub
231
+ </h2>
232
+ <label for="repo-name" class="block text-sm text-muted mb-1">
233
+ Repository name
234
+ </label>
235
+ <input
236
+ id="repo-name"
237
+ type="text"
238
+ value={repo()}
239
+ onInput={(e) => setRepo(e.currentTarget.value)}
240
+ placeholder="my-docs"
241
+ class="w-full h-10 px-3 rounded-md border border-border bg-background text-foreground mb-4 outline-none focus:border-focus"
242
+ />
243
+ <div class="mb-4">
244
+ <Show
245
+ when={!showManual()}
246
+ fallback={
247
+ <div class="space-y-2">
248
+ <label
249
+ for="github-token"
250
+ class="block text-sm text-muted mb-1"
251
+ >
252
+ GitHub personal access token
253
+ </label>
254
+ <input
255
+ id="github-token"
256
+ type="password"
257
+ value={token()}
258
+ onInput={(e) => setToken(e.currentTarget.value)}
259
+ placeholder="ghp_..."
260
+ class="w-full h-10 px-3 rounded-md border border-border bg-background text-foreground outline-none focus:border-focus"
261
+ />
262
+ </div>
263
+ }
264
+ >
265
+ <div class="flex items-center justify-between">
266
+ <GitHubAuthButton
267
+ onToken={onAuth}
268
+ label={
269
+ token()
270
+ ? "Re-authorize with GitHub"
271
+ : "Authorize with GitHub"
272
+ }
273
+ />
274
+ <Show when={token()}>
275
+ <div class="flex items-center gap-2 text-sm text-muted">
276
+ <span
277
+ class="i-mdi:check-circle text-primary"
278
+ aria-hidden="true"
279
+ />
280
+ <span>Authorized</span>
281
+ <button
282
+ type="button"
283
+ onClick={() => {
284
+ clearGitHubToken();
285
+ setToken("");
286
+ setShowManual(true);
287
+ }}
288
+ class="text-xs text-destructive hover:underline"
289
+ >
290
+ Clear
291
+ </button>
292
+ </div>
293
+ </Show>
294
+ </div>
295
+ </Show>
296
+ <div class="mt-2">
297
+ <button
298
+ type="button"
299
+ onClick={() => setShowManual(!showManual())}
300
+ class="text-xs text-muted hover:text-foreground underline"
301
+ >
302
+ {showManual()
303
+ ? "Use GitHub OAuth instead"
304
+ : "Use personal access token instead"}
305
+ </button>
306
+ </div>
307
+ </div>
308
+ <Show when={error()}>
309
+ <p class="text-sm text-destructive mb-3">{error()}</p>
310
+ </Show>
311
+ <div class="flex gap-2">
312
+ <button
313
+ type="button"
314
+ onClick={() => setStep("template")}
315
+ class="px-4 h-10 rounded-md border border-border text-foreground hover:bg-background transition-colors"
316
+ >
317
+ Back
318
+ </button>
319
+ <button
320
+ type="submit"
321
+ disabled={loading()}
322
+ class="px-4 h-10 rounded-md bg-primary text-primary-foreground hover:bg-primary-hover transition-colors disabled:opacity-60"
323
+ >
324
+ {loading() ? "Creating…" : "Create repository"}
325
+ </button>
326
+ </div>
327
+ </form>
328
+ </Show>
329
+
330
+ <Show when={step() === "deploy"}>
331
+ <form
332
+ class="border border-border rounded-xl p-6 bg-surface mb-4"
333
+ onSubmit={(e) => {
334
+ e.preventDefault();
335
+ deploy();
336
+ }}
337
+ >
338
+ <h2 class="font-semibold mb-4 flex items-center gap-2">
339
+ <span class="i-mdi:cloud" aria-hidden="true" />
340
+ Deploy to Cloudflare
341
+ </h2>
342
+ <p class="text-sm text-muted mb-4">
343
+ Enter your Cloudflare credentials to create a Pages project for the
344
+ new docs site.
345
+ <span class="block mt-1 text-xs">
346
+ The token needs the "Cloudflare Pages: Edit" permission. Find your
347
+ account ID on the Cloudflare dashboard sidebar.
348
+ </span>
349
+ </p>
350
+ <label for="cf-token" class="block text-sm text-muted mb-1">
351
+ Cloudflare API token
352
+ </label>
353
+ <input
354
+ id="cf-token"
355
+ type="password"
356
+ value={cfToken()}
357
+ onInput={(e) => setCfToken(e.currentTarget.value)}
358
+ placeholder="..."
359
+ class="w-full h-10 px-3 rounded-md border border-border bg-background text-foreground mb-4 outline-none focus:border-focus"
360
+ />
361
+ <label for="cf-account" class="block text-sm text-muted mb-1">
362
+ Cloudflare account ID
363
+ </label>
364
+ <input
365
+ id="cf-account"
366
+ type="text"
367
+ value={cfAccountId()}
368
+ onInput={(e) => setCfAccountId(e.currentTarget.value)}
369
+ placeholder="a1b2c3d4..."
370
+ class="w-full h-10 px-3 rounded-md border border-border bg-background text-foreground mb-4 outline-none focus:border-focus"
371
+ />
372
+ <Show when={error()}>
373
+ <p class="text-sm text-destructive mb-3">{error()}</p>
374
+ </Show>
375
+ <div class="flex gap-2">
376
+ <button
377
+ type="button"
378
+ onClick={() => setStep("github")}
379
+ class="px-4 h-10 rounded-md border border-border text-foreground hover:bg-background transition-colors"
380
+ >
381
+ Back
382
+ </button>
383
+ <button
384
+ type="submit"
385
+ disabled={loading()}
386
+ class="px-4 h-10 rounded-md bg-primary text-primary-foreground hover:bg-primary-hover transition-colors disabled:opacity-60"
387
+ >
388
+ {loading() ? "Deploying…" : "Deploy to Cloudflare"}
389
+ </button>
390
+ </div>
391
+ </form>
392
+ </Show>
393
+
394
+ <Show when={step() === "done"}>
395
+ <div class="text-center border border-border rounded-xl p-8 bg-surface">
396
+ <div class="w-16 h-16 bg-primary/10 rounded-full flex items-center justify-center mx-auto mb-4">
397
+ <span
398
+ class="i-mdi:check text-3xl text-primary"
399
+ aria-hidden="true"
400
+ />
401
+ </div>
402
+ <h2 class="text-xl font-semibold mb-2">You're ready to ship!</h2>
403
+ <p class="text-sm text-muted mb-6">
404
+ Repository <code class="font-mono">{repo()}</code> created
405
+ <Show when={deployUrl()}>
406
+ {" "}
407
+ and a Cloudflare Pages project is connected — the first deployment
408
+ runs on the next push to <code class="font-mono">main</code>.
409
+ </Show>
410
+ .
411
+ </p>
412
+ <div class="flex items-center justify-center gap-3 flex-wrap">
413
+ <a
414
+ href={repoUrl() || `https://github.com/${repo()}`}
415
+ target="_blank"
416
+ rel="noreferrer"
417
+ class="inline-flex items-center gap-2 px-5 h-11 rounded-md bg-primary text-primary-foreground no-underline font-medium hover:bg-primary-hover transition-colors"
418
+ >
419
+ <span class="i-mdi:github" aria-hidden="true" />
420
+ Open repository
421
+ </a>
422
+ <Show when={deployUrl()}>
423
+ <a
424
+ href={deployUrl()}
425
+ target="_blank"
426
+ rel="noreferrer"
427
+ class="inline-flex items-center gap-2 px-5 h-11 rounded-md border border-border text-foreground no-underline font-medium hover:bg-background transition-colors"
428
+ >
429
+ <span class="i-mdi:cloud" aria-hidden="true" />
430
+ Open site
431
+ </a>
432
+ </Show>
433
+ </div>
434
+ </div>
435
+ </Show>
436
+ </div>
437
+ );
438
+ }
439
+
440
+ function stepOrder(s: "template" | "github" | "deploy" | "done") {
441
+ return { template: 0, github: 1, deploy: 2, done: 3 }[s];
442
+ }
443
+
444
+ function parseRepoUrl(url: string) {
445
+ const match = url.match(/github\.com[:/]([^/]+)\/([^/]+)/);
446
+ if (!match) return null;
447
+ return { owner: match[1], repo: match[2].replace(/\.git$/, "") };
448
+ }
@@ -0,0 +1,193 @@
1
+ import { useParams } from "@tanstack/solid-router";
2
+ import { dump as dumpYaml } from "js-yaml";
3
+ import { createResource, createSignal, Show } from "solid-js";
4
+ import { AskAiDialog } from "../components/AskAiDialog";
5
+ import { Breadcrumbs } from "../components/Breadcrumbs";
6
+ import { DocMarkdown } from "../components/DocMarkdown";
7
+ import { DocPrevNext } from "../components/DocPrevNext";
8
+ import { DocToc } from "../components/DocToc";
9
+ import { PageActions } from "../components/PageActions";
10
+ import { RelatedDocs } from "../components/RelatedDocs";
11
+ import { SkeletonPage } from "../components/Skeleton";
12
+ import { useDocs } from "../context";
13
+ import { createDocsList } from "../data";
14
+
15
+ function formatLastUpdated(iso?: string) {
16
+ if (!iso) return "";
17
+ try {
18
+ return new Date(iso).toLocaleDateString(undefined, {
19
+ year: "numeric",
20
+ month: "short",
21
+ day: "numeric",
22
+ });
23
+ } catch {
24
+ return "";
25
+ }
26
+ }
27
+
28
+ function formatFrontmatter(value: unknown) {
29
+ try {
30
+ return dumpYaml(value, { indent: 2 } as import("js-yaml").DumpOptions);
31
+ } catch {
32
+ return JSON.stringify(value, null, 2);
33
+ }
34
+ }
35
+
36
+ export function DocPage() {
37
+ const params = useParams({ strict: false });
38
+ const collection = () => params().collection ?? "";
39
+ const docId = () => params().docId ?? "";
40
+ const [askOpen, setAskOpen] = createSignal(false);
41
+ const [fmOpen, setFmOpen] = createSignal(false);
42
+ const config = useDocs();
43
+ const dataSource = useDocs().dataSource;
44
+ const showBreadcrumbs = () => config.features?.breadcrumbs !== false;
45
+ const showLastUpdated = () => config.features?.lastUpdated !== false;
46
+
47
+ const [docs] = createDocsList(collection);
48
+ const meta = () => (docs() ?? []).find((d) => d.id === docId());
49
+
50
+ const [doc] = createResource(
51
+ () => ({ collection: collection(), id: docId() }),
52
+ async ({ collection, id }) => {
53
+ if (!collection || !id)
54
+ return {
55
+ id: "",
56
+ label: "",
57
+ content: "",
58
+ frontmatter: {},
59
+ };
60
+ return dataSource.get(collection, id);
61
+ },
62
+ );
63
+
64
+ const frontmatter = () => doc()?.frontmatter;
65
+ const showFrontmatterToggle = () =>
66
+ config.features?.frontmatterToggle !== false &&
67
+ frontmatter() &&
68
+ Object.keys(frontmatter()!).length > 0;
69
+
70
+ const pageLayout = () => frontmatter()?.layout ?? "doc";
71
+ const showToc = () =>
72
+ pageLayout() === "doc" &&
73
+ frontmatter()?.toc !== false &&
74
+ config.features?.toc !== false;
75
+ const showAside = () =>
76
+ pageLayout() === "doc" &&
77
+ frontmatter()?.aside !== false &&
78
+ config.features?.aside !== false;
79
+ const showEditLink = () =>
80
+ frontmatter()?.editLink !== false && config.features?.editLink !== false;
81
+
82
+ return (
83
+ <div class="flex gap-8 max-w-6xl mx-auto px-6 py-8">
84
+ <article class="flex-1 min-w-0">
85
+ <Show when={meta()}>
86
+ {(m) => (
87
+ <>
88
+ <Show when={showBreadcrumbs() && pageLayout() === "doc"}>
89
+ <Breadcrumbs
90
+ collection={collection()}
91
+ category={m().category}
92
+ label={m().label}
93
+ />
94
+ </Show>
95
+ <div class="flex items-center gap-2 pb-4 mb-2 border-b border-border flex-wrap">
96
+ <Show when={showEditLink()}>
97
+ <PageActions
98
+ collection={collection()}
99
+ doc={m()}
100
+ source={doc()?.content ?? ""}
101
+ />
102
+ </Show>
103
+ <button
104
+ type="button"
105
+ onClick={() => setAskOpen(true)}
106
+ class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-md border border-border text-xs text-muted hover:text-foreground hover:bg-surface transition-colors cursor-pointer bg-transparent"
107
+ >
108
+ <span class="i-mdi:robot-happy-outline" aria-hidden="true" />
109
+ Ask AI
110
+ </button>
111
+ <Show when={showFrontmatterToggle()}>
112
+ <button
113
+ type="button"
114
+ onClick={() => setFmOpen(!fmOpen())}
115
+ class={`inline-flex items-center gap-1.5 px-2.5 h-8 rounded-md border text-xs transition-colors cursor-pointer bg-transparent ${
116
+ fmOpen()
117
+ ? "border-primary text-primary bg-primary/10"
118
+ : "border-border text-muted hover:text-foreground hover:bg-surface"
119
+ }`}
120
+ >
121
+ <span
122
+ class={fmOpen() ? "i-mdi:eye-off" : "i-mdi:eye"}
123
+ aria-hidden="true"
124
+ />
125
+ {fmOpen() ? "Hide frontmatter" : "Show frontmatter"}
126
+ </button>
127
+ </Show>
128
+ <span class="ml-auto inline-flex items-center gap-1.5 text-xs text-muted min-w-0">
129
+ <span class="i-mdi:folder-open-outline" aria-hidden="true" />
130
+ <code class="font-mono truncate">{m().path}</code>
131
+ </span>
132
+ </div>
133
+ <Show when={showLastUpdated() && m().lastUpdated}>
134
+ <div class="text-xs text-muted pb-4">
135
+ Last updated: {formatLastUpdated(m().lastUpdated)}
136
+ </div>
137
+ </Show>
138
+ </>
139
+ )}
140
+ </Show>
141
+ <Show when={fmOpen() && frontmatter()}>
142
+ {(f) => (
143
+ <div class="mb-4 border border-border rounded-lg overflow-hidden bg-surface/50">
144
+ <div class="flex items-center gap-2 px-3 py-2 text-xs font-medium text-muted border-b border-border bg-surface">
145
+ <span class="i-mdi:code-json" aria-hidden="true" />
146
+ Frontmatter
147
+ </div>
148
+ <pre class="text-xs text-foreground p-3 m-0 overflow-x-auto whitespace-pre-wrap break-all font-mono">
149
+ {formatFrontmatter(f())}
150
+ </pre>
151
+ </div>
152
+ )}
153
+ </Show>
154
+ <Show
155
+ when={doc()}
156
+ fallback={
157
+ <Show when={doc.error} fallback={<SkeletonPage />}>
158
+ <p class="text-muted text-sm">Failed to load document.</p>
159
+ </Show>
160
+ }
161
+ >
162
+ {(d) => <DocMarkdown source={d().content ?? ""} />}
163
+ </Show>
164
+ <Show when={pageLayout() === "doc"}>
165
+ <DocPrevNext
166
+ collection={collection()}
167
+ docs={docs() ?? []}
168
+ currentId={docId()}
169
+ />
170
+ <Show when={meta()}>
171
+ {(m) => <RelatedDocs currentId={m().id} currentTags={m().tags} />}
172
+ </Show>
173
+ </Show>
174
+ </article>
175
+ <Show when={showAside()}>
176
+ <aside class="hidden xl:block w-56 shrink-0">
177
+ <div class="sticky top-20 max-h-[calc(100vh-6rem)] overflow-y-auto pr-2">
178
+ <Show when={showToc() && doc()}>
179
+ {(d) => <DocToc source={d().content ?? ""} />}
180
+ </Show>
181
+ </div>
182
+ </aside>
183
+ </Show>
184
+ <AskAiDialog
185
+ open={askOpen()}
186
+ onClose={() => setAskOpen(false)}
187
+ collection={collection()}
188
+ docId={docId()}
189
+ docTitle={meta()?.label ?? docId()}
190
+ />
191
+ </div>
192
+ );
193
+ }