doc-render-sdk 0.0.9 → 0.0.12
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 +126 -1
- package/bin/doc-render-sdk.js +551 -210
- package/dist/_chunks/index-C3VNauf3.d.mts +88 -0
- package/dist/_chunks/index-C3VNauf3.d.mts.map +1 -0
- package/dist/_chunks/plugin-DCF0RLbi.mjs +228 -0
- package/dist/_chunks/plugin-DCF0RLbi.mjs.map +1 -0
- package/dist/index.d.mts +3 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +32 -3070
- package/dist/index.mjs.map +1 -1
- package/dist/plugin/index.d.mts +2 -0
- package/dist/plugin/index.mjs +3 -0
- package/package.json +30 -13
package/bin/doc-render-sdk.js
CHANGED
|
@@ -46,18 +46,11 @@ program
|
|
|
46
46
|
program
|
|
47
47
|
.command('dev')
|
|
48
48
|
.description('启动开发服务器')
|
|
49
|
-
.option('-p, --port <port>', '端口号', '
|
|
49
|
+
.option('-p, --port <port>', '端口号', '3000')
|
|
50
50
|
.option('-h, --host <host>', '主机地址', 'localhost')
|
|
51
51
|
.action(async (options) => {
|
|
52
52
|
console.log('🚀 启动开发服务器...');
|
|
53
|
-
|
|
54
|
-
const configPath = findConfig();
|
|
55
|
-
if (!configPath) {
|
|
56
|
-
console.error('❌ 未找到配置文件');
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
await startDevServer(configPath, options);
|
|
53
|
+
await startDevServer(options);
|
|
61
54
|
});
|
|
62
55
|
|
|
63
56
|
// 构建项目
|
|
@@ -67,14 +60,7 @@ program
|
|
|
67
60
|
.option('-o, --output <dir>', '输出目录', 'dist')
|
|
68
61
|
.action(async (options) => {
|
|
69
62
|
console.log('📦 构建文档站点...');
|
|
70
|
-
|
|
71
|
-
const configPath = findConfig();
|
|
72
|
-
if (!configPath) {
|
|
73
|
-
console.error('❌ 未找到配置文件');
|
|
74
|
-
process.exit(1);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
await buildProject(configPath, options);
|
|
63
|
+
await buildProject(options);
|
|
78
64
|
});
|
|
79
65
|
|
|
80
66
|
|
|
@@ -92,241 +78,618 @@ program
|
|
|
92
78
|
program.parse();
|
|
93
79
|
|
|
94
80
|
/**
|
|
95
|
-
*
|
|
81
|
+
* 创建组件目录结构
|
|
96
82
|
*/
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
83
|
+
function createComponentStructure(projectDir) {
|
|
84
|
+
const components = ['button', 'input', 'card'];
|
|
85
|
+
|
|
86
|
+
components.forEach(comp => {
|
|
87
|
+
const compDir = path.join(projectDir, 'components', comp, 'demo');
|
|
88
|
+
fs.mkdirSync(compDir, { recursive: true });
|
|
89
|
+
|
|
90
|
+
// 创建 demo 文件
|
|
91
|
+
createDemoFiles(projectDir, comp);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
100
94
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
build: 'doc-render-sdk build',
|
|
110
|
-
// TODO
|
|
111
|
-
// preview: 'doc-render-sdk preview'
|
|
112
|
-
},
|
|
113
|
-
dependencies: {
|
|
114
|
-
'doc-render-sdk': sdkVersion,
|
|
115
|
-
"react": "^18.2.0",
|
|
116
|
-
"react-dom": "^18.2.0"
|
|
117
|
-
},
|
|
118
|
-
devDependencies: {
|
|
119
|
-
vite: '^5.0.0',
|
|
120
|
-
'@vitejs/plugin-react': '^3.1.0'
|
|
121
|
-
}
|
|
122
|
-
};
|
|
95
|
+
/**
|
|
96
|
+
* 创建 demo 文件
|
|
97
|
+
*/
|
|
98
|
+
function createDemoFiles(projectDir, componentName) {
|
|
99
|
+
const demos = {
|
|
100
|
+
button: {
|
|
101
|
+
basic: `import React from 'react';
|
|
102
|
+
import { Button } from 'antd';
|
|
123
103
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
104
|
+
export default function BasicButton() {
|
|
105
|
+
return (
|
|
106
|
+
<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
|
|
107
|
+
<Button>Default</Button>
|
|
108
|
+
<Button type="primary">Primary</Button>
|
|
109
|
+
<Button type="dashed">Dashed</Button>
|
|
110
|
+
<Button type="text">Text</Button>
|
|
111
|
+
<Button type="link">Link</Button>
|
|
112
|
+
</div>
|
|
127
113
|
);
|
|
114
|
+
}`,
|
|
115
|
+
sizes: `import React from 'react';
|
|
116
|
+
import { Button } from 'antd';
|
|
128
117
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
118
|
+
export default function ButtonSizes() {
|
|
119
|
+
return (
|
|
120
|
+
<div style={{ display: 'flex', gap: '8px', alignItems: 'center', flexWrap: 'wrap' }}>
|
|
121
|
+
<Button size="large">Large</Button>
|
|
122
|
+
<Button>Default</Button>
|
|
123
|
+
<Button size="small">Small</Button>
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
}`
|
|
127
|
+
},
|
|
128
|
+
input: {
|
|
129
|
+
basic: `import React from 'react';
|
|
130
|
+
import { Input } from 'antd';
|
|
131
|
+
|
|
132
|
+
export default function BasicInput() {
|
|
133
|
+
return (
|
|
134
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '400px' }}>
|
|
135
|
+
<Input placeholder="Basic usage" />
|
|
136
|
+
<Input placeholder="Disabled" disabled />
|
|
137
|
+
<Input.Password placeholder="Password" />
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
}`
|
|
141
|
+
},
|
|
142
|
+
card: {
|
|
143
|
+
basic: `import React from 'react';
|
|
144
|
+
import { Card } from 'antd';
|
|
145
|
+
|
|
146
|
+
export default function BasicCard() {
|
|
147
|
+
return (
|
|
148
|
+
<Card title="Card Title" style={{ width: 300 }}>
|
|
149
|
+
<p>Card content</p>
|
|
150
|
+
<p>Card content</p>
|
|
151
|
+
<p>Card content</p>
|
|
152
|
+
</Card>
|
|
153
|
+
);
|
|
154
|
+
}`
|
|
152
155
|
}
|
|
153
156
|
};
|
|
154
157
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
const componentDemos = demos[componentName] || {};
|
|
159
|
+
|
|
160
|
+
Object.entries(componentDemos).forEach(([demoName, content]) => {
|
|
161
|
+
const demoPath = path.join(projectDir, 'components', componentName, 'demo', `${demoName}.jsx`);
|
|
162
|
+
fs.writeFileSync(demoPath, content);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
159
165
|
|
|
160
|
-
|
|
166
|
+
/**
|
|
167
|
+
* 创建 Vite 配置
|
|
168
|
+
*/
|
|
169
|
+
function createViteConfig(projectDir) {
|
|
170
|
+
const viteConfig = `import { defineConfig } from 'vite';
|
|
171
|
+
import react from '@vitejs/plugin-react';
|
|
172
|
+
import { resolve } from 'path';
|
|
173
|
+
import { createDemoCodePlugin } from 'doc-render-sdk/plugin';
|
|
174
|
+
|
|
175
|
+
export default defineConfig({
|
|
176
|
+
plugins: [
|
|
177
|
+
react(),
|
|
178
|
+
createDemoCodePlugin({
|
|
179
|
+
include: 'index.js',
|
|
180
|
+
demoPattern: '/demo/',
|
|
181
|
+
globalVar: 'window.__DOC_SDK_DEMO_CODES__',
|
|
182
|
+
debug: process.env.NODE_ENV === 'development',
|
|
183
|
+
})
|
|
184
|
+
],
|
|
185
|
+
resolve: {
|
|
186
|
+
alias: {
|
|
187
|
+
'@': resolve(__dirname, 'src')
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
server: {
|
|
191
|
+
port: 3000,
|
|
192
|
+
open: true
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
`;
|
|
196
|
+
|
|
197
|
+
fs.writeFileSync(path.join(projectDir, 'vite.config.js'), viteConfig);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* 创建入口文件
|
|
202
|
+
*/
|
|
203
|
+
function createIndexFile(projectDir) {
|
|
161
204
|
const indexJs = `import DocSDK from 'doc-render-sdk';
|
|
162
|
-
import config from './doc.config.js';
|
|
163
205
|
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
206
|
+
// Button 组件 demos
|
|
207
|
+
import buttonBasic from './components/button/demo/basic.jsx';
|
|
208
|
+
import buttonSizes from './components/button/demo/sizes.jsx';
|
|
209
|
+
|
|
210
|
+
// Input 组件 demos
|
|
211
|
+
import inputBasic from './components/input/demo/basic.jsx';
|
|
212
|
+
|
|
213
|
+
// Card 组件 demos
|
|
214
|
+
import cardBasic from './components/card/demo/basic.jsx';
|
|
173
215
|
|
|
174
216
|
// 注册全局组件
|
|
175
217
|
window.__DOC_SDK_DEMOS__ = {
|
|
176
|
-
'
|
|
177
|
-
'basic':
|
|
178
|
-
|
|
218
|
+
'button': {
|
|
219
|
+
'basic': buttonBasic,
|
|
220
|
+
'sizes': buttonSizes,
|
|
221
|
+
},
|
|
222
|
+
'input': {
|
|
223
|
+
'basic': inputBasic,
|
|
224
|
+
},
|
|
225
|
+
'card': {
|
|
226
|
+
'basic': cardBasic,
|
|
227
|
+
},
|
|
179
228
|
};
|
|
180
229
|
|
|
181
|
-
|
|
182
|
-
'example': {
|
|
183
|
-
'basic': \`const ExampleComponent = () => {
|
|
184
|
-
return (
|
|
185
|
-
<div style={{ padding: '20px' }}>
|
|
186
|
-
<h3>Example Component</h3>
|
|
187
|
-
<p>This is an example component.</p>
|
|
188
|
-
</div>
|
|
189
|
-
);
|
|
190
|
-
};\`
|
|
191
|
-
}
|
|
192
|
-
};
|
|
230
|
+
// Demo 源码将由 vite-plugin-demo-code 自动注入
|
|
193
231
|
|
|
232
|
+
// 注册 API 文档
|
|
194
233
|
window.__DOC_SDK_APIS__ = {
|
|
195
|
-
'
|
|
196
|
-
'
|
|
234
|
+
'button': {
|
|
235
|
+
'Button': [
|
|
236
|
+
{
|
|
237
|
+
param: 'type',
|
|
238
|
+
type: 'string',
|
|
239
|
+
desc: '按钮类型',
|
|
240
|
+
option: 'default | primary | dashed | text | link',
|
|
241
|
+
default: 'default',
|
|
242
|
+
required: false
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
param: 'size',
|
|
246
|
+
type: 'string',
|
|
247
|
+
desc: '按钮尺寸',
|
|
248
|
+
option: 'small | middle | large',
|
|
249
|
+
default: 'middle',
|
|
250
|
+
required: false
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
param: 'disabled',
|
|
254
|
+
type: 'boolean',
|
|
255
|
+
desc: '是否禁用',
|
|
256
|
+
option: 'true | false',
|
|
257
|
+
default: 'false',
|
|
258
|
+
required: false
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
param: 'onClick',
|
|
262
|
+
type: 'function',
|
|
263
|
+
desc: '点击事件回调',
|
|
264
|
+
option: '(event) => void',
|
|
265
|
+
default: '-',
|
|
266
|
+
required: false
|
|
267
|
+
},
|
|
268
|
+
]
|
|
269
|
+
},
|
|
270
|
+
'input': {
|
|
271
|
+
'Input': [
|
|
272
|
+
{
|
|
273
|
+
param: 'value',
|
|
274
|
+
type: 'string',
|
|
275
|
+
desc: '输入框的值',
|
|
276
|
+
option: '-',
|
|
277
|
+
default: '-',
|
|
278
|
+
required: false
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
param: 'placeholder',
|
|
282
|
+
type: 'string',
|
|
283
|
+
desc: '占位文本',
|
|
284
|
+
option: '-',
|
|
285
|
+
default: '-',
|
|
286
|
+
required: false
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
param: 'disabled',
|
|
290
|
+
type: 'boolean',
|
|
291
|
+
desc: '是否禁用',
|
|
292
|
+
option: 'true | false',
|
|
293
|
+
default: 'false',
|
|
294
|
+
required: false
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
param: 'onChange',
|
|
298
|
+
type: 'function',
|
|
299
|
+
desc: '值变化时的回调',
|
|
300
|
+
option: '(e) => void',
|
|
301
|
+
default: '-',
|
|
302
|
+
required: false
|
|
303
|
+
},
|
|
304
|
+
]
|
|
305
|
+
},
|
|
306
|
+
'card': {
|
|
307
|
+
'Card': [
|
|
308
|
+
{
|
|
309
|
+
param: 'title',
|
|
310
|
+
type: 'string | ReactNode',
|
|
311
|
+
desc: '卡片标题',
|
|
312
|
+
option: '-',
|
|
313
|
+
default: '-',
|
|
314
|
+
required: false
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
param: 'bordered',
|
|
318
|
+
type: 'boolean',
|
|
319
|
+
desc: '是否有边框',
|
|
320
|
+
option: 'true | false',
|
|
321
|
+
default: 'true',
|
|
322
|
+
required: false
|
|
323
|
+
},
|
|
197
324
|
{
|
|
198
325
|
param: 'children',
|
|
199
326
|
type: 'ReactNode',
|
|
200
|
-
desc: '
|
|
201
|
-
option: '',
|
|
202
|
-
default: '',
|
|
327
|
+
desc: '卡片内容',
|
|
328
|
+
option: '-',
|
|
329
|
+
default: '-',
|
|
203
330
|
required: false
|
|
204
|
-
}
|
|
331
|
+
},
|
|
205
332
|
]
|
|
206
|
-
}
|
|
333
|
+
},
|
|
207
334
|
};
|
|
208
335
|
|
|
209
|
-
|
|
336
|
+
// 创建文档SDK实例
|
|
337
|
+
const docSdk = new DocSDK({
|
|
338
|
+
title: 'My Component Library',
|
|
339
|
+
description: '基于 Doc SDK 构建的组件文档',
|
|
340
|
+
version: '1.0.0',
|
|
341
|
+
|
|
342
|
+
theme: {
|
|
343
|
+
name: 'default',
|
|
344
|
+
colors: {
|
|
345
|
+
primary: '#1890ff'
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
|
|
349
|
+
layout: {
|
|
350
|
+
type: 'sidebar',
|
|
351
|
+
sidebar: {
|
|
352
|
+
width: 280,
|
|
353
|
+
collapsible: true
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
|
|
357
|
+
components: {
|
|
358
|
+
'button': {
|
|
359
|
+
label: 'Button 按钮',
|
|
360
|
+
description: '按钮用于触发一个操作',
|
|
361
|
+
group: '基础组件',
|
|
362
|
+
demos: [
|
|
363
|
+
{
|
|
364
|
+
title: '按钮类型',
|
|
365
|
+
desc: '按钮有五种类型:默认按钮、主要按钮、虚线按钮、文本按钮和链接按钮',
|
|
366
|
+
source: 'basic'
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
title: '按钮尺寸',
|
|
370
|
+
desc: '按钮有三种尺寸:大、中、小',
|
|
371
|
+
source: 'sizes'
|
|
372
|
+
}
|
|
373
|
+
],
|
|
374
|
+
apis: [
|
|
375
|
+
{
|
|
376
|
+
title: 'Button Props',
|
|
377
|
+
apiKey: 'Button'
|
|
378
|
+
}
|
|
379
|
+
]
|
|
380
|
+
},
|
|
381
|
+
'input': {
|
|
382
|
+
label: 'Input 输入框',
|
|
383
|
+
description: '通过鼠标或键盘输入内容',
|
|
384
|
+
group: '表单组件',
|
|
385
|
+
demos: [
|
|
386
|
+
{
|
|
387
|
+
title: '基础用法',
|
|
388
|
+
desc: '基础的输入框用法',
|
|
389
|
+
source: 'basic'
|
|
390
|
+
}
|
|
391
|
+
],
|
|
392
|
+
apis: [
|
|
393
|
+
{
|
|
394
|
+
title: 'Input Props',
|
|
395
|
+
apiKey: 'Input'
|
|
396
|
+
}
|
|
397
|
+
]
|
|
398
|
+
},
|
|
399
|
+
'card': {
|
|
400
|
+
label: 'Card 卡片',
|
|
401
|
+
description: '通用卡片容器',
|
|
402
|
+
group: '数据展示',
|
|
403
|
+
demos: [
|
|
404
|
+
{
|
|
405
|
+
title: '基础卡片',
|
|
406
|
+
desc: '包含标题、内容的基础卡片',
|
|
407
|
+
source: 'basic'
|
|
408
|
+
}
|
|
409
|
+
],
|
|
410
|
+
apis: [
|
|
411
|
+
{
|
|
412
|
+
title: 'Card Props',
|
|
413
|
+
apiKey: 'Card'
|
|
414
|
+
}
|
|
415
|
+
]
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
|
|
419
|
+
installation: \`# 使用 npm
|
|
420
|
+
npm install my-component-library
|
|
421
|
+
|
|
422
|
+
# 使用 yarn
|
|
423
|
+
yarn add my-component-library
|
|
424
|
+
|
|
425
|
+
# 使用 pnpm
|
|
426
|
+
pnpm add my-component-library\`,
|
|
427
|
+
|
|
428
|
+
usage: \`import { Button } from 'my-component-library';
|
|
429
|
+
|
|
430
|
+
function App() {
|
|
431
|
+
return <Button type="primary">Click me</Button>;
|
|
432
|
+
}\`,
|
|
433
|
+
|
|
434
|
+
features: [
|
|
435
|
+
{
|
|
436
|
+
icon: '🎨',
|
|
437
|
+
title: '主题定制',
|
|
438
|
+
description: '支持自定义主题颜色、字体、间距等'
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
icon: '📱',
|
|
442
|
+
title: '响应式设计',
|
|
443
|
+
description: '完美适配桌面端和移动端'
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
icon: '⚡',
|
|
447
|
+
title: '高性能',
|
|
448
|
+
description: '采用 React 18 和虚拟滚动技术'
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
icon: '🔍',
|
|
452
|
+
title: '智能搜索',
|
|
453
|
+
description: '内置全文搜索功能'
|
|
454
|
+
}
|
|
455
|
+
],
|
|
456
|
+
|
|
457
|
+
footerLinks: [
|
|
458
|
+
{
|
|
459
|
+
text: 'GitHub',
|
|
460
|
+
url: 'https://github.com/yourusername/your-repo',
|
|
461
|
+
external: true
|
|
462
|
+
}
|
|
463
|
+
]
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// 渲染文档
|
|
210
467
|
docSdk.render('#app');
|
|
211
468
|
`;
|
|
212
469
|
|
|
213
|
-
fs.writeFileSync(path.join(projectDir, 'index.
|
|
470
|
+
fs.writeFileSync(path.join(projectDir, 'index.js'), indexJs);
|
|
471
|
+
}
|
|
214
472
|
|
|
215
|
-
|
|
473
|
+
/**
|
|
474
|
+
* 创建 HTML 文件
|
|
475
|
+
*/
|
|
476
|
+
function createIndexHtml(projectDir) {
|
|
216
477
|
const indexHtml = `<!DOCTYPE html>
|
|
217
478
|
<html lang="zh-CN">
|
|
218
479
|
<head>
|
|
219
480
|
<meta charset="UTF-8">
|
|
220
481
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
221
|
-
<title>My
|
|
222
|
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css">
|
|
223
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
|
|
482
|
+
<title>My Component Library</title>
|
|
224
483
|
</head>
|
|
225
484
|
<body>
|
|
226
485
|
<div id="app"></div>
|
|
227
|
-
<script src="index.
|
|
486
|
+
<script src="index.js" type="module"></script>
|
|
228
487
|
</body>
|
|
229
488
|
</html>`;
|
|
230
489
|
|
|
231
490
|
fs.writeFileSync(path.join(projectDir, 'index.html'), indexHtml);
|
|
491
|
+
}
|
|
232
492
|
|
|
233
|
-
|
|
493
|
+
/**
|
|
494
|
+
* 创建 README
|
|
495
|
+
*/
|
|
496
|
+
function createReadme(projectDir) {
|
|
234
497
|
const readme = `# ${path.basename(projectDir)}
|
|
235
498
|
|
|
236
|
-
|
|
499
|
+
基于 Doc SDK 构建的组件文档站点。
|
|
237
500
|
|
|
238
|
-
##
|
|
501
|
+
## 快速开始
|
|
239
502
|
|
|
240
503
|
\`\`\`bash
|
|
504
|
+
# 安装依赖
|
|
241
505
|
npm install
|
|
506
|
+
|
|
507
|
+
# 启动开发服务器
|
|
242
508
|
npm run dev
|
|
509
|
+
|
|
510
|
+
# 构建生产版本
|
|
511
|
+
npm run build
|
|
512
|
+
|
|
513
|
+
# 预览构建结果
|
|
514
|
+
npm run preview
|
|
515
|
+
\`\`\`
|
|
516
|
+
|
|
517
|
+
## 项目结构
|
|
518
|
+
|
|
519
|
+
\`\`\`
|
|
520
|
+
${path.basename(projectDir)}/
|
|
521
|
+
├── components/ # 组件目录
|
|
522
|
+
│ ├── button/
|
|
523
|
+
│ │ └── demo/ # Button 组件示例
|
|
524
|
+
│ ├── input/
|
|
525
|
+
│ │ └── demo/ # Input 组件示例
|
|
526
|
+
│ └── card/
|
|
527
|
+
│ └── demo/ # Card 组件示例
|
|
528
|
+
├── index.html # HTML 入口
|
|
529
|
+
├── index.js # JS 入口
|
|
530
|
+
├── vite.config.js # Vite 配置
|
|
531
|
+
└── package.json
|
|
243
532
|
\`\`\`
|
|
244
533
|
|
|
245
|
-
##
|
|
534
|
+
## 添加新组件
|
|
246
535
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
536
|
+
1. 在 \`components/\` 目录下创建组件文件夹
|
|
537
|
+
2. 在 \`components/your-component/demo/\` 下创建示例文件
|
|
538
|
+
3. 在 \`index.js\` 中注册组件和 API 文档
|
|
250
539
|
|
|
251
|
-
##
|
|
540
|
+
## 文档
|
|
252
541
|
|
|
253
|
-
- [Doc SDK
|
|
542
|
+
- [Doc SDK 文档](https://github.com/Sunny-117/doc-render-sdk)
|
|
543
|
+
- [Vite 文档](https://vitejs.dev/)
|
|
544
|
+
- [React 文档](https://react.dev/)
|
|
254
545
|
`;
|
|
255
546
|
|
|
256
547
|
fs.writeFileSync(path.join(projectDir, 'README.md'), readme);
|
|
257
548
|
}
|
|
258
549
|
|
|
259
550
|
/**
|
|
260
|
-
*
|
|
551
|
+
* 创建新项目
|
|
261
552
|
*/
|
|
262
|
-
function
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
553
|
+
async function createProject(projectDir, template) {
|
|
554
|
+
// 创建项目目录
|
|
555
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
556
|
+
|
|
557
|
+
// 生成package.json
|
|
558
|
+
const packageJson = {
|
|
559
|
+
name: path.basename(projectDir),
|
|
560
|
+
version: '1.0.0',
|
|
561
|
+
description: 'Documentation site built with Doc SDK',
|
|
562
|
+
type: 'module',
|
|
563
|
+
main: 'index.js',
|
|
564
|
+
scripts: {
|
|
565
|
+
dev: 'doc-render-sdk dev',
|
|
566
|
+
build: 'doc-render-sdk build',
|
|
567
|
+
preview: 'doc-render-sdk preview'
|
|
568
|
+
},
|
|
569
|
+
dependencies: {
|
|
570
|
+
'doc-render-sdk': `^${sdkVersion}`,
|
|
571
|
+
'react': '^18.2.0',
|
|
572
|
+
'react-dom': '^18.2.0',
|
|
573
|
+
'antd': '6.0.0-alpha.3'
|
|
574
|
+
},
|
|
575
|
+
devDependencies: {
|
|
576
|
+
'vite': '7.1.8',
|
|
577
|
+
'@vitejs/plugin-react': '5.0.4'
|
|
273
578
|
}
|
|
274
|
-
}
|
|
579
|
+
};
|
|
275
580
|
|
|
276
|
-
|
|
581
|
+
fs.writeFileSync(
|
|
582
|
+
path.join(projectDir, 'package.json'),
|
|
583
|
+
JSON.stringify(packageJson, null, 2)
|
|
584
|
+
);
|
|
585
|
+
|
|
586
|
+
// 创建组件目录结构
|
|
587
|
+
createComponentStructure(projectDir);
|
|
588
|
+
|
|
589
|
+
// 生成 vite.config.js
|
|
590
|
+
createViteConfig(projectDir);
|
|
591
|
+
|
|
592
|
+
// 生成入口文件
|
|
593
|
+
createIndexFile(projectDir);
|
|
594
|
+
|
|
595
|
+
// 生成HTML文件
|
|
596
|
+
createIndexHtml(projectDir);
|
|
597
|
+
|
|
598
|
+
// 生成README
|
|
599
|
+
createReadme(projectDir);
|
|
277
600
|
}
|
|
278
601
|
|
|
279
602
|
/**
|
|
280
603
|
* 启动开发服务器
|
|
281
604
|
*/
|
|
282
|
-
function startDevServer(
|
|
283
|
-
|
|
284
|
-
|
|
605
|
+
async function startDevServer(options) {
|
|
606
|
+
try {
|
|
607
|
+
const { createServer } = require('vite');
|
|
608
|
+
const react = require('@vitejs/plugin-react');
|
|
609
|
+
|
|
610
|
+
// 尝试加载 doc-render-sdk 插件
|
|
611
|
+
let demoPlugin = null;
|
|
285
612
|
try {
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
plugins: createVitePlugins()
|
|
613
|
+
const { createDemoCodePlugin } = require('doc-render-sdk/plugin');
|
|
614
|
+
demoPlugin = createDemoCodePlugin({
|
|
615
|
+
include: 'index.js',
|
|
616
|
+
demoPattern: '/demo/',
|
|
617
|
+
globalVar: 'window.__DOC_SDK_DEMO_CODES__',
|
|
618
|
+
debug: true,
|
|
293
619
|
});
|
|
294
|
-
|
|
295
|
-
await server.listen();
|
|
296
|
-
server.printUrls();
|
|
297
620
|
} catch (err) {
|
|
298
|
-
console.
|
|
299
|
-
|
|
621
|
+
console.warn('⚠️ 未找到 doc-render-sdk 插件,将跳过 demo 代码注入功能');
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
const plugins = [react()];
|
|
625
|
+
if (demoPlugin) {
|
|
626
|
+
plugins.push(demoPlugin);
|
|
300
627
|
}
|
|
301
|
-
|
|
628
|
+
|
|
629
|
+
const server = await createServer({
|
|
630
|
+
root: process.cwd(),
|
|
631
|
+
server: {
|
|
632
|
+
port: Number(options.port) || 3000,
|
|
633
|
+
host: options.host || 'localhost',
|
|
634
|
+
open: true
|
|
635
|
+
},
|
|
636
|
+
plugins
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
await server.listen();
|
|
640
|
+
server.printUrls();
|
|
641
|
+
|
|
642
|
+
console.log('\n✨ 开发服务器已启动!');
|
|
643
|
+
} catch (err) {
|
|
644
|
+
console.error('❌ 启动开发服务器失败:', err);
|
|
645
|
+
process.exit(1);
|
|
646
|
+
}
|
|
302
647
|
}
|
|
303
648
|
|
|
304
649
|
/**
|
|
305
650
|
* 构建项目
|
|
306
651
|
*/
|
|
307
|
-
function buildProject(
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
const outDir = options.output || 'dist';
|
|
313
|
-
|
|
314
|
-
console.log('📦 running vite build...');
|
|
652
|
+
async function buildProject(options) {
|
|
653
|
+
try {
|
|
654
|
+
const { build } = require('vite');
|
|
655
|
+
const react = require('@vitejs/plugin-react');
|
|
656
|
+
const outDir = options.output || 'dist';
|
|
315
657
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
658
|
+
// 尝试加载 doc-render-sdk 插件
|
|
659
|
+
let demoPlugin = null;
|
|
660
|
+
try {
|
|
661
|
+
const { createDemoCodePlugin } = require('doc-render-sdk/plugin');
|
|
662
|
+
demoPlugin = createDemoCodePlugin({
|
|
663
|
+
include: 'index.js',
|
|
664
|
+
demoPattern: '/demo/',
|
|
665
|
+
globalVar: 'window.__DOC_SDK_DEMO_CODES__',
|
|
666
|
+
debug: false,
|
|
322
667
|
});
|
|
323
|
-
|
|
324
|
-
console.log('✅ 构建完成!');
|
|
325
668
|
} catch (err) {
|
|
326
|
-
console.
|
|
327
|
-
|
|
669
|
+
console.warn('⚠️ 未找到 doc-render-sdk 插件,将跳过 demo 代码注入功能');
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const plugins = [react()];
|
|
673
|
+
if (demoPlugin) {
|
|
674
|
+
plugins.push(demoPlugin);
|
|
328
675
|
}
|
|
329
|
-
|
|
676
|
+
|
|
677
|
+
console.log('📦 开始构建...');
|
|
678
|
+
|
|
679
|
+
await build({
|
|
680
|
+
root: process.cwd(),
|
|
681
|
+
build: {
|
|
682
|
+
outDir
|
|
683
|
+
},
|
|
684
|
+
plugins
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
console.log('✅ 构建完成!');
|
|
688
|
+
console.log(`📁 输出目录: ${outDir}`);
|
|
689
|
+
} catch (err) {
|
|
690
|
+
console.error('❌ 构建失败:', err);
|
|
691
|
+
process.exit(1);
|
|
692
|
+
}
|
|
330
693
|
}
|
|
331
694
|
|
|
332
695
|
/**
|
|
@@ -351,47 +714,25 @@ function createVitePlugins() {
|
|
|
351
714
|
/**
|
|
352
715
|
* 预览构建结果
|
|
353
716
|
*/
|
|
354
|
-
function previewBuild(options) {
|
|
355
|
-
// Use Vite programmatic preview API if available, else fallback to npx vite preview
|
|
356
|
-
const distDir = options.dir || 'dist';
|
|
357
|
-
const port = Number(options.port) || 3000;
|
|
358
|
-
|
|
717
|
+
async function previewBuild(options) {
|
|
359
718
|
try {
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
// Vite exposes preview function in some versions
|
|
363
|
-
(async () => {
|
|
364
|
-
try {
|
|
365
|
-
const server = await vite.preview({ root: process.cwd(), preview: { port } });
|
|
366
|
-
console.log(`📖 预览地址: http://localhost:${port}`);
|
|
367
|
-
} catch (err) {
|
|
368
|
-
console.error('❌ 启动 Vite preview 失败:', err);
|
|
369
|
-
process.exit(1);
|
|
370
|
-
}
|
|
371
|
-
})();
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
719
|
+
const { preview } = require('vite');
|
|
720
|
+
const port = Number(options.port) || 3000;
|
|
374
721
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
return;
|
|
388
|
-
}
|
|
722
|
+
console.log('👀 启动预览服务器...');
|
|
723
|
+
|
|
724
|
+
const server = await preview({
|
|
725
|
+
root: process.cwd(),
|
|
726
|
+
preview: {
|
|
727
|
+
port,
|
|
728
|
+
open: true
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
server.printUrls();
|
|
733
|
+
console.log('\n✨ 预览服务器已启动!');
|
|
389
734
|
} catch (err) {
|
|
390
|
-
|
|
735
|
+
console.error('❌ 启动预览服务器失败:', err);
|
|
736
|
+
process.exit(1);
|
|
391
737
|
}
|
|
392
|
-
|
|
393
|
-
// Final fallback: spawn npx vite preview
|
|
394
|
-
const args = ['vite', 'preview', '--port', String(port)];
|
|
395
|
-
const child = spawn('npx', args, { stdio: 'inherit', shell: true, cwd: process.cwd() });
|
|
396
|
-
child.on('close', (code) => process.exit(code));
|
|
397
738
|
}
|