wot-design-uni/scripts/component-helper.ts
2025-01-24 23:30:36 +08:00

162 lines
4.3 KiB
TypeScript

import fg from 'fast-glob'
import { read, parse, vetur, webTypes, write, isString } from 'components-helper'
import type { Config, InstallOptions, NormalizeData, Options, ParseData, ParseTable } from 'components-helper'
const config: Config = {
tags: 'tags.json',
attributes: 'attributes.json',
webTypes: 'web-types.json',
titleRegExp: /#+\s+(.*)\n+([^(#|\n)]*)/g,
tableRegExp: /#+\s+(.*)\n+(\|?.+\|.+)\n\|?\s*:?-+:?\s*\|.+((\n\|?.+\|.+)+)/g,
fileNameRegExp: /\/((\w|-)+)\.\w+$/,
separator: '/',
props: 'props',
propsName: 'Name',
propsType: 'Type',
propsDescription: 'Description',
propsOptions: 'Options',
propsDefault: 'Default',
events: 'events',
eventsName: 'Name',
eventsDescription: 'Description',
slots: 'slots',
slotsName: 'Name',
slotsDescription: 'Description',
slotsType: 'Type',
slotsSubtags: 'Subtags',
directives: 'directives',
directivesName: 'Name',
directivesType: 'Type',
directivesDescription: 'Description'
}
function normalize(options: Options, data: ParseData, path: string): NormalizeData {
const { fileNameRegExp, props, events, slots, directives } = options
const _fileNameRegExp = isString(fileNameRegExp) ? new RegExp(fileNameRegExp) : fileNameRegExp
const _path = path.match(_fileNameRegExp)
const fileName = _path ? _path[1] : ''
const _data: NormalizeData = Object.assign(data, { path, fileName })
const _props = new RegExp(props, 'i')
const _events = new RegExp(events, 'i')
const _slots = new RegExp(slots, 'i')
const _directives = new RegExp(directives, 'i')
if (!_data.table || !_data.table.length) return _data
for (let i = 0; i < _data.table.length; i++) {
const item = _data.table[i]
const title = item.title
if (!title) continue
if (_props.test(title)) {
setData({
data: _data,
item,
path,
fileName,
title,
key: 'props',
regExp: _props
})
} else if (_events.test(title)) {
setData({
data: _data,
item,
path,
fileName,
title,
key: 'events',
regExp: _events
})
} else if (_slots.test(title)) {
setData({
data: _data,
item,
path,
fileName,
title,
key: 'slots',
regExp: _slots
})
} else if (_directives.test(title)) {
setData({
data: _data,
item,
path,
fileName,
title,
key: 'directives',
regExp: _directives
})
}
}
return _data
}
function setData({
data,
key,
item,
title,
path,
fileName,
regExp
}: {
data: NormalizeData
key: 'props' | 'events' | 'slots' | 'directives'
item: ParseTable
title: string
path: string
fileName: string
regExp: RegExp
}) {
const childTitle = title.replace(regExp, '').trim()
if (childTitle) {
const childHeader = data.headers?.find((item) => item.title === childTitle)
const childItem = {
path,
fileName,
title: childTitle,
description: childHeader?.description || data.description,
[key]: item
}
if (!data.children) {
data.children = [childItem]
} else {
const child = data.children.find((item) => item.title === childTitle)
if (child) {
child[key] = item
} else {
data.children.push(childItem)
}
}
} else {
data[key] = item
}
}
export function generateWebTypes(options = {} as InstallOptions) {
if (!options.entry) throw new Error('entry must be a string (non empty) or an array of strings')
if (!options.outDir) throw new Error('outDir must be a string (non empty)')
if (!options.name) console.warn('missing property "name"')
if (!options.version) console.warn('missing property "version"')
const _options: Options = Object.assign(config, options)
const files: string[] = fg.sync(_options.entry, _options.fastGlobConfig)
const data = files.map((path) => {
const fileContent = read(path)
const parseContent = parse(_options, fileContent)
const content = normalize(_options, parseContent, path)
return content
})
const { tags, attributes } = vetur(_options, data)
const webTypesData = webTypes(_options, data)
write(_options, 'tags', tags)
write(_options, 'attributes', attributes)
write(_options, 'webTypes', webTypesData)
}