build-svg.js 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /**
  2. * 转换svg元素成React组件
  3. */
  4. const svgr = require('@svgr/core').default;
  5. const { optimize } = require('svgo');
  6. const fs = require('fs');
  7. const { resolve, basename, extname } = require('path');
  8. const camelCase = require('camelcase');
  9. const prettier = require('prettier');
  10. /**
  11. *
  12. * @param {*} entryDir 存放svg文件夹
  13. * @param {*} outDir 输出React组件文件夹
  14. * @param {*} decolorize 是否去色
  15. * @param {*} prefix 图标前缀
  16. * @param {*} suffix 图标后缀
  17. */
  18. async function build(entryDir, outDir, prefix, suffix, svgoPlugins = [], svgrOptions = {}) {
  19. const prettierConfig = require(resolve(__dirname, '../.prettierrc.js'));
  20. fs.rmdirSync(outDir, { recursive: true });
  21. fs.mkdirSync(outDir);
  22. // 读取svg文件夹下的文件,转译成React组件,并输出
  23. const files = fs.readdirSync(entryDir, 'utf-8');
  24. const indexFileName = 'index.ts';
  25. const batches = files.filter(f => extname(f) === '.svg').map(async file => {
  26. try {
  27. const svgFileName = basename(file, '.svg');
  28. // 此处为对 ai icon 的特殊处理
  29. let tempName = svgFileName;
  30. if (svgFileName.startsWith('ai_')) {
  31. tempName = tempName.replace('ai_', 'a_i_');
  32. }
  33. const componentName = `${prefix}${camelCase(tempName, { pascalCase: true })}${suffix}`;
  34. const reactFileName = `${componentName}.tsx`;
  35. const svgContent = fs.readFileSync(resolve(entryDir, file), 'utf-8');
  36. const svgProps = {
  37. focusable: '{false}',
  38. 'aria-hidden': true
  39. };
  40. const result = optimize(svgContent, {
  41. plugins: svgoPlugins,
  42. });
  43. const jsxCode = await svgr(result.data, {
  44. plugins: ['@svgr/plugin-jsx'],
  45. svgProps,
  46. iconType: svgFileName,
  47. ...svgrOptions,
  48. });
  49. const formattedCode = prettier.format(jsxCode, prettierConfig);
  50. fs.writeFileSync(resolve(outDir, reactFileName), formattedCode, 'utf-8');
  51. return { fileName: reactFileName, componentName };
  52. } catch (error) {
  53. console.error(error);
  54. throw error;
  55. }
  56. });
  57. const arr = await Promise.all(batches);
  58. const indexFileContent = arr.map(a => `export { default as ${a.componentName} } from './${a.componentName}';`).join('\n');
  59. fs.writeFileSync(resolve(outDir, indexFileName), indexFileContent, 'utf-8');
  60. return arr;
  61. }
  62. module.exports = build;