@clidey/dory 0.29.0 → 0.31.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/bin/dist/dory.js +108 -29
- package/bin/dist/dory.js.map +1 -1
- package/package.json +20 -4
- package/src/components/hooks.tsx +8 -0
- package/src/components/search.tsx +17 -4
- package/src/embed/loader.ts +200 -0
- package/src/embed/types.ts +54 -0
- package/src/embed/widget-iframe.ts +302 -0
- package/src/plugins/html-files-middleware.ts +108 -0
- package/src/sdk/index.ts +89 -0
- package/src/sdk/react.tsx +139 -0
- package/src/sdk/vue.ts +107 -0
- package/src/types/config.ts +42 -0
- package/src/ui/header.tsx +6 -1
- package/src/ui/layout.tsx +16 -5
- package/src/ui/mobile-navigation.tsx +11 -3
- package/src/ui/table-of-content.tsx +2 -1
- package/tsconfig.bin.json +1 -0
- package/vite.config.embed-loader.ts +28 -0
- package/vite.config.embed-widget.ts +31 -0
- package/vite.config.ts +2 -0
- package/.dockerignore +0 -4
- package/CLAUDE.md +0 -178
- package/CODE_OF_CONDUCT.md +0 -128
- package/CONTRIBUTING.md +0 -91
- package/SECURITY.md +0 -11
- package/bin/dory.ts +0 -433
- package/dist/favicon.svg +0 -75
- package/dist/frontmatter.json +0 -77
- package/dist/index.html +0 -55
- package/dist/llms.txt +0 -561
- package/dist/logo/logo.svg +0 -18
- package/docs/api-playground-demo.mdx +0 -119
- package/docs/api-reference/asyncapi.json +0 -324
- package/docs/api-reference/openapi.json +0 -366
- package/docs/api-reference/operations/create.mdx +0 -5
- package/docs/api-reference/operations/delete.mdx +0 -5
- package/docs/api-reference/operations/get.mdx +0 -5
- package/docs/api-reference/operations/update.mdx +0 -5
- package/docs/api-reference/websocket-operations/receive-chat-message.mdx +0 -5
- package/docs/api-reference/websocket-operations/receive-notifications.mdx +0 -5
- package/docs/api-reference/websocket-operations/receive-presence-update.mdx +0 -5
- package/docs/api-reference/websocket-operations/send-chat-message.mdx +0 -5
- package/docs/api-reference/websocket-operations/send-presence-update.mdx +0 -5
- package/docs/dory.json +0 -64
- package/docs/favicon.svg +0 -75
- package/docs/features.mdx +0 -440
- package/docs/introduction.mdx +0 -44
- package/docs/logo/logo.svg +0 -18
- package/docs/websocket-playground-demo.mdx +0 -135
- package/scripts/generate-frontmatter-json.js +0 -154
- package/scripts/generate-llm-txt.js +0 -115
package/src/sdk/vue.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vue SDK for Dory Embedded Documentation
|
|
3
|
+
* Usage: npm install @clidey/dory-embedded
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// @ts-ignore - Vue is an optional peer dependency
|
|
7
|
+
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
|
8
|
+
import type { DoryDocsAPI } from '../embed/types';
|
|
9
|
+
|
|
10
|
+
interface DoryDocsConfig {
|
|
11
|
+
docsUrl: string;
|
|
12
|
+
position?: 'left' | 'right' | 'bottom';
|
|
13
|
+
width?: number | string;
|
|
14
|
+
height?: string;
|
|
15
|
+
theme?: 'light' | 'dark' | 'inherit';
|
|
16
|
+
initialPath?: string;
|
|
17
|
+
showOverlay?: boolean;
|
|
18
|
+
closeOnEscape?: boolean;
|
|
19
|
+
closeOnOverlayClick?: boolean;
|
|
20
|
+
onOpen?: () => void;
|
|
21
|
+
onClose?: () => void;
|
|
22
|
+
onNavigate?: (path: string) => void;
|
|
23
|
+
onReady?: () => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Composable to use Dory Documentation in Vue components
|
|
28
|
+
*/
|
|
29
|
+
export function useDoryDocs(config: DoryDocsConfig) {
|
|
30
|
+
const docsInstance = ref<any>(null);
|
|
31
|
+
const isReady = ref(false);
|
|
32
|
+
|
|
33
|
+
const initDocs = () => {
|
|
34
|
+
if (window.DoryDocs) {
|
|
35
|
+
docsInstance.value = window.DoryDocs.init(config);
|
|
36
|
+
isReady.value = true;
|
|
37
|
+
} else {
|
|
38
|
+
console.warn('[useDoryDocs] DoryDocs not loaded. Make sure to include the embed script.');
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
onMounted(() => {
|
|
43
|
+
if (document.readyState === 'loading') {
|
|
44
|
+
window.addEventListener('dory:ready', initDocs);
|
|
45
|
+
} else {
|
|
46
|
+
initDocs();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
onUnmounted(() => {
|
|
51
|
+
window.removeEventListener('dory:ready', initDocs);
|
|
52
|
+
if (docsInstance.value) {
|
|
53
|
+
docsInstance.value.destroy();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const open = async (path?: string) => {
|
|
58
|
+
if (docsInstance.value) {
|
|
59
|
+
await docsInstance.value.open(path);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const close = async () => {
|
|
64
|
+
if (docsInstance.value) {
|
|
65
|
+
await docsInstance.value.close();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const toggle = async () => {
|
|
70
|
+
if (docsInstance.value) {
|
|
71
|
+
await docsInstance.value.toggle();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const navigate = async (path: string) => {
|
|
76
|
+
if (docsInstance.value) {
|
|
77
|
+
await docsInstance.value.navigate(path);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const setTheme = async (theme: 'light' | 'dark') => {
|
|
82
|
+
if (docsInstance.value) {
|
|
83
|
+
await docsInstance.value.setTheme(theme);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const isOpen = computed(() => {
|
|
88
|
+
return docsInstance.value?.isOpen() || false;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
open,
|
|
93
|
+
close,
|
|
94
|
+
toggle,
|
|
95
|
+
navigate,
|
|
96
|
+
setTheme,
|
|
97
|
+
isOpen: isOpen.value,
|
|
98
|
+
isReady,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Type declarations
|
|
103
|
+
declare global {
|
|
104
|
+
interface Window {
|
|
105
|
+
DoryDocs: DoryDocsAPI;
|
|
106
|
+
}
|
|
107
|
+
}
|
package/src/types/config.ts
CHANGED
|
@@ -37,6 +37,47 @@ export interface DoryNavigation {
|
|
|
37
37
|
tabs: DoryNavigationTab[];
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
export interface DoryEmbedConfig {
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
version?: string;
|
|
43
|
+
defaults?: {
|
|
44
|
+
position?: 'left' | 'right' | 'bottom';
|
|
45
|
+
width?: number;
|
|
46
|
+
height?: string;
|
|
47
|
+
theme?: 'light' | 'dark' | 'inherit';
|
|
48
|
+
showOverlay?: boolean;
|
|
49
|
+
closeOnEscape?: boolean;
|
|
50
|
+
closeOnOverlayClick?: boolean;
|
|
51
|
+
};
|
|
52
|
+
branding?: {
|
|
53
|
+
showLogo?: boolean;
|
|
54
|
+
showName?: boolean;
|
|
55
|
+
customCSS?: string;
|
|
56
|
+
};
|
|
57
|
+
features?: {
|
|
58
|
+
search?: boolean;
|
|
59
|
+
toc?: boolean;
|
|
60
|
+
codeBlocks?: boolean;
|
|
61
|
+
mermaid?: boolean;
|
|
62
|
+
katex?: boolean;
|
|
63
|
+
apiPlayground?: boolean;
|
|
64
|
+
darkMode?: boolean;
|
|
65
|
+
};
|
|
66
|
+
analytics?: {
|
|
67
|
+
enabled?: boolean;
|
|
68
|
+
trackEvents?: string[];
|
|
69
|
+
};
|
|
70
|
+
security?: {
|
|
71
|
+
allowedOrigins?: string[];
|
|
72
|
+
corsEnabled?: boolean;
|
|
73
|
+
};
|
|
74
|
+
performance?: {
|
|
75
|
+
lazyLoadImages?: boolean;
|
|
76
|
+
prefetchPages?: boolean;
|
|
77
|
+
cacheStrategy?: 'cache-first' | 'network-first';
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
40
81
|
export interface DoryConfig {
|
|
41
82
|
name: string;
|
|
42
83
|
favicon: string;
|
|
@@ -44,4 +85,5 @@ export interface DoryConfig {
|
|
|
44
85
|
fonts?: DoryFonts;
|
|
45
86
|
navigation: DoryNavigation;
|
|
46
87
|
logo: DoryLogo;
|
|
88
|
+
embed?: DoryEmbedConfig;
|
|
47
89
|
}
|
package/src/ui/header.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { MobileSearch, Search } from '../components/search';
|
|
|
8
8
|
import { ALL_NAVIGATION } from '../components/store';
|
|
9
9
|
import { MobileNavigation } from './mobile-navigation';
|
|
10
10
|
import { ModeToggle } from '@clidey/ux';
|
|
11
|
+
import { useIsEmbedded } from '../components/hooks';
|
|
11
12
|
|
|
12
13
|
const config = docsConfig as DoryConfig;
|
|
13
14
|
|
|
@@ -32,6 +33,7 @@ function TopLevelNavItem({ href, children, isActive }: { href: string; children:
|
|
|
32
33
|
export function Header({ className }: { className?: string }) {
|
|
33
34
|
const [isScrolled, setIsScrolled] = useState(false);
|
|
34
35
|
const pathname = usePathname();
|
|
36
|
+
const isEmbedded = useIsEmbedded();
|
|
35
37
|
|
|
36
38
|
const { light, dark } = useMemo(() => {
|
|
37
39
|
return { light: config.logo.light, dark: config.logo.dark };
|
|
@@ -82,7 +84,10 @@ export function Header({ className }: { className?: string }) {
|
|
|
82
84
|
<div className="flex items-center gap-3" data-testid="header-actions">
|
|
83
85
|
<MobileSearch />
|
|
84
86
|
<Search />
|
|
85
|
-
|
|
87
|
+
{
|
|
88
|
+
!isEmbedded &&
|
|
89
|
+
<ModeToggle data-testid="mode-toggle" />
|
|
90
|
+
}
|
|
86
91
|
<MobileNavigation />
|
|
87
92
|
</div>
|
|
88
93
|
</div>
|
package/src/ui/layout.tsx
CHANGED
|
@@ -12,6 +12,8 @@ import { Loading } from '../components/loading';
|
|
|
12
12
|
import Dropdown from '../components/dropdown';
|
|
13
13
|
import { useNotification } from '../components/notification';
|
|
14
14
|
import { SparkleIcon } from 'lucide-react';
|
|
15
|
+
import { useIsEmbedded } from '../components/hooks';
|
|
16
|
+
import { cn } from '@clidey/ux';
|
|
15
17
|
|
|
16
18
|
interface LayoutProps {
|
|
17
19
|
children: ComponentChildren;
|
|
@@ -25,6 +27,7 @@ export default function Layout({ children }: LayoutProps) {
|
|
|
25
27
|
const [loading, setLoading] = useState(true);
|
|
26
28
|
const [pathname] = useLocation();
|
|
27
29
|
const { showNotification } = useNotification();
|
|
30
|
+
const isEmbedded = useIsEmbedded();
|
|
28
31
|
|
|
29
32
|
const handleOpenMDX = useCallback(() => {
|
|
30
33
|
window.open(`${window.location.origin}${pathname}.mdx`, '_blank');
|
|
@@ -178,13 +181,21 @@ export default function Layout({ children }: LayoutProps) {
|
|
|
178
181
|
return (
|
|
179
182
|
<div className="flex w-full flex-col">
|
|
180
183
|
<Header />
|
|
181
|
-
<div id="container" className="relative flex w-full
|
|
182
|
-
|
|
184
|
+
<div id="container" className={cn("relative flex w-full", {
|
|
185
|
+
"max-w-8xl sm:px-2 lg:px-8": !isEmbedded,
|
|
186
|
+
"px-0": isEmbedded,
|
|
187
|
+
})}>
|
|
188
|
+
<div className={cn("hidden lg:relative lg:block lg:flex-none", {
|
|
189
|
+
"lg:hidden": isEmbedded,
|
|
190
|
+
})}>
|
|
183
191
|
<div className="sticky top-[4.75rem] -ml-0.5 h-[calc(100vh-4.75rem)] w-64 overflow-x-hidden overflow-y-auto py-16 pr-8 pl-0.5 xl:w-72 xl:pr-16">
|
|
184
192
|
<Navigation />
|
|
185
193
|
</div>
|
|
186
194
|
</div>
|
|
187
|
-
<main className="flex
|
|
195
|
+
<main className={cn("flex grow max-w-full", {
|
|
196
|
+
"px-4 py-16 sm:px-6 lg:px-8": !isEmbedded,
|
|
197
|
+
"p-8": isEmbedded,
|
|
198
|
+
})}>
|
|
188
199
|
<div className="min-w-0 w-full">
|
|
189
200
|
<article className="h-full flex flex-1 flex-col">
|
|
190
201
|
<div className="flex justify-between items-start">
|
|
@@ -206,7 +217,7 @@ export default function Layout({ children }: LayoutProps) {
|
|
|
206
217
|
}
|
|
207
218
|
</div>
|
|
208
219
|
<div className="flex-1 min-h-[calc(100vh-2rem)]">
|
|
209
|
-
{openAPIJSON && tab && "openapi" in tab && method && path ?
|
|
220
|
+
{openAPIJSON && tab && "openapi" in tab && method && path ?
|
|
210
221
|
<OpenAPI openAPIJson={JSON.parse(openAPIJSON)} method={method} path={path} />
|
|
211
222
|
: asyncAPIJSON && tab && "asyncapi" in tab && operation && channel ?
|
|
212
223
|
<AsyncAPI asyncAPIJson={JSON.parse(asyncAPIJSON)} operation={operation} channel={channel} />
|
|
@@ -216,7 +227,7 @@ export default function Layout({ children }: LayoutProps) {
|
|
|
216
227
|
</article>
|
|
217
228
|
</div>
|
|
218
229
|
{
|
|
219
|
-
openAPIJSON == null && asyncAPIJSON == null &&
|
|
230
|
+
openAPIJSON == null && asyncAPIJSON == null && !isEmbedded &&
|
|
220
231
|
<TableOfContents />
|
|
221
232
|
}
|
|
222
233
|
</main>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import { Sheet, SheetContent, Button } from '@clidey/ux'
|
|
3
|
+
import { Sheet, SheetContent, Button, ModeToggle } from '@clidey/ux'
|
|
4
4
|
import { createContext, Suspense, useCallback, useContext, useRef, useState } from 'react'
|
|
5
5
|
|
|
6
6
|
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
|
|
7
7
|
import { Navigation } from '../components/navigation'
|
|
8
|
+
import { useIsEmbedded } from '../components/hooks'
|
|
8
9
|
|
|
9
10
|
const IsInsideMobileNavigationContext = createContext(false)
|
|
10
11
|
|
|
@@ -31,9 +32,10 @@ export function useMobileNavigation() {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export function MobileNavigation() {
|
|
34
|
-
const isInsideMobileNavigation = useIsInsideMobileNavigation()
|
|
35
|
-
const { isOpen, open, close } = useMobileNavigation()
|
|
35
|
+
const isInsideMobileNavigation = useIsInsideMobileNavigation();
|
|
36
|
+
const { isOpen, open, close } = useMobileNavigation();
|
|
36
37
|
const ToggleIcon = isOpen ? XMarkIcon : Bars3Icon;
|
|
38
|
+
const isEmbedded = useIsEmbedded();
|
|
37
39
|
|
|
38
40
|
return (
|
|
39
41
|
<IsInsideMobileNavigationContext.Provider value={true}>
|
|
@@ -55,6 +57,12 @@ export function MobileNavigation() {
|
|
|
55
57
|
<Suspense fallback={null}>
|
|
56
58
|
<SheetContent side="left" className="w-full sm:max-w-sm p-8 overflow-y-auto flex flex-col justify-between">
|
|
57
59
|
<Navigation />
|
|
60
|
+
{
|
|
61
|
+
isEmbedded &&
|
|
62
|
+
<div className="flex items-center justify-end">
|
|
63
|
+
<ModeToggle data-testid="mode-toggle" />
|
|
64
|
+
</div>
|
|
65
|
+
}
|
|
58
66
|
</SheetContent>
|
|
59
67
|
</Suspense>
|
|
60
68
|
)}
|
|
@@ -28,7 +28,8 @@ export function TableOfContents() {
|
|
|
28
28
|
let currentSection: Section | null = null
|
|
29
29
|
|
|
30
30
|
headings.forEach((heading) => {
|
|
31
|
-
// Check if heading is visible
|
|
31
|
+
// Check if heading is a valid Element and is visible
|
|
32
|
+
if (!(heading instanceof Element)) return
|
|
32
33
|
const style = window.getComputedStyle(heading)
|
|
33
34
|
if (style.display === 'none' || style.visibility === 'hidden') return
|
|
34
35
|
|
package/tsconfig.bin.json
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
build: {
|
|
6
|
+
rollupOptions: {
|
|
7
|
+
input: resolve(__dirname, 'src/embed/loader.ts'),
|
|
8
|
+
output: {
|
|
9
|
+
entryFileNames: 'embed.js',
|
|
10
|
+
format: 'iife',
|
|
11
|
+
inlineDynamicImports: true,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
outDir: 'dist',
|
|
15
|
+
emptyOutDir: false,
|
|
16
|
+
minify: 'terser',
|
|
17
|
+
terserOptions: {
|
|
18
|
+
compress: {
|
|
19
|
+
drop_console: false, // Keep console for user feedback
|
|
20
|
+
drop_debugger: true,
|
|
21
|
+
pure_funcs: ['console.debug'],
|
|
22
|
+
},
|
|
23
|
+
mangle: {
|
|
24
|
+
safari10: true,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
build: {
|
|
6
|
+
lib: {
|
|
7
|
+
entry: resolve(__dirname, 'src/embed/widget-iframe.ts'),
|
|
8
|
+
name: '__DoryWidget__',
|
|
9
|
+
fileName: () => 'embed-widget.js',
|
|
10
|
+
formats: ['es'],
|
|
11
|
+
},
|
|
12
|
+
outDir: 'dist',
|
|
13
|
+
emptyOutDir: false,
|
|
14
|
+
minify: 'terser',
|
|
15
|
+
terserOptions: {
|
|
16
|
+
compress: {
|
|
17
|
+
drop_console: false,
|
|
18
|
+
drop_debugger: true,
|
|
19
|
+
},
|
|
20
|
+
mangle: {
|
|
21
|
+
safari10: true,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
rollupOptions: {
|
|
25
|
+
output: {
|
|
26
|
+
format: 'es',
|
|
27
|
+
inlineDynamicImports: false,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
});
|
package/vite.config.ts
CHANGED
|
@@ -9,11 +9,13 @@ import { frontmatterGenerator } from './src/plugins/frontmatter-generator';
|
|
|
9
9
|
import { frontmatterDevServer } from './src/plugins/frontmatter-dev-server';
|
|
10
10
|
import { docsAssetsPlugin } from './src/plugins/docs-assets';
|
|
11
11
|
import { htmlMetadataInjector } from './src/plugins/html-metadata-injector';
|
|
12
|
+
import { htmlFilesMiddleware } from './src/plugins/html-files-middleware';
|
|
12
13
|
import { getMdxConfig } from './src/config/mdx';
|
|
13
14
|
|
|
14
15
|
export default defineConfig(({ command }) => ({
|
|
15
16
|
plugins: [
|
|
16
17
|
// SINGLE SOURCE OF TRUTH: All MDX preprocessing happens in src/mdx/processor.ts
|
|
18
|
+
htmlFilesMiddleware(), // Must be first to intercept HTML file requests
|
|
17
19
|
unifiedMdxPreprocessor(),
|
|
18
20
|
preact(),
|
|
19
21
|
mdx(getMdxConfig(command === 'serve')),
|
package/.dockerignore
DELETED
package/CLAUDE.md
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Communication Style
|
|
6
|
-
- Maintain a professional, neutral tone in all communications
|
|
7
|
-
- Use exclamation points sparingly and only when genuinely necessary
|
|
8
|
-
- Approach problems with the measured perspective of an experienced software engineer
|
|
9
|
-
- Keep a level head when discussing technical challenges and solutions
|
|
10
|
-
- Focus on clear, factual explanations without unnecessary enthusiasm
|
|
11
|
-
|
|
12
|
-
## Development requirements
|
|
13
|
-
To develop Dory, follow the below requirements every time you do a task:
|
|
14
|
-
1. Clean code is paramount—make sure it is easy to understand and follow
|
|
15
|
-
2. Do not overengineer if you can help it—only add what is required.
|
|
16
|
-
3. Do not remove or modify existing functionally UNLESS you have to and UNLESS you can justify it.
|
|
17
|
-
4. Do not change existing variable names UNLESS absolutely necessary.
|
|
18
|
-
5. Do not leave unused code lying around.
|
|
19
|
-
6. Ask as many questions as you have to in order to understand your task.
|
|
20
|
-
7. You MUST use multiple subagents wherever possible to help you accomplish your task faster.
|
|
21
|
-
|
|
22
|
-
## Project Overview
|
|
23
|
-
|
|
24
|
-
Dory is a lightweight static site generator for technical documentation, published as `@clidey/dory` on npm. It uses Preact, Vite, TypeScript, and Tailwind CSS.
|
|
25
|
-
|
|
26
|
-
## Essential Commands
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
# Install dependencies
|
|
30
|
-
pnpm install
|
|
31
|
-
|
|
32
|
-
# Development server with hot reload
|
|
33
|
-
pnpm run dev
|
|
34
|
-
|
|
35
|
-
# Build the project (includes TypeScript checking)
|
|
36
|
-
pnpm run build
|
|
37
|
-
|
|
38
|
-
# Preview built site
|
|
39
|
-
pnpm run preview
|
|
40
|
-
|
|
41
|
-
# Publish to npm
|
|
42
|
-
pnpm run publish
|
|
43
|
-
|
|
44
|
-
# CLI commands (after build)
|
|
45
|
-
node bin/dory.js build # Build documentation site
|
|
46
|
-
node bin/dory.js preview # Serve built site
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## High-Level Architecture
|
|
50
|
-
|
|
51
|
-
### Core Technologies
|
|
52
|
-
- **Frontend**: Preact (React-compatible)
|
|
53
|
-
- **Build**: Vite with custom plugins
|
|
54
|
-
- **Styling**: Tailwind CSS v4 + SCSS
|
|
55
|
-
- **Content**: MDX (Markdown + JSX)
|
|
56
|
-
- **Language**: TypeScript (strict mode)
|
|
57
|
-
|
|
58
|
-
### Key Directories
|
|
59
|
-
- `bin/` - CLI tool implementation
|
|
60
|
-
- `src/components/` - UI components (Header, Footer, Search, etc.)
|
|
61
|
-
- `src/mdx/` - MDX-specific components (Code, Tabs, Mermaid)
|
|
62
|
-
- `src/plugins/` - Custom Vite plugins for LLM support
|
|
63
|
-
- `docs/` - Documentation content (MDX files)
|
|
64
|
-
|
|
65
|
-
### Important Files
|
|
66
|
-
- `dory.json` - Site configuration (navigation, branding)
|
|
67
|
-
- `vite.config.ts` - Build configuration with custom plugins
|
|
68
|
-
- `src/main.tsx` - Application entry point
|
|
69
|
-
- `src/store.ts` - Global state management
|
|
70
|
-
|
|
71
|
-
### Custom Vite Plugins
|
|
72
|
-
1. **llm-txt-generator**: Generates `llms.txt` files for AI consumption
|
|
73
|
-
2. **llm-txt-dev-server**: Serves LLM-friendly content in development
|
|
74
|
-
3. **remarkSafeVars**: Sanitizes MDX content for security
|
|
75
|
-
|
|
76
|
-
### Development Patterns
|
|
77
|
-
- Functional components with hooks
|
|
78
|
-
- MDX Provider pattern for content rendering
|
|
79
|
-
- Custom store for state management (dark mode, search)
|
|
80
|
-
- Tailwind utilities for styling
|
|
81
|
-
- No test framework currently configured
|
|
82
|
-
|
|
83
|
-
### Key Features to Maintain
|
|
84
|
-
- MDX support with custom components
|
|
85
|
-
- Client-side search with FlexSearch
|
|
86
|
-
- API Playground for OpenAPI specs
|
|
87
|
-
- Mermaid diagram rendering
|
|
88
|
-
- LaTeX math with KaTeX
|
|
89
|
-
- Dark mode toggle
|
|
90
|
-
- Responsive navigation
|
|
91
|
-
|
|
92
|
-
When making changes:
|
|
93
|
-
- Ensure TypeScript strict mode compliance
|
|
94
|
-
- Follow existing component patterns in `src/components/`
|
|
95
|
-
- Update `dory.json` for navigation changes
|
|
96
|
-
- Test both light and dark modes
|
|
97
|
-
- Verify MDX content renders correctly
|
|
98
|
-
|
|
99
|
-
## Common Command Guidelines
|
|
100
|
-
|
|
101
|
-
### Git Commands
|
|
102
|
-
```bash
|
|
103
|
-
# Check current status before making changes
|
|
104
|
-
git status
|
|
105
|
-
|
|
106
|
-
# View uncommitted changes
|
|
107
|
-
git diff
|
|
108
|
-
git diff --staged # for staged changes
|
|
109
|
-
|
|
110
|
-
# Stage and commit changes
|
|
111
|
-
git add -A # Stage all changes
|
|
112
|
-
git commit -m "feat(component): add new feature" # Use conventional commits
|
|
113
|
-
|
|
114
|
-
# Branch operations
|
|
115
|
-
git checkout -b feature/new-feature # Create and switch to new branch
|
|
116
|
-
git push -u origin feature/new-feature # Push new branch to remote
|
|
117
|
-
|
|
118
|
-
# View recent commits
|
|
119
|
-
git log --oneline -10 # Last 10 commits
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### npm/pnpm Commands
|
|
123
|
-
```bash
|
|
124
|
-
# Always use pnpm in this project (not npm or yarn)
|
|
125
|
-
pnpm install # Install dependencies
|
|
126
|
-
pnpm add <package> # Add new dependency
|
|
127
|
-
pnpm add -D <package> # Add dev dependency
|
|
128
|
-
pnpm remove <package> # Remove dependency
|
|
129
|
-
|
|
130
|
-
# Check for outdated packages
|
|
131
|
-
pnpm outdated
|
|
132
|
-
|
|
133
|
-
# Run scripts from package.json
|
|
134
|
-
pnpm run <script-name>
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### Bash/Shell Commands
|
|
138
|
-
```bash
|
|
139
|
-
# Navigate directories
|
|
140
|
-
cd src/components # Change to components directory
|
|
141
|
-
pwd # Show current directory
|
|
142
|
-
|
|
143
|
-
# File operations
|
|
144
|
-
ls -la # List all files with details
|
|
145
|
-
mkdir -p src/new-feature # Create directories recursively
|
|
146
|
-
rm -rf dist # Remove build directory (be careful!)
|
|
147
|
-
|
|
148
|
-
# Search and find
|
|
149
|
-
grep -r "searchTerm" src/ # Search in source files
|
|
150
|
-
find . -name "*.tsx" -type f # Find all TSX files
|
|
151
|
-
|
|
152
|
-
# Process management
|
|
153
|
-
lsof -i :5173 # Check what's using the dev server port
|
|
154
|
-
kill -9 <PID> # Force kill a process if needed
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### Development Workflow Commands
|
|
158
|
-
```bash
|
|
159
|
-
# Start fresh development session
|
|
160
|
-
git pull origin main
|
|
161
|
-
pnpm install
|
|
162
|
-
pnpm run dev
|
|
163
|
-
|
|
164
|
-
# Before committing
|
|
165
|
-
pnpm run build # Ensure build passes
|
|
166
|
-
git status # Review changes
|
|
167
|
-
git diff # Check modifications
|
|
168
|
-
|
|
169
|
-
# After making changes
|
|
170
|
-
git add -A
|
|
171
|
-
git commit -m "type(scope): description"
|
|
172
|
-
git push
|
|
173
|
-
|
|
174
|
-
# Publishing new version
|
|
175
|
-
pnpm version patch/minor/major
|
|
176
|
-
pnpm run build
|
|
177
|
-
pnpm run publish
|
|
178
|
-
```
|