optimize.mjs 5.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import glob from 'glob'
  2. import { readFileSync, writeFileSync } from 'fs'
  3. import { join, basename } from 'path'
  4. import { optimizePath, ICONS_SRC_DIR } from './helpers.mjs'
  5. glob(join(ICONS_SRC_DIR, '*.svg'), {}, function(er, files) {
  6. files.forEach(function(file, i) {
  7. console.log(`Optimize ${basename(file)}`);
  8. let svgFile = readFileSync(file),
  9. svgFileContent = svgFile.toString()
  10. svgFileContent = svgFileContent.replace(/><\/(polyline|line|rect|circle|path|ellipse)>/g, '/>')
  11. .replace(/rx="([^"]+)"\s+ry="\1"/g, 'rx="$1"')
  12. .replace(/<path stroke="red" stroke-width="\.1"([^>]+)?\/>/g, '')
  13. .replace(/\s?\/>/g, ' />')
  14. .replace(/\n\s*<(line|circle|path|polyline|rect|ellipse)/g, '\n <$1')
  15. // .replace(/polyline points="([0-9.]+)\s([0-9.]+)\s([0-9.]+)\s([0-9.]+)"/g, 'line x1="$1" y1="$2" x2="$3" y2="$4"')
  16. .replace(/<line x1="([^"]+)" y1="([^"]+)" x2="([^"]+)" y2="([^"]+)"\s*\/>/g, function(f, x1, y1, x2, y2) {
  17. return `<path d="M${x1} ${y1}L${x2} ${y2}" />`
  18. })
  19. .replace(/<circle cx="([^"]+)" cy="([^"]+)" r="([^"]+)"\s+\/>/g, function(f, cx, cy, r) {
  20. return `<path d="M ${cx} ${cy}m -${r} 0a ${r} ${r} 0 1 0 ${r * 2} 0a ${r} ${r} 0 1 0 ${r * -2} 0" />`
  21. })
  22. .replace(/<ellipse cx="([^"]+)" cy="([^"]+)" rx="([^"]+)"\s+\/>/g, function(f, cx, cy, rx) {
  23. return `<ellipse cx="${cx}" cy="${cy}" rx="${rx}" ry="${rx}" />`
  24. })
  25. .replace(/<ellipse cx="([^"]+)" cy="([^"]+)" rx="([^"]+)" ry="([^"]+)"\s+\/>/g, function(f, cx, cy, rx, ry) {
  26. return `<path d="M${cx} ${cy}m -${rx} 0a${rx} ${ry} 0 1 0 ${rx * 2} 0a ${rx} ${ry} 0 1 0 -${rx * 2} 0" />`
  27. })
  28. .replace(/<rect width="([^"]+)" height="([^"]+)" x="([^"]+)" y="([^"]+)" rx="([^"]+)"\s+\/>/g, function(f, width, height, x, y, rx) {
  29. return `<rect x="${x}" y="${y}" width="${height}" height="${height}" rx="${rx}" />`
  30. })
  31. .replace(/<rect x="([^"]+)" y="([^"]+)" rx="([^"]+)" width="([^"]+)" height="([^"]+)"\s+\/>/g, function(f, x, y, rx, width, height) {
  32. return `<rect x="${x}" y="${y}" width="${height}" height="${height}" rx="${rx}" />`
  33. })
  34. .replace(/<rect x="([^"]+)" y="([^"]+)" width="([^"]+)" height="([^"]+)" rx="([^"]+)"\s+\/>/g, function(f, x, y, width, height, rx) {
  35. return `<path d="M ${x} ${y}m 0 ${rx}a${rx} ${rx} 0 0 1 ${rx} ${-rx}h${width - rx * 2}a${rx} ${rx} 0 0 1 ${rx} ${rx}v${height - rx *
  36. 2}a${rx} ${rx} 0 0 1 ${-rx} ${rx}h${-width + rx * 2}a${rx} ${rx} 0 0 1 ${-rx} ${-rx}Z" />`
  37. })
  38. .replace(/<rect x="([^"]+)" y="([^"]+)" width="([^"]+)" height="([^"]+)"\s+\/>/g, function(f, x, y, width, height) {
  39. return `<path d="M ${x} ${y}h${width}v${height}h${-width}Z" />`
  40. })
  41. .replace(/<polyline points="([^"]+)\s?"\s+\/>/g, function(f, points) {
  42. const path = points.split(' ').reduce(
  43. (accumulator, currentValue, currentIndex) => `${accumulator}${currentIndex % 2 === 0 ? (currentIndex === 0 ? 'M' : 'L') : ''}${currentValue} `,
  44. ''
  45. )
  46. return `<path d="${path}" />`
  47. })
  48. .replace(/<path\s+d="([^"]+)"/g, function(f, d) {
  49. const d2 = d
  50. .replace(/([0-9]+)+\.00[1-6]/g, (f, m) => `${m}`)
  51. .replace(/([0-9]+)+\.99[4-9]/g, (f, m) => `${parseInt(m) + 1}`)
  52. .replace(/\.99[4-9]/g, (f, m) => `1`)
  53. .replace(/-\.00[1-6]/g, (f, m) => `0`)
  54. .replace(/\.00[1-6]/g, (f, m) => `0`)
  55. .replace(/m0 0/g, (f, m) => ``)
  56. return `<path d="${d2}"`
  57. })
  58. // .replace(/(?<=M[^"]+)"\s+\/>[\n\s\t]+<path d="M(?=([^"]+)"\s+\/>)/g, function() {
  59. // return `M`
  60. // })
  61. .replace(/<path d="([^"]+)"/g, function(f, r1) {
  62. r1 = optimizePath(r1)
  63. return `<path d="${r1}"`
  64. })
  65. .replace(/d="m/g, 'd="M')
  66. .replace(/([Aa])\s?([0-9.]+)[\s,]([0-9.]+)[\s,]([0-9.]+)[\s,]?([0-1])[\s,]?([0-1])[\s,]?(-?[0-9.]+)[\s,]?(-?[0-9.]+)/gi, '$1$2 $3 $4 $5 $6 $7 $8')
  67. .replace(/\n\s+\n+/g, '\n')
  68. .replace(/<path d="M([0-9.]*) ([0-9.]*)l\s?([-0-9.]*) ([-0-9.]*)"/g, function(f, r1, r2, r3, r4) {
  69. return `<line x1="${r1}" y1="${r2}" x2="${addFloats(r1, r3)}" y2="${addFloats(r2, r4)}"`
  70. })
  71. .replace(/<path d="M([0-9.]*) ([0-9.]*)v\s?([-0-9.]*)"/g, function(f, r1, r2, r3) {
  72. return `<line x1="${r1}" y1="${r2}" x2="${r1}" y2="${addFloats(r2, r3)}"`
  73. })
  74. .replace(/<path d="M([0-9.]*) ([0-9.]*)h\s?([-0-9.]*)"/g, function(f, r1, r2, r3) {
  75. return `<line x1="${r1}" y1="${r2}" x2="${addFloats(r1, r3)}" y2="${r2}"`
  76. })
  77. .replace(/<path d="([^"]+)"/g, function(f, r1) {
  78. r1 = r1.replace(/ -0\./g, ' -.').replace(/ 0\./g, ' .').replace(/\s([a-z])/gi, '$1').replace(/([a-z])\s/gi, '$1')
  79. return `<path d="${r1}"`
  80. })
  81. if (!svgFileContent.match(/<svg>[\n\t\s]*<path d="([^"]+)"( fill="currentColor")? \/>[\n\t\s]*<\/svg>/)) {
  82. console.log(`Fix ${file}!`);
  83. }
  84. if (svgFile.toString() !== svgFileContent) {
  85. writeFileSync(file, svgFileContent)
  86. }
  87. })
  88. })