Socket
Socket
Sign inDemoInstall

svgo

Package Overview
Dependencies
16
Maintainers
4
Versions
99
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.0.3 to 3.0.4

plugins/removeXlink.js

1

lib/builtin.js

@@ -51,2 +51,3 @@ 'use strict';

require('../plugins/removeViewBox.js'),
require('../plugins/removeXlink.js'),
require('../plugins/removeXMLNS.js'),

@@ -53,0 +54,0 @@ require('../plugins/removeXMLProcInst.js'),

2

lib/parser.js

@@ -18,3 +18,3 @@ 'use strict';

const SAX = require('@trysound/sax');
const { textElems } = require('../plugins/_collections.js');
const { textElems } = require('../plugins/_collections');

@@ -21,0 +21,0 @@ class SvgoParserError extends Error {

@@ -15,3 +15,3 @@ 'use strict';

const { textElems } = require('../plugins/_collections.js');
const { textElems } = require('../plugins/_collections');

@@ -37,5 +37,3 @@ /**

/**
* @type {Options}
*/
/** @type {Options} */
const defaults = {

@@ -63,3 +61,3 @@ doctypeStart: '<!DOCTYPE',

regValEntities: /[&"<>]/g,
encodeEntity: encodeEntity,
encodeEntity,
pretty: false,

@@ -71,5 +69,3 @@ useShortTags: true,

/**
* @type {Record<string, string>}
*/
/** @type {Record<string, string>} */
const entities = {

@@ -120,3 +116,3 @@ '&': '&amp;',

let svg = stringifyNode(data, config, state);
if (config.finalNewline && svg.length > 0 && svg[svg.length - 1] !== '\n') {
if (config.finalNewline && svg.length > 0 && !svg.endsWith('\n')) {
svg += eol;

@@ -123,0 +119,0 @@ }

@@ -17,2 +17,3 @@ 'use strict';

const csstree = require('css-tree');
const csswhat = require('css-what');
const {

@@ -92,3 +93,6 @@ // @ts-ignore internal api

if (cssNode.type === 'Atrule') {
if (cssNode.name === 'keyframes') {
if (
cssNode.name === 'keyframes' ||
cssNode.name === '-webkit-keyframes'
) {
return csstreeWalkSkip;

@@ -278,1 +282,55 @@ }

exports.computeStyle = computeStyle;
/**
* Determines if the CSS selector includes or traverses the given attribute.
*
* Classes and IDs are generated as attribute selectors, so you can check for
* if a `.class` or `#id` is included by passing `name=class` or `name=id`
* respectively.
*
* @param {csstree.ListItem<csstree.CssNode>|string} selector
* @param {string} name
* @param {?string} value
* @param {boolean} traversed
* @returns {boolean}
*/
const includesAttrSelector = (
selector,
name,
value = null,
traversed = false
) => {
const selectors =
typeof selector === 'string'
? csswhat.parse(selector)
: csswhat.parse(csstree.generate(selector.data));
for (const subselector of selectors) {
const hasAttrSelector = subselector.some((segment, index) => {
if (traversed) {
if (index === subselector.length - 1) {
return false;
}
const isNextTraversal = csswhat.isTraversal(subselector[index + 1]);
if (!isNextTraversal) {
return false;
}
}
if (segment.type !== 'attribute' || segment.name !== name) {
return false;
}
return value == null ? true : segment.value === value;
});
if (hasAttrSelector) {
return true;
}
}
return false;
};
exports.includesAttrSelector = includesAttrSelector;

@@ -179,1 +179,16 @@ 'use strict';

exports.hasScripts = hasScripts;
/**
* For example, a string that contains one or more of following would match and
* return true:
*
* * `url(#gradient001)`
* * `url('#gradient001')`
*
* @param {string} body
* @returns {boolean} If the given string includes a URL reference.
*/
const includesUrlReference = (body) => {
return /\burl\((["'])?#(.+?)\1\)/g.test(body);
};
exports.includesUrlReference = includesUrlReference;
{
"packageManager": "yarn@2.4.3",
"name": "svgo",
"version": "3.0.3",
"version": "3.0.4",
"description": "Nodejs-based tool for optimizing SVG vector graphics files",

@@ -118,2 +118,3 @@ "license": "MIT",

"css-tree": "^2.2.1",
"css-what": "^6.1.0",
"csso": "5.0.5",

@@ -120,0 +121,0 @@ "picocolors": "^1.0.0"

@@ -96,9 +96,15 @@ 'use strict';

exports.textElems = exports.elemsGroups.textContent.concat('title');
/**
* Elements where adding or removing whitespace may effect rendering, metadata,
* or semantic meaning.
*
* @see https://developer.mozilla.org/docs/Web/HTML/Element/pre
*/
exports.textElems = [...exports.elemsGroups.textContent, 'title', 'pre'];
exports.pathElems = ['path', 'glyph', 'missing-glyph'];
// https://www.w3.org/TR/SVG11/intro.html#Definitions
/**
* @type {Record<string, Array<string>>}
* @see https://www.w3.org/TR/SVG11/intro.html#Definitions
*/

@@ -367,3 +373,2 @@ exports.attrsGroups = {

// https://www.w3.org/TR/SVG11/eltindex.html
/**

@@ -377,2 +382,3 @@ * @type {Record<string, {

* }>}
* @see https://www.w3.org/TR/SVG11/eltindex.html
*/

@@ -1954,3 +1960,5 @@ exports.elems = {

// https://www.w3.org/TR/SVG11/linking.html#processingIRI
/**
* @see https://www.w3.org/TR/SVG11/linking.html#processingIRI
*/
exports.referencesProps = [

@@ -1969,3 +1977,5 @@ 'clip-path',

// https://www.w3.org/TR/SVG11/propidx.html
/**
* @see https://www.w3.org/TR/SVG11/propidx.html
*/
exports.inheritableAttrs = [

@@ -2224,3 +2234,5 @@ 'clip-rule',

// https://www.w3.org/TR/SVG11/single-page.html#types-DataTypeColor
/**
* @see https://www.w3.org/TR/SVG11/single-page.html#types-DataTypeColor
*/
exports.colorsProps = [

@@ -2227,0 +2239,0 @@ 'color',

@@ -15,3 +15,6 @@ 'use strict';

const { path2js } = require('./_path.js');
const { removeLeadingZero } = require('../lib/svgo/tools.js');
const {
removeLeadingZero,
includesUrlReference,
} = require('../lib/svgo/tools.js');
const { referencesProps, attrsGroupsDefaults } = require('./_collections.js');

@@ -39,5 +42,2 @@

enter: (node) => {
const computedStyle = computeStyle(stylesheet, node);
// used only for paths for now
if (node.attributes.d == null) {

@@ -53,3 +53,3 @@ return;

// if there are no 'stroke' attr and references to other objects such as
// gradiends or clip-path which are also subjects to transform.
// gradients or clip-path which are also subjects to transform.
if (

@@ -63,3 +63,3 @@ node.attributes.transform == null ||

([name, value]) =>
referencesProps.includes(name) && value.includes('url(')
referencesProps.includes(name) && includesUrlReference(value)
)

@@ -70,7 +70,19 @@ ) {

const computedStyle = computeStyle(stylesheet, node);
const transformStyle = computedStyle.transform;
// Transform overridden in <style> tag which is not considered
if (
transformStyle.type === 'static' &&
transformStyle.value !== node.attributes.transform
) {
return;
}
const matrix = transformsMultiply(
transform2js(node.attributes.transform)
);
const stroke =
computedStyle.stroke != null && computedStyle.stroke.type === 'static'
computedStyle.stroke?.type === 'static'
? computedStyle.stroke.value

@@ -80,4 +92,3 @@ : null;

const strokeWidth =
computedStyle['stroke-width'] != null &&
computedStyle['stroke-width'].type === 'static'
computedStyle['stroke-width']?.type === 'static'
? computedStyle['stroke-width'].value

@@ -88,6 +99,4 @@ : null;

if (
(computedStyle.stroke != null &&
computedStyle.stroke.type === 'dynamic') ||
(computedStyle.strokeWidth != null &&
computedStyle['stroke-width'].type === 'dynamic')
computedStyle.stroke?.type === 'dynamic' ||
computedStyle['stroke-width']?.type === 'dynamic'
) {

@@ -104,3 +113,3 @@ return;

if (stroke && stroke != 'none') {
if (params.applyTransformsStroked === false) {
if (!params.applyTransformsStroked) {
return;

@@ -107,0 +116,0 @@ }

@@ -25,4 +25,4 @@ 'use strict';

* @type {import('./plugins-types').Plugin<'convertOneStopGradients'>}
* @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
* @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/radialGradient
* @see https://developer.mozilla.org/docs/Web/SVG/Element/linearGradient
* @see https://developer.mozilla.org/docs/Web/SVG/Element/radialGradient
*/

@@ -29,0 +29,0 @@ exports.fn = (root) => {

@@ -49,2 +49,3 @@ 'use strict';

* lineShorthands: boolean,
* convertToZ: boolean,
* curveSmoothShorthands: boolean,

@@ -99,2 +100,3 @@ * floatPrecision: number | false,

lineShorthands = true,
convertToZ = true,
curveSmoothShorthands = true,

@@ -121,2 +123,3 @@ floatPrecision = 3,

lineShorthands,
convertToZ,
curveSmoothShorthands,

@@ -173,2 +176,8 @@ floatPrecision,

const maybeHasStrokeAndLinecap = maybeHasStroke && maybeHasLinecap;
const isSafeToUseZ = maybeHasStroke
? computedStyle['stroke-linecap']?.type === 'static' &&
computedStyle['stroke-linecap'].value === 'round' &&
computedStyle['stroke-linejoin']?.type === 'static' &&
computedStyle['stroke-linejoin'].value === 'round'
: true;

@@ -182,2 +191,3 @@ var data = path2js(node);

data = filters(data, newParams, {
isSafeToUseZ,
maybeHasStrokeAndLinecap,

@@ -379,6 +389,10 @@ hasMarkerMid,

* params: InternalParams,
* aux: { maybeHasStrokeAndLinecap: boolean, hasMarkerMid: boolean }
* aux: { isSafeToUseZ: boolean, maybeHasStrokeAndLinecap: boolean, hasMarkerMid: boolean }
* ) => PathDataItem[]}
*/
function filters(path, params, { maybeHasStrokeAndLinecap, hasMarkerMid }) {
function filters(
path,
params,
{ isSafeToUseZ, maybeHasStrokeAndLinecap, hasMarkerMid }
) {
var stringify = data2Path.bind(null, params),

@@ -673,2 +687,16 @@ relSubpoint = [0, 0],

// convert going home to z
// m 0 0 h 5 v 5 l -5 -5 -> m 0 0 h 5 v 5 z
if (
params.convertToZ &&
(isSafeToUseZ || next?.command === 'Z' || next?.command === 'z') &&
(command === 'l' || command === 'h' || command === 'v')
) {
// @ts-ignore
if (pathBase[0] === item.coords[0] && pathBase[1] === item.coords[1]) {
command = 'z';
data = [];
}
}
// collapse repeated commands

@@ -816,2 +844,12 @@ // h 20 h 30 -> h 50

}
if (
(command === 'Z' || command === 'z') &&
params.removeUseless &&
isSafeToUseZ &&
// @ts-ignore
item.base[0] === item.coords[0] &&
// @ts-ignore
item.base[1] === item.coords[1]
)
return false;

@@ -818,0 +856,0 @@ return true;

'use strict';
/**
* @typedef {import('../lib/types').Specificity} Specificity
* @typedef {import('../lib/types').XastElement} XastElement

@@ -19,3 +18,4 @@ * @typedef {import('../lib/types').XastParent} XastParent

} = require('../lib/xast.js');
const { compareSpecificity } = require('../lib/style');
const { compareSpecificity, includesAttrSelector } = require('../lib/style');
const { attrsGroups } = require('./_collections');

@@ -56,11 +56,8 @@ exports.name = 'inlineStyles';

enter: (node, parentNode) => {
// skip <foreignObject /> content
if (node.name === 'foreignObject') {
return visitSkip;
}
// collect only non-empty <style /> elements
if (node.name !== 'style' || node.children.length === 0) {
return;
}
// values other than the empty string or text/css are not used
if (

@@ -73,12 +70,10 @@ node.attributes.type != null &&

}
// parse css in style element
let cssText = '';
for (const child of node.children) {
if (child.type === 'text' || child.type === 'cdata') {
cssText += child.value;
}
}
/**
* @type {?csstree.CssNode}
*/
const cssText = node.children
.filter((child) => child.type === 'text' || child.type === 'cdata')
// @ts-ignore
.map((child) => child.value)
.join('');
/** @type {?csstree.CssNode} */
let cssAst = null;

@@ -108,10 +103,10 @@ try {

// skip media queries not included into useMqs param
let mq = '';
let mediaQuery = '';
if (atrule != null) {
mq = atrule.name;
mediaQuery = atrule.name;
if (atrule.prelude != null) {
mq += ` ${csstree.generate(atrule.prelude)}`;
mediaQuery += ` ${csstree.generate(atrule.prelude)}`;
}
}
if (useMqs.includes(mq) === false) {
if (!useMqs.includes(mediaQuery)) {
return;

@@ -145,3 +140,4 @@ }

});
if (usePseudos.includes(pseudoSelectors) === false) {
if (!usePseudos.includes(pseudoSelectors)) {
return;

@@ -168,4 +164,4 @@ }

}
// stable sort selectors
const sortedSelectors = [...selectors]
const sortedSelectors = selectors
.slice()
.sort((a, b) => {

@@ -216,5 +212,13 @@ const aSpecificity = specificity(a.item.data);

const styleDeclarationItems = new Map();
/** @type {csstree.ListItem<csstree.CssNode>} */
let firstListItem;
csstree.walk(styleDeclarationList, {
visit: 'Declaration',
enter(node, item) {
if (firstListItem == null) {
firstListItem = item;
}
styleDeclarationItems.set(node.property.toLowerCase(), item);

@@ -231,9 +235,21 @@ },

// inline styles, external styles higher priority than inline styles, external styles used
const matchedItem = styleDeclarationItems.get(
ruleDeclaration.property
);
const property = ruleDeclaration.property;
if (
attrsGroups.presentation.includes(property) &&
!selectors.some((selector) =>
includesAttrSelector(selector.item, property)
)
) {
delete selectedEl.attributes[property];
}
const matchedItem = styleDeclarationItems.get(property);
const ruleDeclarationItem =
styleDeclarationList.children.createItem(ruleDeclaration);
if (matchedItem == null) {
styleDeclarationList.children.append(ruleDeclarationItem);
styleDeclarationList.children.insert(
ruleDeclarationItem,
firstListItem
);
} else if (

@@ -247,6 +263,3 @@ matchedItem.data.important !== true &&

);
styleDeclarationItems.set(
ruleDeclaration.property,
ruleDeclarationItem
);
styleDeclarationItems.set(property, ruleDeclarationItem);
}

@@ -274,3 +287,3 @@ },

// no further processing required
if (removeMatchedSelectors === false) {
if (!removeMatchedSelectors) {
return;

@@ -299,3 +312,8 @@ }

for (const child of selector.node.children) {
if (child.type === 'ClassSelector') {
if (
child.type === 'ClassSelector' &&
!selectors.some((selector) =>
includesAttrSelector(selector.item, 'class', child.name, true)
)
) {
classList.delete(child.name);

@@ -314,5 +332,12 @@ }

if (
firstSubSelector != null &&
firstSubSelector.type === 'IdSelector' &&
selectedEl.attributes.id === firstSubSelector.name
firstSubSelector?.type === 'IdSelector' &&
selectedEl.attributes.id === firstSubSelector.name &&
!selectors.some((selector) =>
includesAttrSelector(
selector.item,
'id',
firstSubSelector.name,
true
)
)
) {

@@ -319,0 +344,0 @@ delete selectedEl.attributes.id;

'use strict';
const { pathElems, referencesProps } = require('./_collections.js');
const { includesUrlReference } = require('../lib/svgo/tools.js');

@@ -39,3 +40,3 @@ exports.name = 'moveGroupAttrsToElems';

([name, value]) =>
referencesProps.includes(name) && value.includes('url(')
referencesProps.includes(name) && includesUrlReference(value)
) === false &&

@@ -42,0 +43,0 @@ node.children.every(

@@ -45,2 +45,3 @@ import type {

lineShorthands?: boolean;
convertToZ?: boolean;
curveSmoothShorthands?: boolean;

@@ -142,3 +143,3 @@ floatPrecision?: number | false;

removeComments: {
preservePatterns: Array<RegExp|string> | false
preservePatterns: Array<RegExp | string> | false;
};

@@ -245,2 +246,12 @@ removeDesc: {

removeStyleElement: void;
removeXlink: {
/**
* By default this plugin ignores legacy elements that were deprecated or
* removed in SVG 2. Set to true to force performing operations on those
* too.
*
* @default false
*/
includeLegacy: boolean
};
removeXMLNS: void;

@@ -247,0 +258,0 @@ reusePaths: void;

@@ -72,3 +72,3 @@ 'use strict';

*
* @link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors|MDN CSS Selectors
* @link https://developer.mozilla.org/docs/Web/CSS/CSS_Selectors|MDN CSS Selectors
*

@@ -75,0 +75,0 @@ * @author Bradley Mease

@@ -15,3 +15,3 @@ 'use strict';

*
* https://developer.mozilla.org/en-US/docs/Web/SVG/Element/desc
* https://developer.mozilla.org/docs/Web/SVG/Element/desc
*

@@ -18,0 +18,0 @@ * @author Daniel Wabyick

@@ -33,3 +33,3 @@ 'use strict';

enter: (node, parentNode) => {
// collect namespace aliases from svg element
// collect namespace prefixes from svg element
if (node.name === 'svg') {

@@ -36,0 +36,0 @@ for (const [name, value] of Object.entries(node.attributes)) {

@@ -11,3 +11,3 @@ 'use strict';

*
* https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title
* https://developer.mozilla.org/docs/Web/SVG/Element/title
*

@@ -14,0 +14,0 @@ * @author Igor Kalashnikov

@@ -25,3 +25,2 @@ 'use strict';

delete node.attributes.xmlns;
delete node.attributes['xmlns:xlink'];
}

@@ -28,0 +27,0 @@ },

@@ -39,3 +39,3 @@ 'use strict';

* @type {XastElement}
* @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs
* @see https://developer.mozilla.org/docs/Web/SVG/Element/defs
*/

@@ -42,0 +42,0 @@ let svgDefs;

<div align="center">
<img src="./logo/logo-web.svg" width="348.61" height="100" alt="SVGO logo"/>
<img src="./logo/logo-web.svg" width="348.61" height="100" alt=""/>
</div>
## SVGO [![npm version](https://img.shields.io/npm/v/svgo)](https://npmjs.org/package/svgo) [![Discord](https://img.shields.io/discord/815166721315831868)](https://discord.gg/z8jX8NYxrE)
# SVGO [![npm](https://img.shields.io/npm/v/svgo)](https://npmjs.org/package/svgo) [![chat](https://img.shields.io/discord/815166721315831868)](https://discord.gg/z8jX8NYxrE) [![docs](https://img.shields.io/badge/docs-svgo.dev-blue)](https://svgo.dev/)
**SVG O**ptimizer is a Node.js-based tool for optimizing SVG vector graphics files.
SVGO, short for **SVG O**ptimizer, is a Node.js library and command-line application for optimizing SVG files.
## Why?
SVG files, especially those exported from various editors, usually contain a lot of redundant and useless information. This can include editor metadata, comments, hidden elements, default or non-optimal values and other stuff that can be safely removed or converted without affecting the SVG rendering result.
SVG files, especially those exported from vector editors, usually contain a lot of redundant information. This includes editor metadata, comments, hidden elements, default or suboptimal values, and other stuff that can be safely removed or converted without impacting rendering.
## Installation
Via npm:
You can install SVGO globablly through npm, yarn, or pnpm. Alternatively, drop the global flag (`global`/`-g`) to use it in your Node.js project.
```sh
npm -g install svgo
```
Via yarn:
```sh
# npm
npm install -g svgo
# yarn
yarn global add svgo
# pnpm
pnpm add -g svgo
```
## CLI usage
## Command-line usage
Processing single files:
Process single files:
```sh
svgo one.svg two.svg -o one.min.svg two.min.svg
```
Processing directory of svg files, recursively using `-f`, `--folder`:
Process a directory of files recursively with `-f`/`--folder`:
```sh
svgo -f ./path/to/folder/with/svg/files -o ./path/to/folder/with/svg/output
svgo -f path/to/directory_with_svgs -o path/to/output_directory
```
Help for advanced usage:
```sh

@@ -41,37 +49,34 @@ svgo --help

SVGO has a plugin-based architecture, separate plugins allows various xml svg optimizations. See [built-in plugins](#built-in-plugins).
SVGO automatically loads configuration from `svgo.config.js` or from `--config ./path/myconfig.js`. Some general options can be configured via CLI.
SVGO has a plugin architecture. You can read more about all plugins in [Plugins | SVGO Documentation](https://svgo.dev/docs/plugins/), and the default plugins in [Preset Default | SVGO Documentation](https://svgo.dev/docs/preset-default/).
SVGO reads the configuration from `svgo.config.js` or the `--config path/to/config.js` command-line option. Some other parameters can be configured though command-line options too.
**`svgo.config.js`**
```js
// svgo.config.js
module.exports = {
multipass: true, // boolean. false by default
datauri: 'enc', // 'base64' (default), 'enc' or 'unenc'.
multipass: false, // boolean
datauri: 'base64', // 'base64'|'enc'|'unenc'
js2svg: {
indent: 2, // string with spaces or number of spaces. 4 by default
pretty: true, // boolean, false by default
indent: 4, // number
pretty: false // boolean
},
plugins: [
// set of built-in plugins enabled by default
'preset-default',
'preset-default', // built-in plugins enabled by default
'prefixIds', // enable built-in plugins by name
// enable built-in plugins by name
'prefixIds',
// or by expanded notation which allows to configure plugin
// enable built-in plugins with an object to configure plugins
{
name: 'sortAttrs',
name: 'prefixIds',
params: {
xmlnsOrder: 'alphabetical',
},
},
],
prefix: 'uwu'
}
}
]
};
```
### Default preset
When extending default configuration specify `preset-default` plugin to enable optimisations.
Each plugin of default preset can be disabled or configured with "overrides" param.
Instead of configuring SVGO from scratch, you can tweak the default preset to suit your needs by configuring or disabling the respective plugin.
**`svgo.config.js`**
```js

@@ -84,35 +89,40 @@ module.exports = {

overrides: {
// customize default plugin options
// disable a default plugin
removeViewBox: false,
// customize the params of a default plugin
inlineStyles: {
onlyMatchedOnce: false,
},
// or disable plugins
removeDoctype: false,
},
},
},
],
}
}
}
}
]
};
```
The default preset includes plugins marked with 'Yes' in the [plugin list](#built-in-plugins) below.
You can find a list of the default plugins in the order they run in [Preset Default | SVGO Documentation](https://svgo.dev/docs/preset-default/#plugins-list).
### Custom plugin
### Custom plugins
It's also possible to specify a custom plugin:
You can also specify custom plugins:
**`svgo.config.js`**
```js
const anotherCustomPlugin = require('./another-custom-plugin.js');
const importedPlugin = require('./imported-plugin');
module.exports = {
plugins: [
// plugin imported from another JavaScript file
importedPlugin,
// plugin defined inline
{
name: 'customPluginName',
name: 'customPlugin',
params: {
optionName: 'optionValue',
paramName: 'paramValue',
},
fn: (ast, params, info) => {},
},
anotherCustomPlugin,
],
fn: (ast, params, info) => {}
}
]
};

@@ -131,8 +141,8 @@ ```

const { optimize } = require('svgo');
const result = optimize(svgString, {
// optional but recommended field
path: 'path-to.svg',
// all config fields are also available here
multipass: true,
path: 'path-to.svg', // recommended
multipass: true // all other config fields are available here
});
const optimizedSvgString = result.data;

@@ -143,10 +153,12 @@ ```

If you write a tool on top of SVGO you might need a way to load SVGO config.
If you write a tool on top of SVGO you may want to resolve the `svgo.config.js` file.
```js
const { loadConfig } = require('svgo');
const config = await loadConfig();
```
You can also specify a relative or absolute path and customize the current working directory.
You can also specify a path and customize the current working directory.
```js

@@ -156,84 +168,15 @@ const config = await loadConfig(configFile, cwd);

## Troubleshooting
### SVG won't scale when CSS is applied on it.
**Observed Problem:** I'm using my SVG files on a website. It looks like the rendered SVG doesn't scale when the dimensions are altered using CSS.
**Possible Solution:** Try disabling `removeViewBox` in the configuration. See [issue #1128](https://github.com/svg/svgo/issues/1128) for details and discussion.
## Built-in plugins
| Plugin | Description | Default |
| ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| [addAttributesToSVGElement](https://github.com/svg/svgo/blob/main/plugins/addAttributesToSVGElement.js) | adds attributes to an outer `<svg>` element | |
| [addClassesToSVGElement](https://github.com/svg/svgo/blob/main/plugins/addClassesToSVGElement.js) | add classnames to an outer `<svg>` element | |
| [cleanupAttrs](https://github.com/svg/svgo/blob/main/plugins/cleanupAttrs.js) | cleanup attributes from newlines, trailing, and repeating spaces | Yes |
| [cleanupEnableBackground](https://github.com/svg/svgo/blob/main/plugins/cleanupEnableBackground.js) | remove or cleanup `enable-background` attribute when possible | Yes |
| [cleanupIds](https://github.com/svg/svgo/blob/main/plugins/cleanupIds.js) | remove unused and minify used IDs | Yes |
| [cleanupListOfValues](https://github.com/svg/svgo/blob/main/plugins/cleanupListOfValues.js) | round numeric values in attributes that take a list of numbers (like `viewBox` or `enable-background`) | |
| [cleanupNumericValues](https://github.com/svg/svgo/blob/main/plugins/cleanupNumericValues.js) | round numeric values to the fixed precision, remove default `px` units | Yes |
| [collapseGroups](https://github.com/svg/svgo/blob/main/plugins/collapseGroups.js) | collapse useless groups | Yes |
| [convertColors](https://github.com/svg/svgo/blob/main/plugins/convertColors.js) | convert colors (from `rgb()` to `#rrggbb`, from `#rrggbb` to `#rgb`) | Yes |
| [convertEllipseToCircle](https://github.com/svg/svgo/blob/main/plugins/convertEllipseToCircle.js) | convert non-eccentric `<ellipse>` to `<circle>` | Yes |
| [convertOneStopGradients](https://github.com/svg/svgo/blob/main/plugins/convertOneStopGradients.js) | converts one-stop (single color) gradients to a plain color | |
| [convertPathData](https://github.com/svg/svgo/blob/main/plugins/convertPathData.js) | convert Path data to relative or absolute (whichever is shorter), convert one segment to another, trim useless delimiters, smart rounding, and much more | Yes |
| [convertShapeToPath](https://github.com/svg/svgo/blob/main/plugins/convertShapeToPath.js) | convert some basic shapes to `<path>` | Yes |
| [convertStyleToAttrs](https://github.com/svg/svgo/blob/main/plugins/convertStyleToAttrs.js) | convert styles into attributes | |
| [convertTransform](https://github.com/svg/svgo/blob/main/plugins/convertTransform.js) | collapse multiple transforms into one, convert matrices to the short aliases, and much more | Yes |
| [inlineStyles](https://github.com/svg/svgo/blob/main/plugins/inlineStyles.js) | move and merge styles from `<style>` elements to element `style` attributes | Yes |
| [mergePaths](https://github.com/svg/svgo/blob/main/plugins/mergePaths.js) | merge multiple Paths into one | Yes |
| [mergeStyles](https://github.com/svg/svgo/blob/main/plugins/mergeStyles.js) | merge multiple style elements into one | Yes |
| [minifyStyles](https://github.com/svg/svgo/blob/main/plugins/minifyStyles.js) | minify `<style>` elements content with [CSSO](https://github.com/css/csso) | Yes |
| [moveElemsAttrsToGroup](https://github.com/svg/svgo/blob/main/plugins/moveElemsAttrsToGroup.js) | move elements' attributes to their enclosing group | Yes |
| [moveGroupAttrsToElems](https://github.com/svg/svgo/blob/main/plugins/moveGroupAttrsToElems.js) | move some group attributes to the contained elements | Yes |
| [prefixIds](https://github.com/svg/svgo/blob/main/plugins/prefixIds.js) | prefix IDs and classes with the SVG filename or an arbitrary string | |
| [removeAttributesBySelector](https://github.com/svg/svgo/blob/main/plugins/removeAttributesBySelector.js) | removes attributes of elements that match a CSS selector | |
| [removeAttrs](https://github.com/svg/svgo/blob/main/plugins/removeAttrs.js) | remove attributes by pattern | |
| [removeComments](https://github.com/svg/svgo/blob/main/plugins/removeComments.js) | remove comments | Yes |
| [removeDesc](https://github.com/svg/svgo/blob/main/plugins/removeDesc.js) | remove `<desc>` | Yes |
| [removeDimensions](https://github.com/svg/svgo/blob/main/plugins/removeDimensions.js) | remove `width`/`height` and add `viewBox` if it's missing (opposite to removeViewBox, disable it first) | |
| [removeDoctype](https://github.com/svg/svgo/blob/main/plugins/removeDoctype.js) | remove `doctype` declaration | Yes |
| [removeEditorsNSData](https://github.com/svg/svgo/blob/main/plugins/removeEditorsNSData.js) | remove editors namespaces, elements, and attributes | Yes |
| [removeElementsByAttr](https://github.com/svg/svgo/blob/main/plugins/removeElementsByAttr.js) | remove arbitrary elements by `ID` or `className` | |
| [removeEmptyAttrs](https://github.com/svg/svgo/blob/main/plugins/removeEmptyAttrs.js) | remove empty attributes | Yes |
| [removeEmptyContainers](https://github.com/svg/svgo/blob/main/plugins/removeEmptyContainers.js) | remove empty Container elements | Yes |
| [removeEmptyText](https://github.com/svg/svgo/blob/main/plugins/removeEmptyText.js) | remove empty Text elements | Yes |
| [removeHiddenElems](https://github.com/svg/svgo/blob/main/plugins/removeHiddenElems.js) | remove hidden elements | Yes |
| [removeMetadata](https://github.com/svg/svgo/blob/main/plugins/removeMetadata.js) | remove `<metadata>` | Yes |
| [removeNonInheritableGroupAttrs](https://github.com/svg/svgo/blob/main/plugins/removeNonInheritableGroupAttrs.js) | remove non-inheritable group's "presentation" attributes | Yes |
| [removeOffCanvasPaths](https://github.com/svg/svgo/blob/main/plugins/removeOffCanvasPaths.js) | removes elements that are drawn outside of the viewbox | |
| [removeRasterImages](https://github.com/svg/svgo/blob/main/plugins/removeRasterImages.js) | remove raster images | |
| [removeScriptElement](https://github.com/svg/svgo/blob/main/plugins/removeScriptElement.js) | remove scripts | |
| [removeStyleElement](https://github.com/svg/svgo/blob/main/plugins/removeStyleElement.js) | remove `<style>` elements | |
| [removeTitle](https://github.com/svg/svgo/blob/main/plugins/removeTitle.js) | remove `<title>` | Yes |
| [removeUnknownsAndDefaults](https://github.com/svg/svgo/blob/main/plugins/removeUnknownsAndDefaults.js) | remove unknown elements content and attributes, remove attributes with default values | Yes |
| [removeUnusedNS](https://github.com/svg/svgo/blob/main/plugins/removeUnusedNS.js) | remove unused namespaces declaration | Yes |
| [removeUselessDefs](https://github.com/svg/svgo/blob/main/plugins/removeUselessDefs.js) | remove elements of `<defs>` without `id` | Yes |
| [removeUselessStrokeAndFill](https://github.com/svg/svgo/blob/main/plugins/removeUselessStrokeAndFill.js) | remove useless `stroke` and `fill` attributes | Yes |
| [removeViewBox](https://github.com/svg/svgo/blob/main/plugins/removeViewBox.js) | remove `viewBox` attribute when possible | Yes |
| [removeXMLNS](https://github.com/svg/svgo/blob/main/plugins/removeXMLNS.js) | removes the `xmlns` attribute (for inline SVG) | |
| [removeXMLProcInst](https://github.com/svg/svgo/blob/main/plugins/removeXMLProcInst.js) | remove XML processing instructions | Yes |
| [reusePaths](https://github.com/svg/svgo/blob/main/plugins/reusePaths.js) | Find duplicated <path> elements and replace them with <use> links | |
| [sortAttrs](https://github.com/svg/svgo/blob/main/plugins/sortAttrs.js) | sort element attributes for epic readability | Yes |
| [sortDefsChildren](https://github.com/svg/svgo/blob/main/plugins/sortDefsChildren.js) | sort children of `<defs>` in order to improve compression | Yes |
## Other ways to use SVGO
| Method | Reference |
| ------ | --------- |
| --- | --- |
| Web app | [SVGOMG](https://jakearchibald.github.io/svgomg/) |
| GitHub Action | [SVGO Action](https://github.com/marketplace/actions/svgo-action) |
| Grunt task | [grunt-svgmin](https://github.com/sindresorhus/grunt-svgmin) |
| Gulp task | [gulp-svgmin](https://github.com/ben-eb/gulp-svgmin) |
| Mimosa module | [mimosa-minify-svg](https://github.com/dbashford/mimosa-minify-svg) |
| OSX Folder Action | [svgo-osx-folder-action](https://github.com/svg/svgo-osx-folder-action) |
| Webpack loader | [image-minimizer-webpack-plugin](https://github.com/webpack-contrib/image-minimizer-webpack-plugin/#optimize-with-svgo) |
| Telegram Bot | [svgo_bot](https://github.com/maksugr/svgo_bot) |
| PostCSS plugin | [postcss-svgo](https://github.com/cssnano/cssnano/tree/master/packages/postcss-svgo) |
| Inkscape plugin | [inkscape-svgo](https://github.com/konsumer/inkscape-svgo) |
| Sketch plugin | [svgo-compressor](https://github.com/BohemianCoding/svgo-compressor) |
| macOS app | [Image Shrinker](https://image-shrinker.com) |
| Rollup plugin | [rollup-plugin-svgo](https://github.com/porsager/rollup-plugin-svgo) |
| VS Code plugin | [vscode-svgo](https://github.com/1000ch/vscode-svgo) |
| Visual Studio Code plugin | [vscode-svgo](https://github.com/1000ch/vscode-svgo) |
| Atom plugin | [atom-svgo](https://github.com/1000ch/atom-svgo) |

@@ -249,4 +192,4 @@ | Sublime plugin | [Sublime-svgo](https://github.com/1000ch/Sublime-svgo) |

| [<img src="https://sheetjs.com/sketch128.png" width="80">](https://sheetjs.com/) | [<img src="https://raw.githubusercontent.com/fontello/fontello/8.0.0/fontello-image.svg" width="80">](https://fontello.com/) |
| :------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------: |
| [SheetJS LLC](https://sheetjs.com/) | [Fontello](https://fontello.com/) |
| :---: | :---: |
| [SheetJS LLC](https://sheetjs.com/) | [Fontello](https://fontello.com/) |

@@ -253,0 +196,0 @@ ## License and Copyright

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc