生成 icon 组件脚本

83 阅读1分钟

svgx.ts

const axios = require('axios');
const transform = require('@svgr/core').transform;
const fs = require('fs');
const path = require('path');
const lodash = require('lodash');
const prettier = require('prettier');
const prettierrc = require('../../../.prettierrc.js');

type SvgxSourceConfig = { dist: string };

type SvgxConfig = { dist: string };

const svgx = async (svgxConfig: SvgxConfig) => {

  const { dist } = svgxConfig;
  const compNameList: string[] = [];

  if (!dist) {
    console.error('dist 为必填');
  }

  // 指定保存 SVG 文件的目录
  try {
    // 创建输出目录,如果不存在的话
    if (!fs.existsSync(outputDir)) {
      fs.mkdirSync(outputDir, { recursive: true });
    }
       //这里的地址 是 你的图标库的js 链接
    const response = await axios.get('https://at.alicdn.com/t/c/font_4558008_jkghb11o0e8.js');
    const data = response.data;

    // 使用正则表达式提取所有的 <symbol> 标签
    const symbolRegex = /<symbol id="([^"]+)" viewBox="([^"]+)">([\s\S]*?)<\/symbol>/g;
    let match;
    let count = 0;

    while ((match = symbolRegex.exec(data)) !== null) {
      const id = match[1];
      const viewBox = match[2];
      const content = match[3];
      // 获取 path  d 属性
      const pathDAttributeRegex = /d=\"(.*?)\"/;
      const pathDAttribute = content.match(pathDAttributeRegex)?.[0];
      // 提取 icon- 之后的部分
      const iconFileName = lodash.capitalize(lodash.camelCase(id.replace('icon-', '')));
      // 构造一个 SVG 标签替换 <symbol> 标签
      // 生成所需格式的 React 组件
      const formattedComponent =
        `import React from 'react';
         import { CustomSVGProps } from '../type';
         import '../index.less';

         const ${iconFileName} = (props: CustomSVGProps) => (
          <span className={'icon'}>
            <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="${viewBox}" {...props}>
            <path
              fill="currentColor"
              fillRule="nonzero"
              ${pathDAttribute}
            />
            </svg>
        </span>);

        export default ${iconFileName};`

      compNameList.push(iconFileName);

      if (!fs.existsSync(`${dist}/icons/${iconFileName}.tsx`)) {
        fs.writeFileSync(
          `${dist}/icons/${iconFileName}.tsx`,
          prettier.format(formattedComponent, { parser: 'babel', ...prettierrc }),
        );
        count++
      }
      const indexContent = `${compNameList.map((n) => `export { default as ${n} } from "./icons/${n}";`).join('\n')}`;

      fs.writeFileSync(
        `${dist}/index.ts`,
        prettier.format(indexContent, { parser: 'babel-ts', ...prettierrc }),
      );
    }
    console.log(count, 'updated');


  } catch (error) {
    console.error(error);
  }

  return 'public';
}

const svgxConfig = {
  dist: 'src'
}
svgx(svgxConfig);