Files
2026-10-07 22:01:17 +08:00

96 lines
2.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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)
})