import gulp from 'gulp' import minimist from 'minimist' import shell from 'shelljs' import path from 'path' import { generateKey } from 'crypto' const build = gulp.series(init, read, write, clean) build.description = '将本地文档的组件api, 转换为低代码需要的bundle.json 格式' build.flags = { '--apiPath': '设置api文档路径,默认为: examples/sites/demos/pc', '--tinyVer': '设置生成中,tinyVer的版本号,默认为 3.11.0' } export default build const rootPath = process.cwd() let apiPath = 'examples/sites/demos/pc' let tinyVer = '3.11.0' let guid = 1 let menus = [] const ignoreKeys = ['color', 'font', 'icon'] const mixinKeys = { 'form': [{ key: 'form-item', nameCn: '表单项', desc: '表单中的一行表单域对象' }], 'layout': [ { key: 'row', nameCn: '行元素', desc: '行元素' }, { key: 'col', nameCn: '列元素', desc: '列元素' } ], 'breadcrumb': [{ key: 'breadcrumb-item', nameCn: '面包屑项', desc: '面包屑的层级对象' }], 'timeline': [{ key: 'timeline-item', nameCn: '时间线数据项', desc: '时间线数据项' }], 'dropdown': [ { key: 'dropdown-menu', nameCn: '下拉菜单', desc: '下拉菜单' }, { key: 'dropdown-item', nameCn: '下拉菜单项', desc: '下拉菜单项' } ], 'carousel': [{ key: 'carousel-item', nameCn: '走马灯数据项', desc: '走马灯数据项' }], 'checkbox': [ { key: 'checkbox-group', nameCn: '复选框组', desc: '复选框组' }, { key: 'checkbox-button', nameCn: '复选框按钮', desc: '复选框按钮' } ], 'radio': [ { key: 'radio-group', nameCn: '单选框组', desc: '单选框组' }, { key: 'radio-button', nameCn: '单选框按钮', desc: '单选框按钮' } ], 'grid': [ { key: 'grid-column', nameCn: '表格列对象', desc: '表格列对象' }, { key: 'grid-toolbar', nameCn: '表格工具栏', desc: '表格工具栏' } ] } const result = { 'data': { 'framework': 'Vue', 'materials': { 'components': [], 'snippets': [], 'blocks': [] } } } // 1. 初始化 function init(cb) { const argv = minimist(process.argv.slice(2)) if (argv.apiPath) { apiPath = argv.apiPath } if (argv.tinyVer) { tinyVer = argv.tinyVer } // 读菜单 shell.cp(path.join(apiPath, '/menus.js'), 'gulp/menus.mjs') shell.sed('-i', 'import.meta.env.VITE_BUILD_TARGET', 'false', 'gulp/menus.mjs') import('./menus.mjs').then((res) => { menus = res.cmpMenus cb() }) } // 2. 遍历菜单,处理每一个组件 function read(cb) { menus.forEach((group) => { const snippetItem = { 'group': group.label, 'children': [] } group.children.forEach((component) => { if (ignoreKeys.includes(component.key)) { return } if (component.key.startsWith('grid-') || component.key.startsWith('chart-')) { return } const componentInfo = _readOneComp(component) const componentItem = genComp(componentInfo) const snipItem = genSnip(componentInfo) result.data.materials.components.push(componentItem) snippetItem.children.push(snipItem) // 特殊的混合组件判断, 比如遍历到form时,要插入 form-item的定义 if (mixinKeys[component.key]) { mixinKeys[component.key].forEach((mixin) => { const componentInfo = _readOneComp(component, mixin) const componentItem = genComp(componentInfo) const snipItem = genSnip(componentInfo) result.data.materials.components.push(componentItem) snippetItem.children.push(snipItem) }) } }) result.data.materials.snippets.push(snippetItem) }) cb() } function _readOneComp(component, mixin = '') { if (!mixin) { shell.echo('---正在读取组件', component.key) const key = component.key const camelizeKey = camelize(key) const cmpName = component.nameCn const desc = readMdDesc(key) const jsStr = shell.cat(`${apiPath}/app/${key}/webdoc/${key}.js`).replace('export default', '(') + ')' const api = eval(jsStr).apis.filter((item) => item.name === key)[0] const props = api?.props || api?.properties || [] const events = api?.events || [] const slots = api?.slots || [] guid++ const componentInfo = { id: guid, version: tinyVer, key, camelizeKey, cmpName, desc, props, events, slots } return componentInfo } else { shell.echo('---正在读取混入的组件', component.key, mixin.key) const key = mixin.key const camelizeKey = camelize(key) const cmpName = mixin.nameCn const desc = mixin.desc const jsStr = shell.cat(`${apiPath}/app/${component.key}/webdoc/${component.key}.js`).replace('export default', '(') + ')' const api = eval(jsStr).apis.filter((item) => item.name === mixin.key)[0] const props = api?.props || api?.properties || [] const events = api?.events || [] const slots = api?.slots || [] guid++ const componentInfo = { id: guid, version: tinyVer, key, camelizeKey, cmpName, desc, props, events, slots } return componentInfo } } // 3. 将结果写bundle.json function write(cb) { shell.ShellString(JSON.stringify(result, null, ' ')).to('gulp/bundle.json') cb() } // 4. 清除 function clean(cb) { shell.rm('gulp/menus.mjs') cb() } // 以下辅助方法 // 转换:button-group ==> ButtonGroup const camelize = (str) => { return str .replace(/-(\w)/g, (_, c) => (c ? c.toUpperCase() : '')) .replace(/^(\w)/g, (_, c) => (c ? c.toUpperCase() : '')) } // 从标签中,提取文字。