scripts/mini-program-site/utils/index.js (154 lines of code) (raw):

const mdastFromMarkdown = require('mdast-util-from-markdown'); const pinyin = require('pinyin'); const fse = require('fs-extra'); const path = require('path'); const coreDir = path.resolve(__dirname, '../../../packages/bui-core/src'); const iconsDir = path.resolve(__dirname, '../../../packages/bui-icons/src'); const flatten = (arr) => { return arr.reduce((result, item) => { return result.concat(Array.isArray(item) ? flatten(item) : item); }, []); }; /** 解析markdown代码模块 */ const parseCodeModules = (modules, theme, index) => { // if (theme.enName === 'Tabs') { // debugger; // } const codeItem = modules.find((moduleItem) => moduleItem.type === 'code'); let code = ''; if (codeItem) { code = codeItem.value; } else { let childrenItem; // 处理<code src="xxx"> const isCodeFlagModule = modules.some((module) => (module.children || []).find((it) => { childrenItem = it; return (it?.value || '')?.includes('<code'); }), ); if (isCodeFlagModule && childrenItem) { const reg = /(?<=src=(['|"])).*?(?=(['|"]))/gi; const relativePath = `${childrenItem.value}`.match(reg)?.[0]; const isSvgIcons = theme.enName === 'Icons'; const rootDir = isSvgIcons ? iconsDir : coreDir; const realPath = path.join( rootDir, isSvgIcons ? './' : theme.enName, relativePath, ); code = fse.readFileSync(realPath, 'utf-8'); if (isSvgIcons) { // TODO 暂时对SVG demo/index.tsx中的import相对路径做特殊处理 code = code .replace('../components', `${iconsDir}/components`) .replace('./index.less', `${iconsDir}/demo/index.less`); } } } const codeModule = { no: index + 1, descriptions: [], componentName: `${theme?.enName}Demo${index + 1}`, code, }; modules.forEach((item) => { const { type, depth, children } = item; const childs = children ? getChildrenValues(children) : []; if ( type !== 'code' && !childs.some((it) => `${it?.value}`?.includes('<code')) ) { if (type === 'list') { childs.forEach((child) => { codeModule.descriptions.push({ type, depth, value: child.value, }); }); } else { codeModule.descriptions.push({ type, depth, value: (childs || []).reduce( (prev, child) => prev.concat(child?.value || ''), '', ), }); } } }); return codeModule; }; const getChildrenValues = (nodeList = [], result = []) => { nodeList.forEach((node) => { if (node.children) { getChildrenValues(node.children, result); } else { const { type, depth, value } = node; result.push({ type, depth, value }); } }); return result; }; /** 解析markdown主题 */ const parseTheme = (theme) => { if (!theme) return; // 截取group:和name:之间的字符串 const groupReg = /(?<=group([:|:]))(.|\n|\r)*?(?=name([:|:]))/gi; const groupStr = theme?.match(groupReg)?.[0]; let groupName = groupStr?.replace(/\s/g, ''), order = 0; if (/title/.test(groupStr)) { // 截取title:和\n之间的字符串 const titleReg = /(?<=title([:|:]\s*))\S*?(?=\n)/gi; groupName = groupStr?.match(titleReg)?.[0]?.replace(/\s/g, ''); } if (/order/.test(groupStr)) { // 截取order:和\n之间的字符串 const orderReg = /(?<=order([:|:]\s*))\S*?(?=\n)/gi; order = groupStr?.match(orderReg)?.[0].replace(/\s/g, ''); order = order ? +order : 0; } const groupEnName = flatten( pinyin(groupName, { style: pinyin.STYLE_NORMAL }), ).join(''); const componentTitle = theme?.split(/name[:|:]/)?.[1]?.trim(); const componentInfo = componentTitle?.split(/\s/)?.filter((item) => !!item); return { order, groupName, groupEnName, componentTitle: componentTitle?.replace(/\s/, ''), enName: componentInfo?.[0], zhName: componentInfo?.[1], }; }; const formatMarkdown = (mdPath) => { const content = fse.readFileSync(mdPath, 'utf-8'); // if (mdPath.includes('Tabs')) { // debugger; // } const mdAst = mdastFromMarkdown(content)?.children || []; const contentAst = mdAst.filter( (item) => ['heading', 'paragraph', 'list'].includes(item.type) || (item.type === 'code' && /^[j|t]sx$/g.test(item?.lang)), ); // contentAst第1项为分组信息,剔除 const themeStr = (contentAst.splice(0, 1)?.[0]?.children || []).find((item) => (item?.value || '')?.includes('group:'), ).value; const theme = parseTheme(themeStr); const codeAstList = []; let inx = 0; contentAst.forEach((child, index) => { const isCodeFlag = (child.children || []).some((it) => it.value?.includes('<code'), ); if (child?.type === 'code' || isCodeFlag) { codeAstList.push(contentAst.slice(inx, index + 1)); inx = index + 1; } }); // if (mdPath.includes('Tabs')) { // codeAstList; // debugger; // } // markdown文件信息 const mdFile = { theme, codeModules: [], }; codeAstList.forEach((modules, index) => { const codeModule = parseCodeModules(modules, theme, index); mdFile.codeModules.push(codeModule); }); return mdFile; }; module.exports = { flatten, formatMarkdown, };