@clidey/dory 0.2.0 โ 0.4.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/dory.js +57 -32
- package/package.json +7 -9
- package/src/mdx/fence.tsx +2 -1
- package/src/mdx/mermaid.tsx +39 -11
package/bin/dory.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
|
-
import { existsSync, rmSync, mkdirSync, cpSync, readFileSync } from 'fs';
|
|
4
|
+
import { existsSync, rmSync, mkdirSync, cpSync, readFileSync, readdirSync } from 'fs';
|
|
5
5
|
import { resolve, dirname } from 'path';
|
|
6
6
|
import { fileURLToPath } from 'url'
|
|
7
7
|
import http from 'http';
|
|
@@ -12,40 +12,63 @@ const __dirname = dirname(__filename);
|
|
|
12
12
|
|
|
13
13
|
const commands = {
|
|
14
14
|
build: () => {
|
|
15
|
-
console.log('
|
|
15
|
+
console.log('๐ Dory is ready to build your docs!');
|
|
16
|
+
|
|
17
|
+
// Clear the docs folder if it exists
|
|
18
|
+
const docsDir = resolve(__dirname, '..', 'docs');
|
|
19
|
+
if (existsSync(docsDir)) {
|
|
20
|
+
console.log('๐งน Tidying up the workspace...');
|
|
21
|
+
rmSync(docsDir, { recursive: true, force: true });
|
|
22
|
+
}
|
|
16
23
|
|
|
17
24
|
// Check if dory.json exists in current directory
|
|
18
25
|
const currentDir = process.cwd();
|
|
19
26
|
const doryConfigPath = resolve(currentDir, 'dory.json');
|
|
20
27
|
|
|
21
28
|
if (!existsSync(doryConfigPath)) {
|
|
22
|
-
console.error('โ dory.json
|
|
29
|
+
console.error('โ Oops! dory.json is missing from your project');
|
|
23
30
|
process.exit(1);
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
// Read and validate dory.json
|
|
27
34
|
try {
|
|
28
35
|
const config = JSON.parse(readFileSync(doryConfigPath, 'utf8'));
|
|
29
|
-
console.log(`๐
|
|
36
|
+
console.log(`๐ Building: ${config.name || 'Your awesome project'}`);
|
|
30
37
|
} catch (error) {
|
|
31
|
-
console.error('โ
|
|
38
|
+
console.error('โ Your dory.json seems to have some issues:', error.message);
|
|
32
39
|
process.exit(1);
|
|
33
40
|
}
|
|
34
41
|
|
|
35
|
-
// Clear and prepare docs folder
|
|
36
|
-
const docsDir = resolve(currentDir, 'docs');
|
|
37
|
-
if (existsSync(docsDir)) {
|
|
38
|
-
console.log('๐งน Clearing docs folder...');
|
|
39
|
-
rmSync(docsDir, { recursive: true, force: true });
|
|
40
|
-
}
|
|
41
42
|
mkdirSync(docsDir, { recursive: true });
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
console.log('๐ Gathering your project files...');
|
|
44
45
|
cpSync(doryConfigPath, resolve(docsDir, 'dory.json'));
|
|
45
|
-
|
|
46
|
+
|
|
47
|
+
const copyFiles = (src, dest) => {
|
|
48
|
+
if (existsSync(src)) {
|
|
49
|
+
if (existsSync(dest)) {
|
|
50
|
+
rmSync(dest, { recursive: true, force: true });
|
|
51
|
+
}
|
|
52
|
+
cpSync(src, dest, { recursive: true });
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Copy all files and directories except node_modules, dist, and .git
|
|
57
|
+
const excludeDirs = ['node_modules', 'dist', '.git', 'docs', 'pnpm-lock.yaml'];
|
|
58
|
+
|
|
59
|
+
const items = readdirSync(currentDir);
|
|
60
|
+
for (const item of items) {
|
|
61
|
+
if (!excludeDirs.includes(item)) {
|
|
62
|
+
const srcPath = resolve(currentDir, item);
|
|
63
|
+
const destPath = resolve(docsDir, item);
|
|
64
|
+
copyFiles(srcPath, destPath);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
console.log('โ
All files gathered successfully!');
|
|
46
69
|
|
|
47
70
|
// Run the build command
|
|
48
|
-
console.log('โก
|
|
71
|
+
console.log('โก Magic is happening...');
|
|
49
72
|
try {
|
|
50
73
|
execSync('npm run build', { stdio: 'inherit', cwd: __dirname });
|
|
51
74
|
} catch (error) {
|
|
@@ -56,19 +79,23 @@ const commands = {
|
|
|
56
79
|
// Check if dist folder was created
|
|
57
80
|
const distDir = resolve(__dirname, '..', 'dist');
|
|
58
81
|
if (existsSync(distDir)) {
|
|
59
|
-
console.log('
|
|
60
|
-
console.log(
|
|
61
|
-
console.log('๐ Moving build output to current directory...');
|
|
82
|
+
console.log('๐ Build completed successfully!');
|
|
83
|
+
console.log('๐ฆ Moving your docs to the right place...');
|
|
62
84
|
cpSync(distDir, resolve(currentDir, 'dist'), { recursive: true });
|
|
63
|
-
console.log(
|
|
85
|
+
console.log('โจ Your docs are ready in the dist folder!');
|
|
64
86
|
} else {
|
|
65
|
-
console.log('โ ๏ธ Build completed but no
|
|
87
|
+
console.log('โ ๏ธ Build completed but no output found');
|
|
66
88
|
}
|
|
67
89
|
rmSync(distDir, { recursive: true, force: true });
|
|
90
|
+
|
|
91
|
+
// Revert docs folder back to original state
|
|
92
|
+
console.log('๐งน Cleaning up...');
|
|
93
|
+
rmSync(docsDir, { recursive: true, force: true });
|
|
94
|
+
console.log('โ
All done!');
|
|
68
95
|
},
|
|
69
96
|
|
|
70
97
|
preview: () => {
|
|
71
|
-
console.log('๐ Starting
|
|
98
|
+
console.log('๐ Starting your docs preview...');
|
|
72
99
|
const currentDir = process.cwd();
|
|
73
100
|
const distDir = resolve(currentDir, 'dist');
|
|
74
101
|
const port = process.env.PORT || 3000;
|
|
@@ -86,33 +113,31 @@ const commands = {
|
|
|
86
113
|
});
|
|
87
114
|
|
|
88
115
|
server.listen(port, () => {
|
|
89
|
-
console.log(`๐
|
|
116
|
+
console.log(`๐ Your docs are live at http://localhost:${port}`);
|
|
90
117
|
});
|
|
91
118
|
},
|
|
92
119
|
|
|
93
120
|
help: () => {
|
|
94
121
|
console.log(`
|
|
95
|
-
๐ Dory CLI - Documentation
|
|
122
|
+
๐ Dory CLI - Your Friendly Documentation Builder
|
|
96
123
|
|
|
97
124
|
Usage:
|
|
98
125
|
dory <command>
|
|
99
126
|
|
|
100
127
|
Commands:
|
|
101
|
-
build Build
|
|
102
|
-
-
|
|
103
|
-
-
|
|
104
|
-
- Runs build command
|
|
105
|
-
- Creates dist folder with build output
|
|
128
|
+
build Build your documentation site
|
|
129
|
+
- Needs dory.json in your project
|
|
130
|
+
- Creates a beautiful dist folder
|
|
106
131
|
|
|
107
|
-
preview Preview
|
|
108
|
-
-
|
|
109
|
-
-
|
|
132
|
+
preview Preview your built documentation
|
|
133
|
+
- Shows your docs in the browser
|
|
134
|
+
- Run build first!
|
|
110
135
|
|
|
111
136
|
help Show this help message
|
|
112
137
|
|
|
113
138
|
Examples:
|
|
114
|
-
dory build # Build
|
|
115
|
-
dory preview # Preview
|
|
139
|
+
dory build # Build your docs
|
|
140
|
+
dory preview # Preview your docs
|
|
116
141
|
`);
|
|
117
142
|
}
|
|
118
143
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clidey/dory",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "A CLI tool for building and previewing documentation sites",
|
|
7
7
|
"keywords": [
|
|
@@ -41,10 +41,13 @@
|
|
|
41
41
|
"@heroicons/react": "^2.2.0",
|
|
42
42
|
"@mdx-js/preact": "^3.1.0",
|
|
43
43
|
"@mdx-js/rollup": "^3.1.0",
|
|
44
|
+
"@preact/preset-vite": "^2.10.1",
|
|
44
45
|
"@tailwindcss/vite": "^4.1.8",
|
|
46
|
+
"@types/react-highlight-words": "^0.20.0",
|
|
45
47
|
"classnames": "^2.5.1",
|
|
46
48
|
"flexsearch": "^0.8.205",
|
|
47
49
|
"gray-matter": "^4.0.3",
|
|
50
|
+
"gzip-size-cli": "^5.1.0",
|
|
48
51
|
"katex": "^0.16.22",
|
|
49
52
|
"lucide-react": "^0.513.0",
|
|
50
53
|
"mermaid": "^11.6.0",
|
|
@@ -54,19 +57,14 @@
|
|
|
54
57
|
"react-highlight-words": "^0.21.0",
|
|
55
58
|
"remark-gfm": "^4.0.1",
|
|
56
59
|
"saas": "^1.0.0",
|
|
60
|
+
"sass-embedded": "^1.89.2",
|
|
57
61
|
"sirv": "^3.0.1",
|
|
58
62
|
"tailwindcss": "^4.1.8",
|
|
63
|
+
"typescript": "~5.8.3",
|
|
59
64
|
"unist-util-visit": "^5.0.0",
|
|
65
|
+
"vite": "^6.3.5",
|
|
60
66
|
"vite-plugin-mdx": "^3.6.1",
|
|
61
67
|
"wouter-preact": "^3.7.1"
|
|
62
68
|
},
|
|
63
|
-
"devDependencies": {
|
|
64
|
-
"@preact/preset-vite": "^2.10.1",
|
|
65
|
-
"@types/react-highlight-words": "^0.20.0",
|
|
66
|
-
"gzip-size-cli": "^5.1.0",
|
|
67
|
-
"sass-embedded": "^1.89.2",
|
|
68
|
-
"typescript": "~5.8.3",
|
|
69
|
-
"vite": "^6.3.5"
|
|
70
|
-
},
|
|
71
69
|
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
|
|
72
70
|
}
|
package/src/mdx/fence.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import { Code, CodeGroup, CodeGroupContext, supportedLanguages } from './code'
|
|
|
4
4
|
import { MermaidRenderer } from './mermaid'
|
|
5
5
|
import { Loading } from '../components/loading'
|
|
6
6
|
import { useDarkMode } from '../utils/hooks'
|
|
7
|
+
import classNames from 'classnames'
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
export function Fence({
|
|
@@ -34,7 +35,7 @@ export function Fence({
|
|
|
34
35
|
theme={isDark ? themes.vsDark : themes.vsLight}>
|
|
35
36
|
{({ className, style, tokens, getTokenProps }) => (
|
|
36
37
|
<pre>
|
|
37
|
-
<Code className={className} style={style} title={supportedLanguage}>
|
|
38
|
+
<Code className={classNames(className, "whitespace-pre-wrap")} style={style} title={supportedLanguage}>
|
|
38
39
|
{tokens.map((line, lineIndex) => (
|
|
39
40
|
<Fragment key={lineIndex}>
|
|
40
41
|
{line
|
package/src/mdx/mermaid.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ExclamationTriangleIcon } from '@heroicons/react/24/outline'
|
|
1
2
|
import classNames from 'classnames'
|
|
2
3
|
import { useEffect, useMemo, useRef, useState } from 'preact/compat'
|
|
3
4
|
|
|
@@ -6,6 +7,7 @@ export function MermaidRenderer({ content }: { content: string }) {
|
|
|
6
7
|
const [isFullscreen, setIsFullscreen] = useState(false)
|
|
7
8
|
const [isLoaded, setIsLoaded] = useState(false)
|
|
8
9
|
const [error, setError] = useState<string | null>(null)
|
|
10
|
+
const [isValid, setIsValid] = useState<boolean | null>(null)
|
|
9
11
|
|
|
10
12
|
const diagramId = useMemo(() => `mermaid-${btoa(content).replace(/[^a-zA-Z0-9]/g, '').substring(0, 10)}`, [content])
|
|
11
13
|
|
|
@@ -15,8 +17,7 @@ export function MermaidRenderer({ content }: { content: string }) {
|
|
|
15
17
|
const renderMermaid = async () => {
|
|
16
18
|
try {
|
|
17
19
|
const mermaid = (await import('mermaid')).default
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
|
|
20
21
|
if (!mounted || !mermaidRef.current) return
|
|
21
22
|
|
|
22
23
|
mermaid.initialize({
|
|
@@ -24,14 +25,14 @@ export function MermaidRenderer({ content }: { content: string }) {
|
|
|
24
25
|
theme: 'base',
|
|
25
26
|
themeVariables: {
|
|
26
27
|
fontSize: '14px',
|
|
27
|
-
nodePadding: 20,
|
|
28
|
+
nodePadding: 20,
|
|
28
29
|
notePadding: 15,
|
|
29
|
-
padding: 10,
|
|
30
|
-
nodeBorderRadius: 8,
|
|
30
|
+
padding: 10,
|
|
31
|
+
nodeBorderRadius: 8,
|
|
31
32
|
},
|
|
32
33
|
flowchart: {
|
|
33
|
-
nodeSpacing: 50,
|
|
34
|
-
rankSpacing: 80,
|
|
34
|
+
nodeSpacing: 50,
|
|
35
|
+
rankSpacing: 80,
|
|
35
36
|
padding: 20,
|
|
36
37
|
useMaxWidth: true,
|
|
37
38
|
},
|
|
@@ -45,9 +46,20 @@ export function MermaidRenderer({ content }: { content: string }) {
|
|
|
45
46
|
.replace(/^\s*style .*$/gm, '')
|
|
46
47
|
.replace(/^\s*classDef .*$/gm, '')
|
|
47
48
|
.replace(/^\s*class .*$/gm, '');
|
|
49
|
+
|
|
50
|
+
// Validate the mermaid syntax first
|
|
51
|
+
try {
|
|
52
|
+
await mermaid.parse(contentWithoutStyle)
|
|
53
|
+
setIsValid(true)
|
|
54
|
+
} catch (parseError) {
|
|
55
|
+
setIsValid(false)
|
|
56
|
+
if (mounted) {
|
|
57
|
+
setError(parseError instanceof Error ? parseError.message : 'Invalid diagram syntax')
|
|
58
|
+
}
|
|
59
|
+
return
|
|
60
|
+
}
|
|
48
61
|
|
|
49
62
|
const { svg } = await mermaid.render(diagramId, contentWithoutStyle);
|
|
50
|
-
|
|
51
63
|
|
|
52
64
|
if (mounted && mermaidRef.current) {
|
|
53
65
|
mermaidRef.current.innerHTML = svg
|
|
@@ -56,6 +68,7 @@ export function MermaidRenderer({ content }: { content: string }) {
|
|
|
56
68
|
} catch (err) {
|
|
57
69
|
console.error('Mermaid rendering error:', err)
|
|
58
70
|
if (mounted) {
|
|
71
|
+
setIsValid(false)
|
|
59
72
|
setError(err instanceof Error ? err.message : 'Failed to render diagram')
|
|
60
73
|
}
|
|
61
74
|
}
|
|
@@ -72,10 +85,25 @@ export function MermaidRenderer({ content }: { content: string }) {
|
|
|
72
85
|
setIsFullscreen(!isFullscreen)
|
|
73
86
|
}
|
|
74
87
|
|
|
75
|
-
if (error) {
|
|
88
|
+
if (error || isValid === false) {
|
|
76
89
|
return (
|
|
77
|
-
<div className="
|
|
78
|
-
<
|
|
90
|
+
<div className="mermaid-wrapper my-8">
|
|
91
|
+
<div className="flex flex-col items-center justify-center py-12 px-6 text-center bg-gradient-to-br from-red-50 to-red-100 dark:from-red-900/20 dark:to-red-800/20 border-2 border-dashed border-red-300 dark:border-red-700 rounded-lg">
|
|
92
|
+
<div className="w-16 h-16 mb-4 flex items-center justify-center bg-red-100 dark:bg-red-900/30 rounded-full">
|
|
93
|
+
<ExclamationTriangleIcon className="w-8 h-8 text-red-500" />
|
|
94
|
+
</div>
|
|
95
|
+
<h3 className="text-lg font-semibold text-red-700 dark:text-red-300 mb-2">
|
|
96
|
+
Diagram Syntax Error
|
|
97
|
+
</h3>
|
|
98
|
+
<p className="text-red-600 dark:text-red-400 mb-4 max-w-md">
|
|
99
|
+
The Mermaid diagram contains invalid syntax and cannot be rendered.
|
|
100
|
+
</p>
|
|
101
|
+
<div className="bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-md p-3 max-w-md">
|
|
102
|
+
<p className="text-sm text-red-700 dark:text-red-300 font-mono break-all">
|
|
103
|
+
{error}
|
|
104
|
+
</p>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
79
107
|
</div>
|
|
80
108
|
)
|
|
81
109
|
}
|