@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,88 @@
1
+ import { useNavigate, useParams, useSearch } from "@tanstack/solid-router";
2
+ import { createResource, createSignal, Show } from "solid-js";
3
+ import { DocMarkdown } from "../components/DocMarkdown";
4
+ import { useDocs } from "../context";
5
+
6
+ export function AbTestPage() {
7
+ const params = useParams({ strict: false });
8
+ const search = useSearch({ strict: false });
9
+ const navigate = useNavigate();
10
+ const config = useDocs();
11
+ const dataSource = config.dataSource;
12
+ const collection = () => params().collection ?? "docs";
13
+ const baseId = () => params().docId ?? "index";
14
+
15
+ const variant = () =>
16
+ (search().v as string) ?? (Math.random() > 0.5 ? "a" : "b");
17
+ const [v, setV] = createSignal(variant());
18
+
19
+ const docId = () => `${baseId()}-${v()}`;
20
+
21
+ const [doc] = createResource(
22
+ () => ({ collection: collection(), id: docId() }),
23
+ async ({ collection, id }) => {
24
+ try {
25
+ return await dataSource.get(collection, id);
26
+ } catch {
27
+ return {
28
+ content: `> Variant ${v().toUpperCase()} not found for **${baseId()}**.\n\nCreate \`${baseId()}-a.md\` and \`${baseId()}-b.md\`.`,
29
+ };
30
+ }
31
+ },
32
+ );
33
+
34
+ const [converted, setConverted] = createSignal(false);
35
+
36
+ const record = (action: string) => {
37
+ const key = `ab:${baseId()}:${v()}:${action}`;
38
+ const count = Number(localStorage.getItem(key) ?? 0) + 1;
39
+ localStorage.setItem(key, String(count));
40
+ };
41
+
42
+ const switchVariant = () => {
43
+ const next = v() === "a" ? "b" : "a";
44
+ setV(next);
45
+ navigate({
46
+ to: "/ab/$collection/$docId",
47
+ params: { collection: collection(), docId: baseId() },
48
+ search: { v: next },
49
+ });
50
+ };
51
+
52
+ const convert = () => {
53
+ setConverted(true);
54
+ record("convert");
55
+ };
56
+
57
+ return (
58
+ <div class="max-w-4xl mx-auto px-6 py-8">
59
+ <div class="flex items-center gap-3 mb-6">
60
+ <span class="px-2 py-1 text-xs font-medium rounded-full border border-border text-muted">
61
+ Variant {v().toUpperCase()}
62
+ </span>
63
+ <button
64
+ type="button"
65
+ onClick={switchVariant}
66
+ class="inline-flex items-center gap-1.5 px-3 h-8 rounded-md border border-border text-xs text-muted hover:text-foreground hover:bg-surface transition-colors bg-transparent"
67
+ >
68
+ <span class="i-mdi:swap-horizontal" aria-hidden="true" />
69
+ Switch variant
70
+ </button>
71
+ <button
72
+ type="button"
73
+ onClick={convert}
74
+ class="inline-flex items-center gap-1.5 px-3 h-8 rounded-md bg-primary text-primary-foreground text-xs font-medium hover:bg-primary-hover transition-colors"
75
+ >
76
+ <span class="i-mdi:check" aria-hidden="true" />
77
+ Convert
78
+ </button>
79
+ <Show when={converted()}>
80
+ <span class="text-xs text-success">Recorded conversion</span>
81
+ </Show>
82
+ </div>
83
+ <Show when={doc()} fallback={<p class="text-muted">Loading variant…</p>}>
84
+ {(d) => <DocMarkdown source={d().content ?? ""} />}
85
+ </Show>
86
+ </div>
87
+ );
88
+ }
@@ -0,0 +1,90 @@
1
+ import { createMemo, createSignal, For, Show } from "solid-js";
2
+ import { getPageViews, resetPageViews } from "../analytics";
3
+
4
+ function formatDate(iso: string) {
5
+ try {
6
+ return new Date(iso).toLocaleString(undefined, {
7
+ dateStyle: "medium",
8
+ timeStyle: "short",
9
+ });
10
+ } catch {
11
+ return iso;
12
+ }
13
+ }
14
+
15
+ export function AnalyticsPage() {
16
+ const [records, setRecords] = createSignal(getPageViews());
17
+
18
+ const totalViews = createMemo(() =>
19
+ records().reduce((sum, r) => sum + r.views, 0),
20
+ );
21
+ const sorted = createMemo(() =>
22
+ [...records()].sort((a, b) => b.views - a.views),
23
+ );
24
+ const maxViews = createMemo(() => sorted()[0]?.views ?? 1);
25
+
26
+ return (
27
+ <div class="max-w-3xl mx-auto px-6 py-8">
28
+ <h1 class="text-3xl font-bold mb-2">Analytics</h1>
29
+ <p class="text-muted mb-8">Page views tracked locally in this browser</p>
30
+
31
+ <div class="grid grid-cols-2 gap-4 mb-8">
32
+ <div class="border border-border rounded-lg p-4">
33
+ <div class="text-2xl font-bold">{totalViews()}</div>
34
+ <div class="text-xs text-muted">Total page views</div>
35
+ </div>
36
+ <div class="border border-border rounded-lg p-4">
37
+ <div class="text-2xl font-bold">{records().length}</div>
38
+ <div class="text-xs text-muted">Pages visited</div>
39
+ </div>
40
+ </div>
41
+
42
+ <Show when={records().length === 0}>
43
+ <p class="text-muted">
44
+ No page views yet — browse the docs to see stats here.
45
+ </p>
46
+ </Show>
47
+
48
+ <Show when={records().length > 0}>
49
+ <div class="space-y-3 mb-8">
50
+ <For each={sorted()}>
51
+ {(r) => (
52
+ <div>
53
+ <div class="flex items-baseline justify-between gap-3 mb-1">
54
+ <code class="text-sm truncate">{r.path}</code>
55
+ <span class="text-xs text-muted shrink-0">
56
+ {r.views} views · {formatDate(r.lastVisit)}
57
+ </span>
58
+ </div>
59
+ <div
60
+ class="h-2 rounded-full bg-muted/20 overflow-hidden"
61
+ role="progressbar"
62
+ aria-valuenow={r.views}
63
+ aria-valuemin={0}
64
+ aria-valuemax={maxViews()}
65
+ >
66
+ <div
67
+ class="h-full bg-primary transition-all"
68
+ style={{
69
+ width: `${Math.max((r.views / maxViews()) * 100, 2)}%`,
70
+ }}
71
+ />
72
+ </div>
73
+ </div>
74
+ )}
75
+ </For>
76
+ </div>
77
+ <button
78
+ type="button"
79
+ onClick={() => {
80
+ resetPageViews();
81
+ setRecords([]);
82
+ }}
83
+ class="px-3 h-9 rounded-md border border-border text-sm text-muted hover:text-foreground hover:bg-surface transition-colors cursor-pointer"
84
+ >
85
+ Reset stats
86
+ </button>
87
+ </Show>
88
+ </div>
89
+ );
90
+ }
@@ -0,0 +1,86 @@
1
+ import { createMemo, For, Show } from "solid-js";
2
+ import { diffApiCollections, type EndpointChange } from "../api-diff";
3
+ import { useDocs } from "../context";
4
+
5
+ const badgeClass: Record<EndpointChange["type"], string> = {
6
+ added: "bg-emerald-500/15 text-emerald-500",
7
+ removed: "bg-red-500/15 text-red-500",
8
+ changed: "bg-amber-500/15 text-amber-500",
9
+ };
10
+
11
+ const methodClass: Record<string, string> = {
12
+ GET: "text-emerald-500",
13
+ POST: "text-blue-500",
14
+ PUT: "text-amber-500",
15
+ DELETE: "text-red-500",
16
+ PATCH: "text-violet-500",
17
+ };
18
+
19
+ export function ApiDiffPage() {
20
+ const config = useDocs();
21
+
22
+ const changes = createMemo(() =>
23
+ diffApiCollections(
24
+ config.apiDiff?.previous ?? [],
25
+ config.apiCollections ?? [],
26
+ ),
27
+ );
28
+
29
+ const counts = createMemo(() => ({
30
+ added: changes().filter((c) => c.type === "added").length,
31
+ removed: changes().filter((c) => c.type === "removed").length,
32
+ changed: changes().filter((c) => c.type === "changed").length,
33
+ }));
34
+
35
+ return (
36
+ <div class="max-w-3xl mx-auto px-6 py-8">
37
+ <h1 class="text-3xl font-bold mb-2">API Changelog</h1>
38
+ <p class="text-muted mb-8">
39
+ Endpoint changes between the previous and current API snapshot
40
+ </p>
41
+
42
+ <div class="flex gap-4 mb-8 text-sm">
43
+ <span class="text-emerald-500">+{counts().added} added</span>
44
+ <span class="text-amber-500">~{counts().changed} changed</span>
45
+ <span class="text-red-500">−{counts().removed} removed</span>
46
+ </div>
47
+
48
+ <Show when={changes().length === 0}>
49
+ <p class="text-muted">No API changes detected.</p>
50
+ </Show>
51
+
52
+ <div class="space-y-3">
53
+ <For each={changes()}>
54
+ {(change) => (
55
+ <article class="border border-border rounded-lg p-4">
56
+ <div class="flex items-center gap-2 flex-wrap">
57
+ <span
58
+ class={`text-xs font-semibold px-2 py-0.5 rounded-full uppercase ${badgeClass[change.type]}`}
59
+ >
60
+ {change.type}
61
+ </span>
62
+ <code
63
+ class={`text-xs font-bold ${methodClass[change.endpoint.method] ?? ""}`}
64
+ >
65
+ {change.endpoint.method}
66
+ </code>
67
+ <code class="text-sm">{change.endpoint.path}</code>
68
+ <span class="text-xs text-muted ml-auto">
69
+ {change.collection}
70
+ </span>
71
+ </div>
72
+ <Show when={change.endpoint.summary}>
73
+ <p class="text-sm text-muted mt-1">{change.endpoint.summary}</p>
74
+ </Show>
75
+ <Show when={change.changes.length > 0}>
76
+ <ul class="mt-2 text-sm list-disc pl-5 space-y-0.5 text-muted">
77
+ <For each={change.changes}>{(c) => <li>{c}</li>}</For>
78
+ </ul>
79
+ </Show>
80
+ </article>
81
+ )}
82
+ </For>
83
+ </div>
84
+ </div>
85
+ );
86
+ }
@@ -0,0 +1,248 @@
1
+ import { useParams } from "@tanstack/solid-router";
2
+ import { createMemo, Show } from "solid-js";
3
+ import { ApiPlayground } from "../components/ApiPlayground";
4
+ import { DocMarkdown } from "../components/DocMarkdown";
5
+ import { DocPrevNext } from "../components/DocPrevNext";
6
+ import { findApiCollection, useDocs } from "../context";
7
+ import type { ApiEndpoint, DocEntry } from "../types";
8
+
9
+ const METHOD_BADGE: Record<string, string> = {
10
+ GET: "bg-accent/15 text-accent border-accent/30",
11
+ POST: "bg-success/15 text-success border-success/30",
12
+ PUT: "bg-warning/15 text-warning border-warning/30",
13
+ PATCH: "bg-warning/15 text-warning border-warning/30",
14
+ DELETE: "bg-destructive/15 text-destructive border-destructive/30",
15
+ };
16
+
17
+ const STYLE_ICON: Record<string, string> = {
18
+ rest: "i-mdi:earth",
19
+ graphql: "i-mdi:graphql",
20
+ cli: "i-mdi:console",
21
+ rpc: "i-mdi:api",
22
+ };
23
+
24
+ function endpointMarkdown(ep: ApiEndpoint, style: string): string {
25
+ const lines: string[] = [];
26
+
27
+ if (style === "cli") {
28
+ if (ep.description) lines.push(ep.description, "");
29
+ const cmd = ep.cli
30
+ ? [
31
+ ep.cli.command,
32
+ ep.cli.subcommand,
33
+ ...(ep.cli.args?.map((a) =>
34
+ a.required ? `<${a.name}>` : `[${a.name}]`,
35
+ ) ?? []),
36
+ ].join(" ")
37
+ : `${ep.method} ${ep.path}`;
38
+ lines.push("## Usage", "", "```bash", cmd, "```", "");
39
+ if (ep.cli?.args?.length) {
40
+ lines.push(
41
+ "## Arguments",
42
+ "",
43
+ "| Name | Required | Description |",
44
+ "| --- | --- | --- |",
45
+ );
46
+ for (const a of ep.cli.args) {
47
+ lines.push(
48
+ `| \`${a.name}\` | ${a.required ? "yes" : "no"} | ${a.description ?? ""} |`,
49
+ );
50
+ }
51
+ lines.push("");
52
+ }
53
+ if (ep.requestBody?.example != null) {
54
+ lines.push("## Options", "");
55
+ lines.push(
56
+ "```json",
57
+ JSON.stringify(ep.requestBody.example, null, 2),
58
+ "```",
59
+ "",
60
+ );
61
+ }
62
+ } else if (style === "graphql") {
63
+ if (ep.description) lines.push(ep.description, "");
64
+ if (ep.graphql?.query) {
65
+ lines.push("## Query", "", "```graphql", ep.graphql.query, "```", "");
66
+ }
67
+ if (ep.graphql?.variables != null) {
68
+ lines.push("## Variables", "");
69
+ lines.push(
70
+ "```json",
71
+ JSON.stringify(ep.graphql.variables, null, 2),
72
+ "```",
73
+ "",
74
+ );
75
+ }
76
+ } else {
77
+ if (ep.description) lines.push(ep.description, "");
78
+ if (ep.parameters.length > 0) {
79
+ lines.push(
80
+ "## Parameters",
81
+ "",
82
+ "| Name | In | Required | Description |",
83
+ "| --- | --- | --- | --- |",
84
+ );
85
+ for (const p of ep.parameters) {
86
+ lines.push(
87
+ `| \`${p.name}\` | ${p.in} | ${p.required ? "yes" : "no"} | ${p.description ?? ""} |`,
88
+ );
89
+ }
90
+ lines.push("");
91
+ }
92
+ if (ep.requestBody) {
93
+ lines.push("## Request Body", "");
94
+ if (ep.requestBody.description)
95
+ lines.push(ep.requestBody.description, "");
96
+ if (ep.requestBody.example != null) {
97
+ lines.push(
98
+ "```json",
99
+ JSON.stringify(ep.requestBody.example, null, 2),
100
+ "```",
101
+ "",
102
+ );
103
+ }
104
+ }
105
+ }
106
+
107
+ const codes = Object.keys(ep.responses);
108
+ if (codes.length > 0) {
109
+ lines.push(style === "cli" ? "## Exit codes" : "## Responses", "");
110
+ for (const code of codes) {
111
+ const r = ep.responses[code]!;
112
+ lines.push(`### ${code} — ${r.description}`);
113
+ if (r.example != null) {
114
+ lines.push(
115
+ "",
116
+ "```json",
117
+ JSON.stringify(r.example, null, 2),
118
+ "```",
119
+ "",
120
+ );
121
+ }
122
+ }
123
+ }
124
+ return lines.join("\n");
125
+ }
126
+
127
+ function endpointHeader(ep: ApiEndpoint, style: string) {
128
+ if (style === "cli") {
129
+ const cmd = ep.cli
130
+ ? [ep.cli.command, ep.cli.subcommand].filter(Boolean).join(" ")
131
+ : `${ep.method} ${ep.path}`;
132
+ return { label: cmd, icon: "i-mdi:console-line" };
133
+ }
134
+ if (style === "graphql") {
135
+ return {
136
+ label: ep.graphql?.operation ?? ep.summary ?? "GraphQL",
137
+ icon: "i-mdi:graphql",
138
+ };
139
+ }
140
+ return { label: `${ep.method} ${ep.path}`, icon: "" };
141
+ }
142
+
143
+ export function ApiEndpointPage() {
144
+ const params = useParams({ strict: false });
145
+ const collection = () => params().collection ?? "";
146
+ const docId = () => params().docId ?? "";
147
+ const config = useDocs();
148
+
149
+ const api = createMemo(() => findApiCollection(config, collection()));
150
+ const style = () => api()?.style ?? "rest";
151
+ const endpoint = () => api()?.endpoints.find((e) => e.id === docId());
152
+ const entries = createMemo<DocEntry[]>(() =>
153
+ (api()?.endpoints ?? []).map((e) => ({
154
+ id: e.id,
155
+ label:
156
+ e.summary ??
157
+ e.graphql?.operation ??
158
+ e.cli?.subcommand ??
159
+ e.cli?.command ??
160
+ `${e.method} ${e.path}`,
161
+ category: e.tag ?? style() ?? "Endpoints",
162
+ description: e.description ?? "",
163
+ path: e.path,
164
+ type: "api" as const,
165
+ })),
166
+ );
167
+
168
+ const header = () => {
169
+ const ep = endpoint();
170
+ if (!ep) return { label: "", icon: "" };
171
+ return endpointHeader(ep, style());
172
+ };
173
+
174
+ return (
175
+ <div class="flex gap-8 max-w-7xl mx-auto px-6 py-8">
176
+ <article class="flex-1 min-w-0">
177
+ <Show
178
+ when={endpoint()}
179
+ fallback={<p class="text-muted text-sm">Endpoint not found.</p>}
180
+ >
181
+ {(ep) => (
182
+ <>
183
+ <div class="flex flex-wrap items-center gap-2 pb-4 mb-4 border-b border-border">
184
+ <Show when={style() === "rest" || style() === "rpc"}>
185
+ <span
186
+ class={`inline-flex items-center px-2.5 py-1 rounded-md border text-xs font-bold ${METHOD_BADGE[ep().method] ?? ""}`}
187
+ >
188
+ {ep().method}
189
+ </span>
190
+ <code class="text-sm font-mono text-foreground">
191
+ {ep().path}
192
+ </code>
193
+ </Show>
194
+
195
+ <Show when={style() === "graphql" || style() === "cli"}>
196
+ <span class="inline-flex items-center gap-1.5 text-sm font-mono text-foreground">
197
+ <span
198
+ class={`${header().icon} text-primary`}
199
+ aria-hidden="true"
200
+ />
201
+ {header().label}
202
+ </span>
203
+ </Show>
204
+
205
+ <span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-border bg-surface text-[10px] uppercase tracking-wide font-semibold text-muted">
206
+ <span
207
+ class={`${STYLE_ICON[style()] ?? "i-mdi:api"} text-xs`}
208
+ aria-hidden="true"
209
+ />
210
+ {style()}
211
+ </span>
212
+
213
+ <Show when={ep().tag}>
214
+ <span class="ml-auto text-[11px] uppercase tracking-wide text-muted">
215
+ {ep().tag}
216
+ </span>
217
+ </Show>
218
+ </div>
219
+
220
+ <Show when={ep().summary}>
221
+ <h1 class="text-2xl font-bold text-foreground mt-0 mb-4">
222
+ {ep().summary}
223
+ </h1>
224
+ </Show>
225
+
226
+ <DocMarkdown source={endpointMarkdown(ep(), style())} />
227
+ </>
228
+ )}
229
+ </Show>
230
+ <DocPrevNext
231
+ collection={collection()}
232
+ docs={entries()}
233
+ currentId={docId()}
234
+ />
235
+ </article>
236
+ <aside class="hidden lg:block w-96 shrink-0">
237
+ <div class="sticky top-20 max-h-[calc(100vh-6rem)] overflow-y-auto">
238
+ <p class="text-[11px] font-semibold uppercase tracking-wide text-muted m-0 mb-2">
239
+ Try it
240
+ </p>
241
+ <Show when={endpoint()}>
242
+ {(ep) => <ApiPlayground endpoint={ep()} style={style()} />}
243
+ </Show>
244
+ </div>
245
+ </aside>
246
+ </div>
247
+ );
248
+ }
@@ -0,0 +1,150 @@
1
+ import { createSignal, For } from "solid-js";
2
+ import { DocMarkdown } from "../components/DocMarkdown";
3
+
4
+ type Block = { id: string; label: string; markdown: (title: string) => string };
5
+
6
+ const blocks: Block[] = [
7
+ {
8
+ id: "hero",
9
+ label: "Hero",
10
+ markdown: (t) => `---\nlayout: page\n---\n\n# ${t}\n\nA generated page.`,
11
+ },
12
+ {
13
+ id: "features",
14
+ label: "Feature grid",
15
+ markdown: () =>
16
+ `<card-grid>\n<card title="Fast" icon="i-mdi:lightning-bolt">Fast docs</card>\n<card title="Pluggable" icon="i-mdi:puzzle">Pluggable data sources</card>\n</card-grid>`,
17
+ },
18
+ {
19
+ id: "code",
20
+ label: "Code block",
21
+ markdown: () => "```ts\nconst app = mountDocsApp();\n```",
22
+ },
23
+ {
24
+ id: "faq",
25
+ label: "FAQ",
26
+ markdown: () => `<accordion>\n<item title="Q1?">A1</item>\n</accordion>`,
27
+ },
28
+ ];
29
+
30
+ export function BuilderPage() {
31
+ const [title, setTitle] = createSignal("My Page");
32
+ const [active, setActive] = createSignal<string[]>(["hero", "features"]);
33
+ const [copyText, setCopyText] = createSignal("");
34
+
35
+ const markdown = () => {
36
+ const parts = [`---\nlayout: page\n---\n\n# ${title()}\n`];
37
+ for (const id of active()) {
38
+ const block = blocks.find((b) => b.id === id);
39
+ if (block) parts.push(block.markdown(title()));
40
+ }
41
+ return parts.join("\n\n");
42
+ };
43
+
44
+ const move = (i: number, dir: number) => {
45
+ const arr = [...active()];
46
+ const j = i + dir;
47
+ if (j < 0 || j >= arr.length) return;
48
+ [arr[i], arr[j]] = [arr[j], arr[i]];
49
+ setActive(arr);
50
+ };
51
+
52
+ const remove = (i: number) =>
53
+ setActive(active().filter((_, idx) => idx !== i));
54
+ const add = (id: string) => setActive([...active(), id]);
55
+
56
+ const copy = async () => {
57
+ await navigator.clipboard.writeText(markdown());
58
+ setCopyText("Copied!");
59
+ setTimeout(() => setCopyText(""), 1500);
60
+ };
61
+
62
+ return (
63
+ <div class="max-w-6xl mx-auto px-6 py-8">
64
+ <h1 class="text-2xl font-semibold text-foreground mb-6">
65
+ Visual Page Builder
66
+ </h1>
67
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
68
+ <div class="space-y-4">
69
+ <div class="p-4 rounded-md border border-border bg-surface">
70
+ <div class="text-sm text-muted mb-1">Page title</div>
71
+ <input
72
+ type="text"
73
+ value={title()}
74
+ onInput={(e) => setTitle(e.currentTarget.value)}
75
+ class="w-full px-3 py-2 rounded-md border border-border bg-background text-sm text-foreground outline-none focus:border-focus"
76
+ />
77
+ </div>
78
+ <div class="p-4 rounded-md border border-border bg-surface">
79
+ <div class="text-sm font-medium text-foreground mb-2">
80
+ Add blocks
81
+ </div>
82
+ <div class="flex flex-wrap gap-2">
83
+ <For each={blocks}>
84
+ {(b) => (
85
+ <button
86
+ type="button"
87
+ onClick={() => add(b.id)}
88
+ class="px-2.5 h-8 rounded-md border border-border text-xs text-muted hover:text-foreground hover:bg-background transition-colors"
89
+ >
90
+ {b.label}
91
+ </button>
92
+ )}
93
+ </For>
94
+ </div>
95
+ </div>
96
+ <div class="p-4 rounded-md border border-border bg-surface">
97
+ <div class="text-sm font-medium text-foreground mb-2">Blocks</div>
98
+ <For each={active()}>
99
+ {(id, i) => {
100
+ const label = () =>
101
+ blocks.find((b) => b.id === id)?.label ?? id;
102
+ return (
103
+ <div class="flex items-center gap-2 py-1.5">
104
+ <span class="text-sm text-foreground flex-1">
105
+ {label()}
106
+ </span>
107
+ <button
108
+ type="button"
109
+ onClick={() => move(i(), -1)}
110
+ class="w-7 h-7 inline-flex items-center justify-center rounded-md border border-border text-muted hover:text-foreground hover:bg-background"
111
+ >
112
+ <span class="i-mdi:arrow-up" aria-hidden="true" />
113
+ </button>
114
+ <button
115
+ type="button"
116
+ onClick={() => move(i(), 1)}
117
+ class="w-7 h-7 inline-flex items-center justify-center rounded-md border border-border text-muted hover:text-foreground hover:bg-background"
118
+ >
119
+ <span class="i-mdi:arrow-down" aria-hidden="true" />
120
+ </button>
121
+ <button
122
+ type="button"
123
+ onClick={() => remove(i())}
124
+ class="w-7 h-7 inline-flex items-center justify-center rounded-md border border-border text-destructive hover:bg-background"
125
+ >
126
+ <span class="i-mdi:close" aria-hidden="true" />
127
+ </button>
128
+ </div>
129
+ );
130
+ }}
131
+ </For>
132
+ <div class="mt-4 flex gap-2">
133
+ <button
134
+ type="button"
135
+ onClick={copy}
136
+ class="inline-flex items-center gap-1.5 px-3 h-9 rounded-md bg-primary text-primary-foreground text-sm font-medium hover:bg-primary-hover transition-colors"
137
+ >
138
+ <span class="i-mdi:content-copy" aria-hidden="true" />
139
+ {copyText() || "Copy markdown"}
140
+ </button>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ <div class="lg:col-span-2 rounded-md border border-border bg-surface p-6 min-h-[60vh]">
145
+ <DocMarkdown source={markdown()} />
146
+ </div>
147
+ </div>
148
+ </div>
149
+ );
150
+ }