Parsing colors in SVG
This function is part of icon manipulation functions in Iconify Tools.
Function parseColors() parses colors in SVG.
It can:
- Find all colors.
- Replace colors.
- Add missing default color.
Function parses colors in:
- Stylesheets.
- Inline styles.
- Shapes, including gradients and filters.
- SVG animations that animate one of color attributes.
Function does not parse colors in:
- Masks.
Usage
Function has the following parameters:
- svg, SVG. Icon instance.
- options, object. Options.
Function returns array of colors.
Colors
Colors used in callback and returned by function can be two types:
- Color object, same as in Iconify Utils.
- string. Value is a string if color cannot be parsed.
Options
The options object has the following properties:
- defaultColor, Color|string. Default color to add to shapes that use system default color. See below.
- callback, function. Callback to call for each color. See below.
Default color
Some icons use system color. Example:
<svg viewBox="0 0 1200 400" xmlns="http://www.w3.org/2000/svg" width="1200" height="400">
<path d="M300 200H150A150 150 0 10300 50z"/>
</svg>
In that icon path uses default fill. In Iconify all icons should use colors set by color attribute, which means shapes should use "currentColor" for fill.
If you set defaultColor option, parser will automatically set color for shapes that use default color.
Example:
import { SVG, parseColors } from '@iconify/tools';
(async () => {
const svg = new SVG(
'<svg viewBox="0 0 1200 400" xmlns="http://www.w3.org/2000/svg" width="1200" height="400"><path d="M300 200H150A150 150 0 10300 50z"/></svg>'
);
// Add 'currentColor' to shapes that use default color
await parseColors(svg, {
defaultColor: 'currentColor',
});
console.log(svg.toMinifiedString());
})();
<svg viewBox="0 0 1200 400" xmlns="http://www.w3.org/2000/svg" width="1200" height="400"><path d="M300 200H150A150 150 0 10300 50z" fill="currentColor"/></svg>
Replacing colors
With callback option you can replace colors.
Callback has the following parameters:
- attr, string. Attribute where color is used, such as "fill" or "stroke".
- colorStr, string. Color value as string.
- color, Color|null. Parsed color value. If color can be parsed, callback will have Color value. If color cannot be parsed, callback will have null value.
- tagName, string. Optional parameter. Name of tag where color is found. If color is found in stylesheet, parameter will be undefined.
Callback should return:
- Color or string to set new color. If you do not want to change color, return color passed to callback (either colorStr or non-null color object).
- "remove" to remove the current element. This is used to remove stuff like white background rectangle left by some editors.
- "unset" to remove color.
Example
import { compareColors, stringToColor } from '@iconify/utils/lib/colors';
import { IconSet, parseColors, isEmptyColor } from '@iconify/tools';
const iconSet = new IconSet({
prefix: 'codicon',
icons: {
'add': {
body: '<path d="M14 7v1H8v6H7V8H1V7h6V1h1v6h6z"/>',
},
'debug-pause': {
body: '<path d="M4.5 3H6v10H4.5V3zm7 0v10H10V3h1.5z" fill="#000"/>',
hidden: true,
},
'triangle-left': {
body: '<path d="M10.44 2l.56.413v11.194l-.54.393L5 8.373v-.827L10.44 2z" fill="#000"/>',
},
},
aliases: {
'plus': {
parent: 'add',
},
'triangle-right': {
parent: 'triangle-left',
hFlip: true,
},
},
});
// Parse all icons in icon set
iconSet.forEach((name, type) => {
if (type !== 'icon') {
// Ignore aliases and variations: they inherit content from parent icon, so there is nothing to change
return;
}
// Get icon as SVG class instance
const svg = iconSet.toSVG(name);
if (svg) {
// Parse colors in SVG instance
parseColors(svg, {
// Change default color to 'currentColor'
defaultColor: 'currentColor',
// Callback to parse each color
callback: (attr, colorStr, color) => {
if (!color) {
// color === null, so color cannot be parsed
// Return colorStr to keep old value
return colorStr;
}
if (isEmptyColor(color)) {
// Color is empty: 'none' or 'transparent'
// Return color object to keep old value
return color;
}
// Black color: change to 'currentColor'
if (compareColors(color, stringToColor('black'))) {
return 'currentColor';
}
// White color: belongs to white background rectangle: remove rectangle
if (compareColors(color, stringToColor('white'))) {
return 'remove';
}
// Unexpected color. Add code to check for it
throw new Error(
`Unexpected color "${colorStr}" in attribute ${attr}`
);
},
});
// Update icon in icon set
iconSet.fromSVG(name, svg);
}
});
// Export icon set
console.log(iconSet.export());
{
"prefix": "codicon",
"icons": {
"add": {
"body": "<path d=\"M14 7v1H8v6H7V8H1V7h6V1h1v6h6z\" fill=\"currentColor\"/>"
},
"debug-pause": {
"body": "<path d=\"M4.5 3H6v10H4.5V3zm7 0v10H10V3h1.5z\" fill=\"currentColor\"/>",
"hidden": true
},
"triangle-left": {
"body": "<path d=\"M10.44 2l.56.413v11.194l-.54.393L5 8.373v-.827L10.44 2z\" fill=\"currentColor\"/>"
}
},
"aliases": {
"plus": {
"parent": "add"
},
"triangle-right": {
"parent": "triangle-left",
"hFlip": true
}
}
}