press-ui
Version:
简单、易用的跨端组件库,兼容 Vue2 和 Vue3,同时支持 uni-app和普通 Vue 项目
216 lines (169 loc) • 5.36 kB
JavaScript
const fs = require('fs');
const path = require('path');
const { replaceAllPolyfill, hyphenate } = require('t-comm');
// eslint-disable-next-line import/order
const glob = require('glob');
replaceAllPolyfill();
const PACKAGE_ENTRY_JS = './src/packages/index.js';
const MAIN_TEMPLATE = `/* eslint-disable import/order */
/* Automatically generated by 'press-ui/script/generate-component-config/generate-entry.js' */
{{install}}
const components = {
{{components}}
};
const install = function (Vue) {
Object.values(components).forEach((component) => {
Vue.component(component.name, component);
});
};
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue);
}
export default {
install,
...components,
};
export * from './packages/common/public/public';
`;
const CSS_BASE = `/* 基础样式 */
@import './packages/common/style/press/index.scss';
@import './packages/common/style/press/var.scss';
/* 组件样式 */
`;
function getAllPressComponents(globMatch) {
const list = glob.sync(globMatch);
const preNames = {};
const compList = list.map((item) => {
const list = item.split('/');
const file = list[list.length - 1];
const componentName = file.replace(/^press-/, '').replace(/\.vue$/, '');
const parsedComponentName = componentName.replace(/(?:^|-)(\w)/g, (_, c) => (c ? c.toUpperCase() : ''));
preNames[parsedComponentName] = (preNames[parsedComponentName] || 0) + 1;
return {
dir: path.dirname(item),
name: componentName,
folder: list[list.length - 2],
componentName: preNames[parsedComponentName] > 1
? parsedComponentName + preNames[parsedComponentName]
: parsedComponentName,
};
});
const componentNameList = compList.map(item => item.componentName);
const importList = compList.map(item => `import ${item.componentName} from './packages/${item.folder}/press-${item.name}.vue';`);
sortByStr(compList, 'name');
sortByStr(importList);
sortByStr(componentNameList);
return {
compList,
importList,
componentNameList,
};
}
function generateIndexScss({ scssPath, globMatch, targetDir }) {
const { compList } = getAllPressComponents(globMatch);
let result = [];
for (const comp of compList) {
const globMatch = `${comp.dir}/css/*`;
const list = glob.sync(globMatch);
sortByStr(list);
result.push(...list.map((item) => {
let relativePath = path.relative(targetDir, item);
if (process.platform === 'win32') {
relativePath = relativePath.replace(/\\/g, '/');
}
const str = `@import './${relativePath}';`;
return str;
}));
}
result = Array.from(new Set(result));
const resultStr = `${CSS_BASE}${result.join('\n')}`;
fs.writeFileSync(scssPath, resultStr, {
encoding: 'utf-8',
});
}
function getComponentPath(component) {
const SPECIAL_COMPONENT_MAP = {
'message-board': 'message-board-list',
};
return SPECIAL_COMPONENT_MAP[component] || component;
}
function sortByStr(list, key) {
list.sort((a, b) => {
const valueA = key ? a[key] : a;
const valueB = key ? b[key] : b;
return valueA.localeCompare(valueB);
// if (valueA - valueB > 0) {
// return 1;
// }
// if (valueA - valueB < 0) {
// return -1;
// }
// return 0;
});
}
function getCompList(componentConfig) {
const importList = [];
const componentNameList = [];
Object.keys(componentConfig)
.forEach((key) => {
const value = componentConfig[key];
const { list } = value;
list.forEach((item) => {
const hyphenatedName = hyphenate(item.name);
const shortName = item.name.replace(/$Press/, '');
const compPath = getComponentPath(hyphenatedName);
importList.push(`import ${shortName} from './packages/press-${hyphenatedName}/press-${compPath}.vue';`);
componentNameList.push(shortName);
});
});
sortByStr(importList);
sortByStr(componentNameList);
return {
importList,
componentNameList,
};
}
function getSrcIndexJs({ componentConfig, allComponent = false, globMatch }) {
let {
importList,
componentNameList,
} = getCompList(componentConfig);
if (allComponent) {
const info = getAllPressComponents(globMatch);
importList = info.importList;
componentNameList = info.componentNameList;
}
const res = MAIN_TEMPLATE
.replace('{{install}}', importList.join('\n'))
.replaceAll('{{components}}', componentNameList.map(item => `${item},`).join('\n '));
return res;
}
function writeSrcIndexJs({
componentConfig,
filePath,
allComponent = false,
scssPath,
globMatch,
targetDir,
}) {
const js = getSrcIndexJs({ componentConfig, allComponent, globMatch });
fs.writeFileSync(filePath, js, {
encoding: 'utf-8',
});
const packageEntryJsContent = getAllPressComponents(globMatch)
.compList
.map((item) => {
const result = (`export { default as ${item.componentName} } from './${item.folder}/press-${item.name}.vue';`);
return result;
})
.join('\n');
generateIndexScss({ scssPath, globMatch, targetDir });
fs.writeFileSync(PACKAGE_ENTRY_JS, `/* eslint-disable no-duplicate-imports */\n${packageEntryJsContent}\n`, {
encoding: 'utf-8',
});
}
module.exports = {
hyphenate,
getComponentPath,
writeSrcIndexJs,
};