@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,225 @@
1
+ import { useParams } from "@tanstack/solid-router";
2
+ import { createEffect } from "solid-js";
3
+ import { useDocs } from "../context";
4
+ import { createDocsList, useCollections } from "../data";
5
+
6
+ const HEAD_MARKER = "data-docs-head";
7
+
8
+ function cleanupHead() {
9
+ for (const el of Array.from(document.querySelectorAll(`[${HEAD_MARKER}]`))) {
10
+ el.remove();
11
+ }
12
+ }
13
+
14
+ function setMeta(name: string, content: string, property = false) {
15
+ const el = document.createElement("meta");
16
+ el.setAttribute(HEAD_MARKER, "meta");
17
+ if (property) {
18
+ el.setAttribute("property", name);
19
+ } else {
20
+ el.setAttribute("name", name);
21
+ }
22
+ el.content = content;
23
+ document.head.appendChild(el);
24
+ }
25
+
26
+ function setLink(rel: string, href: string, attrs?: Record<string, string>) {
27
+ if (!href) return;
28
+ const el = document.createElement("link");
29
+ el.setAttribute(HEAD_MARKER, "link");
30
+ el.setAttribute("rel", rel);
31
+ el.href = href;
32
+ for (const [k, v] of Object.entries(attrs ?? {})) {
33
+ el.setAttribute(k, v);
34
+ }
35
+ document.head.appendChild(el);
36
+ }
37
+
38
+ function setJsonLd(payload: unknown) {
39
+ const id = "docs-json-ld";
40
+ let script = document.getElementById(id) as HTMLScriptElement | null;
41
+ if (!script) {
42
+ script = document.createElement("script");
43
+ script.id = id;
44
+ script.type = "application/ld+json";
45
+ document.head.appendChild(script);
46
+ }
47
+ script.textContent = JSON.stringify(payload);
48
+ }
49
+
50
+ export function Head() {
51
+ const config = useDocs();
52
+ const params = useParams({ strict: false });
53
+ const collections = useCollections();
54
+ const collection = () => params().collection ?? "";
55
+ const docId = () => params().docId ?? "";
56
+ const [docs] = createDocsList(collection);
57
+
58
+ createEffect(() => {
59
+ cleanupHead();
60
+
61
+ const site = config.site;
62
+ const siteUrl = (site.url ?? "").replace(/\/$/, "");
63
+ const colMeta = collections()?.find((c) => c.id === collection());
64
+ const docMeta = (docs() ?? []).find((d) => d.id === docId());
65
+ const docSeo = docMeta?.seo;
66
+
67
+ const parts: string[] = [];
68
+ if (docMeta) parts.push(docSeo?.title ?? docMeta.label);
69
+ if (colMeta) parts.push(colMeta.label);
70
+ parts.push(site.title);
71
+ const title = parts.join(" — ");
72
+
73
+ const description =
74
+ docSeo?.description ||
75
+ docMeta?.description ||
76
+ colMeta?.description ||
77
+ site.description ||
78
+ "";
79
+
80
+ const path = collection()
81
+ ? docId()
82
+ ? `${collection()}/${docId()}`
83
+ : collection()
84
+ : "";
85
+ const canonical = siteUrl ? `${siteUrl}/${path}`.replace(/\/$/, "") : "";
86
+ const ogImage = docSeo?.image || site.ogImage || `${siteUrl}/og-image.png`;
87
+
88
+ const ogType: "article" | "website" =
89
+ docSeo?.ogType ?? (docMeta ? "article" : "website");
90
+
91
+ document.title = title;
92
+ if (config.i18n?.current) {
93
+ document.documentElement.lang = config.i18n.current;
94
+ }
95
+
96
+ if (docSeo?.noIndex) {
97
+ setMeta("robots", "noindex, nofollow");
98
+ }
99
+
100
+ setMeta("description", description);
101
+ setMeta("og:title", title, true);
102
+ setMeta("og:description", description, true);
103
+ setMeta("og:url", canonical, true);
104
+ setMeta("og:image", ogImage, true);
105
+ setMeta("og:type", ogType, true);
106
+ if (docMeta?.publishedAt) {
107
+ setMeta("article:published_time", docMeta.publishedAt, true);
108
+ }
109
+ if (docMeta?.lastUpdated) {
110
+ setMeta("article:modified_time", docMeta.lastUpdated, true);
111
+ }
112
+ if (config.i18n?.current) {
113
+ setMeta("og:locale", config.i18n.current.replace("-", "_"), true);
114
+ }
115
+
116
+ setMeta("twitter:card", "summary_large_image");
117
+ setMeta("twitter:title", title);
118
+ setMeta("twitter:description", description);
119
+ if (ogImage) setMeta("twitter:image", ogImage);
120
+ setLink("canonical", canonical);
121
+
122
+ if (config.i18n?.list && siteUrl) {
123
+ for (const locale of config.i18n.list) {
124
+ const href = locale.url
125
+ ? `${locale.url.replace(/\/$/, "")}/${path}`.replace(/\/$/, "")
126
+ : `${siteUrl}/${locale.id}/${path}`.replace(/\/$/, "");
127
+ setLink("alternate", href, { hreflang: locale.id });
128
+ }
129
+ setLink("alternate", canonical, { hreflang: "x-default" });
130
+ }
131
+
132
+ if (config.features?.rss !== false) {
133
+ setLink("alternate", `${siteUrl}/rss.xml`, {
134
+ type: "application/rss+xml",
135
+ title: `${site.title} RSS`,
136
+ });
137
+ }
138
+ setLink("alternate", `${siteUrl}/feed.atom`, {
139
+ type: "application/atom+xml",
140
+ title: `${site.title} Atom Feed`,
141
+ });
142
+ setLink("alternate", `${siteUrl}/feed.json`, {
143
+ type: "application/feed+json",
144
+ title: `${site.title} JSON Feed`,
145
+ });
146
+ setLink("alternate", `${siteUrl}/llm.txt`, {
147
+ type: "text/plain",
148
+ title: `${site.title} LLMs.txt`,
149
+ });
150
+ setLink("alternate", `${siteUrl}/llms-plugins.txt`, {
151
+ type: "text/plain",
152
+ title: `${site.title} Plugins LLMs.txt`,
153
+ });
154
+
155
+ const schemas: unknown[] = [];
156
+ schemas.push({
157
+ "@context": "https://schema.org",
158
+ "@type": "WebSite",
159
+ name: site.title,
160
+ description: site.description || "",
161
+ url: siteUrl || "/",
162
+ potentialAction: {
163
+ "@type": "SearchAction",
164
+ target: {
165
+ "@type": "EntryPoint",
166
+ urlTemplate: `${siteUrl || ""}/?q={search_term_string}`,
167
+ },
168
+ "query-input": "required name=search_term_string",
169
+ },
170
+ });
171
+
172
+ if (docMeta && siteUrl) {
173
+ const breadcrumb = {
174
+ "@context": "https://schema.org",
175
+ "@type": "BreadcrumbList",
176
+ itemListElement: [
177
+ {
178
+ "@type": "ListItem",
179
+ position: 1,
180
+ name: site.title,
181
+ item: siteUrl,
182
+ },
183
+ {
184
+ "@type": "ListItem",
185
+ position: 2,
186
+ name: colMeta?.label ?? collection(),
187
+ item: `${siteUrl}/${collection()}`,
188
+ },
189
+ {
190
+ "@type": "ListItem",
191
+ position: 3,
192
+ name: docMeta.label,
193
+ item: `${siteUrl}/${collection()}/${docMeta.id}`,
194
+ },
195
+ ],
196
+ };
197
+ schemas.push(breadcrumb);
198
+
199
+ const article: Record<string, unknown> = {
200
+ "@context": "https://schema.org",
201
+ "@type": "TechArticle",
202
+ headline: docMeta.label,
203
+ description: docMeta.description,
204
+ url: `${siteUrl}/${collection()}/${docMeta.id}`,
205
+ author: {
206
+ "@type": "Organization",
207
+ name: site.title,
208
+ },
209
+ publisher: {
210
+ "@type": "Organization",
211
+ name: site.title,
212
+ logo: ogImage,
213
+ },
214
+ };
215
+ if (docMeta.publishedAt) article.datePublished = docMeta.publishedAt;
216
+ if (docMeta.lastUpdated) article.dateModified = docMeta.lastUpdated;
217
+ if (ogImage) article.image = ogImage;
218
+ schemas.push(article);
219
+ }
220
+
221
+ setJsonLd(schemas);
222
+ });
223
+
224
+ return null;
225
+ }
@@ -0,0 +1,75 @@
1
+ import { createSignal, For, onCleanup, onMount, Show } from "solid-js";
2
+ import { useDocs } from "../context";
3
+
4
+ export function LocaleDropdown() {
5
+ const [open, setOpen] = createSignal(false);
6
+ const config = useDocs();
7
+ let rootEl: HTMLDivElement | undefined;
8
+
9
+ const i18n = () => config.i18n;
10
+ const current = () => i18n()?.list.find((l) => l.id === i18n()?.current);
11
+
12
+ const onDocClick = (e: MouseEvent) => {
13
+ if (rootEl && !rootEl.contains(e.target as Node)) setOpen(false);
14
+ };
15
+ const onKey = (e: KeyboardEvent) => {
16
+ if (e.key === "Escape") setOpen(false);
17
+ };
18
+
19
+ onMount(() => {
20
+ document.addEventListener("click", onDocClick);
21
+ document.addEventListener("keydown", onKey);
22
+ });
23
+ onCleanup(() => {
24
+ document.removeEventListener("click", onDocClick);
25
+ document.removeEventListener("keydown", onKey);
26
+ });
27
+
28
+ return (
29
+ <Show when={(i18n()?.list.length ?? 0) > 1}>
30
+ <div ref={rootEl} class="relative">
31
+ <button
32
+ type="button"
33
+ onClick={() => setOpen(!open())}
34
+ aria-expanded={open()}
35
+ aria-haspopup="listbox"
36
+ aria-label="Select language"
37
+ class="inline-flex items-center gap-1.5 px-2.5 h-9 rounded-md border border-border bg-surface text-xs font-medium text-foreground hover:border-focus transition-colors cursor-pointer"
38
+ >
39
+ <span class="i-mdi:translate text-muted" aria-hidden="true" />
40
+ {current()?.label ?? i18n()?.current}
41
+ <span
42
+ class={`i-mdi:chevron-down text-muted transition-transform ${open() ? "rotate-180" : ""}`}
43
+ aria-hidden="true"
44
+ />
45
+ </button>
46
+ <Show when={open()}>
47
+ <ul
48
+ role="listbox"
49
+ aria-label="Languages"
50
+ class="absolute right-0 top-full mt-2 min-w-36 rounded-lg border border-border bg-surface shadow-lg py-1 z-50 list-none m-0"
51
+ >
52
+ <For each={i18n()?.list ?? []}>
53
+ {(l) => (
54
+ <li role="option" aria-selected={l.id === i18n()?.current}>
55
+ <a
56
+ href={l.url ?? "/"}
57
+ hreflang={l.id}
58
+ onClick={() => setOpen(false)}
59
+ class={`block px-3 py-2 text-sm no-underline transition-colors hover:bg-background ${
60
+ l.id === i18n()?.current
61
+ ? "text-primary font-medium"
62
+ : "text-foreground"
63
+ }`}
64
+ >
65
+ {l.label}
66
+ </a>
67
+ </li>
68
+ )}
69
+ </For>
70
+ </ul>
71
+ </Show>
72
+ </div>
73
+ </Show>
74
+ );
75
+ }
@@ -0,0 +1,111 @@
1
+ import { Link, useParams } from "@tanstack/solid-router";
2
+ import { For } from "solid-js";
3
+ import { createDocsList, useCollections } from "../data";
4
+ import { setSearchOpen } from "./SearchPalette";
5
+
6
+ export function MobileBottomNav(props: { onMenuToggle: () => void }) {
7
+ const collections = useCollections();
8
+ const params = useParams({ strict: false });
9
+
10
+ const [docsList] = createDocsList(() => "docs");
11
+ const [apiList] = createDocsList(() => "api");
12
+ const [showcaseList] = createDocsList(() => "showcase");
13
+
14
+ const firstDoc = (list: import("../types").DocEntry[]) => {
15
+ const idx = list.find((d) => d.id === "index");
16
+ return idx ? idx.id : list[0]?.id;
17
+ };
18
+
19
+ const items = () => {
20
+ const c = collections() ?? [];
21
+ const docsMeta = c.find((x) => x.id === "docs");
22
+ const apiMeta = c.find((x) => x.id === "api");
23
+ const showcaseMeta = c.find((x) => x.id === "showcase");
24
+ const out = [] as {
25
+ to: string;
26
+ icon: string;
27
+ label: string;
28
+ active?: boolean;
29
+ }[];
30
+ out.push({ to: "/", icon: "i-mdi:home", label: "Home" });
31
+ if (docsMeta) {
32
+ const docId = firstDoc(docsList() ?? []);
33
+ out.push({
34
+ to: docId ? `/${docsMeta.id}/${docId}` : `/${docsMeta.id}`,
35
+ icon: "i-mdi:book-open-page-variant",
36
+ label: "Docs",
37
+ });
38
+ }
39
+ if (apiMeta) {
40
+ const docId = firstDoc(apiList() ?? []);
41
+ out.push({
42
+ to: docId ? `/${apiMeta.id}/${docId}` : `/${apiMeta.id}`,
43
+ icon: "i-mdi:code-json",
44
+ label: "API",
45
+ });
46
+ }
47
+ if (showcaseMeta) {
48
+ const docId = firstDoc(showcaseList() ?? []);
49
+ out.push({
50
+ to: docId ? `/${showcaseMeta.id}/${docId}` : `/${showcaseMeta.id}`,
51
+ icon: "i-mdi:view-dashboard",
52
+ label: "Showcase",
53
+ });
54
+ }
55
+ return out;
56
+ };
57
+
58
+ const active = (to: string) => {
59
+ const p = params();
60
+ if (to === "/") return p.collection == null;
61
+ return p.collection === to.split("/")[1];
62
+ };
63
+
64
+ return (
65
+ <nav
66
+ aria-label="Mobile bottom navigation"
67
+ class="fixed bottom-0 left-0 right-0 z-50 bg-background/95 backdrop-blur border-t border-border lg:hidden pb-[env(safe-area-inset-bottom)]"
68
+ >
69
+ <div
70
+ class="h-16 min-h-16 grid items-center"
71
+ style={{
72
+ "grid-template-columns": `repeat(${items().length + 2}, minmax(0, 1fr))`,
73
+ }}
74
+ >
75
+ <For each={items()}>
76
+ {(item) => (
77
+ <Link
78
+ to={item.to}
79
+ class={`flex flex-col items-center justify-center h-full gap-0.5 text-xs no-underline transition-colors ${
80
+ active(item.to)
81
+ ? "text-primary"
82
+ : "text-muted hover:text-foreground"
83
+ }`}
84
+ >
85
+ <span class={`${item.icon} text-xl`} aria-hidden="true" />
86
+ <span class="scale-90">{item.label}</span>
87
+ </Link>
88
+ )}
89
+ </For>
90
+ <button
91
+ type="button"
92
+ aria-label="Search"
93
+ class="flex flex-col items-center justify-center h-full gap-0.5 text-xs text-muted hover:text-foreground transition-colors"
94
+ onClick={() => setSearchOpen(true)}
95
+ >
96
+ <span class="i-mdi:magnify text-xl" aria-hidden="true" />
97
+ <span class="scale-90">Search</span>
98
+ </button>
99
+ <button
100
+ type="button"
101
+ aria-label="Menu"
102
+ class="flex flex-col items-center justify-center h-full gap-0.5 text-xs text-muted hover:text-foreground transition-colors"
103
+ onClick={props.onMenuToggle}
104
+ >
105
+ <span class="i-mdi:menu text-xl" aria-hidden="true" />
106
+ <span class="scale-90">Menu</span>
107
+ </button>
108
+ </div>
109
+ </nav>
110
+ );
111
+ }
@@ -0,0 +1,139 @@
1
+ import { Link } from "@tanstack/solid-router";
2
+ import { createSignal, For, Show } from "solid-js";
3
+ import { useDocs } from "../context";
4
+ import { useCollections } from "../data";
5
+ import { setSearchOpen } from "./SearchPalette";
6
+
7
+ export function NotFound() {
8
+ const config = useDocs();
9
+ const [search, setSearch] = createSignal("");
10
+ const collections = useCollections();
11
+
12
+ const features = () =>
13
+ (config.home?.features ?? []).map((f) => ({
14
+ label: f.title,
15
+ to: f.link,
16
+ icon: f.icon ?? "i-mdi:arrow-right",
17
+ }));
18
+
19
+ const extra = () => [
20
+ ...(config.github?.issues
21
+ ? [{ label: "Issues", to: "/issues", icon: "i-mdi:alert-circle-outline" }]
22
+ : []),
23
+ ...(config.github?.releases
24
+ ? [{ label: "Release", to: "/changelog", icon: "i-mdi:tag" }]
25
+ : []),
26
+ ...(config.github?.contributors
27
+ ? [{ label: "Community", to: "/community", icon: "i-mdi:account-group" }]
28
+ : []),
29
+ ...(config.plugins?.length
30
+ ? [{ label: "Plugins", to: "/plugins", icon: "i-mdi:puzzle" }]
31
+ : []),
32
+ ...(config.showcase?.length
33
+ ? [{ label: "Showcase", to: "/showcase", icon: "i-mdi:view-dashboard" }]
34
+ : []),
35
+ ];
36
+
37
+ const quick = () => {
38
+ const first = collections()?.[0]?.id;
39
+ const docsLink = first ? `/${first}` : "/";
40
+ return [
41
+ { label: "Home", to: "/", icon: "i-mdi:home" },
42
+ {
43
+ label: "Documentation",
44
+ to: docsLink,
45
+ icon: "i-mdi:book-open-page-variant",
46
+ },
47
+ ...(config.apiCollections?.[0]
48
+ ? [
49
+ {
50
+ label: "API reference",
51
+ to: `/${config.apiCollections[0].id}`,
52
+ icon: "i-mdi:api",
53
+ },
54
+ ]
55
+ : []),
56
+ ...features(),
57
+ ...extra(),
58
+ ];
59
+ };
60
+
61
+ const onSearch = (e: Event) => {
62
+ e.preventDefault();
63
+ if (search().trim()) {
64
+ setSearchOpen(true);
65
+ // Populate search input if possible through global signal would need wiring;
66
+ // the palette will show with the current query typed by the user in separate state.
67
+ } else {
68
+ setSearchOpen(true);
69
+ }
70
+ };
71
+
72
+ return (
73
+ <div class="min-h-[70vh] flex flex-col items-center justify-center text-center px-6 py-20">
74
+ <span
75
+ class="i-mdi:robot-confused text-7xl text-primary/80 mb-6"
76
+ aria-hidden="true"
77
+ />
78
+ <h1 class="text-5xl font-bold text-foreground mb-3">404</h1>
79
+ <p class="text-lg text-muted mb-2">This page is lost in hyperspace.</p>
80
+ <p class="text-sm text-muted mb-8 max-w-md">
81
+ The page you are looking for does not exist or has been moved.
82
+ </p>
83
+
84
+ <form
85
+ onSubmit={onSearch}
86
+ class="w-full max-w-sm flex items-center gap-2 px-3 h-11 rounded-lg border border-border bg-surface mb-8 focus-within:border-focus"
87
+ >
88
+ <span class="i-mdi:magnify text-muted" aria-hidden="true" />
89
+ <input
90
+ type="search"
91
+ value={search()}
92
+ onInput={(e) => setSearch(e.currentTarget.value)}
93
+ placeholder="Search docs…"
94
+ class="bg-transparent outline-none border-none flex-1 text-sm text-foreground placeholder:text-muted"
95
+ />
96
+ <button
97
+ type="submit"
98
+ class="text-sm text-primary font-medium hover:underline"
99
+ >
100
+ Search
101
+ </button>
102
+ </form>
103
+
104
+ <div class="flex flex-wrap gap-3 justify-center mb-8">
105
+ <For each={quick()}>
106
+ {(item) => (
107
+ <Link
108
+ to={item.to}
109
+ class="px-4 h-10 inline-flex items-center gap-2 rounded-lg border border-border text-foreground no-underline hover:bg-surface transition-colors"
110
+ >
111
+ <span class={item.icon} aria-hidden="true" />
112
+ {item.label}
113
+ </Link>
114
+ )}
115
+ </For>
116
+ </div>
117
+
118
+ <div class="flex flex-wrap gap-3 justify-center">
119
+ <Link
120
+ to="/"
121
+ class="px-5 h-11 inline-flex items-center rounded-lg bg-primary text-primary-foreground no-underline font-medium hover:bg-primary-hover transition-colors"
122
+ >
123
+ Back home
124
+ </Link>
125
+ <Show when={config.site.repoUrl}>
126
+ <a
127
+ href={`${config.site.repoUrl}/issues`}
128
+ target="_blank"
129
+ rel="noreferrer"
130
+ class="px-5 h-11 inline-flex items-center gap-2 rounded-lg border border-border text-foreground no-underline hover:bg-surface transition-colors"
131
+ >
132
+ <span class="i-mdi:github" aria-hidden="true" />
133
+ Report an issue
134
+ </a>
135
+ </Show>
136
+ </div>
137
+ </div>
138
+ );
139
+ }
@@ -0,0 +1,144 @@
1
+ import { Link } from "@tanstack/solid-router";
2
+ import { createSignal, Show } from "solid-js";
3
+ import { useDocs } from "../context";
4
+ import { useCollections } from "../data";
5
+ import type { DocEntry } from "../types";
6
+
7
+ export function PageActions(props: {
8
+ collection: string;
9
+ doc: DocEntry;
10
+ source: string;
11
+ }) {
12
+ const [copied, setCopied] = createSignal(false);
13
+ const collections = useCollections();
14
+ const config = useDocs();
15
+ const branch = () => config.github?.branch ?? "main";
16
+ const repoUrl = () => config.site.repoUrl;
17
+ const collectionRepo = () =>
18
+ collections()?.find((c) => c.id === props.collection)?.repoUrl;
19
+
20
+ const effectiveRepo = () => collectionRepo() ?? repoUrl() ?? "";
21
+ const gitPath = () =>
22
+ props.doc.path || `${props.collection}/${props.doc.id}.md`;
23
+
24
+ const copyMarkdown = async () => {
25
+ try {
26
+ await navigator.clipboard.writeText(props.source);
27
+ setCopied(true);
28
+ setTimeout(() => setCopied(false), 1500);
29
+ } catch {
30
+ // ignore
31
+ }
32
+ };
33
+
34
+ const editUrl = () => `${effectiveRepo()}/edit/${branch()}/${gitPath()}`;
35
+ const viewUrl = () => `${effectiveRepo()}/blob/${branch()}/${gitPath()}`;
36
+ const reportUrl = () =>
37
+ `${effectiveRepo()}/issues/new?title=docs(${props.doc.id}): &body=Issue on page ${props.collection}/${props.doc.id}`;
38
+ const prUrl = () =>
39
+ `${effectiveRepo()}/compare/${branch()}?quick_pull=1&title=docs(${props.doc.id}): `;
40
+
41
+ const aiPrompt = () => {
42
+ const title = props.doc.label || `${props.collection}/${props.doc.id}`;
43
+ return `Please review the following documentation page titled "${title}" and summarize the key points, suggest improvements, and answer any questions the user may have:\n\n${props.source}`;
44
+ };
45
+ const chatGptUrl = () =>
46
+ `https://chat.openai.com/?q=${encodeURIComponent(aiPrompt())}`;
47
+ const claudeUrl = () =>
48
+ `https://claude.ai/chat?q=${encodeURIComponent(aiPrompt())}`;
49
+
50
+ return (
51
+ <div class="flex items-center gap-2 flex-wrap">
52
+ <button
53
+ type="button"
54
+ onClick={copyMarkdown}
55
+ 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"
56
+ >
57
+ <span
58
+ class={copied() ? "i-mdi:check text-success" : "i-mdi:content-copy"}
59
+ aria-hidden="true"
60
+ />
61
+ {copied() ? "Copied" : "Copy"}
62
+ </button>
63
+ <a
64
+ href={`/docs/${props.collection}/${props.doc.id}.md`}
65
+ target="_blank"
66
+ rel="noreferrer"
67
+ 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 no-underline"
68
+ >
69
+ <span class="i-mdi:language-markdown-outline" aria-hidden="true" />
70
+ View .md
71
+ </a>
72
+ <a
73
+ href={chatGptUrl()}
74
+ target="_blank"
75
+ rel="noreferrer"
76
+ title="Open in ChatGPT"
77
+ 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 no-underline"
78
+ >
79
+ <span class="i-mdi:robot-outline" aria-hidden="true" />
80
+ ChatGPT
81
+ </a>
82
+ <a
83
+ href={claudeUrl()}
84
+ target="_blank"
85
+ rel="noreferrer"
86
+ title="Open in Claude"
87
+ 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 no-underline"
88
+ >
89
+ <span class="i-mdi:sparkles" aria-hidden="true" />
90
+ Claude
91
+ </a>
92
+ <Link
93
+ to="/edit/$collection/$docId"
94
+ params={{ collection: props.collection, docId: props.doc.id }}
95
+ 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 no-underline"
96
+ >
97
+ <span class="i-mdi:pencil-box" aria-hidden="true" />
98
+ Edit local
99
+ </Link>
100
+ <Show when={effectiveRepo()}>
101
+ <a
102
+ href={editUrl()}
103
+ target="_blank"
104
+ rel="noreferrer"
105
+ 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 no-underline"
106
+ >
107
+ <span class="i-mdi:pencil-outline" aria-hidden="true" />
108
+ Edit
109
+ </a>
110
+ <a
111
+ href={viewUrl()}
112
+ target="_blank"
113
+ rel="noreferrer"
114
+ 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 no-underline"
115
+ >
116
+ <span class="i-mdi:github" aria-hidden="true" />
117
+ Source
118
+ </a>
119
+ <Show when={config.features?.reportIssue !== false}>
120
+ <a
121
+ href={reportUrl()}
122
+ target="_blank"
123
+ rel="noreferrer"
124
+ 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 no-underline"
125
+ >
126
+ <span class="i-mdi:alert-circle-outline" aria-hidden="true" />
127
+ Report
128
+ </a>
129
+ </Show>
130
+ <Show when={config.features?.openPR}>
131
+ <a
132
+ href={prUrl()}
133
+ target="_blank"
134
+ rel="noreferrer"
135
+ 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 no-underline"
136
+ >
137
+ <span class="i-mdi:source-pull" aria-hidden="true" />
138
+ PR
139
+ </a>
140
+ </Show>
141
+ </Show>
142
+ </div>
143
+ );
144
+ }