fileUtil.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. const fs = require('fs');
  2. const SVGO = require('svgo');
  3. let rimraf = require('rimraf');
  4. let mkdirp = require('mkdirp');
  5. let svgConfig = {
  6. plugins: [{
  7. cleanupAttrs: true,
  8. }, {
  9. removeDoctype: true,
  10. }, {
  11. removeXMLProcInst: true,
  12. }, {
  13. removeComments: true,
  14. }, {
  15. removeMetadata: true,
  16. }, {
  17. removeTitle: true,
  18. }, {
  19. removeDesc: true,
  20. }, {
  21. removeUselessDefs: true,
  22. }, {
  23. removeEditorsNSData: true,
  24. }, {
  25. removeEmptyAttrs: true,
  26. }, {
  27. removeHiddenElems: true,
  28. }, {
  29. removeEmptyText: true,
  30. }, {
  31. removeEmptyContainers: true,
  32. }, {
  33. removeViewBox: false,
  34. }, {
  35. cleanUpEnableBackground: true,
  36. }, {
  37. convertStyleToAttrs: true,
  38. }, {
  39. convertColors: false,
  40. }, {
  41. convertPathData: false,
  42. }, {
  43. convertTransform: true,
  44. }, {
  45. removeUnknownsAndDefaults: true,
  46. }, {
  47. removeNonInheritableGroupAttrs: true,
  48. }, {
  49. removeUselessStrokeAndFill: true,
  50. }, {
  51. removeUnusedNS: true,
  52. }, {
  53. cleanupIDs: true,
  54. }, {
  55. cleanupNumericValues: true,
  56. }, {
  57. moveElemsAttrsToGroup: true,
  58. }, {
  59. moveGroupAttrsToElems: true,
  60. }, {
  61. collapseGroups: true,
  62. }, {
  63. removeRasterImages: false,
  64. }, {
  65. mergePaths: false,
  66. }, {
  67. convertShapeToPath: true,
  68. }, {
  69. sortAttrs: true,
  70. }, {
  71. transformsWithOnePath: false,
  72. }, {
  73. removeDimensions: true,
  74. }]
  75. };
  76. module.exports = {
  77. /**
  78. * 递归创建文件夹
  79. *
  80. * @param {String} fPath 文件夹路径
  81. * @return {Object} 成功对象
  82. */
  83. async createDirector (fPath) {
  84. if (!fPath) {
  85. throw new Error('file fPath error');
  86. }
  87. await mkdirp.sync(fPath);
  88. return true;
  89. },
  90. /**
  91. * 读取文件夹中的所有文件
  92. *
  93. * @param {String} fPath 文件夹路径
  94. * @param {Object} options 读取配置
  95. * @return {Array} 文件夹下的文件数组
  96. */
  97. async readDirector (fPath, options) {
  98. if (!fPath) {
  99. throw new Error('file fPath error')
  100. }
  101. return await fs.readdirSync(fPath, options)
  102. },
  103. /**
  104. * 读取文件夹中的文件
  105. *
  106. * @param {String} fPath 文件夹路径
  107. * @param {Object} options 读取配置
  108. * @return {Object} data 文件内容
  109. */
  110. async readFile (fPath, options = {}) {
  111. if (!fPath || !await this.exists(fPath)) {
  112. throw new Error('file fPath error')
  113. }
  114. return await fs.readFileSync(fPath, options);
  115. },
  116. /**
  117. * 删除文件夹中的文件
  118. *
  119. * @param {String} fPath 文件夹路径
  120. * @return {Object} promise
  121. */
  122. async deleteFile (fPath) {
  123. if (!fPath) {
  124. throw new Error('file fPath error')
  125. }
  126. if (this.exists(fPath)) {
  127. return await fs.unlinkSync(fPath);
  128. } else {
  129. return true;
  130. }
  131. },
  132. /**
  133. * 删除文件夹中的文件
  134. *
  135. * @param {String} fPath 文件夹路径
  136. * @return {Object} promise
  137. */
  138. async deleteDirector (fPath) {
  139. if (!fPath) {
  140. throw new Error('file fPath error')
  141. }
  142. await rimraf.sync(fPath);
  143. return true;
  144. },
  145. /**
  146. * 创建文件
  147. *
  148. * @param {String} fPath 文件路径
  149. * @param {String} content 文件内容
  150. * @param {String} encode 文件编码
  151. * @return {void}
  152. */
  153. async createFile (fPath, content, encode = 'utf8') {
  154. if (!fPath) {
  155. throw new Error('file fPath error')
  156. }
  157. return await fs.writeFileSync(fPath, content, encode);
  158. },
  159. /**
  160. * 删除文件夹中的文件
  161. *
  162. * @param {String} fPath 文件夹路径
  163. */
  164. async exists (fPath) {
  165. let result = await fs.existsSync(fPath);
  166. return !!result;
  167. },
  168. /**
  169. * 对svg内容进行处理
  170. *
  171. * @param {String} content 文件内容
  172. * @param {Boolean} resetColor 重置颜色
  173. * @return {Object} 处理后的对象
  174. */
  175. async formatSvgFile (content, resetColor = false) {
  176. // 添加style
  177. let styleValue = 'width: 1em; height: 1em;vertical-align: middle;overflow: hidden;';
  178. if (/style=\"\S*\"/.test(content)) {
  179. content = content.replace(/style="(.*?)"/, `style="${styleValue}"`);
  180. } else {
  181. content = content.replace(/<svg/, `<svg style="${styleValue}"`);
  182. }
  183. if (resetColor) {
  184. svgConfig.plugins.push({
  185. removeAttrs: {attrs: '(stroke|fill)'}
  186. })
  187. }
  188. const svgo = new SVGO(svgConfig);
  189. let result = await svgo.optimize(content);
  190. // 把宽高加到viewBox中
  191. if (result.data.indexOf('viewBox=') === -1 && result.info.width && result.info.height) {
  192. result.data = result.data.replace(/<svg/, `<svg viewBox="0 0 ${result.info.width} ${result.info.height}"`);
  193. }
  194. // todo 需要把svg统一格式,重新绘制
  195. return {
  196. svgPath: content,
  197. iconContent: result.data,
  198. iconOriginContent: content
  199. }
  200. }
  201. }