151 lines
4.5 KiB
TypeScript
151 lines
4.5 KiB
TypeScript
import type { ComponentMeta, MetaCheckerOptions, PropertyMeta, PropertyMetaSchema } from 'vue-component-meta'
|
|
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
|
import { join, parse, resolve } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import fg from 'fast-glob'
|
|
import MarkdownIt from 'markdown-it'
|
|
import { createComponentMetaChecker } from 'vue-component-meta'
|
|
|
|
const __dirname = fileURLToPath(new URL('.', import.meta.url))
|
|
|
|
const md = new MarkdownIt()
|
|
|
|
const ROOTPATH = '../'
|
|
const OUTPUTPATH = '../src/content/meta'
|
|
|
|
const checkerOptions: MetaCheckerOptions = {
|
|
forceUseTs: true,
|
|
printer: { newLine: 1 },
|
|
}
|
|
|
|
const tsconfigChecker = createComponentMetaChecker(
|
|
resolve(__dirname, ROOTPATH, 'tsconfig.registry.json'),
|
|
checkerOptions,
|
|
)
|
|
|
|
const components = fg.sync(['chart/**/*.vue', 'chart*/**/*.vue'], {
|
|
cwd: resolve(__dirname, ROOTPATH, 'registry/default/ui/'),
|
|
absolute: true,
|
|
})
|
|
|
|
components.forEach((componentPath) => {
|
|
try {
|
|
const componentName = parse(componentPath).name
|
|
const meta = parseMeta(tsconfigChecker.getComponentMeta(componentPath))
|
|
|
|
const metaDirPath = resolve(__dirname, OUTPUTPATH)
|
|
// if meta dir doesn't exist create
|
|
if (!existsSync(metaDirPath))
|
|
mkdirSync(metaDirPath)
|
|
|
|
const metaMdFilePath = join(metaDirPath, `${componentName}.md`)
|
|
|
|
let parsedString = '<!-- This file was automatic generated. Do not edit it manually -->\n\n'
|
|
if (meta.props.length)
|
|
parsedString += `<APITable :type="'prop'" :data="${JSON.stringify(meta.props, null, 2).replace(/"/g, '\'')}" />\n`
|
|
|
|
if (meta.events.length)
|
|
parsedString += `\n<APITable :type="'emit'" :data="${JSON.stringify(meta.events, null, 2).replace(/"/g, '\'')}" />\n`
|
|
|
|
if (meta.slots.length)
|
|
parsedString += `\n<APITable :type="'slot'" :data="${JSON.stringify(meta.slots, null, 2).replace(/"/g, '\'')}" />\n`
|
|
|
|
if (meta.methods.length)
|
|
parsedString += `\n<APITable :type="'method'" :data="${JSON.stringify(meta.methods, null, 2).replace(/"/g, '\'')}" />\n`
|
|
|
|
writeFileSync(metaMdFilePath, parsedString)
|
|
}
|
|
catch (err) {
|
|
console.log(err)
|
|
}
|
|
})
|
|
|
|
function parseTypeFromSchema(schema: PropertyMetaSchema): string {
|
|
if (typeof schema === 'object' && (schema.kind === 'enum' || schema.kind === 'array')) {
|
|
const isFlatEnum = schema.schema?.every(val => typeof val === 'string')
|
|
const enumValue = schema?.schema?.filter(i => i !== 'undefined') ?? []
|
|
|
|
if (isFlatEnum && /^[A-Z]/.test(schema.type))
|
|
return enumValue.join(' | ')
|
|
else if (typeof schema.schema?.[0] === 'object' && schema.schema?.[0].kind === 'enum')
|
|
return schema.schema.map((s: PropertyMetaSchema) => parseTypeFromSchema(s)).join(' | ')
|
|
else
|
|
return schema.type
|
|
}
|
|
else if (typeof schema === 'object' && schema.kind === 'object') {
|
|
return schema.type
|
|
}
|
|
else if (typeof schema === 'string') {
|
|
return schema
|
|
}
|
|
else {
|
|
return ''
|
|
}
|
|
}
|
|
|
|
// Utilities
|
|
function parseMeta(meta: ComponentMeta) {
|
|
const props = meta.props
|
|
// Exclude global props
|
|
.filter(prop => !prop.global)
|
|
.map((prop) => {
|
|
let defaultValue = prop.default
|
|
const { name, description, required } = prop
|
|
|
|
if (name === 'as')
|
|
defaultValue = defaultValue ?? '"div"'
|
|
|
|
if (defaultValue === 'undefined')
|
|
defaultValue = undefined
|
|
|
|
return ({
|
|
name,
|
|
description: md.render(description),
|
|
type: prop.type.replace(/\s*\|\s*undefined/g, ''),
|
|
required,
|
|
default: defaultValue ?? undefined,
|
|
})
|
|
})
|
|
|
|
const events = meta.events
|
|
.map((event) => {
|
|
const { name, type } = event
|
|
return ({
|
|
name,
|
|
type: type.replace(/\s*\|\s*undefined/g, ''),
|
|
})
|
|
})
|
|
|
|
const defaultSlot = meta.slots?.[0]
|
|
const slots: { name: string, description: string, type: string }[] = []
|
|
|
|
if (defaultSlot && defaultSlot.type !== '{}') {
|
|
const schema = defaultSlot.schema
|
|
if (typeof schema === 'object' && schema.schema) {
|
|
Object.values(schema.schema).forEach((childMeta: PropertyMeta) => {
|
|
slots.push({
|
|
name: childMeta.name,
|
|
description: md.render(childMeta.description),
|
|
type: parseTypeFromSchema(childMeta.schema),
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
// exposed method
|
|
const methods = meta.exposed
|
|
.filter(expose => typeof expose.schema === 'object' && expose.schema.kind === 'event')
|
|
.map(expose => ({
|
|
name: expose.name,
|
|
description: md.render(expose.description),
|
|
type: expose.type,
|
|
}))
|
|
|
|
return {
|
|
props,
|
|
events,
|
|
slots,
|
|
methods,
|
|
}
|
|
}
|