mirror of
https://git.hmsn.ink/kospo/svcm/oa.git
synced 2026-03-20 02:22:22 +09:00
158 lines
4.1 KiB
TypeScript
158 lines
4.1 KiB
TypeScript
/// <reference types="node" />
|
|
|
|
import { join, basename } from 'node:path'
|
|
import { readdir, lstat, writeFile } from 'node:fs/promises'
|
|
|
|
import type {
|
|
MetaCheckerOptions,
|
|
EventMeta,
|
|
PropertyMeta,
|
|
ExposeMeta,
|
|
SlotMeta,
|
|
} from 'vue-component-meta'
|
|
import { createCheckerByJson } from 'vue-component-meta'
|
|
|
|
const checkerOptions: MetaCheckerOptions = {
|
|
forceUseTs: true,
|
|
schema: false,
|
|
printer: { newLine: 1 },
|
|
}
|
|
|
|
type Checker = ReturnType<typeof createCheckerByJson>
|
|
async function main() {
|
|
const root = process.cwd()
|
|
const tsconfig = join(root, './tsconfig.json')
|
|
const componentDir = join(root, './src/components/')
|
|
const out = join(root, './src/data/documentation/components-meta.ts')
|
|
|
|
const checker = createCheckerByJson(root, {
|
|
extends: tsconfig,
|
|
}, checkerOptions)
|
|
|
|
const components: Record<string, any> = {}
|
|
const directories = ['base', 'base-addons', 'layouts']
|
|
await Promise.all(
|
|
directories.map(dir => walk(components, checker, join(componentDir, dir))),
|
|
)
|
|
|
|
const sorted: Record<string, any> = {}
|
|
Object.keys(components).sort().forEach((key) => {
|
|
sorted[key] = components[key]
|
|
})
|
|
|
|
const content = [
|
|
`/* eslint-disable */`,
|
|
`// This file is auto generated by scripts/generate-component-meta.ts`,
|
|
`import type { ComponentMeta } from 'vue-component-meta'`,
|
|
``,
|
|
`export const components = ${JSON.stringify(
|
|
Object.keys(sorted),
|
|
)} as const`,
|
|
``,
|
|
...Object.entries(sorted).map(([name, meta]) => {
|
|
return `export const ${name}Meta: ComponentMeta = ${JSON.stringify(
|
|
meta,
|
|
)} as const`
|
|
}),
|
|
].join('\n')
|
|
|
|
await writeFile(out, content)
|
|
}
|
|
|
|
async function walk(
|
|
components: Record<string, any>,
|
|
checker: Checker,
|
|
dir: string,
|
|
) {
|
|
const files = await readdir(dir)
|
|
for (const file of files) {
|
|
const path = join(dir, file)
|
|
const stat = await lstat(path)
|
|
if (stat.isDirectory()) {
|
|
await walk(components, checker, path) // recursive
|
|
}
|
|
|
|
const isVueFile = path.endsWith('.vue')
|
|
if (!isVueFile) continue
|
|
|
|
const name = basename(path, '.vue')
|
|
const meta = await extractMeta(checker, path)
|
|
components[name] = meta
|
|
}
|
|
}
|
|
|
|
async function extractMeta(checker: Checker, path: string) {
|
|
const metaFields = checker.getComponentMeta(path)
|
|
const meta = {
|
|
type: metaFields.type,
|
|
props: metaFields.props.filter(field => !field.global),
|
|
events: metaFields.events,
|
|
exposed: metaFields.exposed.filter((field) => {
|
|
const isProps
|
|
= metaFields.props?.findIndex(prop => prop.name === field.name) >= 0
|
|
const isEvent
|
|
= metaFields.events?.findIndex(
|
|
(event: any) =>
|
|
`on${event.name}`.toLowerCase() === field.name?.toLowerCase(),
|
|
) >= 0
|
|
const isExcluded = field.name?.startsWith('$')
|
|
const isModel = field.name === 'modelValue'
|
|
|
|
return !(isProps || isEvent || isExcluded || isModel)
|
|
}),
|
|
slots: metaFields.slots,
|
|
}
|
|
|
|
meta.props.forEach(field => cleanMeta(field))
|
|
meta.events.forEach(field => cleanMeta(field))
|
|
meta.slots.forEach(field => cleanMeta(field))
|
|
meta.exposed.forEach(field => cleanMeta(field))
|
|
|
|
meta.props.sort((a, b) => {
|
|
// sort required properties first
|
|
if (!a.required && b.required) {
|
|
return 1
|
|
}
|
|
if (a.required && !b.required) {
|
|
return -1
|
|
}
|
|
// then ensure boolean properties are sorted last
|
|
if (a.type === 'boolean' && b.type !== 'boolean') {
|
|
return 1
|
|
}
|
|
if (a.type !== 'boolean' && b.type === 'boolean') {
|
|
return -1
|
|
}
|
|
|
|
return a.name.localeCompare(b.name)
|
|
})
|
|
meta.events.sort((a, b) => a.name.localeCompare(b.name))
|
|
meta.slots.sort((a, b) => a.name.localeCompare(b.name))
|
|
meta.exposed.sort((a, b) => a.name.localeCompare(b.name))
|
|
|
|
return meta
|
|
}
|
|
|
|
function cleanMeta(field: EventMeta | PropertyMeta | ExposeMeta | SlotMeta) {
|
|
if ('schema' in field) {
|
|
// @ts-expect-error can't be undefined
|
|
delete field.schema
|
|
|
|
if ('signature' in field) {
|
|
field.schema = []
|
|
}
|
|
else {
|
|
field.schema = ''
|
|
}
|
|
}
|
|
|
|
if ('declarations' in field) {
|
|
// @ts-expect-error can't be undefined
|
|
delete field.declarations
|
|
|
|
field.declarations = []
|
|
}
|
|
}
|
|
|
|
main().catch(console.error)
|