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(']*>([\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(/]*>([\s\S]*)<\/svg>/i, '$1'); // 返回转换后的代码(不生成 sourcemap,避免 Vite 警告) return { code: `export default {width: ${width}, height: ${height}, body: ${JSON.stringify(innerContent)}}`, map: null, }; }, }; }