svg-generator.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. const fs = require("fs");
  2. const { upperFirst } = require("lodash");
  3. const path = require("path");
  4. let pathName = path.join(__dirname, "../src/assets/icons/svg");
  5. fs.readdir(pathName, function (err, files) {
  6. let icons = [];
  7. (function iterator(i) {
  8. const fileName = files[i];
  9. if (i == files.length) {
  10. fs.writeFileSync(
  11. path.join(__dirname, "../src/assets/icons/index.ts"),
  12. templet_svg(icons)
  13. );
  14. return;
  15. }
  16. let fileUrl = path.join(pathName, fileName);
  17. fs.stat(fileUrl, function (err, data) {
  18. if (data.isFile()) {
  19. const value = formatSvg(fs.readFileSync(fileUrl, "utf-8"));
  20. fs.writeFileSync(fileUrl, value);
  21. const name = ("icon_" + fileName.slice(0, -4))
  22. .split("_")
  23. .map((s) => upperFirst(s))
  24. .join("");
  25. fs.writeFileSync(
  26. path.join(__dirname, `../src/assets/icons/components/${name}.tsx`),
  27. templet_icon({ name, value })
  28. );
  29. icons.push(name);
  30. }
  31. iterator(i + 1);
  32. });
  33. })(0);
  34. });
  35. const templet_svg = template`
  36. export * from "./createIcon";
  37. ${(icons) =>
  38. icons.map((icon) => `export * from "./components/${icon}";`).join("\n")}
  39. `;
  40. const templet_icon = template`
  41. import { createIcon } from '../createIcon';
  42. export const ${(props) => props.name} = createIcon(${(props) => props.value})
  43. `;
  44. function template(arr1, ...arr2) {
  45. return function (props) {
  46. let tpl_str = "";
  47. for (let i = 0; i <= arr1.length; i++) {
  48. tpl_str += (arr1[i] || "") + (arr2[i] ? arr2[i](props) : "");
  49. }
  50. return tpl_str;
  51. };
  52. }
  53. const formatSvg = function (data) {
  54. let classList = {};
  55. let [, styles] = data.match(/<style>((.|\n|\r)+?)<\/style>/) || [];
  56. let [, svgAttr] = data.match(/<svg((.|\n|\r)+?)>/) || [];
  57. const attrs = [];
  58. svgAttr.split(" ").forEach((attr) => {
  59. if (!/^(xmlns|width|height|version|xmlns:xlink|isolation)=/.test(attr)) {
  60. attrs.push(attr);
  61. }
  62. });
  63. let fmtSvgStr = data.replace(/<svg((.|\n|\r)+?)>/, `<svg${attrs.join(" ")}>`);
  64. if (styles) {
  65. styles = styles.replace(/\s/g, "");
  66. const attrs = styles.split(";}");
  67. attrs.forEach((attr) => {
  68. if (!attr) return;
  69. let [cNames, values] = attr.split("{");
  70. valuesObj = {};
  71. values.split(";").forEach((value) => {
  72. let [key, val] = value.split(":");
  73. valuesObj[key] = val;
  74. });
  75. cNames.split(",").forEach((name) => {
  76. name = name.slice(1);
  77. classList[name] = Object.assign({}, classList[name], valuesObj);
  78. });
  79. });
  80. }
  81. fmtSvgStr = fmtSvgStr.replace(/<defs>(.|\n|\r)+?<\/defs>/, "");
  82. for (let className in classList) {
  83. fmtSvgStr = fmtSvgStr.replace(
  84. new RegExp(`class="${className}"`, "g"),
  85. fmtVals(classList[className])
  86. );
  87. }
  88. fmtSvgStr = fmtSvgStr.replace(
  89. / (stroke|fill|class|id|data\-name|p\-id)="(.+?)"/g,
  90. (str, key, value) => {
  91. if (["class", "id", "data-name", "p-id"].indexOf(key) != -1) return "";
  92. if (value === "#000" || value === "#000000") {
  93. return ` ${key}="currentColor"`;
  94. }
  95. return str;
  96. }
  97. );
  98. function fmtVals(obj) {
  99. let valArr = [];
  100. for (let name in obj) {
  101. valArr.push(`${name}="${obj[name]}"`);
  102. }
  103. return valArr.join(" ");
  104. }
  105. return fmtSvgStr;
  106. };