| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- import fs from 'fs';
- import { SVG, cleanupSVG, parseColors, /*runSVGO,*/ isEmptyColor } from '@iconify/tools';
- import { Plugin } from 'vite';
- interface Options {
- singleColorIconDir?: string;
- multiColorIconDir?: string;
- }
- export default function svgConvert(options: Options = {}): Plugin {
- const {
- singleColorIconDir = 'src/assets/iconify/single-color',
- multiColorIconDir = 'src/assets/iconify/multi-color',
- } = options;
- return {
- name: 'vite-plugin-svg-convert',
- async transform(_, id) {
- // 只处理 SVG 文件
- if (!id.endsWith('.svg')) return null;
- // 检查是否是目标目录下的文件
- const isSingleColor = id.includes(singleColorIconDir);
- const isMultiColor = id.includes(multiColorIconDir);
- if (!isSingleColor && !isMultiColor) return null;
- // 读取 SVG 文件内容
- const svgContent = await fs.promises.readFile(id, 'utf-8');
- // 检查是否包含 image 标签
- if (svgContent.includes('<image')) {
- // 如果是多色图标且包含 image 标签,直接返回原始内容
- if (isMultiColor) {
- const viewBox = svgContent.match(/viewBox="([^"]+)"/)?.[1] || '0 0 1 1';
- const [, , width, height] = viewBox.split(' ').map(Number);
- // 提取 SVG 标签内的内容
- const innerContent = svgContent.replace(/<svg[^>]*>([\s\S]*)<\/svg>/i, '$1');
- return {
- code: `export default {width: ${width}, height: ${height}, body: ${JSON.stringify(innerContent)}}`,
- map: null,
- };
- }
- }
- // 创建 SVG 实例
- const svg = new SVG(svgContent);
- // 清理 SVG
- await cleanupSVG(svg);
- // 根据目录类型选择不同的处理方式
- if (isSingleColor) {
- // 单色图标处理
- parseColors(svg, {
- defaultColor: 'currentColor',
- callback: (_, colorStr, color) => {
- return !color || isEmptyColor(color) ? colorStr : 'currentColor';
- },
- });
- }
- // 获取优化后的 SVG 内容
- const width = svg.viewBox.width;
- const height = svg.viewBox.height;
- // const aspectRatio = height / width;
- // const newWidth = '1rem';
- // const newHeight = `${aspectRatio}rem`;
- // // 运行 SVGO 优化
- // await runSVGO(svg, {
- // plugins: [
- // {
- // name: 'removeAttrs',
- // params: {
- // attrs: ['width', 'height'],
- // },
- // },
- // {
- // name: 'addAttributesToSVGElement',
- // params: {
- // attributes: [{ width: newWidth }, { height: newHeight }],
- // },
- // },
- // ],
- // });
- // 获取优化后的 SVG 内容
- const optimizedSvg = svg.toMinifiedString();
- // 提取 SVG 标签内的内容
- const innerContent = optimizedSvg.replace(/<svg[^>]*>([\s\S]*)<\/svg>/i, '$1');
- // 返回转换后的代码(不生成 sourcemap,避免 Vite 警告)
- return {
- code: `export default {width: ${width}, height: ${height}, body: ${JSON.stringify(innerContent)}}`,
- map: null,
- };
- },
- };
- }
|