// vite/vite-plugin-icon-dts.ts import fs from 'fs-extra'; import glob from 'fast-glob'; import path from 'path'; import { useThrottleFn } from '@vueuse/core'; import type { PluginOption } from 'vite'; // glob 默认只支持 / 作为路径分隔符,windows 下会出现问题 const normalizePath = (_path: string) => _path.replace(/\\/g, '/'); interface IconDtsOptions { /** svg 图标文件的路径 */ iconDirs: string; /** 输出的dts文件的路径 */ dts: string; /** 监听变化的延迟时间 */ delay: number; /** 接口名称 */ interfaceName: string; } const defualtOptions: IconDtsOptions = { iconDirs: 'src/icons/', dts: 'svg-icons.d.ts', delay: 200, interfaceName: 'BaseSvgIconPath', }; /** * svg 图标路径生成dts文件 */ export function svgIconPathOption(options: Partial = {}): PluginOption { const finalOptions: IconDtsOptions = { ...defualtOptions, ...options }; const { delay, interfaceName } = finalOptions; let { iconDirs, dts } = finalOptions; iconDirs = normalizePath(iconDirs); dts = normalizePath(dts); let watcher: fs.FSWatcher | undefined = undefined; return { name: 'svg-icons-dts', buildStart: () => { if (!fs.existsSync(iconDirs)) { console.error(`${iconDirs}不存在,请检查`); return; } const update = () => { let assets: string[] = glob.sync(`${iconDirs}/**/*.svg`, {}); assets = assets.map((i: string) => i.replace(iconDirs, '').replace('.svg', '').replace(/\//g, '-').replace(/^-+/, '')); let output = `interface ${interfaceName} {\n`; assets.forEach((_item) => { output += ` '${_item}': string;\n`; }); output += `}\n`; const base = path.dirname(dts); fs.ensureDirSync(base); fs.writeFileSync(dts, output); }; const debounceLogic = useThrottleFn(update, delay); // 监听到文件变化,就重新写一遍 watcher = fs.watch(iconDirs, { recursive: true }, () => { debounceLogic(); }); update(); }, buildEnd: () => { watcher?.close(); }, }; }