20261007220117
This commit is contained in:
1 parent
9217b3fa42
commit
8b1ec67609
275 files changed
+20026
-49299
No files matched your search
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 从组件源码生成 API 数据。
|
||||
*
|
||||
* 用 vue-docgen-api 解析 packages/ui/src 下的 .vue 文件,
|
||||
* 提取 props / events / slots 及其 JSDoc 注释,输出到 docs/data/api/<组件名>.json,
|
||||
* 由文档站的 <ApiTable> 组件读取渲染。
|
||||
*
|
||||
* 这样 API 表格永远与源码一致,禁止手写。
|
||||
* 源码改动后执行:pnpm gen:api
|
||||
*/
|
||||
import { mkdir, readdir, writeFile } from 'node:fs/promises'
|
||||
import { basename, dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { parse } from 'vue-docgen-api'
|
||||
|
||||
const root = fileURLToPath(new URL('..', import.meta.url))
|
||||
const uiSrc = join(root, 'packages/ui/src')
|
||||
const outDir = join(root, 'docs/data/api')
|
||||
|
||||
/** 递归收集所有 .vue 组件文件 */
|
||||
async function findComponents(dir) {
|
||||
const found = []
|
||||
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
||||
const full = join(dir, entry.name)
|
||||
if (entry.isDirectory()) {
|
||||
found.push(...(await findComponents(full)))
|
||||
} else if (entry.name.endsWith('.vue')) {
|
||||
found.push(full)
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
/** packages/ui/src/button/Button.vue -> button */
|
||||
function toKey(file) {
|
||||
return basename(dirname(file))
|
||||
}
|
||||
|
||||
/** docgen 给出的值可能带引号,统一剥掉 */
|
||||
function clean(text = '') {
|
||||
return String(text).replace(/^['"]|['"]$/g, '')
|
||||
}
|
||||
|
||||
/** 把说明文字压成单行,避免表格里出现换行 */
|
||||
function oneLine(text = '') {
|
||||
return String(text).replace(/\s+/g, ' ').trim()
|
||||
}
|
||||
|
||||
function mapMember(item) {
|
||||
return {
|
||||
name: item.name,
|
||||
description: oneLine(item.description),
|
||||
type: item.type?.name ?? '',
|
||||
defaultValue: item.defaultValue ? clean(item.defaultValue.value) : '',
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const files = await findComponents(uiSrc)
|
||||
const results = []
|
||||
|
||||
for (const file of files) {
|
||||
const info = await parse(file)
|
||||
const key = toKey(file)
|
||||
|
||||
results.push([
|
||||
key,
|
||||
{
|
||||
displayName: info.displayName || key,
|
||||
description: oneLine(info.description),
|
||||
props: (info.props ?? []).map(mapMember),
|
||||
events: (info.events ?? []).map(mapMember),
|
||||
slots: (info.slots ?? []).map((slot) => ({
|
||||
name: slot.name,
|
||||
description: oneLine(slot.description),
|
||||
})),
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
await mkdir(outDir, { recursive: true })
|
||||
|
||||
for (const [key, doc] of results) {
|
||||
await writeFile(join(outDir, `${key}.json`), `${JSON.stringify(doc, null, 2)}\n`, 'utf-8')
|
||||
console.log(
|
||||
`✓ ${key.padEnd(12)} props=${doc.props.length} events=${doc.events.length} slots=${doc.slots.length}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('[gen-api] 失败:', error)
|
||||
process.exit(1)
|
||||
})
|
||||
Reference in new issue
Block a user