build-icon.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. const fs = require('fs').promises
  2. const util = require('util')
  3. const rimraf = util.promisify(require('rimraf'))
  4. const path = require('path')
  5. const SVGO = require('svgo')
  6. const compiler = require('vue-template-compiler')
  7. const { camelCase, upperFirst } = require('lodash')
  8. const rawDir = '../src/assets/eva-icons'
  9. const outputDir = '../src/components/EvaIcon'
  10. const prefix = 'eva-icon'
  11. const fullRawDir = path.join(__dirname, rawDir)
  12. const fullOutputDir = path.join(__dirname, outputDir)
  13. buildAllSVG(prefix, fullRawDir, fullOutputDir)
  14. const svgoConfig = {
  15. onlyMatchedOnce: false,
  16. plugins: [
  17. {
  18. removeXMLNS: true
  19. },
  20. {
  21. removeAttrs: { attrs: '(stroke|fill|class)' }
  22. },
  23. { removeStyleElement: true },
  24. {
  25. addAttributesToSVGElement: {
  26. attribute: {
  27. fill: 'currentColor',
  28. width: '1em',
  29. height: '1em'
  30. }
  31. }
  32. }
  33. ]
  34. }
  35. const svgo = new SVGO(svgoConfig)
  36. async function buildAllSVG(prefix, inputDir, outputDir) {
  37. try {
  38. await rimraf(outputDir)
  39. console.log('clear output dir')
  40. fs.mkdir(outputDir, { recursive: true })
  41. } catch (e) {
  42. console.log('no cache')
  43. console.log(e)
  44. }
  45. const files = await collectAllSubFilePath(inputDir)
  46. for (const filePath of files) {
  47. const file = await fs.readFile(filePath)
  48. const optimizedSVG = await (await svgo.optimize(file)).data
  49. const svgRender = compiler
  50. .compile(`<i aria-label="icon" class="${prefix}">${optimizedSVG}</i>`)
  51. .render.replace(/_/g, '_vm._')
  52. const fileBasename = path.basename(filePath, '.svg')
  53. const filename = upperFirst(camelCase(`${prefix}-${fileBasename}`))
  54. fs.writeFile(
  55. path.join(outputDir, `${filename}.js`),
  56. `export default {
  57. functional: true,
  58. render(_h,_vm){
  59. ${removeWith(svgRender)}
  60. }
  61. }
  62. `
  63. )
  64. fs.writeFile(
  65. path.join(outputDir, `${filename}.d.ts`),
  66. `declare const ${filename}: any;
  67. export default ${filename};
  68. `
  69. )
  70. fs.appendFile(
  71. path.join(outputDir, 'index.js'),
  72. `export { default as ${filename} } from './${filename}'
  73. `
  74. )
  75. fs.appendFile(
  76. path.join(outputDir, 'index.d.ts'),
  77. `export { default as ${filename} } from './${filename}'
  78. `
  79. )
  80. }
  81. }
  82. function removeWith(str) {
  83. const regex = /^with\(this\)\{(.*)}$/
  84. return regex.exec(str)[1]
  85. }
  86. /**
  87. * get all sub file path
  88. * @param {string} dirPath
  89. * @return {Promise<string[]>} allFilePath
  90. */
  91. async function collectAllSubFilePath(dirPath) {
  92. const fileList = await fs.readdir(dirPath)
  93. const allFiles = []
  94. for (const filename of fileList) {
  95. const filePath = path.join(dirPath, filename)
  96. const fileStat = await fs.stat(filePath)
  97. if (fileStat.isDirectory()) {
  98. const subFileList = await collectAllSubFilePath(filePath)
  99. allFiles.push(...subFileList)
  100. } else {
  101. allFiles.push(filePath)
  102. }
  103. }
  104. return allFiles
  105. }