| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- /**
- * 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 <image> tag: extract as-is
- if (!isSingleColor && source.includes('<image')) {
- const viewBox = source.match(/viewBox="([^"]+)"/)?.[1] || '0 0 1 1';
- const parts = viewBox.split(' ').map(Number);
- const width = parts[2] || 1;
- const height = parts[3] || 1;
- const innerContent = source.replace(/<svg[^>]*>([\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(/<svg[^>]*>([\s\S]*)<\/svg>/i, '$1');
- callback(null, `export default ${JSON.stringify({ width, height, body: innerContent })}`);
- } catch (err) {
- callback(err);
- }
- };
|