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