@lickle/docs 0.0.0-dev.1
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 +3 -0
- package/dist/esm/_lib/fs/index.js +20 -0
- package/dist/esm/_lib/fs/index.js.map +1 -0
- package/dist/esm/_lib/fs/watch.js +30 -0
- package/dist/esm/_lib/fs/watch.js.map +1 -0
- package/dist/esm/_lib/index.js +9 -0
- package/dist/esm/_lib/index.js.map +1 -0
- package/dist/esm/_lib/jiti/index.js +16 -0
- package/dist/esm/_lib/jiti/index.js.map +1 -0
- package/dist/esm/_lib/path/index.js +42 -0
- package/dist/esm/_lib/path/index.js.map +1 -0
- package/dist/esm/_lib/pkg/index.js +128 -0
- package/dist/esm/_lib/pkg/index.js.map +1 -0
- package/dist/esm/_lib/repo/index.js +100 -0
- package/dist/esm/_lib/repo/index.js.map +1 -0
- package/dist/esm/_lib/slug/index.js +23 -0
- package/dist/esm/_lib/slug/index.js.map +1 -0
- package/dist/esm/_lib/t.js +2 -0
- package/dist/esm/_lib/t.js.map +1 -0
- package/dist/esm/_lib/tsconfig/index.js +12 -0
- package/dist/esm/_lib/tsconfig/index.js.map +1 -0
- package/dist/esm/_lib/util/index.js +54 -0
- package/dist/esm/_lib/util/index.js.map +1 -0
- package/dist/esm/cli/cmd/dev.js +74 -0
- package/dist/esm/cli/cmd/dev.js.map +1 -0
- package/dist/esm/cli/cmd/index.js +4 -0
- package/dist/esm/cli/cmd/index.js.map +1 -0
- package/dist/esm/cli/cmd/init.js +74 -0
- package/dist/esm/cli/cmd/init.js.map +1 -0
- package/dist/esm/cli/cmd/json.js +28 -0
- package/dist/esm/cli/cmd/json.js.map +1 -0
- package/dist/esm/cli/env.js +5 -0
- package/dist/esm/cli/env.js.map +1 -0
- package/dist/esm/cli/index.js +13 -0
- package/dist/esm/cli/index.js.map +1 -0
- package/dist/esm/cli/vite/client/index.jsx +20 -0
- package/dist/esm/cli/vite/client/index.jsx.map +1 -0
- package/dist/esm/cli/vite/index.js +100 -0
- package/dist/esm/cli/vite/index.js.map +1 -0
- package/dist/esm/cli.js +5 -0
- package/dist/esm/cli.js.map +1 -0
- package/dist/esm/config/defaults.js +32 -0
- package/dist/esm/config/defaults.js.map +1 -0
- package/dist/esm/config/file.js +48 -0
- package/dist/esm/config/file.js.map +1 -0
- package/dist/esm/config/index.js +7 -0
- package/dist/esm/config/index.js.map +1 -0
- package/dist/esm/config/load.js +79 -0
- package/dist/esm/config/load.js.map +1 -0
- package/dist/esm/config/types.js +2 -0
- package/dist/esm/config/types.js.map +1 -0
- package/dist/esm/core/index.js +3 -0
- package/dist/esm/core/index.js.map +1 -0
- package/dist/esm/core/project/debug.js +26 -0
- package/dist/esm/core/project/debug.js.map +1 -0
- package/dist/esm/core/project/index.js +39 -0
- package/dist/esm/core/project/index.js.map +1 -0
- package/dist/esm/core/project/naming.js +39 -0
- package/dist/esm/core/project/naming.js.map +1 -0
- package/dist/esm/core/project/routing.js +173 -0
- package/dist/esm/core/project/routing.js.map +1 -0
- package/dist/esm/core/project/types.js +4 -0
- package/dist/esm/core/project/types.js.map +1 -0
- package/dist/esm/core/reflect/index.js +10 -0
- package/dist/esm/core/reflect/index.js.map +1 -0
- package/dist/esm/core/reflect/indexed.js +195 -0
- package/dist/esm/core/reflect/indexed.js.map +1 -0
- package/dist/esm/core/reflect/resolve.js +157 -0
- package/dist/esm/core/reflect/resolve.js.map +1 -0
- package/dist/esm/core/reflect/scan.js +787 -0
- package/dist/esm/core/reflect/scan.js.map +1 -0
- package/dist/esm/core/reflect/state.js +29 -0
- package/dist/esm/core/reflect/state.js.map +1 -0
- package/dist/esm/core/reflect/types.js +16 -0
- package/dist/esm/core/reflect/types.js.map +1 -0
- package/dist/esm/core/reflect/walk.js +106 -0
- package/dist/esm/core/reflect/walk.js.map +1 -0
- package/dist/esm/solidjs/index.js +2 -0
- package/dist/esm/solidjs/index.js.map +1 -0
- package/dist/esm/solidjs/jsx-runtime.js +2 -0
- package/dist/esm/solidjs/jsx-runtime.js.map +1 -0
- package/dist/esm/ui/App.jsx +71 -0
- package/dist/esm/ui/App.jsx.map +1 -0
- package/dist/esm/ui/components/Breadcrumb.jsx +45 -0
- package/dist/esm/ui/components/Breadcrumb.jsx.map +1 -0
- package/dist/esm/ui/components/Code/index.jsx +89 -0
- package/dist/esm/ui/components/Code/index.jsx.map +1 -0
- package/dist/esm/ui/components/Comment.jsx +176 -0
- package/dist/esm/ui/components/Comment.jsx.map +1 -0
- package/dist/esm/ui/components/Declaration.jsx +147 -0
- package/dist/esm/ui/components/Declaration.jsx.map +1 -0
- package/dist/esm/ui/components/Header.jsx +66 -0
- package/dist/esm/ui/components/Header.jsx.map +1 -0
- package/dist/esm/ui/components/Layout.jsx +44 -0
- package/dist/esm/ui/components/Layout.jsx.map +1 -0
- package/dist/esm/ui/components/Link.jsx +34 -0
- package/dist/esm/ui/components/Link.jsx.map +1 -0
- package/dist/esm/ui/components/LivePreview/Example.jsx +76 -0
- package/dist/esm/ui/components/LivePreview/Example.jsx.map +1 -0
- package/dist/esm/ui/components/LivePreview/Sandbox.jsx +25 -0
- package/dist/esm/ui/components/LivePreview/Sandbox.jsx.map +1 -0
- package/dist/esm/ui/components/LivePreview/index.js +4 -0
- package/dist/esm/ui/components/LivePreview/index.js.map +1 -0
- package/dist/esm/ui/components/LivePreview/transform.js +16 -0
- package/dist/esm/ui/components/LivePreview/transform.js.map +1 -0
- package/dist/esm/ui/components/Markdown.jsx +14 -0
- package/dist/esm/ui/components/Markdown.jsx.map +1 -0
- package/dist/esm/ui/components/Page.jsx +121 -0
- package/dist/esm/ui/components/Page.jsx.map +1 -0
- package/dist/esm/ui/components/References.jsx +32 -0
- package/dist/esm/ui/components/References.jsx.map +1 -0
- package/dist/esm/ui/components/SearchPalette.jsx +178 -0
- package/dist/esm/ui/components/SearchPalette.jsx.map +1 -0
- package/dist/esm/ui/components/Sidebar.jsx +63 -0
- package/dist/esm/ui/components/Sidebar.jsx.map +1 -0
- package/dist/esm/ui/components/Syntax.jsx +10 -0
- package/dist/esm/ui/components/Syntax.jsx.map +1 -0
- package/dist/esm/ui/components/ThemeToggle.jsx +25 -0
- package/dist/esm/ui/components/ThemeToggle.jsx.map +1 -0
- package/dist/esm/ui/components/Type.jsx +444 -0
- package/dist/esm/ui/components/Type.jsx.map +1 -0
- package/dist/esm/ui/components/index.js +16 -0
- package/dist/esm/ui/components/index.js.map +1 -0
- package/dist/esm/ui/context/components.jsx +30 -0
- package/dist/esm/ui/context/components.jsx.map +1 -0
- package/dist/esm/ui/context/global.js +15 -0
- package/dist/esm/ui/context/global.js.map +1 -0
- package/dist/esm/ui/context/index.js +5 -0
- package/dist/esm/ui/context/index.js.map +1 -0
- package/dist/esm/ui/context/markup/index.jsx +25 -0
- package/dist/esm/ui/context/markup/index.jsx.map +1 -0
- package/dist/esm/ui/context/markup/markdown.js +34 -0
- package/dist/esm/ui/context/markup/markdown.js.map +1 -0
- package/dist/esm/ui/context/markup/shiki.js +58 -0
- package/dist/esm/ui/context/markup/shiki.js.map +1 -0
- package/dist/esm/ui/context/markup/util.js +22 -0
- package/dist/esm/ui/context/markup/util.js.map +1 -0
- package/dist/esm/ui/context/project/index.jsx +27 -0
- package/dist/esm/ui/context/project/index.jsx.map +1 -0
- package/dist/esm/ui/context/project/indexed.js +47 -0
- package/dist/esm/ui/context/project/indexed.js.map +1 -0
- package/dist/esm/ui/context/project/types.js +2 -0
- package/dist/esm/ui/context/project/types.js.map +1 -0
- package/dist/esm/ui/context/theme.jsx +36 -0
- package/dist/esm/ui/context/theme.jsx.map +1 -0
- package/dist/esm/ui/hooks/index.js +94 -0
- package/dist/esm/ui/hooks/index.js.map +1 -0
- package/dist/esm/ui/index.js +5 -0
- package/dist/esm/ui/index.js.map +1 -0
- package/dist/esm/ui/renderer.jsx +21 -0
- package/dist/esm/ui/renderer.jsx.map +1 -0
- package/dist/esm/ui/util/comment.js +14 -0
- package/dist/esm/ui/util/comment.js.map +1 -0
- package/dist/esm/ui/util/kind.js +85 -0
- package/dist/esm/ui/util/kind.js.map +1 -0
- package/dist/esm/ui/util/markdown.js +66 -0
- package/dist/esm/ui/util/markdown.js.map +1 -0
- package/dist/esm/ui/util/search.js +75 -0
- package/dist/esm/ui/util/search.js.map +1 -0
- package/dist/ts/_lib/fs/index.d.ts +6 -0
- package/dist/ts/_lib/fs/index.d.ts.map +1 -0
- package/dist/ts/_lib/fs/watch.d.ts +14 -0
- package/dist/ts/_lib/fs/watch.d.ts.map +1 -0
- package/dist/ts/_lib/index.d.ts +10 -0
- package/dist/ts/_lib/index.d.ts.map +1 -0
- package/dist/ts/_lib/jiti/index.d.ts +2 -0
- package/dist/ts/_lib/jiti/index.d.ts.map +1 -0
- package/dist/ts/_lib/path/index.d.ts +12 -0
- package/dist/ts/_lib/path/index.d.ts.map +1 -0
- package/dist/ts/_lib/pkg/index.d.ts +28 -0
- package/dist/ts/_lib/pkg/index.d.ts.map +1 -0
- package/dist/ts/_lib/repo/index.d.ts +30 -0
- package/dist/ts/_lib/repo/index.d.ts.map +1 -0
- package/dist/ts/_lib/slug/index.d.ts +4 -0
- package/dist/ts/_lib/slug/index.d.ts.map +1 -0
- package/dist/ts/_lib/t.d.ts +11 -0
- package/dist/ts/_lib/t.d.ts.map +1 -0
- package/dist/ts/_lib/tsconfig/index.d.ts +8 -0
- package/dist/ts/_lib/tsconfig/index.d.ts.map +1 -0
- package/dist/ts/_lib/util/index.d.ts +9 -0
- package/dist/ts/_lib/util/index.d.ts.map +1 -0
- package/dist/ts/cli/cmd/dev.d.ts +27 -0
- package/dist/ts/cli/cmd/dev.d.ts.map +1 -0
- package/dist/ts/cli/cmd/index.d.ts +4 -0
- package/dist/ts/cli/cmd/index.d.ts.map +1 -0
- package/dist/ts/cli/cmd/init.d.ts +14 -0
- package/dist/ts/cli/cmd/init.d.ts.map +1 -0
- package/dist/ts/cli/cmd/json.d.ts +12 -0
- package/dist/ts/cli/cmd/json.d.ts.map +1 -0
- package/dist/ts/cli/env.d.ts +2 -0
- package/dist/ts/cli/env.d.ts.map +1 -0
- package/dist/ts/cli/index.d.ts +78 -0
- package/dist/ts/cli/index.d.ts.map +1 -0
- package/dist/ts/cli/vite/client/index.d.ts +10 -0
- package/dist/ts/cli/vite/client/index.d.ts.map +1 -0
- package/dist/ts/cli/vite/index.d.ts +12 -0
- package/dist/ts/cli/vite/index.d.ts.map +1 -0
- package/dist/ts/cli.d.ts +3 -0
- package/dist/ts/cli.d.ts.map +1 -0
- package/dist/ts/config/defaults.d.ts +10 -0
- package/dist/ts/config/defaults.d.ts.map +1 -0
- package/dist/ts/config/file.d.ts +3 -0
- package/dist/ts/config/file.d.ts.map +1 -0
- package/dist/ts/config/index.d.ts +6 -0
- package/dist/ts/config/index.d.ts.map +1 -0
- package/dist/ts/config/load.d.ts +36 -0
- package/dist/ts/config/load.d.ts.map +1 -0
- package/dist/ts/config/types.d.ts +56 -0
- package/dist/ts/config/types.d.ts.map +1 -0
- package/dist/ts/core/index.d.ts +3 -0
- package/dist/ts/core/index.d.ts.map +1 -0
- package/dist/ts/core/project/debug.d.ts +3 -0
- package/dist/ts/core/project/debug.d.ts.map +1 -0
- package/dist/ts/core/project/index.d.ts +17 -0
- package/dist/ts/core/project/index.d.ts.map +1 -0
- package/dist/ts/core/project/naming.d.ts +23 -0
- package/dist/ts/core/project/naming.d.ts.map +1 -0
- package/dist/ts/core/project/routing.d.ts +61 -0
- package/dist/ts/core/project/routing.d.ts.map +1 -0
- package/dist/ts/core/project/types.d.ts +56 -0
- package/dist/ts/core/project/types.d.ts.map +1 -0
- package/dist/ts/core/reflect/index.d.ts +22 -0
- package/dist/ts/core/reflect/index.d.ts.map +1 -0
- package/dist/ts/core/reflect/indexed.d.ts +83 -0
- package/dist/ts/core/reflect/indexed.d.ts.map +1 -0
- package/dist/ts/core/reflect/resolve.d.ts +3 -0
- package/dist/ts/core/reflect/resolve.d.ts.map +1 -0
- package/dist/ts/core/reflect/scan.d.ts +218 -0
- package/dist/ts/core/reflect/scan.d.ts.map +1 -0
- package/dist/ts/core/reflect/state.d.ts +44 -0
- package/dist/ts/core/reflect/state.d.ts.map +1 -0
- package/dist/ts/core/reflect/types.d.ts +289 -0
- package/dist/ts/core/reflect/types.d.ts.map +1 -0
- package/dist/ts/core/reflect/walk.d.ts +28 -0
- package/dist/ts/core/reflect/walk.d.ts.map +1 -0
- package/dist/ts/solidjs/index.d.ts +2 -0
- package/dist/ts/solidjs/index.d.ts.map +1 -0
- package/dist/ts/solidjs/jsx-runtime.d.ts +2 -0
- package/dist/ts/solidjs/jsx-runtime.d.ts.map +1 -0
- package/dist/ts/ui/App.d.ts +17 -0
- package/dist/ts/ui/App.d.ts.map +1 -0
- package/dist/ts/ui/components/Breadcrumb.d.ts +4 -0
- package/dist/ts/ui/components/Breadcrumb.d.ts.map +1 -0
- package/dist/ts/ui/components/Code/index.d.ts +17 -0
- package/dist/ts/ui/components/Code/index.d.ts.map +1 -0
- package/dist/ts/ui/components/Comment.d.ts +49 -0
- package/dist/ts/ui/components/Comment.d.ts.map +1 -0
- package/dist/ts/ui/components/Declaration.d.ts +122 -0
- package/dist/ts/ui/components/Declaration.d.ts.map +1 -0
- package/dist/ts/ui/components/Header.d.ts +5 -0
- package/dist/ts/ui/components/Header.d.ts.map +1 -0
- package/dist/ts/ui/components/Layout.d.ts +5 -0
- package/dist/ts/ui/components/Layout.d.ts.map +1 -0
- package/dist/ts/ui/components/Link.d.ts +15 -0
- package/dist/ts/ui/components/Link.d.ts.map +1 -0
- package/dist/ts/ui/components/LivePreview/Example.d.ts +16 -0
- package/dist/ts/ui/components/LivePreview/Example.d.ts.map +1 -0
- package/dist/ts/ui/components/LivePreview/Sandbox.d.ts +20 -0
- package/dist/ts/ui/components/LivePreview/Sandbox.d.ts.map +1 -0
- package/dist/ts/ui/components/LivePreview/index.d.ts +4 -0
- package/dist/ts/ui/components/LivePreview/index.d.ts.map +1 -0
- package/dist/ts/ui/components/LivePreview/transform.d.ts +19 -0
- package/dist/ts/ui/components/LivePreview/transform.d.ts.map +1 -0
- package/dist/ts/ui/components/Markdown.d.ts +11 -0
- package/dist/ts/ui/components/Markdown.d.ts.map +1 -0
- package/dist/ts/ui/components/Page.d.ts +21 -0
- package/dist/ts/ui/components/Page.d.ts.map +1 -0
- package/dist/ts/ui/components/References.d.ts +2 -0
- package/dist/ts/ui/components/References.d.ts.map +1 -0
- package/dist/ts/ui/components/SearchPalette.d.ts +5 -0
- package/dist/ts/ui/components/SearchPalette.d.ts.map +1 -0
- package/dist/ts/ui/components/Sidebar.d.ts +5 -0
- package/dist/ts/ui/components/Sidebar.d.ts.map +1 -0
- package/dist/ts/ui/components/Syntax.d.ts +15 -0
- package/dist/ts/ui/components/Syntax.d.ts.map +1 -0
- package/dist/ts/ui/components/ThemeToggle.d.ts +2 -0
- package/dist/ts/ui/components/ThemeToggle.d.ts.map +1 -0
- package/dist/ts/ui/components/Type.d.ts +82 -0
- package/dist/ts/ui/components/Type.d.ts.map +1 -0
- package/dist/ts/ui/components/index.d.ts +15 -0
- package/dist/ts/ui/components/index.d.ts.map +1 -0
- package/dist/ts/ui/context/components.d.ts +124 -0
- package/dist/ts/ui/context/components.d.ts.map +1 -0
- package/dist/ts/ui/context/global.d.ts +210 -0
- package/dist/ts/ui/context/global.d.ts.map +1 -0
- package/dist/ts/ui/context/index.d.ts +5 -0
- package/dist/ts/ui/context/index.d.ts.map +1 -0
- package/dist/ts/ui/context/markup/index.d.ts +20 -0
- package/dist/ts/ui/context/markup/index.d.ts.map +1 -0
- package/dist/ts/ui/context/markup/markdown.d.ts +4 -0
- package/dist/ts/ui/context/markup/markdown.d.ts.map +1 -0
- package/dist/ts/ui/context/markup/shiki.d.ts +17 -0
- package/dist/ts/ui/context/markup/shiki.d.ts.map +1 -0
- package/dist/ts/ui/context/markup/util.d.ts +11 -0
- package/dist/ts/ui/context/markup/util.d.ts.map +1 -0
- package/dist/ts/ui/context/project/index.d.ts +25 -0
- package/dist/ts/ui/context/project/index.d.ts.map +1 -0
- package/dist/ts/ui/context/project/indexed.d.ts +4 -0
- package/dist/ts/ui/context/project/indexed.d.ts.map +1 -0
- package/dist/ts/ui/context/project/types.d.ts +13 -0
- package/dist/ts/ui/context/project/types.d.ts.map +1 -0
- package/dist/ts/ui/context/theme.d.ts +12 -0
- package/dist/ts/ui/context/theme.d.ts.map +1 -0
- package/dist/ts/ui/hooks/index.d.ts +29 -0
- package/dist/ts/ui/hooks/index.d.ts.map +1 -0
- package/dist/ts/ui/index.d.ts +5 -0
- package/dist/ts/ui/index.d.ts.map +1 -0
- package/dist/ts/ui/renderer.d.ts +200 -0
- package/dist/ts/ui/renderer.d.ts.map +1 -0
- package/dist/ts/ui/util/comment.d.ts +4 -0
- package/dist/ts/ui/util/comment.d.ts.map +1 -0
- package/dist/ts/ui/util/kind.d.ts +15 -0
- package/dist/ts/ui/util/kind.d.ts.map +1 -0
- package/dist/ts/ui/util/markdown.d.ts +8 -0
- package/dist/ts/ui/util/markdown.d.ts.map +1 -0
- package/dist/ts/ui/util/search.d.ts +20 -0
- package/dist/ts/ui/util/search.d.ts.map +1 -0
- package/package.json +89 -0
- package/src/_lib/fs/index.ts +23 -0
- package/src/_lib/fs/watch.ts +40 -0
- package/src/_lib/index.ts +9 -0
- package/src/_lib/jiti/index.ts +18 -0
- package/src/_lib/path/index.ts +44 -0
- package/src/_lib/pkg/index.ts +165 -0
- package/src/_lib/repo/index.ts +138 -0
- package/src/_lib/slug/index.ts +26 -0
- package/src/_lib/t.ts +17 -0
- package/src/_lib/tsconfig/index.ts +20 -0
- package/src/_lib/util/index.ts +53 -0
- package/src/cli/cmd/dev.ts +86 -0
- package/src/cli/cmd/index.ts +3 -0
- package/src/cli/cmd/init.ts +80 -0
- package/src/cli/cmd/json.ts +28 -0
- package/src/cli/env.ts +6 -0
- package/src/cli/index.ts +14 -0
- package/src/cli/vite/client/index.html +27 -0
- package/src/cli/vite/client/index.tsx +30 -0
- package/src/cli/vite/client/public/apple-touch-icon.png +0 -0
- package/src/cli/vite/client/public/favicon-96x96.png +0 -0
- package/src/cli/vite/client/public/favicon.ico +0 -0
- package/src/cli/vite/client/public/favicon.svg +1 -0
- package/src/cli/vite/client/public/site.webmanifest +21 -0
- package/src/cli/vite/client/public/web-app-manifest-192x192.png +0 -0
- package/src/cli/vite/client/public/web-app-manifest-512x512.png +0 -0
- package/src/cli/vite/index.ts +115 -0
- package/src/cli.ts +6 -0
- package/src/config/defaults.ts +36 -0
- package/src/config/file.ts +53 -0
- package/src/config/index.ts +11 -0
- package/src/config/load.ts +95 -0
- package/src/config/types.ts +59 -0
- package/src/core/index.ts +2 -0
- package/src/core/project/debug.ts +30 -0
- package/src/core/project/index.ts +58 -0
- package/src/core/project/naming.ts +49 -0
- package/src/core/project/routing.ts +234 -0
- package/src/core/project/types.ts +47 -0
- package/src/core/reflect/index.ts +18 -0
- package/src/core/reflect/indexed.ts +242 -0
- package/src/core/reflect/resolve.ts +159 -0
- package/src/core/reflect/scan.ts +816 -0
- package/src/core/reflect/state.ts +75 -0
- package/src/core/reflect/types.ts +164 -0
- package/src/core/reflect/walk.ts +121 -0
- package/src/solidjs/index.ts +1 -0
- package/src/solidjs/jsx-runtime.ts +1 -0
- package/src/ui/App.tsx +115 -0
- package/src/ui/components/Breadcrumb.tsx +53 -0
- package/src/ui/components/Code/index.tsx +112 -0
- package/src/ui/components/Comment.tsx +221 -0
- package/src/ui/components/Declaration.tsx +210 -0
- package/src/ui/components/Header.tsx +99 -0
- package/src/ui/components/Layout.tsx +62 -0
- package/src/ui/components/Link.tsx +43 -0
- package/src/ui/components/LivePreview/Example.tsx +104 -0
- package/src/ui/components/LivePreview/Sandbox.tsx +36 -0
- package/src/ui/components/LivePreview/index.ts +3 -0
- package/src/ui/components/LivePreview/transform.ts +28 -0
- package/src/ui/components/Markdown.tsx +16 -0
- package/src/ui/components/Page.tsx +162 -0
- package/src/ui/components/References.tsx +34 -0
- package/src/ui/components/SearchPalette.tsx +266 -0
- package/src/ui/components/Sidebar.tsx +107 -0
- package/src/ui/components/Syntax.tsx +10 -0
- package/src/ui/components/ThemeToggle.tsx +50 -0
- package/src/ui/components/Type.tsx +583 -0
- package/src/ui/components/index.ts +15 -0
- package/src/ui/context/components.tsx +103 -0
- package/src/ui/context/global.ts +33 -0
- package/src/ui/context/index.ts +4 -0
- package/src/ui/context/markup/index.tsx +39 -0
- package/src/ui/context/markup/markdown.ts +37 -0
- package/src/ui/context/markup/shiki.ts +72 -0
- package/src/ui/context/markup/util.ts +20 -0
- package/src/ui/context/project/index.tsx +47 -0
- package/src/ui/context/project/indexed.ts +52 -0
- package/src/ui/context/project/types.ts +14 -0
- package/src/ui/context/theme.tsx +45 -0
- package/src/ui/hooks/index.ts +116 -0
- package/src/ui/index.ts +4 -0
- package/src/ui/renderer.tsx +31 -0
- package/src/ui/util/comment.ts +12 -0
- package/src/ui/util/kind.ts +120 -0
- package/src/ui/util/markdown.ts +74 -0
- package/src/ui/util/search.ts +84 -0
- package/theme.css +301 -0
- package/tsconfig.client.json +12 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { createContext, createMemo, Show, useContext } from 'solid-js'
|
|
2
|
+
import type { Accessor, Component } from 'solid-js'
|
|
3
|
+
import type { JSX } from 'solid-js/jsx-runtime'
|
|
4
|
+
import { Dynamic } from 'solid-js/web'
|
|
5
|
+
|
|
6
|
+
import type { Types } from '../context/index.ts'
|
|
7
|
+
import type { t } from '../../_lib/index.ts'
|
|
8
|
+
|
|
9
|
+
const ComponentsCtx = createContext<Accessor<Components>>(() => ({}))
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Provide a component registry to descendants. When nested inside another
|
|
13
|
+
* `<ComponentsProvider>` the inner value is shallow-merged onto the outer one,
|
|
14
|
+
* so a wrapper preset can establish defaults that an app extends without
|
|
15
|
+
* losing the outer's entries.
|
|
16
|
+
*/
|
|
17
|
+
export const ComponentsProvider = (props: { value?: Components; children: JSX.Element }) => {
|
|
18
|
+
const outer = useContext(ComponentsCtx)
|
|
19
|
+
const merged = createMemo<Components>(() => ({ ...outer(), ...window.lickle.components[0](), ...props.value }))
|
|
20
|
+
return <ComponentsCtx.Provider value={merged}>{props.children}</ComponentsCtx.Provider>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Read the active (already-merged) component registry. */
|
|
24
|
+
export const useComponents = (): Accessor<Components> => useContext(ComponentsCtx)
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Build a slot dispatcher in one line: look up the override under `key`,
|
|
28
|
+
* forward `Default` so it can decorate, otherwise render the default. The
|
|
29
|
+
* override and default share the same prop shape — that's what the
|
|
30
|
+
* `WithDefault<P>` wrapper in {@link Slots} pins down.
|
|
31
|
+
*/
|
|
32
|
+
export const createSlot =
|
|
33
|
+
<K extends keyof Components>(
|
|
34
|
+
key: K,
|
|
35
|
+
Default: Component<t.Compute<Omit<Params<Components[K]>[0], 'Default'>>>,
|
|
36
|
+
): Component<t.Compute<Omit<Params<Components[K]>[0], 'Default'>>> =>
|
|
37
|
+
(props) => {
|
|
38
|
+
const slots = useComponents()
|
|
39
|
+
const override = createMemo(() => slots()[key] as Component<any> | undefined)
|
|
40
|
+
return (
|
|
41
|
+
<Show when={override()} fallback={<Default {...(props as any)} />} keyed>
|
|
42
|
+
{(Override) => <Dynamic component={Override} {...(props as any)} Default={Default} />}
|
|
43
|
+
</Show>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type Params<T> = T extends (...args: infer P) => any ? P : never
|
|
48
|
+
|
|
49
|
+
type WithDefault<P extends Record<string, any>> = P & { Default: Component<P> }
|
|
50
|
+
|
|
51
|
+
export type DeclarationProps<K extends keyof Types.DeclarationMap> = WithDefault<{
|
|
52
|
+
decl: Types.DeclarationMap[K]
|
|
53
|
+
}>
|
|
54
|
+
|
|
55
|
+
type PageProps = { decl: Types.Declaration; route: Types.RouteNode<'declaration' | 'module'> }
|
|
56
|
+
|
|
57
|
+
export type SlotComponent<K extends keyof Components> = Components[K]
|
|
58
|
+
/**
|
|
59
|
+
* Slot override signatures. Every slot receives `Default` typed to the
|
|
60
|
+
* stock component's props so the override can decorate (`<Default {...p} />`
|
|
61
|
+
* plus extras) instead of replacing wholesale.
|
|
62
|
+
*/
|
|
63
|
+
export interface Components {
|
|
64
|
+
home?: Component<WithDefault<{}>>
|
|
65
|
+
layout?: Component<WithDefault<{ children: JSX.Element }>>
|
|
66
|
+
header?: Component<WithDefault<{ onMenu?: () => void; onSearch?: () => void }>>
|
|
67
|
+
sidebar?: Component<WithDefault<{ onNavigate?: () => void; class?: string }>>
|
|
68
|
+
|
|
69
|
+
// Page slots
|
|
70
|
+
page?: Component<WithDefault<PageProps>>
|
|
71
|
+
'page.markdown'?: Component<WithDefault<{ route: Types.RouteNode<'markdown'> }>>
|
|
72
|
+
'page.header'?: Component<WithDefault<PageProps>>
|
|
73
|
+
'page.header.breadcrumb'?: Component<WithDefault<{ id: number }>>
|
|
74
|
+
'page.source'?: Component<WithDefault<{ sources?: Types.Source[] }>>
|
|
75
|
+
'page.references'?: Component<WithDefault<{ id: number }>>
|
|
76
|
+
|
|
77
|
+
// Declaration page slots
|
|
78
|
+
declaration?: Component<WithDefault<{ decl: Types.Declaration }>>
|
|
79
|
+
'declaration.function'?: Component<DeclarationProps<'function'>>
|
|
80
|
+
'declaration.variable'?: Component<DeclarationProps<'variable'>>
|
|
81
|
+
'declaration.type-alias'?: Component<DeclarationProps<'type-alias'>>
|
|
82
|
+
'declaration.class'?: Component<DeclarationProps<'class'>>
|
|
83
|
+
'declaration.interface'?: Component<DeclarationProps<'interface'>>
|
|
84
|
+
'declaration.enum'?: Component<DeclarationProps<'enum'>>
|
|
85
|
+
'declaration.module'?: Component<DeclarationProps<'module'>>
|
|
86
|
+
'declaration.namespace'?: Component<DeclarationProps<'namespace'>>
|
|
87
|
+
|
|
88
|
+
comment?: Component<WithDefault<{ comment?: Types.Comment; class?: string }>>
|
|
89
|
+
'comment.parameters'?: Component<WithDefault<{ tags: Types.CommentTagMap['@param'][] }>>
|
|
90
|
+
'comment.properties'?: Component<WithDefault<{ tags: Types.CommentTagMap['@property'][] }>>
|
|
91
|
+
|
|
92
|
+
tag?: Component<WithDefault<{ tag: Types.CommentTag }>>
|
|
93
|
+
'tag.returns'?: Component<WithDefault<{ tag: t.Compute<Types.CommentTagMap['@returns']> }>>
|
|
94
|
+
'tag.throws'?: Component<WithDefault<{ tag: Types.CommentTagMap['@throws'] }>>
|
|
95
|
+
'tag.type'?: Component<WithDefault<{ tag: Types.CommentTagMap['@type'] }>>
|
|
96
|
+
'tag.satisfies'?: Component<WithDefault<{ tag: Types.CommentTagMap['@satisfies'] }>>
|
|
97
|
+
'tag.example'?: Component<WithDefault<{ tag: Types.CommentTagMap['@example'] }>>
|
|
98
|
+
'tag.see'?: Component<WithDefault<{ tag: Types.CommentTagMap['@see'] }>>
|
|
99
|
+
'tag.template'?: Component<WithDefault<{ tag: Types.CommentTagMap['@template'] }>>
|
|
100
|
+
'tag.augments'?: Component<WithDefault<{ tag: Types.CommentTagMap['@augments'] }>>
|
|
101
|
+
'tag.implements'?: Component<WithDefault<{ tag: Types.CommentTagMap['@implements'] }>>
|
|
102
|
+
'tag.*'?: Component<WithDefault<{ tag: Types.CommentTag }>>
|
|
103
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createSignal, type Signal } from 'solid-js'
|
|
2
|
+
|
|
3
|
+
import type { Types } from '../context/index.ts'
|
|
4
|
+
import type { Components } from './components.tsx'
|
|
5
|
+
|
|
6
|
+
declare global {
|
|
7
|
+
interface Lickle {
|
|
8
|
+
components: Signal<Components>
|
|
9
|
+
json: Signal<Types.ProjectJson | null>
|
|
10
|
+
rendered: Signal<boolean>
|
|
11
|
+
}
|
|
12
|
+
interface Window {
|
|
13
|
+
lickle: Lickle
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (typeof window !== 'undefined') {
|
|
18
|
+
window.lickle = {
|
|
19
|
+
components: createSignal<Components>({}),
|
|
20
|
+
json: createSignal<Types.ProjectJson | null>(null),
|
|
21
|
+
rendered: createSignal<boolean>(false),
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const getComponents = () => window.lickle.components[0]()
|
|
26
|
+
export const setComponents = (components: Partial<Components>) =>
|
|
27
|
+
window.lickle.components[1]({ ...window.lickle.components[0](), ...components })
|
|
28
|
+
|
|
29
|
+
export const getJson = () => window.lickle.json[0]()
|
|
30
|
+
export const setJson = (json: Types.ProjectJson | null) => window.lickle.json[1](json)
|
|
31
|
+
|
|
32
|
+
export const getRendered = () => window.lickle.rendered[0]()
|
|
33
|
+
export const setRendered = (rendered: boolean) => window.lickle.rendered[1](rendered)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createContext, createMemo, createResource, useContext } from 'solid-js'
|
|
2
|
+
import type { JSX } from 'solid-js/jsx-runtime'
|
|
3
|
+
import type { Marked } from 'marked'
|
|
4
|
+
|
|
5
|
+
import { highlighter, type Highlighter, type CodeToHtmlOptions } from './shiki.ts'
|
|
6
|
+
import { useProject } from '../project/index.tsx'
|
|
7
|
+
import { buildMarked } from './markdown.ts'
|
|
8
|
+
|
|
9
|
+
export * from './util.ts'
|
|
10
|
+
|
|
11
|
+
export type { Highlighter, CodeToHtmlOptions }
|
|
12
|
+
|
|
13
|
+
const H = highlighter()
|
|
14
|
+
|
|
15
|
+
type MarkupContext = {
|
|
16
|
+
promise: Promise<Highlighter>
|
|
17
|
+
highlighter: () => Highlighter | undefined
|
|
18
|
+
marked: () => Marked | undefined
|
|
19
|
+
}
|
|
20
|
+
const Context = createContext<MarkupContext>()
|
|
21
|
+
|
|
22
|
+
export const MarkupProvider = (props: { children: JSX.Element }) => {
|
|
23
|
+
const project = useProject()
|
|
24
|
+
const lookup = (name: string) => project().routeByName(name)?.slug
|
|
25
|
+
const [h] = createResource(async () => await H)
|
|
26
|
+
const marked = createMemo(() => buildMarked(h(), lookup))
|
|
27
|
+
return <Context.Provider value={{ promise: H, highlighter: () => h(), marked }}>{props.children}</Context.Provider>
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const useMarkup = (): MarkupContext => {
|
|
31
|
+
const ctx = useContext(Context)
|
|
32
|
+
if (!ctx) throw new Error('useMarkup must be used within a <MarkupProvider>')
|
|
33
|
+
return ctx
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const useCodeToHtml = (p: { code: string; lang?: string; structure?: 'inline' | 'classic' }) => {
|
|
37
|
+
const markup = useMarkup()
|
|
38
|
+
return createMemo(() => markup.highlighter()?.codeToHtml({ ...p, text: p.code, markdown: true }))
|
|
39
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Marked } from 'marked'
|
|
2
|
+
|
|
3
|
+
import type { Highlighter } from './shiki.ts'
|
|
4
|
+
import { langOf } from './util.ts'
|
|
5
|
+
|
|
6
|
+
export const buildMarked = (h: Highlighter | undefined, lookup?: (raw: string) => string | undefined) => {
|
|
7
|
+
const m = new Marked({
|
|
8
|
+
gfm: true,
|
|
9
|
+
breaks: false,
|
|
10
|
+
renderer: {
|
|
11
|
+
code({ text, lang }) {
|
|
12
|
+
const language = langOf(lang)
|
|
13
|
+
if (h && language !== 'text') {
|
|
14
|
+
try {
|
|
15
|
+
return h.codeToHtml({ text, lang: language })
|
|
16
|
+
} catch {
|
|
17
|
+
/* fall through */
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return `<pre class="codeblock"><code>${escape(text)}</code></pre>`
|
|
21
|
+
},
|
|
22
|
+
codespan({ text }) {
|
|
23
|
+
if (lookup && ID.test(text)) {
|
|
24
|
+
const slug = lookup(text)
|
|
25
|
+
if (slug) return `<a href="/${slug}" class="codelink"><code>${text}</code></a>`
|
|
26
|
+
}
|
|
27
|
+
return `<code>${text}</code>`
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
return m
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const escape = (s: string) =>
|
|
35
|
+
s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')
|
|
36
|
+
|
|
37
|
+
const ID = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { HighlighterCore } from 'shiki/core'
|
|
2
|
+
|
|
3
|
+
import { extractCodeBlocks } from './util.ts'
|
|
4
|
+
|
|
5
|
+
export type CodeToHtmlOptions = {
|
|
6
|
+
text: string
|
|
7
|
+
lang?: string
|
|
8
|
+
structure?: 'inline' | 'classic'
|
|
9
|
+
markdown?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type Highlighter = { codeToHtml: (options: CodeToHtmlOptions) => string }
|
|
13
|
+
|
|
14
|
+
export const highlighter = async (): Promise<Highlighter> => {
|
|
15
|
+
const h = await getHighlighter()
|
|
16
|
+
const codeToHtml = (options: CodeToHtmlOptions) => {
|
|
17
|
+
const opts = {
|
|
18
|
+
lang: options.lang ?? 'ts',
|
|
19
|
+
themes: { light: 'github-light', dark: 'github-dark' },
|
|
20
|
+
defaultColor: false,
|
|
21
|
+
structure: options.structure,
|
|
22
|
+
} as const
|
|
23
|
+
|
|
24
|
+
if (options.markdown) {
|
|
25
|
+
const extracted = extractCodeBlocks(options.text)?.[0]
|
|
26
|
+
if (extracted) {
|
|
27
|
+
if (!h || !extracted) return ''
|
|
28
|
+
const text = extracted.code ?? options.text
|
|
29
|
+
const lang = extracted.lang ?? options.lang ?? 'ts'
|
|
30
|
+
return h.codeToHtml(text, { ...opts, lang: lang })
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return h.codeToHtml(options.text, opts)
|
|
34
|
+
}
|
|
35
|
+
return { codeToHtml }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Fine-grained Shiki bundle: only the langs/themes below are emitted as chunks.
|
|
40
|
+
* Importing the default `shiki` entry would code-split every grammar and theme.
|
|
41
|
+
*/
|
|
42
|
+
export const getHighlighter = (): Promise<HighlighterCore> => {
|
|
43
|
+
if (!highlighterPromise) highlighterPromise = buildHighlighter()
|
|
44
|
+
return highlighterPromise
|
|
45
|
+
}
|
|
46
|
+
let highlighterPromise: Promise<HighlighterCore> | null = null
|
|
47
|
+
|
|
48
|
+
const buildHighlighter = (): Promise<HighlighterCore> => {
|
|
49
|
+
return Promise.all([
|
|
50
|
+
import('shiki/core'),
|
|
51
|
+
import('shiki/engine/javascript'),
|
|
52
|
+
import('shiki/themes/github-light.mjs'),
|
|
53
|
+
import('shiki/themes/github-dark.mjs'),
|
|
54
|
+
Promise.all([
|
|
55
|
+
import('shiki/langs/typescript.mjs'),
|
|
56
|
+
import('shiki/langs/tsx.mjs'),
|
|
57
|
+
import('shiki/langs/javascript.mjs'),
|
|
58
|
+
import('shiki/langs/jsx.mjs'),
|
|
59
|
+
import('shiki/langs/json.mjs'),
|
|
60
|
+
import('shiki/langs/bash.mjs'),
|
|
61
|
+
import('shiki/langs/html.mjs'),
|
|
62
|
+
import('shiki/langs/css.mjs'),
|
|
63
|
+
import('shiki/langs/markdown.mjs'),
|
|
64
|
+
]),
|
|
65
|
+
]).then(([core, js, light, dark, langs]) =>
|
|
66
|
+
core.createHighlighterCore({
|
|
67
|
+
engine: js.createJavaScriptRegexEngine(),
|
|
68
|
+
themes: [light.default, dark.default],
|
|
69
|
+
langs: langs.map((m) => m.default),
|
|
70
|
+
}),
|
|
71
|
+
)
|
|
72
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const CODE_BLOCK_RE = /```([^\n]*)\n([\s\S]*?)```/g
|
|
2
|
+
export const extractCodeBlocks = (input: string): { lang: string; code: string }[] => [
|
|
3
|
+
...(input?.matchAll(CODE_BLOCK_RE)?.map((m) => ({ lang: m[1]!, code: m[2]! })) ?? []),
|
|
4
|
+
]
|
|
5
|
+
|
|
6
|
+
export const firstCodeBlock = (input: string): { lang: string; code: string } =>
|
|
7
|
+
extractCodeBlocks(input)?.[0] ?? { lang: '', code: input }
|
|
8
|
+
|
|
9
|
+
export const getUnfencedCode = (code: string) => firstCodeBlock(code).code
|
|
10
|
+
|
|
11
|
+
const LANGS = ['ts', 'tsx', 'js', 'jsx', 'json', 'bash', 'html', 'css', 'md']
|
|
12
|
+
export const langOf = (info: string | undefined) => {
|
|
13
|
+
const raw = (info ?? '').trim().split(/\s+/)[0]?.toLowerCase() ?? ''
|
|
14
|
+
if (!raw) return 'text'
|
|
15
|
+
if (LANGS.includes(raw)) return raw
|
|
16
|
+
if (raw === 'sh' || raw === 'zsh') return 'bash'
|
|
17
|
+
if (raw === 'typescript') return 'ts'
|
|
18
|
+
if (raw === 'javascript') return 'js'
|
|
19
|
+
return 'text'
|
|
20
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createContext, createMemo, useContext, type Accessor } from 'solid-js'
|
|
2
|
+
import type { JSX } from 'solid-js/jsx-runtime'
|
|
3
|
+
|
|
4
|
+
import type { ProjectJson } from './types.ts'
|
|
5
|
+
|
|
6
|
+
import { ComponentsProvider, type Components } from '../components.tsx'
|
|
7
|
+
import { createProject } from './indexed.ts'
|
|
8
|
+
|
|
9
|
+
import * as T from './types.ts'
|
|
10
|
+
export * as Types from './types.ts'
|
|
11
|
+
|
|
12
|
+
const ProjectCtx = createContext<Accessor<T.Project>>()
|
|
13
|
+
|
|
14
|
+
export type ProjectProviderProps = {
|
|
15
|
+
children: JSX.Element
|
|
16
|
+
json: Accessor<ProjectJson>
|
|
17
|
+
/** Component overrides — pages, tags, slots, member sections. */
|
|
18
|
+
components?: Components
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const ProjectProvider = (props: ProjectProviderProps) => {
|
|
22
|
+
const bag = createMemo<T.Project>(() => createProject(props.json()))
|
|
23
|
+
return (
|
|
24
|
+
<ComponentsProvider value={props.components}>
|
|
25
|
+
<ProjectCtx.Provider value={bag}>{props.children}</ProjectCtx.Provider>
|
|
26
|
+
</ComponentsProvider>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const useProject = (): Accessor<T.Project> => {
|
|
31
|
+
const fn = useContext(ProjectCtx)
|
|
32
|
+
if (!fn) throw new Error('useProject must be used within <ProjectProvider>')
|
|
33
|
+
return fn
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const DeclarationIdContext = createContext<Accessor<number | undefined>>(() => undefined)
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Scope a subtree to a reflection id so nested `<Comment>`s pass it to tag
|
|
40
|
+
* handlers. The id is exposed as a reactive accessor so consumers re-track
|
|
41
|
+
* when the surrounding route swaps to a new declaration.
|
|
42
|
+
*/
|
|
43
|
+
export const DeclarationScope = (props: { id: number; children: JSX.Element }) => (
|
|
44
|
+
<DeclarationIdContext.Provider value={() => props.id}>{props.children}</DeclarationIdContext.Provider>
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
export const useDeclarationId = (): Accessor<number | undefined> => useContext(DeclarationIdContext)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ProjectJson, RouteNode } from '../../../core/project/index.ts'
|
|
2
|
+
import * as Types from './types.ts'
|
|
3
|
+
|
|
4
|
+
export const createProject = (json: ProjectJson): Types.Project => {
|
|
5
|
+
const _byId = new Map<number, Types.Declaration>()
|
|
6
|
+
const _bySlug = new Map<string, Types.Declaration>()
|
|
7
|
+
const _routesById = new Map<number, RouteNode>()
|
|
8
|
+
const _routesBySlug = new Map<string, RouteNode>()
|
|
9
|
+
const _slugByName = new Map<string, RouteNode>()
|
|
10
|
+
|
|
11
|
+
const sourceLink = (src: Types.Source) => {
|
|
12
|
+
if (!json.repository?.fileUrl) return undefined
|
|
13
|
+
return json.repository.fileUrl.replace('{PATH}', src.file).replace('{LINE}', src.line.toString())
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
for (const declaration of json.declarations) {
|
|
17
|
+
_byId.set(declaration.id, declaration)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const indexRoute = (r: RouteNode) => {
|
|
21
|
+
_routesBySlug.set(r.slug, r)
|
|
22
|
+
// Markdown pages carry no declaration id, so they only resolve by slug.
|
|
23
|
+
if (r.page.kind !== 'markdown') {
|
|
24
|
+
_bySlug.set(r.slug, _byId.get(r.page.id)!)
|
|
25
|
+
_routesById.set(r.page.id, r)
|
|
26
|
+
const name = _byId.get(r.page.id)?.name
|
|
27
|
+
if (name && !_slugByName.has(name)) _slugByName.set(name, r)
|
|
28
|
+
_slugByName.set(r.page.qualified, r)
|
|
29
|
+
}
|
|
30
|
+
for (const child of r.children) indexRoute(child)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (const route of json.routes) indexRoute(route)
|
|
34
|
+
|
|
35
|
+
const byId = (id: number): Types.Declaration | undefined => _byId.get(id)
|
|
36
|
+
const bySlug = (slug: string): Types.Declaration | undefined => _bySlug.get(slug)
|
|
37
|
+
const routeForId = (id: number): RouteNode | undefined => _routesById.get(id)
|
|
38
|
+
const routeForSlug = (slug: string): RouteNode | undefined => _routesBySlug.get(slug)
|
|
39
|
+
const routeByName = (name: string): RouteNode | undefined => _slugByName.get(name)
|
|
40
|
+
const p: Types.Project = json as Types.Project
|
|
41
|
+
|
|
42
|
+
hide(p, 'byId', byId)
|
|
43
|
+
hide(p, 'bySlug', bySlug)
|
|
44
|
+
hide(p, 'routeForId', routeForId)
|
|
45
|
+
hide(p, 'routeForSlug', routeForSlug)
|
|
46
|
+
hide(p, 'routeByName', routeByName)
|
|
47
|
+
hide(p, 'sourceLink', sourceLink)
|
|
48
|
+
return p
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const hide = <T, K extends keyof T>(obj: T, key: K, value: T[K]) =>
|
|
52
|
+
Object.defineProperty(obj, key, { value, enumerable: false, configurable: true })
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ProjectJson, RouteNode } from '../../../core/project/types.ts'
|
|
2
|
+
import type { Declaration, Source } from '../../../core/reflect/types.ts'
|
|
3
|
+
|
|
4
|
+
export interface Project extends ProjectJson {
|
|
5
|
+
byId(id: number): Declaration | undefined
|
|
6
|
+
bySlug(slug: string): Declaration | undefined
|
|
7
|
+
routeByName(name: string): RouteNode | undefined
|
|
8
|
+
routeForId(id: number): RouteNode | undefined
|
|
9
|
+
routeForSlug(slug: string): RouteNode | undefined
|
|
10
|
+
sourceLink(src: Source): string | undefined
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type * from '../../../core/project/types.ts'
|
|
14
|
+
export type * from '../../../core/reflect/types.ts'
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createContext, createSignal, onMount, useContext } from 'solid-js'
|
|
2
|
+
import type { JSX } from 'solid-js/jsx-runtime'
|
|
3
|
+
|
|
4
|
+
export type ThemeMode = 'light' | 'dark' | 'system'
|
|
5
|
+
const STORAGE_KEY = 'lickle-docs-theme'
|
|
6
|
+
|
|
7
|
+
type ThemeCtx = {
|
|
8
|
+
mode: () => ThemeMode
|
|
9
|
+
setMode: (m: ThemeMode) => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Ctx = createContext<ThemeCtx>()
|
|
13
|
+
|
|
14
|
+
const read = (): ThemeMode => {
|
|
15
|
+
if (typeof localStorage === 'undefined') return 'system'
|
|
16
|
+
const v = localStorage.getItem(STORAGE_KEY)
|
|
17
|
+
return v === 'light' || v === 'dark' ? v : 'system'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const apply = (m: ThemeMode) => {
|
|
21
|
+
const el = document.documentElement
|
|
22
|
+
if (m === 'system') delete el.dataset['theme']
|
|
23
|
+
else el.dataset['theme'] = m
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const ThemeProvider = (props: { children: JSX.Element }) => {
|
|
27
|
+
const [mode, set] = createSignal<ThemeMode>(read())
|
|
28
|
+
|
|
29
|
+
onMount(() => apply(mode()))
|
|
30
|
+
|
|
31
|
+
const setMode = (m: ThemeMode) => {
|
|
32
|
+
if (m === 'system') localStorage.removeItem(STORAGE_KEY)
|
|
33
|
+
else localStorage.setItem(STORAGE_KEY, m)
|
|
34
|
+
set(m)
|
|
35
|
+
apply(m)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return <Ctx.Provider value={{ mode, setMode }}>{props.children}</Ctx.Provider>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const useTheme = (): ThemeCtx => {
|
|
42
|
+
const ctx = useContext(Ctx)
|
|
43
|
+
if (!ctx) throw new Error('useTheme must be used within a <ThemeProvider>')
|
|
44
|
+
return ctx
|
|
45
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { createMemo, type Accessor } from 'solid-js'
|
|
2
|
+
|
|
3
|
+
import { createSearchEngine, type SearchEngine } from '../util/search.ts'
|
|
4
|
+
import { useProject, type Types } from '../context/index.ts'
|
|
5
|
+
import { commentSummaryText } from '../util/comment.ts'
|
|
6
|
+
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// SELECTOR HOOKS
|
|
9
|
+
// Thin readers over the project bag. Components should reach for these instead
|
|
10
|
+
// of pulling `project` apart directly.
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Slug accessors keyed two ways. `byId` is the id-driven path used by render
|
|
15
|
+
* code; `byName` powers `{@link Foo}` / `<code>Foo</code>` resolution (short
|
|
16
|
+
* names and qualified names both resolve via the project's name index).
|
|
17
|
+
*/
|
|
18
|
+
export const useSlugFor = () => {
|
|
19
|
+
const project = useProject()
|
|
20
|
+
return {
|
|
21
|
+
byId: (id: number): string | undefined => project().routeForId(id)?.slug,
|
|
22
|
+
byName: (name: string): string | undefined => project().routeByName(name)?.slug,
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// REFERENCES
|
|
28
|
+
// "Used in" rows, materialized from each page's `referencedIn` id list.
|
|
29
|
+
// ============================================================================
|
|
30
|
+
|
|
31
|
+
export interface ReferenceRow {
|
|
32
|
+
decl: Types.Declaration
|
|
33
|
+
slug: string
|
|
34
|
+
/** Everything before the final dot of the qualified name. Empty for top-level symbols. */
|
|
35
|
+
module: string
|
|
36
|
+
name: string
|
|
37
|
+
qualified: string
|
|
38
|
+
summary: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const useReferences = (id: () => number): Accessor<ReferenceRow[]> => {
|
|
42
|
+
const project = useProject()
|
|
43
|
+
return createMemo(() => buildReferenceRows(project(), id()))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const buildReferenceRows = (project: Types.Project, id: number): ReferenceRow[] => {
|
|
47
|
+
const route = project.routeForId(id)
|
|
48
|
+
if (!route || route.page.kind === 'markdown') return []
|
|
49
|
+
|
|
50
|
+
const seen = new Set<number>()
|
|
51
|
+
const out: ReferenceRow[] = []
|
|
52
|
+
for (const refId of route.page.referencedIn) {
|
|
53
|
+
if (refId === id || seen.has(refId)) continue
|
|
54
|
+
seen.add(refId)
|
|
55
|
+
const refRoute = project.routeForId(refId)
|
|
56
|
+
const decl = project.byId(refId)
|
|
57
|
+
if (!refRoute || refRoute.page.kind === 'markdown' || !decl) continue
|
|
58
|
+
const qualified = refRoute.page.qualified
|
|
59
|
+
const dot = qualified.lastIndexOf('.')
|
|
60
|
+
out.push({
|
|
61
|
+
decl,
|
|
62
|
+
slug: refRoute.slug,
|
|
63
|
+
module: dot < 0 ? '' : qualified.slice(0, dot),
|
|
64
|
+
name: dot < 0 ? qualified : qualified.slice(dot + 1),
|
|
65
|
+
qualified,
|
|
66
|
+
summary: commentSummaryText(decl.comment),
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
return out.sort((a, b) => a.qualified.localeCompare(b.qualified))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// SEARCH
|
|
74
|
+
// `createSearchEngine` is async (Orama indexing). Cached per project so the
|
|
75
|
+
// palette pays the cost once per session, even if it opens and closes.
|
|
76
|
+
// ============================================================================
|
|
77
|
+
|
|
78
|
+
const searchCache = new WeakMap<object, Promise<SearchEngine>>()
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Returns a thunk that builds (or returns the cached) search engine for the
|
|
82
|
+
* current project. Callers wrap the thunk in their own resource/effect.
|
|
83
|
+
*/
|
|
84
|
+
export const useSearch = (): (() => Promise<SearchEngine>) => {
|
|
85
|
+
const project = useProject()
|
|
86
|
+
return () => buildSearch(project())
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const buildSearch = (project: Types.Project): Promise<SearchEngine> => {
|
|
90
|
+
const cached = searchCache.get(project)
|
|
91
|
+
if (cached) return cached
|
|
92
|
+
const p = createSearchEngine(project)
|
|
93
|
+
searchCache.set(project, p)
|
|
94
|
+
return p
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export const useCommentMarkdown = (comment: () => Types.Comment) => {
|
|
98
|
+
const slugs = useSlugFor()
|
|
99
|
+
const slugOf = (name: string) => slugs.byName(name)
|
|
100
|
+
return createMemo(() => commentToMarkdown(comment(), slugOf))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const commentToMarkdown = (comment: Types.Comment, slugOf: (name: string) => string | undefined): string => {
|
|
104
|
+
let out = ''
|
|
105
|
+
for (const p of comment.parts) {
|
|
106
|
+
if (p.kind === 'text') {
|
|
107
|
+
out += p.text
|
|
108
|
+
continue
|
|
109
|
+
}
|
|
110
|
+
const label = p.text ?? p.target
|
|
111
|
+
const slug = slugOf(p.target)
|
|
112
|
+
const display = p.style === 'code' ? `\`${label}\`` : label
|
|
113
|
+
out += slug ? `[${display}](/${slug})` : display
|
|
114
|
+
}
|
|
115
|
+
return out
|
|
116
|
+
}
|
package/src/ui/index.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createMemo, type Accessor } from 'solid-js'
|
|
2
|
+
import { render } from 'solid-js/web'
|
|
3
|
+
|
|
4
|
+
import type { Components } from './context/components.tsx'
|
|
5
|
+
import { App } from './App.tsx'
|
|
6
|
+
|
|
7
|
+
import { getJson, getComponents, setComponents } from './context/global.ts'
|
|
8
|
+
import type { Types } from './context/index.ts'
|
|
9
|
+
|
|
10
|
+
export const renderApp = (props?: {
|
|
11
|
+
json?: Accessor<Types.ProjectJson | null> | Types.ProjectJson | null
|
|
12
|
+
components?: Accessor<Components> | Components
|
|
13
|
+
root?: HTMLElement
|
|
14
|
+
}) => {
|
|
15
|
+
const json = createMemo(() => {
|
|
16
|
+
const j = typeof props?.json === 'function' ? props?.json() : (props?.json ?? null)
|
|
17
|
+
if (!j) return getJson()
|
|
18
|
+
return j
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const components = createMemo(() => {
|
|
22
|
+
const c = typeof props?.components === 'function' ? props?.components() : (props?.components ?? null)
|
|
23
|
+
if (!c) return getComponents()
|
|
24
|
+
return c
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
render(() => <App json={json} components={components} />, props?.root ?? document.getElementById('root')!)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const registerComponent = <K extends keyof Components>(key: K, Component: Components[K]) =>
|
|
31
|
+
setComponents({ [key]: Component })
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Types } from '../context/index.ts'
|
|
2
|
+
|
|
3
|
+
/** Single-line plain-text preview of a comment. Used by listings/cards. */
|
|
4
|
+
export const commentSummaryText = (comment: Types.Comment | undefined): string => {
|
|
5
|
+
if (!comment) return ''
|
|
6
|
+
let out = ''
|
|
7
|
+
for (const p of comment.parts) {
|
|
8
|
+
if (p.kind === 'text') out += p.text
|
|
9
|
+
else out += p.text ?? p.target
|
|
10
|
+
}
|
|
11
|
+
return out.trim()
|
|
12
|
+
}
|