/** * Webpack loader for SVG icons in svgs/ directory. * Transforms SVG files into Iconify-compatible objects: { width, height, body } * - single-color/: replaces fill/stroke colors with currentColor * - multi-color/: preserves original colors */ let iconifyToolsPromise = null; function getIconifyTools() { if (!iconifyToolsPromise) { iconifyToolsPromise = import('@iconify/tools'); } return iconifyToolsPromise; } module.exports = async function svgIconLoader(source) { const callback = this.async(); const resourcePath = this.resourcePath; const isSingleColor = resourcePath.includes('single-color'); try { const { SVG, cleanupSVG, parseColors, isEmptyColor } = await getIconifyTools(); // Multi-color icons containing tag: extract as-is if (!isSingleColor && source.includes(']*>([\s\S]*)<\/svg>/i, '$1'); callback(null, `export default ${JSON.stringify({ width, height, body: innerContent })}`); return; } const svg = new SVG(source); await cleanupSVG(svg); if (isSingleColor) { parseColors(svg, { defaultColor: 'currentColor', callback: (_, colorStr, color) => { return !color || isEmptyColor(color) ? colorStr : 'currentColor'; }, }); } const width = svg.viewBox.width; const height = svg.viewBox.height; const optimizedSvg = svg.toMinifiedString(); const innerContent = optimizedSvg.replace(/]*>([\s\S]*)<\/svg>/i, '$1'); callback(null, `export default ${JSON.stringify({ width, height, body: innerContent })}`); } catch (err) { callback(err); } };