Repository: svg/svgo
Pull request #1060 (2018-11-22 21:01:58)

Add config to preserve IDs based on prefix matching
There is currently an option to opt out of the ID cleanup by specifying IDs that we want left alone. This would also be useful to do on prefixes. That way, we could say, preserve `rect_*`, without having to enumerate all the possibilities of `*`. And, having both prefix and full string matching is useful, so you ca, for example, preserve `rect` specifically but not `rect_blue`.

This change adds another config array that takes in a list of prefix strings, and preserves any IDs that start with one of those prefixes. Also adds tests for this behaviour standalone, and in conjunction with `force` and the full-string ID preserving config.

PTAL @GreLI 

bkotzz: @GreLI can you take a look when you get a chance please?

Patch:
diff --git a/.gitignore b/.gitignore
index 7ab3c06..b7daeed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ bin/svgo-profiling
 *.log
 .DS_Store
 .idea
+.vscode
diff --git a/.svgo.yml b/.svgo.yml
index 313bf7c..eb02b2d 100644
--- a/.svgo.yml
+++ b/.svgo.yml
@@ -55,11 +55,14 @@ plugins:
   - removeDesc
   - removeDimensions
   - removeAttrs
+  - removeAttributesBySelector
   - removeElementsByAttr
   - addClassesToSVGElement
   - removeStyleElement
   - removeScriptElement
   - addAttributesToSVGElement
+  - removeOffCanvasPaths
+  - reusePaths
 
 # configure the indent (default 4 spaces) used by `--pretty` here:
 #
diff --git a/README.md b/README.md
index 66a254a..ea2ef54 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,7 @@ Today we have:
 | [removeNonInheritableGroupAttrs](https://github.com/svg/svgo/blob/master/plugins/removeNonInheritableGroupAttrs.js) | remove non-inheritable group's "presentation" attributes |
 | [removeUselessStrokeAndFill](https://github.com/svg/svgo/blob/master/plugins/removeUselessStrokeAndFill.js) | remove useless `stroke` and `fill` attrs |
 | [removeUnusedNS](https://github.com/svg/svgo/blob/master/plugins/removeUnusedNS.js) | remove unused namespaces declaration |
+| [prefixIds](https://github.com/svg/svgo/blob/master/plugins/prefixIds.js) | prefix IDs and classes with the SVG filename or an arbitrary string |
 | [cleanupIDs](https://github.com/svg/svgo/blob/master/plugins/cleanupIDs.js) | remove unused and minify used IDs |
 | [cleanupNumericValues](https://github.com/svg/svgo/blob/master/plugins/cleanupNumericValues.js) | round numeric values to the fixed precision, remove default `px` units |
 | [cleanupListOfValues](https://github.com/svg/svgo/blob/master/plugins/cleanupListOfValues.js) | round numeric values in attributes that take a list of numbers (like `viewBox` or `enable-background`) |
@@ -58,11 +59,13 @@ Today we have:
 | [sortAttrs](https://github.com/svg/svgo/blob/master/plugins/sortAttrs.js) | sort element attributes for epic readability (disabled by default) |
 | [removeDimensions](https://github.com/svg/svgo/blob/master/plugins/removeDimensions.js) | remove `width`/`height` attributes if `viewBox` is present (opposite to removeViewBox, disable it first) (disabled by default) |
 | [removeAttrs](https://github.com/svg/svgo/blob/master/plugins/removeAttrs.js) | remove attributes by pattern (disabled by default) |
+| [removeAttributesBySelector](https://github.com/svg/svgo/blob/master/plugins/removeAttributesBySelector.js) | removes attributes of elements that match a css selector (disabled by default) |
 | [removeElementsByAttr](https://github.com/svg/svgo/blob/master/plugins/removeElementsByAttr.js) | remove arbitrary elements by ID or className (disabled by default) |
 | [addClassesToSVGElement](https://github.com/svg/svgo/blob/master/plugins/addClassesToSVGElement.js) | add classnames to an outer `<svg>` element (disabled by default) |
 | [addAttributesToSVGElement](https://github.com/svg/svgo/blob/master/plugins/addAttributesToSVGElement.js) | adds attributes to an outer `<svg>` element (disabled by default) |
 | [removeStyleElement](https://github.com/svg/svgo/blob/master/plugins/removeStyleElement.js) | remove `<style>` elements (disabled by default) |
 | [removeScriptElement](https://github.com/svg/svgo/blob/master/plugins/removeScriptElement.js) | remove `<script>` elements (disabled by default) |
+| [reusePaths](https://github.com/svg/svgo/blob/master/plugins/reusePaths.js) | Find duplicated <path> elements and replace them with <use> links. (disabled by default) |
 
 Want to know how it works and how to write your own plugin? [Of course you want to](https://github.com/svg/svgo/blob/master/docs/how-it-works/en.md). ([동작방법](https://github.com/svg/svgo/blob/master/docs/how-it-works/ko.md))
 
@@ -90,8 +93,8 @@ Options:
   -o OUTPUT, --output=OUTPUT : Output file or folder (by default the same as the input), "-" for STDOUT
   -p PRECISION, --precision=PRECISION : Set number of digits in the fractional part, overrides plugins params
   --config=CONFIG : Config file or JSON string to extend or replace default
-  --disable=PLUGIN : Disable plugin by name, "--disable={PLUGIN1,PLUGIN2}" for multiple plugins (*nix)
-  --enable=PLUGIN : Enable plugin by name, "--enable={PLUGIN3,PLUGIN4}" for multiple plugins (*nix)
+  --disable=PLUGIN : Disable plugin by name, "--disable=PLUGIN1,PLUGIN2" for multiple plugins
+  --enable=PLUGIN : Enable plugin by name, "--enable=PLUGIN3,PLUGIN4" for multiple plugins
   --datauri=DATAURI : Output as Data URI string (base64, URI encoded or unencoded)
   --multipass : Enable multipass
   --pretty : Make SVG pretty printed
diff --git a/README.ru.md b/README.ru.md
index 0c53b14..5557d01 100644
--- a/README.ru.md
+++ b/README.ru.md
@@ -46,6 +46,7 @@ SVGO имеет расширяемую архитектуру, в которой
 | [removeNonInheritableGroupAttrs](https://github.com/svg/svgo/blob/master/plugins/removeNonInheritableGroupAttrs.js) | удаление ненаследуемых "презентационных" атрибутов групп |
 | [removeUselessStrokeAndFill](https://github.com/svg/svgo/blob/master/plugins/removeUselessStrokeAndFill.js) | удаление неиспользуемых атрибутов stroke-* и fill-* |
 | [removeUnusedNS](https://github.com/svg/svgo/blob/master/plugins/removeUnusedNS.js) | удаление  деклараций неиспользуемых пространств имён |
+| [prefixIds](https://github.com/svg/svgo/blob/master/plugins/prefixIds.js) | добавляет префикс в ID или классы в виде имени файла или произвольной строки |
 | [cleanupIDs](https://github.com/svg/svgo/blob/master/plugins/cleanupIDs.js) | удаление неиспользуемых и сокращение используемых ID |
 | [cleanupNumericValues](https://github.com/svg/svgo/blob/master/plugins/cleanupNumericValues.js) | округление дробных чисел до заданной точности, удаление `px` как единицы  |измерения по-умолчанию
 | [cleanupListOfValues](https://github.com/svg/svgo/blob/master/plugins/cleanupListOfValues.js) | округление числовых значений в атрибутах со списком чисел, таких как `viewBox`  |или `enableBackground`
diff --git a/lib/svgo/coa.js b/lib/svgo/coa.js
index 012b51e..0b1f177 100644
--- a/lib/svgo/coa.js
+++ b/lib/svgo/coa.js
@@ -5,6 +5,7 @@ require('colors');
 
 var FS = require('fs'),
     PATH = require('path'),
+    mkdirp = require('mkdirp'),
     promisify = require('util.promisify'),
     readdir = promisify(FS.readdir),
     readFile = promisify(FS.readFile),
@@ -14,6 +15,7 @@ var FS = require('fs'),
     PKG = require('../../package.json'),
     encodeSVGDatauri = require('./tools.js').encodeSVGDatauri,
     decodeSVGDatauri = require('./tools.js').decodeSVGDatauri,
+    checkIsDir = require('./tools.js').checkIsDir,
     regSVGFile = /\.svg$/,
     noop = () => {},
     svgo;
@@ -120,6 +122,11 @@ module.exports = require('coa').Cmd()
             return !isNaN(val) ? val : this.reject("Option '--indent' must be an integer number");
         })
         .end()
+    .opt()
+        .name('recursive').title('Use with \'-f\'. Optimizes *.svg files in folders recursively.')
+        .short('r').long('recursive')
+        .flag()
+        .end()
     .opt()
         .name('quiet').title('Only output error messages, not regular status messages')
         .short('q').long('quiet')
@@ -198,6 +205,11 @@ module.exports = require('coa').Cmd()
             config.quiet = opts.quiet;
         }
 
+        // --recursive
+        if (opts.recursive) {
+            config.recursive = opts.recursive;
+        }
+
         // --precision
         if (opts.precision) {
             var precision = Math.min(Math.max(0, parseInt(opts.precision)), 20);
@@ -296,6 +308,8 @@ module.exports = require('coa').Cmd()
  * @return {Object} changed config
  */
 function changePluginsState(names, state, config) {
+    names.forEach(flattenPluginsCbk);
+
     // extend config
     if (config.plugins) {
         for (var name of names) {
@@ -335,6 +349,25 @@ function changePluginsState(names, state, config) {
     return config;
 }
 
+/**
+ * Flatten an array of plugins by invoking this callback on each element
+ * whose value may be a comma separated list of plugins.
+ * 
+ * @param {String} name Plugin name
+ * @param {Number} index Plugin index
+ * @param {Array} names Plugins being traversed
+ */
+function flattenPluginsCbk(name, index, names)
+{
+    var split = name.split(',');
+
+    if(split.length > 1) {
+        names[index] = split.shift();
+        names.push.apply(names, split);
+    }
+
+}
+
 /**
  * Optimize SVG files in a directory.
  * @param {Object} config options
@@ -358,13 +391,46 @@ function optimizeFolder(config, dir, output) {
  * @return {Promise}
  */
 function processDirectory(config, dir, files, output) {
-    // take only *.svg files
-    var svgFiles = files.filter(name => regSVGFile.test(name));
-    return svgFiles.length ?
-        Promise.all(svgFiles.map(name => optimizeFile(config, PATH.resolve(dir, name), PATH.resolve(output, name)))) :
+    // take only *.svg files, recursively if necessary
+    var svgFilesDescriptions = getFilesDescriptions(config, dir, files, output);
+
+    return svgFilesDescriptions.length ?
+        Promise.all(svgFilesDescriptions.map(fileDescription => optimizeFile(config, fileDescription.inputPath, fileDescription.outputPath))) :
         Promise.reject(new Error(`No SVG files have been found in '${dir}' directory.`));
 }
 
+/**
+ * Get svg files descriptions
+ * @param {Object} config options
+ * @param {string} dir input directory
+ * @param {Array} files list of file names in the directory
+ * @param {string} output output directory
+ * @return {Array}
+ */
+function getFilesDescriptions(config, dir, files, output) {
+    const filesInThisFolder = files
+        .filter(name => regSVGFile.test(name))
+        .map(name => ({
+            inputPath: PATH.resolve(dir, name),
+            outputPath: PATH.resolve(output, name),
+        }));
+
+    return config.recursive ?
+        [].concat(
+            filesInThisFolder,
+            files
+                .filter(name => checkIsDir(PATH.resolve(dir, name)))
+                .map(subFolderName => {
+                    const subFolderPath = PATH.resolve(dir, subFolderName);
+                    const subFolderFiles = FS.readdirSync(subFolderPath);
+                    const subFolderOutput = PATH.resolve(output, subFolderName);
+                    return getFilesDescriptions(config, subFolderPath, subFolderFiles, subFolderOutput);
+                })
+                .reduce((a, b) => [].concat(a, b), [])
+        ) :
+        filesInThisFolder;
+}
+
 /**
  * Read SVG file and pass to processing.
  * @param {Object} config options
@@ -423,9 +489,13 @@ function writeOutput(input, output, data) {
         console.log(data);
         return Promise.resolve();
     }
+
+    mkdirp.sync(PATH.dirname(output));
+
     return writeFile(output, data, 'utf8').catch(error => checkWriteFileError(input, output, data, error));
 }
 
+
 /**
  * Write a time taken by optimization.
  * @param {number} time time in milliseconds.
@@ -483,18 +553,6 @@ function checkWriteFileError(input, output, data, error) {
     }
 }
 
-/**
- * Synchronously check if path is a directory. Tolerant to errors like ENOENT.
- * @param {string} path
- */
-function checkIsDir(path) {
-    try {
-        return FS.lstatSync(path).isDirectory();
-    } catch(e) {
-        return false;
-    }
-}
-
 /**
  * Show list of available plugins with short description.
  */
@@ -518,4 +576,4 @@ function printErrorAndExit(error) {
     console.error(error);
     process.exit(1);
     return Promise.reject(error); // for tests
-}
\ No newline at end of file
+}
diff --git a/lib/svgo/tools.js b/lib/svgo/tools.js
index fb52c9d..c6b3c80 100644
--- a/lib/svgo/tools.js
+++ b/lib/svgo/tools.js
@@ -1,5 +1,7 @@
 'use strict';
 
+var FS = require('fs');
+
 /**
  * Encode plain SVG data string into Data URI string.
  *
@@ -148,3 +150,16 @@ var removeLeadingZero = exports.removeLeadingZero = function(num) {
     return strNum;
 
 };
+
+
+/**
+ * Synchronously check if path is a directory. Tolerant to errors like ENOENT.
+ * @param {string} path
+ */
+exports.checkIsDir = function(path) {
+    try {
+        return FS.lstatSync(path).isDirectory();
+    } catch(e) {
+        return false;
+    }
+};
diff --git a/plugins/cleanupIDs.js b/plugins/cleanupIDs.js
index 2b61b93..f1fdc9f 100644
--- a/plugins/cleanupIDs.js
+++ b/plugins/cleanupIDs.js
@@ -11,6 +11,7 @@ exports.params = {
     minify: true,
     prefix: '',
     preserve: [],
+    preservePrefixes: [],
     force: false
 };
 
@@ -41,6 +42,7 @@ exports.fn = function(data, params) {
         referencesIDs = new Map(),
         hasStyleOrScript = false,
         preserveIDs = new Set(Array.isArray(params.preserve) ? params.preserve : params.preserve ? [params.preserve] : []),
+        preserveIDPrefixes = new Set(Array.isArray(params.preservePrefixes) ? params.preservePrefixes : (params.preservePrefixes ? [params.preservePrefixes] : [])),
         idValuePrefix = '#',
         idValuePostfix = '.';
 
@@ -54,7 +56,7 @@ exports.fn = function(data, params) {
         for (var i = 0; i < items.content.length && !hasStyleOrScript; i++) {
             var item = items.content[i];
 
-            // quit if <style> of <script> presents ('force' param prevents quitting)
+            // quit if <style> or <script> present ('force' param prevents quitting)
             if (!params.force) {
                 if (item.isElem(styleOrScript)) {
                     hasStyleOrScript = true;
@@ -124,7 +126,7 @@ exports.fn = function(data, params) {
 
         if (IDs.has(key)) {
             // replace referenced IDs with the minified ones
-            if (params.minify && !preserveIDs.has(key)) {
+            if (params.minify && !preserveIDs.has(key) && !idMatchesPrefix(preserveIDPrefixes, key)) {
                 currentIDstring = getIDstring(currentID = generateID(currentID), params);
                 IDs.get(key).attr('id').value = currentIDstring;
 
@@ -141,7 +143,7 @@ exports.fn = function(data, params) {
     // remove non-referenced IDs attributes from elements
     if (params.remove) {
         for(var keyElem of IDs) {
-            if (!preserveIDs.has(keyElem[0])) {
+            if (!preserveIDs.has(keyElem[0]) && !idMatchesPrefix(preserveIDPrefixes, keyElem[0])) {
                 keyElem[1].removeAttr('id');
             }
         }
@@ -149,6 +151,20 @@ exports.fn = function(data, params) {
     return data;
 };
 
+/**
+ * Check if an ID starts with any one of a list of strings.
+ *
+ * @param {Array} of prefix strings
+ * @param {String} current ID
+ * @return {Boolean} if currentID starts with one of the strings in prefixArray
+ */
+function idMatchesPrefix(prefixArray, currentID) {
+    if (!currentID) return false;
+
+    for (var prefix of prefixArray) if (currentID.startsWith(prefix)) return true;
+    return false;
+}
+
 /**
  * Generate unique minimal ID.
  *
diff --git a/plugins/removeAttributesBySelector.js b/plugins/removeAttributesBySelector.js
new file mode 100644
index 0000000..3ae7463
--- /dev/null
+++ b/plugins/removeAttributesBySelector.js
@@ -0,0 +1,70 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes attributes of elements that match a css selector';
+
+
+/**
+ * Removes attributes of elements that match a css selector.
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @example
+ * <caption>A selector removing a single attribute</caption>
+ * plugins:
+ *   - removeAttributesBySelector:
+ *       selector: "[fill='#00ff00']"
+ *       attributes: "fill"
+ *
+ * <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
+ *   ↓
+ * <rect x="0" y="0" width="100" height="100" stroke="#00ff00"/>     
+ *
+ * <caption>A selector removing multiple attributes</caption>
+ * plugins:
+ *   - removeAttributesBySelector:
+ *       selector: "[fill='#00ff00']"
+ *       attributes:
+ *         - fill
+ *         - stroke
+ *
+ * <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
+ *   ↓
+ * <rect x="0" y="0" width="100" height="100"/>     
+ *
+ * <caption>Multiple selectors removing attributes</caption>
+ * plugins:
+ *   - removeAttributesBySelector:
+ *       selectors:
+ *         - selector: "[fill='#00ff00']"
+ *           attributes: "fill"
+ *
+ *         - selector: "#remove"
+ *           attributes:
+ *             - stroke
+ *             - id
+ *
+ * <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
+ *   ↓
+ * <rect x="0" y="0" width="100" height="100"/>
+ *
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors|MDN CSS Selectors}
+ *
+ * @author Bradley Mease
+ */
+exports.fn = function(item, params) {
+
+    var selectors = Array.isArray(params.selectors) ? params.selectors : [params];
+
+    selectors.map(function(i) {
+        if (item.matches(i.selector)) {
+            item.removeAttr(i.attributes);
+        }
+    });
+
+};
diff --git a/plugins/removeAttrs.js b/plugins/removeAttrs.js
index c8968c2..0ee35f2 100644
--- a/plugins/removeAttrs.js
+++ b/plugins/removeAttrs.js
@@ -10,6 +10,7 @@ exports.description = 'removes specified attributes';
 
 exports.params = {
     elemSeparator: DEFAULT_SEPARATOR,
+    preserveCurrentColor: false,
     attrs: []
 };
 
@@ -19,6 +20,9 @@ exports.params = {
  * @param elemSeparator
  *   format: string
  *
+ * @param preserveCurrentColor
+ *   format: boolean
+ *
  * @param attrs:
  *
  *   format: [ element* : attribute* ]
@@ -69,7 +73,6 @@ exports.params = {
  * @author Benny Schudel
  */
 exports.fn = function(item, params) {
-
         // wrap into an array if params is not
     if (!Array.isArray(params.attrs)) {
         params.attrs = [params.attrs];
@@ -77,6 +80,7 @@ exports.fn = function(item, params) {
 
     if (item.isElem()) {
         var elemSeparator = typeof params.elemSeparator == 'string' ? params.elemSeparator : DEFAULT_SEPARATOR;
+        var preserveCurrentColor = typeof params.preserveCurrentColor == 'boolean' ? params.preserveCurrentColor : false;
 
             // prepare patterns
         var patterns = params.attrs.map(function(pattern) {
@@ -107,10 +111,15 @@ exports.fn = function(item, params) {
                     // loop attributes
                 item.eachAttr(function(attr) {
                     var name = attr.name;
+                    var value = attr.value;
+                    var isFillCurrentColor = preserveCurrentColor && name == 'fill' && value == 'currentColor';
+                    var isStrokeCurrentColor = preserveCurrentColor && name == 'stroke' && value == 'currentColor';
 
+                    if (!(isFillCurrentColor || isStrokeCurrentColor)) {
                         // matches attribute name
-                    if (pattern[1].test(name)) {
-                        item.removeAttr(name);
+                        if (pattern[1].test(name)) {
+                            item.removeAttr(name);
+                        }
                     }
 
                 });
diff --git a/plugins/removeOffCanvasPaths.js b/plugins/removeOffCanvasPaths.js
new file mode 100644
index 0000000..5bcb9a1
--- /dev/null
+++ b/plugins/removeOffCanvasPaths.js
@@ -0,0 +1,133 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes elements that are drawn outside of the viewbox (disabled by default)';
+
+var SVGO       = require('../lib/svgo.js'),
+	_path      = require('./_path.js'),
+	intersects = _path.intersects,
+	path2js    = _path.path2js,
+	viewBox,
+	viewBoxJS;
+
+/**
+ * Remove elements that are drawn outside of the viewbox.
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author JoshyPHP
+ */
+exports.fn = function(item) {
+
+	if (item.isElem('path') && item.hasAttr('d') && typeof viewBox !== 'undefined')
+	{
+		// Consider that any item with a transform attribute or a M instruction
+		// within the viewBox is visible
+		if (hasTransform(item) || pathMovesWithinViewBox(item.attr('d').value))
+		{
+			return true;
+		}
+
+		var pathJS = path2js(item);
+		if (pathJS.length === 2)
+		{
+			// Use a closed clone of the path if it's too short for intersects()
+			pathJS = JSON.parse(JSON.stringify(pathJS));
+			pathJS.push({ instruction: 'z' });
+		}
+
+		return intersects(viewBoxJS, pathJS);
+	}
+	if (item.isElem('svg'))
+	{
+		parseViewBox(item);
+	}
+
+	return true;
+};
+
+/**
+ * Test whether given item or any of its ancestors has a transform attribute.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ */
+function hasTransform(item)
+{
+	return item.hasAttr('transform') || (item.parentNode && hasTransform(item.parentNode));
+}
+
+/**
+ * Parse the viewBox coordinates and compute the JS representation of its path.
+ *
+ * @param {Object} svg svg element item
+ */
+function parseViewBox(svg)
+{
+	var viewBoxData = '';
+	if (svg.hasAttr('viewBox'))
+	{
+		// Remove commas and plus signs, normalize and trim whitespace
+		viewBoxData = svg.attr('viewBox').value;
+	}
+	else if (svg.hasAttr('height') && svg.hasAttr('width'))
+	{
+		viewBoxData = '0 0 ' + svg.attr('width').value + ' ' + svg.attr('height').value;
+	}
+
+	// Remove commas and plus signs, normalize and trim whitespace
+	viewBoxData = viewBoxData.replace(/[,+]|px/g, ' ').replace(/\s+/g, ' ').replace(/^\s*|\s*$/g, '');
+
+	// Ensure that the dimensions are 4 values separated by space
+	var m = /^(-?\d*\.?\d+) (-?\d*\.?\d+) (\d*\.?\d+) (\d*\.?\d+)$/.exec(viewBoxData);
+	if (!m)
+	{
+		return;
+	}
+
+	// Store the viewBox boundaries
+	viewBox = {
+		left:   parseFloat(m[1]),
+		top:    parseFloat(m[2]),
+		right:  parseFloat(m[1]) + parseFloat(m[3]),
+		bottom: parseFloat(m[2]) + parseFloat(m[4])
+	};
+
+	var path = new SVGO().createContentItem({
+		elem:   'path',
+		prefix: '',
+		local:  'path'
+	});
+	path.addAttr({
+		name:   'd',
+		prefix: '',
+		local:  'd',
+		value:  'M' + m[1] + ' ' + m[2] + 'h' + m[3] + 'v' + m[4] + 'H' + m[1] + 'z'
+	});
+
+	viewBoxJS = path2js(path);
+}
+
+/**
+ * Test whether given path has a M instruction with coordinates within the viewBox.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ */
+function pathMovesWithinViewBox(path)
+{
+	var regexp = /M\s*(-?\d*\.?\d+)(?!\d)\s*(-?\d*\.?\d+)/g, m;
+	while (null !== (m = regexp.exec(path)))
+	{
+		if (m[1] >= viewBox.left && m[1] <= viewBox.right && m[2] >= viewBox.top && m[2] <= viewBox.bottom)
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
diff --git a/plugins/reusePaths.js b/plugins/reusePaths.js
new file mode 100644
index 0000000..ba097da
--- /dev/null
+++ b/plugins/reusePaths.js
@@ -0,0 +1,168 @@
+/**
+ * @license
+ * The MIT License
+ *
+ * Copyright © 2012–2016 Kir Belevich
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ *
+ * Лицензия MIT
+ *
+ * Copyright © 2012–2016 Кир Белевич
+ *
+ * Данная лицензия разрешает лицам, получившим копию
+ * данного
+ * программного обеспечения и сопутствующей
+ * документации
+ * (в дальнейшем именуемыми «Программное Обеспечение»),
+ * безвозмездно
+ * использовать Программное Обеспечение без
+ * ограничений, включая
+ * неограниченное право на использование, копирование,
+ * изменение,
+ * добавление, публикацию, распространение,
+ * сублицензирование
+ * и/или продажу копий Программного Обеспечения, также
+ * как и лицам,
+ * которым предоставляется данное Программное
+ * Обеспечение,
+ * при соблюдении следующих условий:
+ *
+ * Указанное выше уведомление об авторском праве и
+ * данные условия
+ * должны быть включены во все копии или значимые части
+ * данного
+ * Программного Обеспечения.
+ *
+ * ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК
+ * ЕСТЬ»,
+ * БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ
+ * ПОДРАЗУМЕВАЕМЫХ,
+ * ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОВАРНОЙ
+ * ПРИГОДНОСТИ,
+ * СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И
+ * ОТСУТСТВИЯ НАРУШЕНИЙ
+ * ПРАВ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ
+ * НЕСУТ
+ * ОТВЕТСТВЕННОСТИ ПО ИСКАМ О ВОЗМЕЩЕНИИ УЩЕРБА, УБЫТКОВ
+ * ИЛИ ДРУГИХ
+ * ТРЕБОВАНИЙ ПО ДЕЙСТВУЮЩИМ КОНТРАКТАМ, ДЕЛИКТАМ ИЛИ
+ * ИНОМУ,
+ * ВОЗНИКШИМ ИЗ, ИМЕЮЩИМ ПРИЧИНОЙ ИЛИ СВЯЗАННЫМ С
+ * ПРОГРАММНЫМ
+ * ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ПРОГРАММНОГО
+ * ОБЕСПЕЧЕНИЯ
+ * ИЛИ ИНЫМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
+ */
+
+'use strict';
+
+var JSAPI = require('../lib/svgo/jsAPI');
+
+exports.type = 'full';
+
+exports.active = false;
+
+exports.description = 'Finds <path> elements with the same d, fill, and ' +
+                      'stroke, and converts them to <use> elements ' +
+                      'referencing a single <path> def.';
+
+/**
+ * Finds <path> elements with the same d, fill, and stroke, and converts them to
+ * <use> elements referencing a single <path> def.
+ *
+ * @author Jacob Howcroft
+ */
+exports.fn = function(data) {
+  const seen = new Map();
+  let count = 0;
+  const defs = [];
+  traverse(data, item => {
+    if (!item.isElem('path') || !item.hasAttr('d')) {
+      return;
+    }
+    const d = item.attr('d').value;
+    const fill = (item.hasAttr('fill') && item.attr('fill').value) || '';
+    const stroke = (item.hasAttr('stroke') && item.attr('stroke').value) || '';
+    const key = d + ';s:' + stroke + ';f:' + fill;
+    const hasSeen = seen.get(key);
+    if (!hasSeen) {
+      seen.set(key, {elem: item, reused: false});
+      return;
+    }
+    if (!hasSeen.reused) {
+      hasSeen.reused = true;
+      if (!hasSeen.elem.hasAttr('id')) {
+        hasSeen.elem.addAttr({name: 'id', local: 'id',
+                              prefix: '', value: 'reuse-' + (count++)});
+      }
+      defs.push(hasSeen.elem);
+    }
+    item = convertToUse(item, hasSeen.elem.attr('id').value);
+  });
+  const defsTag = new JSAPI({
+    elem: 'defs', prefix: '', local: 'defs', content: [], attrs: []}, data);
+  data.content[0].spliceContent(0, 0, defsTag);
+  for (let def of defs) {
+    // Remove class and style before copying to avoid circular refs in
+    // JSON.stringify. This is fine because we don't actually want class or
+    // style information to be copied.
+    const style = def.style;
+    const defClass = def.class;
+    delete def.style;
+    delete def.class;
+    const defClone = def.clone();
+    def.style = style;
+    def.class = defClass;
+    defClone.removeAttr('transform');
+    defsTag.spliceContent(0, 0, defClone);
+    // Convert the original def to a use so the first usage isn't duplicated.
+    def = convertToUse(def, defClone.attr('id').value);
+    def.removeAttr('id');
+  }
+  return data;
+};
+
+/** */
+function convertToUse(item, href) {
+  item.renameElem('use');
+  item.removeAttr('d');
+  item.removeAttr('stroke');
+  item.removeAttr('fill');
+  item.addAttr({name: 'xlink:href', local: 'xlink:href',
+                prefix: 'none', value: '#' + href});
+  delete item.pathJS;
+  return item;
+}
+
+/** */
+function traverse(parent, callback) {
+  if (parent.isEmpty()) {
+    return;
+  }
+  for (let child of parent.content) {
+    callback(child);
+    traverse(child, callback);
+  }
+}


Test patch:
diff --git a/test/coa/_index.js b/test/coa/_index.js
index 14820f9..ada38de 100644
--- a/test/coa/_index.js
+++ b/test/coa/_index.js
@@ -7,9 +7,11 @@ const fs = require('fs'),
     path = require('path'),
     svgPath = path.resolve(__dirname, 'test.svg'),
     svgFolderPath = path.resolve(__dirname, 'testSvg'),
+    svgFolderPathRecursively = path.resolve(__dirname, 'testSvgRecursively'),
     svgFiles = [path.resolve(__dirname, 'testSvg/test.svg'), path.resolve(__dirname, 'testSvg/test.1.svg')],
     tempFolder = 'temp',
     fse = require('fs-extra'),
+    checkIsDir = require('../../lib/svgo/tools.js').checkIsDir,
     noop = () => {};
 
 describe('coa', function() {
@@ -49,8 +51,10 @@ describe('coa', function() {
     }
 
     function calcFolderSvgWeight(folderPath) {
-        return fs.readdirSync(folderPath).reduce((initWeight, fileName) => (
-            initWeight + (/.svg/.test(fileName) ? fs.statSync(path.join(folderPath, fileName)).size : 0)
+        return fs.readdirSync(folderPath).reduce((initWeight, name) => (
+            initWeight +
+                (/.svg/.test(name) ? fs.statSync(path.join(folderPath, name)).size : 0) +
+                (checkIsDir(path.join(folderPath, name)) ? calcFolderSvgWeight(path.join(folderPath, name)) : 0)
         ), 0);
     }
 
@@ -82,6 +86,16 @@ describe('coa', function() {
         }, error => done(error));
     });
 
+    it('should optimize folder recursively', function(done) {
+        const initWeight = calcFolderSvgWeight(svgFolderPathRecursively);
+
+        svgo({ folder: svgFolderPathRecursively, output: tempFolder, quiet: true, recursive: true }).then(function() {
+            const optimizedWeight = calcFolderSvgWeight(svgFolderPathRecursively);
+
+            done(optimizedWeight > 0 && initWeight <= optimizedWeight ? null : 'Folder was not optimized');
+        }, error => done(error));
+    });
+
     it('should optimize file', function(done) {
         const initialFileLength = fs.readFileSync(path.resolve(__dirname, 'test.svg')).length;
 
diff --git a/test/coa/testSvgRecursively/depth-1/depth-2/test.1.svg b/test/coa/testSvgRecursively/depth-1/depth-2/test.1.svg
new file mode 100644
index 0000000..de7975d
--- /dev/null
+++ b/test/coa/testSvgRecursively/depth-1/depth-2/test.1.svg
@@ -0,0 +1,1 @@
+<!--! https://github.com/svg/svgo--><!--! SVGO project logo by Yegor Bolshakov (http://xizzzy.ru/)--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512"><defs><path id="a" d="M512 274.094v-36.191l-31.59-5.743a224.595 224.595 0 0 0-7.93-40.031l26.958-17.377-13.852-33.438-31.354 6.776a226.088 226.088 0 0 0-22.705-33.898l18.286-26.415-25.594-25.591-26.409 18.285a226.197 226.197 0 0 0-33.898-22.706l6.773-31.354-33.437-13.851-17.376 26.958a224.75 224.75 0 0 0-40.032-7.931L274.098 0h-36.193l-5.744 31.59a224.512 224.512 0 0 0-40.033 7.931l-17.376-26.959-33.438 13.851 6.776 31.354a226.053 226.053 0 0 0-33.899 22.706L87.776 62.185l-25.591 25.59 18.287 26.415a226.089 226.089 0 0 0-22.705 33.898l-31.355-6.776-13.85 33.438 26.959 17.377a224.567 224.567 0 0 0-7.93 40.03L0 237.902v36.191l31.59 5.744a224.484 224.484 0 0 0 7.931 40.032l-26.959 17.378 13.85 33.435 31.355-6.773a226.012 226.012 0 0 0 22.705 33.898l-18.287 26.414 25.591 25.593 26.415-18.287a225.977 225.977 0 0 0 33.899 22.706l-6.776 31.354 33.438 13.852 17.377-26.958a224.932 224.932 0 0 0 40.031 7.93l5.744 31.59h36.192l5.744-31.59a224.62 224.62 0 0 0 40.03-7.93l17.378 26.957 33.436-13.852-6.772-31.354a226.06 226.06 0 0 0 33.897-22.706l26.414 18.286 25.593-25.593-18.286-26.412a226.486 226.486 0 0 0 22.706-33.899l31.354 6.772 13.853-33.435-26.958-17.377a224.943 224.943 0 0 0 7.93-40.032L512 274.094z"/></defs><clipPath id="b"><use xlink:href="#a" overflow="visible"/></clipPath><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="480.818" y1="380.617" x2="31.183" y2="131.38"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><circle clip-path="url(#b)" fill="url(#c)" cx="256" cy="255.998" r="257"/><radialGradient id="d" cx="256" cy="255.998" r="257" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".73" stop-color="#004ED4" stop-opacity=".4"/><stop offset=".784" stop-color="#437CDE" stop-opacity=".319"/><stop offset=".842" stop-color="#83A8E7" stop-opacity=".234"/><stop offset=".894" stop-color="#B5CAEE" stop-opacity=".157"/><stop offset=".94" stop-color="#DAE3F4" stop-opacity=".089"/><stop offset=".977" stop-color="#F0F2F7" stop-opacity=".035"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><circle clip-path="url(#b)" fill="url(#d)" cx="256" cy="255.998" r="257"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="352.299" y1="494.346" x2="159.701" y2="17.65"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#e)" cx="256" cy="255.998" r="257"/><radialGradient id="f" cx="256" cy="255.998" r="257" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".8" stop-color="#6B6B6B" stop-opacity="0"/><stop offset=".826" stop-color="#848484" stop-opacity=".02"/><stop offset=".883" stop-color="#B5B5B5" stop-opacity=".066"/><stop offset=".933" stop-color="#DADADA" stop-opacity=".107"/><stop offset=".974" stop-color="#F0F0F0" stop-opacity=".139"/><stop offset="1" stop-color="#F8F8F8" stop-opacity=".16"/></radialGradient><circle clip-path="url(#b)" fill="url(#f)" cx="256" cy="255.998" r="257"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="74.274" y1="437.724" x2="437.726" y2="74.272"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#g)" cx="256" cy="255.998" r="257"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="45.46" y1="403.419" x2="466.539" y2="108.576"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#h)" cx="256" cy="255.998" r="257"/><defs><path id="i" d="M256.001 50.999C142.777 50.999 51 142.774 51 255.998s91.777 204.999 205.001 204.999C369.226 460.997 461 369.222 461 255.998S369.226 50.999 256.001 50.999z"/></defs><clipPath id="j"><use xlink:href="#i" overflow="visible"/></clipPath><linearGradient id="k" gradientUnits="userSpaceOnUse" x1="441.158" y1="358.64" x2="70.835" y2="153.366" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><path clip-path="url(#j)" fill="url(#k)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><radialGradient id="l" cx="255.997" cy="256.006" r="217.969" gradientTransform="matrix(0 -.971 .971 0 7.396 504.601)" gradientUnits="userSpaceOnUse"><stop offset=".86" stop-color="#0058D4" stop-opacity=".6"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#j)" fill="url(#l)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="m" gradientUnits="userSpaceOnUse" x1="335.313" y1="452.313" x2="176.686" y2="59.7" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#m)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="n" gradientUnits="userSpaceOnUse" x1="106.329" y1="405.673" x2="405.669" y2="106.333" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#n)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="o" gradientUnits="userSpaceOnUse" x1="82.599" y1="377.421" x2="429.401" y2="134.588" gradientTransform="rotate(-90 256 256)"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#o)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><defs><path id="p" d="M446 255.999c0-104.932-85.066-190-190-190s-190 85.068-190 190c0 104.934 85.066 189.998 190 189.998s190-85.064 190-189.998z"/></defs><clipPath id="q"><use xlink:href="#p" overflow="visible"/></clipPath><linearGradient id="r" gradientUnits="userSpaceOnUse" x1="427.61" y1="351.133" x2="84.388" y2="160.881"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><path clip-path="url(#q)" fill="url(#r)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><radialGradient id="s" cx="260.891" cy="260.9" r="191.461" gradientTransform="matrix(.971 0 0 .971 7.397 7.398)" gradientUnits="userSpaceOnUse"><stop offset=".88" stop-color="#0037D4"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#q)" fill="url(#s)" d="M446.679 260.746c0 102.678-83.253 185.939-185.931 185.939-102.677 0-185.928-83.262-185.928-185.939 0-102.676 83.25-185.915 185.928-185.915s185.931 83.239 185.931 185.915z"/><radialGradient id="t" cx="256" cy="256" r="197.367" gradientTransform="matrix(.973 0 0 .973 6.961 6.96)" gradientUnits="userSpaceOnUse"><stop offset=".88" stop-color="#0066D4"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#q)" fill="url(#t)" d="M448 255.987C448 362.019 362.032 448 255.999 448 149.967 448 64 362.019 64 255.987 64 149.957 149.967 64 255.999 64 362.032 64 448 149.957 448 255.987z"/><linearGradient id="u" gradientUnits="userSpaceOnUse" x1="329.512" y1="437.945" x2="182.495" y2="74.067"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#u)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><linearGradient id="v" gradientUnits="userSpaceOnUse" x1="117.285" y1="394.722" x2="394.718" y2="117.289"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#v)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><linearGradient id="w" gradientUnits="userSpaceOnUse" x1="95.291" y1="368.536" x2="416.713" y2="143.474"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#w)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><defs><path id="x" d="M256.001 80.999C159.355 80.999 81 159.354 81 255.998c0 96.644 78.355 174.999 175.001 174.999 96.645 0 174.999-78.355 174.999-174.999 0-96.644-78.354-174.999-174.999-174.999z"/></defs><clipPath id="y"><use xlink:href="#x" overflow="visible"/></clipPath><linearGradient id="z" gradientUnits="userSpaceOnUse" x1="131.906" y1="131.904" x2="380.096" y2="380.094"><stop offset="0" stop-color="#14B9FF"/><stop offset="1" stop-color="#48007F"/></linearGradient><path clip-path="url(#y)" fill="url(#z)" d="M256.001 80.499c-96.922 0-175.501 78.578-175.501 175.499 0 96.92 78.579 175.499 175.501 175.499 96.921 0 175.499-78.579 175.499-175.499 0-96.921-78.578-175.499-175.499-175.499z"/><radialGradient id="A" cx="256" cy="255.998" r="175.5" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".33" stop-color="#006CC2" stop-opacity="0"/><stop offset=".628" stop-color="#016EC3" stop-opacity=".232"/><stop offset=".736" stop-color="#0575C7" stop-opacity=".315"/><stop offset=".813" stop-color="#0D80CE" stop-opacity=".374"/><stop offset=".874" stop-color="#1791D8" stop-opacity=".422"/><stop offset=".927" stop-color="#25A7E4" stop-opacity=".464"/><stop offset=".974" stop-color="#36C2F4" stop-opacity=".499"/><stop offset="1" stop-color="#42D5FF" stop-opacity=".52"/></radialGradient><path clip-path="url(#y)" fill="url(#A)" d="M256.001 80.499c-96.922 0-175.501 78.578-175.501 175.499 0 96.92 78.579 175.499 175.501 175.499 96.921 0 175.499-78.579 175.499-175.499 0-96.921-78.578-175.499-175.499-175.499z"/><radialGradient id="B" cx="202" cy="192.998" r="127" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#E1FFFF" stop-opacity=".5"/><stop offset=".093" stop-color="#D9F9FD" stop-opacity=".453"/><stop offset=".239" stop-color="#C3E7F6" stop-opacity=".38"/><stop offset=".42" stop-color="#9ECAEC" stop-opacity=".29"/><stop offset=".628" stop-color="#6CA2DE" stop-opacity=".186"/><stop offset=".855" stop-color="#2C6FCC" stop-opacity=".072"/><stop offset="1" stop-color="#004CBF" stop-opacity="0"/></radialGradient><path clip-path="url(#y)" fill="url(#B)" d="M202.001 65.999c-70.134 0-127.001 56.867-127.001 127 0 70.128 56.867 126.999 127.001 126.999C272.13 319.998 329 263.127 329 192.999c0-70.133-56.87-127-126.999-127z"/><path opacity=".31" clip-path="url(#y)" fill="#191919" d="M256.001 67C151.62 67 67 151.619 67 256s84.62 189 189.001 189S445 360.381 445 256 360.382 67 256.001 67zm0 361.481c-95.259 0-172.485-77.224-172.485-172.481 0-95.257 77.226-172.484 172.485-172.484 95.259 0 172.48 77.226 172.48 172.484 0 95.258-77.221 172.481-172.48 172.481z"/><path stroke="#E4EAF4" stroke-width="3" stroke-miterlimit="10" fill="none" d="M231.267 242.166l65.335-54.5m0 0L245.867 136.5m50.735 51.166l19.5-49.228m-84.835 103.728l-85.232-23.999m85.232 23.999l-50.7 70.334m50.7-70.334l56.6 63.4m0 0l72.334 24.301m-72.334-24.301l-34.564 63.967"/><defs><circle id="C" cx="231.267" cy="242.166" r="34.333"/></defs><clipPath id="D"><use xlink:href="#C" overflow="visible"/></clipPath><radialGradient id="E" cx="219.436" cy="230.335" r="51.497" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#D)" fill="url(#E)" cx="219.436" cy="230.335" r="51.498"/><radialGradient id="F" cx="228.484" cy="237.666" r="34.647" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F6FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4EBF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDBF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C7EF" stop-opacity=".712"/><stop offset="1" stop-color="#95B2E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#D)" fill="url(#F)" cx="229.934" cy="240.833" r="36.833"/><defs><circle id="G" cx="180.568" cy="312.5" r="24.033"/></defs><clipPath id="H"><use xlink:href="#G" overflow="visible"/></clipPath><radialGradient id="I" cx="172.285" cy="304.218" r="36.048" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#H)" fill="url(#I)" cx="172.285" cy="304.219" r="36.048"/><radialGradient id="J" cx="181.17" cy="304.201" r="24.252" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F6FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4EAF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CED9F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C4EF" stop-opacity=".712"/><stop offset="1" stop-color="#95AEE9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#H)" fill="url(#J)" cx="179.634" cy="311.566" r="25.783"/><defs><circle id="K" cx="288.801" cy="306.5" r="24.033"/></defs><clipPath id="L"><use xlink:href="#K" overflow="visible"/></clipPath><radialGradient id="M" cx="280.519" cy="298.218" r="36.048" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#L)" fill="url(#M)" cx="280.519" cy="298.219" r="36.048"/><radialGradient id="N" cx="282.978" cy="298.557" r="24.253" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F5FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4E7F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CED4F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2BBEF" stop-opacity=".712"/><stop offset="1" stop-color="#95A2E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#L)" fill="url(#N)" cx="287.867" cy="305.566" r="25.783"/><defs><circle id="O" cx="146.035" cy="218.167" r="17.167"/></defs><clipPath id="P"><use xlink:href="#O" overflow="visible"/></clipPath><radialGradient id="Q" cx="140.119" cy="212.251" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#P)" fill="url(#Q)" cx="140.119" cy="212.252" r="25.749"/><radialGradient id="R" cx="148.938" cy="215.719" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFEFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F9FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4F1F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEE5F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2D6EF" stop-opacity=".712"/><stop offset="1" stop-color="#95C7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#P)" fill="url(#R)" cx="145.368" cy="217.5" r="18.416"/><defs><circle id="S" cx="296.603" cy="187.667" r="17.167"/></defs><clipPath id="T"><use xlink:href="#S" overflow="visible"/></clipPath><radialGradient id="U" cx="290.687" cy="181.751" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#T)" fill="url(#U)" cx="290.687" cy="181.751" r="25.749"/><radialGradient id="V" cx="290.568" cy="187.029" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F7FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4ECF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDEF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2CBEF" stop-opacity=".712"/><stop offset="1" stop-color="#95B7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#T)" fill="url(#V)" cx="295.936" cy="187" r="18.416"/><defs><circle id="W" cx="253.304" cy="369.533" r="17.167"/></defs><clipPath id="X"><use xlink:href="#W" overflow="visible"/></clipPath><radialGradient id="Y" cx="247.388" cy="363.618" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#X)" fill="url(#Y)" cx="247.388" cy="363.619" r="25.749"/><radialGradient id="Z" cx="249.839" cy="358.1" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFCFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F3FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4E4F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CECFF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2B4EF" stop-opacity=".712"/><stop offset="1" stop-color="#9598E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#X)" fill="url(#Z)" cx="252.637" cy="368.867" r="18.416"/><defs><circle id="aa" cx="360.868" cy="330.533" r="17.167"/></defs><clipPath id="ab"><use xlink:href="#aa" overflow="visible"/></clipPath><radialGradient id="ac" cx="354.952" cy="324.618" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#ab)" fill="url(#ac)" cx="354.952" cy="324.619" r="25.749"/><radialGradient id="ad" cx="351.019" cy="321.415" r="17.322" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FDFCFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F5F3FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E9E4F9" stop-opacity=".487"/><stop offset=".755" stop-color="#D7CEF5" stop-opacity=".604"/><stop offset=".89" stop-color="#C0B2EF" stop-opacity=".712"/><stop offset="1" stop-color="#A995E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#ab)" fill="url(#ad)" cx="360.201" cy="329.867" r="18.416"/><defs><circle id="ae" cx="245.867" cy="136.5" r="13.733"/></defs><clipPath id="af"><use xlink:href="#ae" overflow="visible"/></clipPath><radialGradient id="ag" cx="241.135" cy="131.768" r="20.599" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#af)" fill="url(#ag)" cx="241.135" cy="131.768" r="20.599"/><radialGradient id="ah" cx="242.97" cy="139.026" r="13.859" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFEFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F9FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4F1F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEE5F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2D6EF" stop-opacity=".712"/><stop offset="1" stop-color="#95C7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#af)" fill="url(#ah)" cx="245.334" cy="135.967" r="14.733"/><defs><circle id="ai" cx="316.102" cy="138.438" r="13.733"/></defs><clipPath id="aj"><use xlink:href="#ai" overflow="visible"/></clipPath><radialGradient id="ak" cx="311.369" cy="133.706" r="20.599" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#aj)" fill="url(#ak)" cx="311.369" cy="133.707" r="20.599"/><radialGradient id="al" cx="309.035" cy="140.85" r="13.859" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F7FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4ECF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDDF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C9EF" stop-opacity=".712"/><stop offset="1" stop-color="#95B5E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#aj)" fill="url(#al)" cx="315.568" cy="137.905" r="14.733"/></svg>
\ No newline at end of file
diff --git a/test/coa/testSvgRecursively/depth-1/depth-2/test.svg b/test/coa/testSvgRecursively/depth-1/depth-2/test.svg
new file mode 100644
index 0000000..de7975d
--- /dev/null
+++ b/test/coa/testSvgRecursively/depth-1/depth-2/test.svg
@@ -0,0 +1,1 @@
+<!--! https://github.com/svg/svgo--><!--! SVGO project logo by Yegor Bolshakov (http://xizzzy.ru/)--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512"><defs><path id="a" d="M512 274.094v-36.191l-31.59-5.743a224.595 224.595 0 0 0-7.93-40.031l26.958-17.377-13.852-33.438-31.354 6.776a226.088 226.088 0 0 0-22.705-33.898l18.286-26.415-25.594-25.591-26.409 18.285a226.197 226.197 0 0 0-33.898-22.706l6.773-31.354-33.437-13.851-17.376 26.958a224.75 224.75 0 0 0-40.032-7.931L274.098 0h-36.193l-5.744 31.59a224.512 224.512 0 0 0-40.033 7.931l-17.376-26.959-33.438 13.851 6.776 31.354a226.053 226.053 0 0 0-33.899 22.706L87.776 62.185l-25.591 25.59 18.287 26.415a226.089 226.089 0 0 0-22.705 33.898l-31.355-6.776-13.85 33.438 26.959 17.377a224.567 224.567 0 0 0-7.93 40.03L0 237.902v36.191l31.59 5.744a224.484 224.484 0 0 0 7.931 40.032l-26.959 17.378 13.85 33.435 31.355-6.773a226.012 226.012 0 0 0 22.705 33.898l-18.287 26.414 25.591 25.593 26.415-18.287a225.977 225.977 0 0 0 33.899 22.706l-6.776 31.354 33.438 13.852 17.377-26.958a224.932 224.932 0 0 0 40.031 7.93l5.744 31.59h36.192l5.744-31.59a224.62 224.62 0 0 0 40.03-7.93l17.378 26.957 33.436-13.852-6.772-31.354a226.06 226.06 0 0 0 33.897-22.706l26.414 18.286 25.593-25.593-18.286-26.412a226.486 226.486 0 0 0 22.706-33.899l31.354 6.772 13.853-33.435-26.958-17.377a224.943 224.943 0 0 0 7.93-40.032L512 274.094z"/></defs><clipPath id="b"><use xlink:href="#a" overflow="visible"/></clipPath><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="480.818" y1="380.617" x2="31.183" y2="131.38"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><circle clip-path="url(#b)" fill="url(#c)" cx="256" cy="255.998" r="257"/><radialGradient id="d" cx="256" cy="255.998" r="257" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".73" stop-color="#004ED4" stop-opacity=".4"/><stop offset=".784" stop-color="#437CDE" stop-opacity=".319"/><stop offset=".842" stop-color="#83A8E7" stop-opacity=".234"/><stop offset=".894" stop-color="#B5CAEE" stop-opacity=".157"/><stop offset=".94" stop-color="#DAE3F4" stop-opacity=".089"/><stop offset=".977" stop-color="#F0F2F7" stop-opacity=".035"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><circle clip-path="url(#b)" fill="url(#d)" cx="256" cy="255.998" r="257"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="352.299" y1="494.346" x2="159.701" y2="17.65"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#e)" cx="256" cy="255.998" r="257"/><radialGradient id="f" cx="256" cy="255.998" r="257" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".8" stop-color="#6B6B6B" stop-opacity="0"/><stop offset=".826" stop-color="#848484" stop-opacity=".02"/><stop offset=".883" stop-color="#B5B5B5" stop-opacity=".066"/><stop offset=".933" stop-color="#DADADA" stop-opacity=".107"/><stop offset=".974" stop-color="#F0F0F0" stop-opacity=".139"/><stop offset="1" stop-color="#F8F8F8" stop-opacity=".16"/></radialGradient><circle clip-path="url(#b)" fill="url(#f)" cx="256" cy="255.998" r="257"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="74.274" y1="437.724" x2="437.726" y2="74.272"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#g)" cx="256" cy="255.998" r="257"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="45.46" y1="403.419" x2="466.539" y2="108.576"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#h)" cx="256" cy="255.998" r="257"/><defs><path id="i" d="M256.001 50.999C142.777 50.999 51 142.774 51 255.998s91.777 204.999 205.001 204.999C369.226 460.997 461 369.222 461 255.998S369.226 50.999 256.001 50.999z"/></defs><clipPath id="j"><use xlink:href="#i" overflow="visible"/></clipPath><linearGradient id="k" gradientUnits="userSpaceOnUse" x1="441.158" y1="358.64" x2="70.835" y2="153.366" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><path clip-path="url(#j)" fill="url(#k)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><radialGradient id="l" cx="255.997" cy="256.006" r="217.969" gradientTransform="matrix(0 -.971 .971 0 7.396 504.601)" gradientUnits="userSpaceOnUse"><stop offset=".86" stop-color="#0058D4" stop-opacity=".6"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#j)" fill="url(#l)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="m" gradientUnits="userSpaceOnUse" x1="335.313" y1="452.313" x2="176.686" y2="59.7" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#m)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="n" gradientUnits="userSpaceOnUse" x1="106.329" y1="405.673" x2="405.669" y2="106.333" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#n)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="o" gradientUnits="userSpaceOnUse" x1="82.599" y1="377.421" x2="429.401" y2="134.588" gradientTransform="rotate(-90 256 256)"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#o)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><defs><path id="p" d="M446 255.999c0-104.932-85.066-190-190-190s-190 85.068-190 190c0 104.934 85.066 189.998 190 189.998s190-85.064 190-189.998z"/></defs><clipPath id="q"><use xlink:href="#p" overflow="visible"/></clipPath><linearGradient id="r" gradientUnits="userSpaceOnUse" x1="427.61" y1="351.133" x2="84.388" y2="160.881"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><path clip-path="url(#q)" fill="url(#r)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><radialGradient id="s" cx="260.891" cy="260.9" r="191.461" gradientTransform="matrix(.971 0 0 .971 7.397 7.398)" gradientUnits="userSpaceOnUse"><stop offset=".88" stop-color="#0037D4"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#q)" fill="url(#s)" d="M446.679 260.746c0 102.678-83.253 185.939-185.931 185.939-102.677 0-185.928-83.262-185.928-185.939 0-102.676 83.25-185.915 185.928-185.915s185.931 83.239 185.931 185.915z"/><radialGradient id="t" cx="256" cy="256" r="197.367" gradientTransform="matrix(.973 0 0 .973 6.961 6.96)" gradientUnits="userSpaceOnUse"><stop offset=".88" stop-color="#0066D4"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#q)" fill="url(#t)" d="M448 255.987C448 362.019 362.032 448 255.999 448 149.967 448 64 362.019 64 255.987 64 149.957 149.967 64 255.999 64 362.032 64 448 149.957 448 255.987z"/><linearGradient id="u" gradientUnits="userSpaceOnUse" x1="329.512" y1="437.945" x2="182.495" y2="74.067"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#u)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><linearGradient id="v" gradientUnits="userSpaceOnUse" x1="117.285" y1="394.722" x2="394.718" y2="117.289"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#v)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><linearGradient id="w" gradientUnits="userSpaceOnUse" x1="95.291" y1="368.536" x2="416.713" y2="143.474"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#w)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><defs><path id="x" d="M256.001 80.999C159.355 80.999 81 159.354 81 255.998c0 96.644 78.355 174.999 175.001 174.999 96.645 0 174.999-78.355 174.999-174.999 0-96.644-78.354-174.999-174.999-174.999z"/></defs><clipPath id="y"><use xlink:href="#x" overflow="visible"/></clipPath><linearGradient id="z" gradientUnits="userSpaceOnUse" x1="131.906" y1="131.904" x2="380.096" y2="380.094"><stop offset="0" stop-color="#14B9FF"/><stop offset="1" stop-color="#48007F"/></linearGradient><path clip-path="url(#y)" fill="url(#z)" d="M256.001 80.499c-96.922 0-175.501 78.578-175.501 175.499 0 96.92 78.579 175.499 175.501 175.499 96.921 0 175.499-78.579 175.499-175.499 0-96.921-78.578-175.499-175.499-175.499z"/><radialGradient id="A" cx="256" cy="255.998" r="175.5" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".33" stop-color="#006CC2" stop-opacity="0"/><stop offset=".628" stop-color="#016EC3" stop-opacity=".232"/><stop offset=".736" stop-color="#0575C7" stop-opacity=".315"/><stop offset=".813" stop-color="#0D80CE" stop-opacity=".374"/><stop offset=".874" stop-color="#1791D8" stop-opacity=".422"/><stop offset=".927" stop-color="#25A7E4" stop-opacity=".464"/><stop offset=".974" stop-color="#36C2F4" stop-opacity=".499"/><stop offset="1" stop-color="#42D5FF" stop-opacity=".52"/></radialGradient><path clip-path="url(#y)" fill="url(#A)" d="M256.001 80.499c-96.922 0-175.501 78.578-175.501 175.499 0 96.92 78.579 175.499 175.501 175.499 96.921 0 175.499-78.579 175.499-175.499 0-96.921-78.578-175.499-175.499-175.499z"/><radialGradient id="B" cx="202" cy="192.998" r="127" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#E1FFFF" stop-opacity=".5"/><stop offset=".093" stop-color="#D9F9FD" stop-opacity=".453"/><stop offset=".239" stop-color="#C3E7F6" stop-opacity=".38"/><stop offset=".42" stop-color="#9ECAEC" stop-opacity=".29"/><stop offset=".628" stop-color="#6CA2DE" stop-opacity=".186"/><stop offset=".855" stop-color="#2C6FCC" stop-opacity=".072"/><stop offset="1" stop-color="#004CBF" stop-opacity="0"/></radialGradient><path clip-path="url(#y)" fill="url(#B)" d="M202.001 65.999c-70.134 0-127.001 56.867-127.001 127 0 70.128 56.867 126.999 127.001 126.999C272.13 319.998 329 263.127 329 192.999c0-70.133-56.87-127-126.999-127z"/><path opacity=".31" clip-path="url(#y)" fill="#191919" d="M256.001 67C151.62 67 67 151.619 67 256s84.62 189 189.001 189S445 360.381 445 256 360.382 67 256.001 67zm0 361.481c-95.259 0-172.485-77.224-172.485-172.481 0-95.257 77.226-172.484 172.485-172.484 95.259 0 172.48 77.226 172.48 172.484 0 95.258-77.221 172.481-172.48 172.481z"/><path stroke="#E4EAF4" stroke-width="3" stroke-miterlimit="10" fill="none" d="M231.267 242.166l65.335-54.5m0 0L245.867 136.5m50.735 51.166l19.5-49.228m-84.835 103.728l-85.232-23.999m85.232 23.999l-50.7 70.334m50.7-70.334l56.6 63.4m0 0l72.334 24.301m-72.334-24.301l-34.564 63.967"/><defs><circle id="C" cx="231.267" cy="242.166" r="34.333"/></defs><clipPath id="D"><use xlink:href="#C" overflow="visible"/></clipPath><radialGradient id="E" cx="219.436" cy="230.335" r="51.497" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#D)" fill="url(#E)" cx="219.436" cy="230.335" r="51.498"/><radialGradient id="F" cx="228.484" cy="237.666" r="34.647" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F6FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4EBF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDBF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C7EF" stop-opacity=".712"/><stop offset="1" stop-color="#95B2E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#D)" fill="url(#F)" cx="229.934" cy="240.833" r="36.833"/><defs><circle id="G" cx="180.568" cy="312.5" r="24.033"/></defs><clipPath id="H"><use xlink:href="#G" overflow="visible"/></clipPath><radialGradient id="I" cx="172.285" cy="304.218" r="36.048" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#H)" fill="url(#I)" cx="172.285" cy="304.219" r="36.048"/><radialGradient id="J" cx="181.17" cy="304.201" r="24.252" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F6FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4EAF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CED9F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C4EF" stop-opacity=".712"/><stop offset="1" stop-color="#95AEE9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#H)" fill="url(#J)" cx="179.634" cy="311.566" r="25.783"/><defs><circle id="K" cx="288.801" cy="306.5" r="24.033"/></defs><clipPath id="L"><use xlink:href="#K" overflow="visible"/></clipPath><radialGradient id="M" cx="280.519" cy="298.218" r="36.048" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#L)" fill="url(#M)" cx="280.519" cy="298.219" r="36.048"/><radialGradient id="N" cx="282.978" cy="298.557" r="24.253" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F5FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4E7F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CED4F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2BBEF" stop-opacity=".712"/><stop offset="1" stop-color="#95A2E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#L)" fill="url(#N)" cx="287.867" cy="305.566" r="25.783"/><defs><circle id="O" cx="146.035" cy="218.167" r="17.167"/></defs><clipPath id="P"><use xlink:href="#O" overflow="visible"/></clipPath><radialGradient id="Q" cx="140.119" cy="212.251" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#P)" fill="url(#Q)" cx="140.119" cy="212.252" r="25.749"/><radialGradient id="R" cx="148.938" cy="215.719" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFEFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F9FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4F1F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEE5F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2D6EF" stop-opacity=".712"/><stop offset="1" stop-color="#95C7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#P)" fill="url(#R)" cx="145.368" cy="217.5" r="18.416"/><defs><circle id="S" cx="296.603" cy="187.667" r="17.167"/></defs><clipPath id="T"><use xlink:href="#S" overflow="visible"/></clipPath><radialGradient id="U" cx="290.687" cy="181.751" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#T)" fill="url(#U)" cx="290.687" cy="181.751" r="25.749"/><radialGradient id="V" cx="290.568" cy="187.029" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F7FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4ECF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDEF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2CBEF" stop-opacity=".712"/><stop offset="1" stop-color="#95B7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#T)" fill="url(#V)" cx="295.936" cy="187" r="18.416"/><defs><circle id="W" cx="253.304" cy="369.533" r="17.167"/></defs><clipPath id="X"><use xlink:href="#W" overflow="visible"/></clipPath><radialGradient id="Y" cx="247.388" cy="363.618" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#X)" fill="url(#Y)" cx="247.388" cy="363.619" r="25.749"/><radialGradient id="Z" cx="249.839" cy="358.1" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFCFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F3FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4E4F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CECFF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2B4EF" stop-opacity=".712"/><stop offset="1" stop-color="#9598E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#X)" fill="url(#Z)" cx="252.637" cy="368.867" r="18.416"/><defs><circle id="aa" cx="360.868" cy="330.533" r="17.167"/></defs><clipPath id="ab"><use xlink:href="#aa" overflow="visible"/></clipPath><radialGradient id="ac" cx="354.952" cy="324.618" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#ab)" fill="url(#ac)" cx="354.952" cy="324.619" r="25.749"/><radialGradient id="ad" cx="351.019" cy="321.415" r="17.322" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FDFCFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F5F3FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E9E4F9" stop-opacity=".487"/><stop offset=".755" stop-color="#D7CEF5" stop-opacity=".604"/><stop offset=".89" stop-color="#C0B2EF" stop-opacity=".712"/><stop offset="1" stop-color="#A995E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#ab)" fill="url(#ad)" cx="360.201" cy="329.867" r="18.416"/><defs><circle id="ae" cx="245.867" cy="136.5" r="13.733"/></defs><clipPath id="af"><use xlink:href="#ae" overflow="visible"/></clipPath><radialGradient id="ag" cx="241.135" cy="131.768" r="20.599" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#af)" fill="url(#ag)" cx="241.135" cy="131.768" r="20.599"/><radialGradient id="ah" cx="242.97" cy="139.026" r="13.859" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFEFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F9FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4F1F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEE5F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2D6EF" stop-opacity=".712"/><stop offset="1" stop-color="#95C7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#af)" fill="url(#ah)" cx="245.334" cy="135.967" r="14.733"/><defs><circle id="ai" cx="316.102" cy="138.438" r="13.733"/></defs><clipPath id="aj"><use xlink:href="#ai" overflow="visible"/></clipPath><radialGradient id="ak" cx="311.369" cy="133.706" r="20.599" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#aj)" fill="url(#ak)" cx="311.369" cy="133.707" r="20.599"/><radialGradient id="al" cx="309.035" cy="140.85" r="13.859" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F7FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4ECF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDDF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C9EF" stop-opacity=".712"/><stop offset="1" stop-color="#95B5E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#aj)" fill="url(#al)" cx="315.568" cy="137.905" r="14.733"/></svg>
\ No newline at end of file
diff --git a/test/coa/testSvgRecursively/test.1.svg b/test/coa/testSvgRecursively/test.1.svg
new file mode 100644
index 0000000..de7975d
--- /dev/null
+++ b/test/coa/testSvgRecursively/test.1.svg
@@ -0,0 +1,1 @@
+<!--! https://github.com/svg/svgo--><!--! SVGO project logo by Yegor Bolshakov (http://xizzzy.ru/)--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512"><defs><path id="a" d="M512 274.094v-36.191l-31.59-5.743a224.595 224.595 0 0 0-7.93-40.031l26.958-17.377-13.852-33.438-31.354 6.776a226.088 226.088 0 0 0-22.705-33.898l18.286-26.415-25.594-25.591-26.409 18.285a226.197 226.197 0 0 0-33.898-22.706l6.773-31.354-33.437-13.851-17.376 26.958a224.75 224.75 0 0 0-40.032-7.931L274.098 0h-36.193l-5.744 31.59a224.512 224.512 0 0 0-40.033 7.931l-17.376-26.959-33.438 13.851 6.776 31.354a226.053 226.053 0 0 0-33.899 22.706L87.776 62.185l-25.591 25.59 18.287 26.415a226.089 226.089 0 0 0-22.705 33.898l-31.355-6.776-13.85 33.438 26.959 17.377a224.567 224.567 0 0 0-7.93 40.03L0 237.902v36.191l31.59 5.744a224.484 224.484 0 0 0 7.931 40.032l-26.959 17.378 13.85 33.435 31.355-6.773a226.012 226.012 0 0 0 22.705 33.898l-18.287 26.414 25.591 25.593 26.415-18.287a225.977 225.977 0 0 0 33.899 22.706l-6.776 31.354 33.438 13.852 17.377-26.958a224.932 224.932 0 0 0 40.031 7.93l5.744 31.59h36.192l5.744-31.59a224.62 224.62 0 0 0 40.03-7.93l17.378 26.957 33.436-13.852-6.772-31.354a226.06 226.06 0 0 0 33.897-22.706l26.414 18.286 25.593-25.593-18.286-26.412a226.486 226.486 0 0 0 22.706-33.899l31.354 6.772 13.853-33.435-26.958-17.377a224.943 224.943 0 0 0 7.93-40.032L512 274.094z"/></defs><clipPath id="b"><use xlink:href="#a" overflow="visible"/></clipPath><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="480.818" y1="380.617" x2="31.183" y2="131.38"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><circle clip-path="url(#b)" fill="url(#c)" cx="256" cy="255.998" r="257"/><radialGradient id="d" cx="256" cy="255.998" r="257" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".73" stop-color="#004ED4" stop-opacity=".4"/><stop offset=".784" stop-color="#437CDE" stop-opacity=".319"/><stop offset=".842" stop-color="#83A8E7" stop-opacity=".234"/><stop offset=".894" stop-color="#B5CAEE" stop-opacity=".157"/><stop offset=".94" stop-color="#DAE3F4" stop-opacity=".089"/><stop offset=".977" stop-color="#F0F2F7" stop-opacity=".035"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><circle clip-path="url(#b)" fill="url(#d)" cx="256" cy="255.998" r="257"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="352.299" y1="494.346" x2="159.701" y2="17.65"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#e)" cx="256" cy="255.998" r="257"/><radialGradient id="f" cx="256" cy="255.998" r="257" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".8" stop-color="#6B6B6B" stop-opacity="0"/><stop offset=".826" stop-color="#848484" stop-opacity=".02"/><stop offset=".883" stop-color="#B5B5B5" stop-opacity=".066"/><stop offset=".933" stop-color="#DADADA" stop-opacity=".107"/><stop offset=".974" stop-color="#F0F0F0" stop-opacity=".139"/><stop offset="1" stop-color="#F8F8F8" stop-opacity=".16"/></radialGradient><circle clip-path="url(#b)" fill="url(#f)" cx="256" cy="255.998" r="257"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="74.274" y1="437.724" x2="437.726" y2="74.272"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#g)" cx="256" cy="255.998" r="257"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="45.46" y1="403.419" x2="466.539" y2="108.576"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#h)" cx="256" cy="255.998" r="257"/><defs><path id="i" d="M256.001 50.999C142.777 50.999 51 142.774 51 255.998s91.777 204.999 205.001 204.999C369.226 460.997 461 369.222 461 255.998S369.226 50.999 256.001 50.999z"/></defs><clipPath id="j"><use xlink:href="#i" overflow="visible"/></clipPath><linearGradient id="k" gradientUnits="userSpaceOnUse" x1="441.158" y1="358.64" x2="70.835" y2="153.366" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><path clip-path="url(#j)" fill="url(#k)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><radialGradient id="l" cx="255.997" cy="256.006" r="217.969" gradientTransform="matrix(0 -.971 .971 0 7.396 504.601)" gradientUnits="userSpaceOnUse"><stop offset=".86" stop-color="#0058D4" stop-opacity=".6"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#j)" fill="url(#l)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="m" gradientUnits="userSpaceOnUse" x1="335.313" y1="452.313" x2="176.686" y2="59.7" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#m)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="n" gradientUnits="userSpaceOnUse" x1="106.329" y1="405.673" x2="405.669" y2="106.333" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#n)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="o" gradientUnits="userSpaceOnUse" x1="82.599" y1="377.421" x2="429.401" y2="134.588" gradientTransform="rotate(-90 256 256)"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#o)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><defs><path id="p" d="M446 255.999c0-104.932-85.066-190-190-190s-190 85.068-190 190c0 104.934 85.066 189.998 190 189.998s190-85.064 190-189.998z"/></defs><clipPath id="q"><use xlink:href="#p" overflow="visible"/></clipPath><linearGradient id="r" gradientUnits="userSpaceOnUse" x1="427.61" y1="351.133" x2="84.388" y2="160.881"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><path clip-path="url(#q)" fill="url(#r)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><radialGradient id="s" cx="260.891" cy="260.9" r="191.461" gradientTransform="matrix(.971 0 0 .971 7.397 7.398)" gradientUnits="userSpaceOnUse"><stop offset=".88" stop-color="#0037D4"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#q)" fill="url(#s)" d="M446.679 260.746c0 102.678-83.253 185.939-185.931 185.939-102.677 0-185.928-83.262-185.928-185.939 0-102.676 83.25-185.915 185.928-185.915s185.931 83.239 185.931 185.915z"/><radialGradient id="t" cx="256" cy="256" r="197.367" gradientTransform="matrix(.973 0 0 .973 6.961 6.96)" gradientUnits="userSpaceOnUse"><stop offset=".88" stop-color="#0066D4"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#q)" fill="url(#t)" d="M448 255.987C448 362.019 362.032 448 255.999 448 149.967 448 64 362.019 64 255.987 64 149.957 149.967 64 255.999 64 362.032 64 448 149.957 448 255.987z"/><linearGradient id="u" gradientUnits="userSpaceOnUse" x1="329.512" y1="437.945" x2="182.495" y2="74.067"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#u)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><linearGradient id="v" gradientUnits="userSpaceOnUse" x1="117.285" y1="394.722" x2="394.718" y2="117.289"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#v)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><linearGradient id="w" gradientUnits="userSpaceOnUse" x1="95.291" y1="368.536" x2="416.713" y2="143.474"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#w)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><defs><path id="x" d="M256.001 80.999C159.355 80.999 81 159.354 81 255.998c0 96.644 78.355 174.999 175.001 174.999 96.645 0 174.999-78.355 174.999-174.999 0-96.644-78.354-174.999-174.999-174.999z"/></defs><clipPath id="y"><use xlink:href="#x" overflow="visible"/></clipPath><linearGradient id="z" gradientUnits="userSpaceOnUse" x1="131.906" y1="131.904" x2="380.096" y2="380.094"><stop offset="0" stop-color="#14B9FF"/><stop offset="1" stop-color="#48007F"/></linearGradient><path clip-path="url(#y)" fill="url(#z)" d="M256.001 80.499c-96.922 0-175.501 78.578-175.501 175.499 0 96.92 78.579 175.499 175.501 175.499 96.921 0 175.499-78.579 175.499-175.499 0-96.921-78.578-175.499-175.499-175.499z"/><radialGradient id="A" cx="256" cy="255.998" r="175.5" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".33" stop-color="#006CC2" stop-opacity="0"/><stop offset=".628" stop-color="#016EC3" stop-opacity=".232"/><stop offset=".736" stop-color="#0575C7" stop-opacity=".315"/><stop offset=".813" stop-color="#0D80CE" stop-opacity=".374"/><stop offset=".874" stop-color="#1791D8" stop-opacity=".422"/><stop offset=".927" stop-color="#25A7E4" stop-opacity=".464"/><stop offset=".974" stop-color="#36C2F4" stop-opacity=".499"/><stop offset="1" stop-color="#42D5FF" stop-opacity=".52"/></radialGradient><path clip-path="url(#y)" fill="url(#A)" d="M256.001 80.499c-96.922 0-175.501 78.578-175.501 175.499 0 96.92 78.579 175.499 175.501 175.499 96.921 0 175.499-78.579 175.499-175.499 0-96.921-78.578-175.499-175.499-175.499z"/><radialGradient id="B" cx="202" cy="192.998" r="127" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#E1FFFF" stop-opacity=".5"/><stop offset=".093" stop-color="#D9F9FD" stop-opacity=".453"/><stop offset=".239" stop-color="#C3E7F6" stop-opacity=".38"/><stop offset=".42" stop-color="#9ECAEC" stop-opacity=".29"/><stop offset=".628" stop-color="#6CA2DE" stop-opacity=".186"/><stop offset=".855" stop-color="#2C6FCC" stop-opacity=".072"/><stop offset="1" stop-color="#004CBF" stop-opacity="0"/></radialGradient><path clip-path="url(#y)" fill="url(#B)" d="M202.001 65.999c-70.134 0-127.001 56.867-127.001 127 0 70.128 56.867 126.999 127.001 126.999C272.13 319.998 329 263.127 329 192.999c0-70.133-56.87-127-126.999-127z"/><path opacity=".31" clip-path="url(#y)" fill="#191919" d="M256.001 67C151.62 67 67 151.619 67 256s84.62 189 189.001 189S445 360.381 445 256 360.382 67 256.001 67zm0 361.481c-95.259 0-172.485-77.224-172.485-172.481 0-95.257 77.226-172.484 172.485-172.484 95.259 0 172.48 77.226 172.48 172.484 0 95.258-77.221 172.481-172.48 172.481z"/><path stroke="#E4EAF4" stroke-width="3" stroke-miterlimit="10" fill="none" d="M231.267 242.166l65.335-54.5m0 0L245.867 136.5m50.735 51.166l19.5-49.228m-84.835 103.728l-85.232-23.999m85.232 23.999l-50.7 70.334m50.7-70.334l56.6 63.4m0 0l72.334 24.301m-72.334-24.301l-34.564 63.967"/><defs><circle id="C" cx="231.267" cy="242.166" r="34.333"/></defs><clipPath id="D"><use xlink:href="#C" overflow="visible"/></clipPath><radialGradient id="E" cx="219.436" cy="230.335" r="51.497" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#D)" fill="url(#E)" cx="219.436" cy="230.335" r="51.498"/><radialGradient id="F" cx="228.484" cy="237.666" r="34.647" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F6FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4EBF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDBF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C7EF" stop-opacity=".712"/><stop offset="1" stop-color="#95B2E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#D)" fill="url(#F)" cx="229.934" cy="240.833" r="36.833"/><defs><circle id="G" cx="180.568" cy="312.5" r="24.033"/></defs><clipPath id="H"><use xlink:href="#G" overflow="visible"/></clipPath><radialGradient id="I" cx="172.285" cy="304.218" r="36.048" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#H)" fill="url(#I)" cx="172.285" cy="304.219" r="36.048"/><radialGradient id="J" cx="181.17" cy="304.201" r="24.252" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F6FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4EAF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CED9F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C4EF" stop-opacity=".712"/><stop offset="1" stop-color="#95AEE9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#H)" fill="url(#J)" cx="179.634" cy="311.566" r="25.783"/><defs><circle id="K" cx="288.801" cy="306.5" r="24.033"/></defs><clipPath id="L"><use xlink:href="#K" overflow="visible"/></clipPath><radialGradient id="M" cx="280.519" cy="298.218" r="36.048" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#L)" fill="url(#M)" cx="280.519" cy="298.219" r="36.048"/><radialGradient id="N" cx="282.978" cy="298.557" r="24.253" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F5FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4E7F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CED4F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2BBEF" stop-opacity=".712"/><stop offset="1" stop-color="#95A2E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#L)" fill="url(#N)" cx="287.867" cy="305.566" r="25.783"/><defs><circle id="O" cx="146.035" cy="218.167" r="17.167"/></defs><clipPath id="P"><use xlink:href="#O" overflow="visible"/></clipPath><radialGradient id="Q" cx="140.119" cy="212.251" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#P)" fill="url(#Q)" cx="140.119" cy="212.252" r="25.749"/><radialGradient id="R" cx="148.938" cy="215.719" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFEFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F9FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4F1F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEE5F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2D6EF" stop-opacity=".712"/><stop offset="1" stop-color="#95C7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#P)" fill="url(#R)" cx="145.368" cy="217.5" r="18.416"/><defs><circle id="S" cx="296.603" cy="187.667" r="17.167"/></defs><clipPath id="T"><use xlink:href="#S" overflow="visible"/></clipPath><radialGradient id="U" cx="290.687" cy="181.751" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#T)" fill="url(#U)" cx="290.687" cy="181.751" r="25.749"/><radialGradient id="V" cx="290.568" cy="187.029" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F7FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4ECF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDEF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2CBEF" stop-opacity=".712"/><stop offset="1" stop-color="#95B7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#T)" fill="url(#V)" cx="295.936" cy="187" r="18.416"/><defs><circle id="W" cx="253.304" cy="369.533" r="17.167"/></defs><clipPath id="X"><use xlink:href="#W" overflow="visible"/></clipPath><radialGradient id="Y" cx="247.388" cy="363.618" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#X)" fill="url(#Y)" cx="247.388" cy="363.619" r="25.749"/><radialGradient id="Z" cx="249.839" cy="358.1" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFCFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F3FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4E4F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CECFF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2B4EF" stop-opacity=".712"/><stop offset="1" stop-color="#9598E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#X)" fill="url(#Z)" cx="252.637" cy="368.867" r="18.416"/><defs><circle id="aa" cx="360.868" cy="330.533" r="17.167"/></defs><clipPath id="ab"><use xlink:href="#aa" overflow="visible"/></clipPath><radialGradient id="ac" cx="354.952" cy="324.618" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#ab)" fill="url(#ac)" cx="354.952" cy="324.619" r="25.749"/><radialGradient id="ad" cx="351.019" cy="321.415" r="17.322" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FDFCFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F5F3FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E9E4F9" stop-opacity=".487"/><stop offset=".755" stop-color="#D7CEF5" stop-opacity=".604"/><stop offset=".89" stop-color="#C0B2EF" stop-opacity=".712"/><stop offset="1" stop-color="#A995E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#ab)" fill="url(#ad)" cx="360.201" cy="329.867" r="18.416"/><defs><circle id="ae" cx="245.867" cy="136.5" r="13.733"/></defs><clipPath id="af"><use xlink:href="#ae" overflow="visible"/></clipPath><radialGradient id="ag" cx="241.135" cy="131.768" r="20.599" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#af)" fill="url(#ag)" cx="241.135" cy="131.768" r="20.599"/><radialGradient id="ah" cx="242.97" cy="139.026" r="13.859" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFEFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F9FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4F1F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEE5F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2D6EF" stop-opacity=".712"/><stop offset="1" stop-color="#95C7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#af)" fill="url(#ah)" cx="245.334" cy="135.967" r="14.733"/><defs><circle id="ai" cx="316.102" cy="138.438" r="13.733"/></defs><clipPath id="aj"><use xlink:href="#ai" overflow="visible"/></clipPath><radialGradient id="ak" cx="311.369" cy="133.706" r="20.599" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#aj)" fill="url(#ak)" cx="311.369" cy="133.707" r="20.599"/><radialGradient id="al" cx="309.035" cy="140.85" r="13.859" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F7FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4ECF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDDF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C9EF" stop-opacity=".712"/><stop offset="1" stop-color="#95B5E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#aj)" fill="url(#al)" cx="315.568" cy="137.905" r="14.733"/></svg>
\ No newline at end of file
diff --git a/test/coa/testSvgRecursively/test.svg b/test/coa/testSvgRecursively/test.svg
new file mode 100644
index 0000000..de7975d
--- /dev/null
+++ b/test/coa/testSvgRecursively/test.svg
@@ -0,0 +1,1 @@
+<!--! https://github.com/svg/svgo--><!--! SVGO project logo by Yegor Bolshakov (http://xizzzy.ru/)--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512"><defs><path id="a" d="M512 274.094v-36.191l-31.59-5.743a224.595 224.595 0 0 0-7.93-40.031l26.958-17.377-13.852-33.438-31.354 6.776a226.088 226.088 0 0 0-22.705-33.898l18.286-26.415-25.594-25.591-26.409 18.285a226.197 226.197 0 0 0-33.898-22.706l6.773-31.354-33.437-13.851-17.376 26.958a224.75 224.75 0 0 0-40.032-7.931L274.098 0h-36.193l-5.744 31.59a224.512 224.512 0 0 0-40.033 7.931l-17.376-26.959-33.438 13.851 6.776 31.354a226.053 226.053 0 0 0-33.899 22.706L87.776 62.185l-25.591 25.59 18.287 26.415a226.089 226.089 0 0 0-22.705 33.898l-31.355-6.776-13.85 33.438 26.959 17.377a224.567 224.567 0 0 0-7.93 40.03L0 237.902v36.191l31.59 5.744a224.484 224.484 0 0 0 7.931 40.032l-26.959 17.378 13.85 33.435 31.355-6.773a226.012 226.012 0 0 0 22.705 33.898l-18.287 26.414 25.591 25.593 26.415-18.287a225.977 225.977 0 0 0 33.899 22.706l-6.776 31.354 33.438 13.852 17.377-26.958a224.932 224.932 0 0 0 40.031 7.93l5.744 31.59h36.192l5.744-31.59a224.62 224.62 0 0 0 40.03-7.93l17.378 26.957 33.436-13.852-6.772-31.354a226.06 226.06 0 0 0 33.897-22.706l26.414 18.286 25.593-25.593-18.286-26.412a226.486 226.486 0 0 0 22.706-33.899l31.354 6.772 13.853-33.435-26.958-17.377a224.943 224.943 0 0 0 7.93-40.032L512 274.094z"/></defs><clipPath id="b"><use xlink:href="#a" overflow="visible"/></clipPath><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="480.818" y1="380.617" x2="31.183" y2="131.38"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><circle clip-path="url(#b)" fill="url(#c)" cx="256" cy="255.998" r="257"/><radialGradient id="d" cx="256" cy="255.998" r="257" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".73" stop-color="#004ED4" stop-opacity=".4"/><stop offset=".784" stop-color="#437CDE" stop-opacity=".319"/><stop offset=".842" stop-color="#83A8E7" stop-opacity=".234"/><stop offset=".894" stop-color="#B5CAEE" stop-opacity=".157"/><stop offset=".94" stop-color="#DAE3F4" stop-opacity=".089"/><stop offset=".977" stop-color="#F0F2F7" stop-opacity=".035"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><circle clip-path="url(#b)" fill="url(#d)" cx="256" cy="255.998" r="257"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="352.299" y1="494.346" x2="159.701" y2="17.65"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#e)" cx="256" cy="255.998" r="257"/><radialGradient id="f" cx="256" cy="255.998" r="257" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".8" stop-color="#6B6B6B" stop-opacity="0"/><stop offset=".826" stop-color="#848484" stop-opacity=".02"/><stop offset=".883" stop-color="#B5B5B5" stop-opacity=".066"/><stop offset=".933" stop-color="#DADADA" stop-opacity=".107"/><stop offset=".974" stop-color="#F0F0F0" stop-opacity=".139"/><stop offset="1" stop-color="#F8F8F8" stop-opacity=".16"/></radialGradient><circle clip-path="url(#b)" fill="url(#f)" cx="256" cy="255.998" r="257"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="74.274" y1="437.724" x2="437.726" y2="74.272"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#g)" cx="256" cy="255.998" r="257"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="45.46" y1="403.419" x2="466.539" y2="108.576"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><circle clip-path="url(#b)" fill="url(#h)" cx="256" cy="255.998" r="257"/><defs><path id="i" d="M256.001 50.999C142.777 50.999 51 142.774 51 255.998s91.777 204.999 205.001 204.999C369.226 460.997 461 369.222 461 255.998S369.226 50.999 256.001 50.999z"/></defs><clipPath id="j"><use xlink:href="#i" overflow="visible"/></clipPath><linearGradient id="k" gradientUnits="userSpaceOnUse" x1="441.158" y1="358.64" x2="70.835" y2="153.366" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><path clip-path="url(#j)" fill="url(#k)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><radialGradient id="l" cx="255.997" cy="256.006" r="217.969" gradientTransform="matrix(0 -.971 .971 0 7.396 504.601)" gradientUnits="userSpaceOnUse"><stop offset=".86" stop-color="#0058D4" stop-opacity=".6"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#j)" fill="url(#l)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="m" gradientUnits="userSpaceOnUse" x1="335.313" y1="452.313" x2="176.686" y2="59.7" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#m)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="n" gradientUnits="userSpaceOnUse" x1="106.329" y1="405.673" x2="405.669" y2="106.333" gradientTransform="rotate(-90 256 256)"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#n)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><linearGradient id="o" gradientUnits="userSpaceOnUse" x1="82.599" y1="377.421" x2="429.401" y2="134.588" gradientTransform="rotate(-90 256 256)"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#j)" fill="url(#o)" d="M256 44.334c116.894 0 211.676 94.771 211.676 211.664S372.894 467.673 256 467.673c-116.893 0-211.665-94.782-211.665-211.675S139.107 44.334 256 44.334z"/><defs><path id="p" d="M446 255.999c0-104.932-85.066-190-190-190s-190 85.068-190 190c0 104.934 85.066 189.998 190 189.998s190-85.064 190-189.998z"/></defs><clipPath id="q"><use xlink:href="#p" overflow="visible"/></clipPath><linearGradient id="r" gradientUnits="userSpaceOnUse" x1="427.61" y1="351.133" x2="84.388" y2="160.881"><stop offset="0" stop-color="#BDC6C9"/><stop offset=".092" stop-color="#ABB4B7"/><stop offset=".277" stop-color="#7D8588"/><stop offset=".483" stop-color="#444A4D"/><stop offset=".584" stop-color="#5E6669"/><stop offset=".772" stop-color="#899396"/><stop offset=".916" stop-color="#A3AFB2"/><stop offset="1" stop-color="#ADBABD"/></linearGradient><path clip-path="url(#q)" fill="url(#r)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><radialGradient id="s" cx="260.891" cy="260.9" r="191.461" gradientTransform="matrix(.971 0 0 .971 7.397 7.398)" gradientUnits="userSpaceOnUse"><stop offset=".88" stop-color="#0037D4"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#q)" fill="url(#s)" d="M446.679 260.746c0 102.678-83.253 185.939-185.931 185.939-102.677 0-185.928-83.262-185.928-185.939 0-102.676 83.25-185.915 185.928-185.915s185.931 83.239 185.931 185.915z"/><radialGradient id="t" cx="256" cy="256" r="197.367" gradientTransform="matrix(.973 0 0 .973 6.961 6.96)" gradientUnits="userSpaceOnUse"><stop offset=".88" stop-color="#0066D4"/><stop offset="1" stop-color="#F8F8F8" stop-opacity="0"/></radialGradient><path clip-path="url(#q)" fill="url(#t)" d="M448 255.987C448 362.019 362.032 448 255.999 448 149.967 448 64 362.019 64 255.987 64 149.957 149.967 64 255.999 64 362.032 64 448 149.957 448 255.987z"/><linearGradient id="u" gradientUnits="userSpaceOnUse" x1="329.512" y1="437.945" x2="182.495" y2="74.067"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#4D5057" stop-opacity=".75"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#u)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><linearGradient id="v" gradientUnits="userSpaceOnUse" x1="117.285" y1="394.722" x2="394.718" y2="117.289"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#828282" stop-opacity=".6"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#v)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><linearGradient id="w" gradientUnits="userSpaceOnUse" x1="95.291" y1="368.536" x2="416.713" y2="143.474"><stop offset=".2" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#fff" stop-opacity=".36"/><stop offset=".8" stop-color="#fff" stop-opacity="0"/></linearGradient><path clip-path="url(#q)" fill="url(#w)" d="M452.182 255.998c0 108.338-87.844 196.19-196.182 196.19-108.339 0-196.179-87.853-196.179-196.19S147.661 59.832 256 59.832c108.338 0 196.182 87.829 196.182 196.166z"/><defs><path id="x" d="M256.001 80.999C159.355 80.999 81 159.354 81 255.998c0 96.644 78.355 174.999 175.001 174.999 96.645 0 174.999-78.355 174.999-174.999 0-96.644-78.354-174.999-174.999-174.999z"/></defs><clipPath id="y"><use xlink:href="#x" overflow="visible"/></clipPath><linearGradient id="z" gradientUnits="userSpaceOnUse" x1="131.906" y1="131.904" x2="380.096" y2="380.094"><stop offset="0" stop-color="#14B9FF"/><stop offset="1" stop-color="#48007F"/></linearGradient><path clip-path="url(#y)" fill="url(#z)" d="M256.001 80.499c-96.922 0-175.501 78.578-175.501 175.499 0 96.92 78.579 175.499 175.501 175.499 96.921 0 175.499-78.579 175.499-175.499 0-96.921-78.578-175.499-175.499-175.499z"/><radialGradient id="A" cx="256" cy="255.998" r="175.5" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset=".33" stop-color="#006CC2" stop-opacity="0"/><stop offset=".628" stop-color="#016EC3" stop-opacity=".232"/><stop offset=".736" stop-color="#0575C7" stop-opacity=".315"/><stop offset=".813" stop-color="#0D80CE" stop-opacity=".374"/><stop offset=".874" stop-color="#1791D8" stop-opacity=".422"/><stop offset=".927" stop-color="#25A7E4" stop-opacity=".464"/><stop offset=".974" stop-color="#36C2F4" stop-opacity=".499"/><stop offset="1" stop-color="#42D5FF" stop-opacity=".52"/></radialGradient><path clip-path="url(#y)" fill="url(#A)" d="M256.001 80.499c-96.922 0-175.501 78.578-175.501 175.499 0 96.92 78.579 175.499 175.501 175.499 96.921 0 175.499-78.579 175.499-175.499 0-96.921-78.578-175.499-175.499-175.499z"/><radialGradient id="B" cx="202" cy="192.998" r="127" gradientTransform="translate(0 .001)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#E1FFFF" stop-opacity=".5"/><stop offset=".093" stop-color="#D9F9FD" stop-opacity=".453"/><stop offset=".239" stop-color="#C3E7F6" stop-opacity=".38"/><stop offset=".42" stop-color="#9ECAEC" stop-opacity=".29"/><stop offset=".628" stop-color="#6CA2DE" stop-opacity=".186"/><stop offset=".855" stop-color="#2C6FCC" stop-opacity=".072"/><stop offset="1" stop-color="#004CBF" stop-opacity="0"/></radialGradient><path clip-path="url(#y)" fill="url(#B)" d="M202.001 65.999c-70.134 0-127.001 56.867-127.001 127 0 70.128 56.867 126.999 127.001 126.999C272.13 319.998 329 263.127 329 192.999c0-70.133-56.87-127-126.999-127z"/><path opacity=".31" clip-path="url(#y)" fill="#191919" d="M256.001 67C151.62 67 67 151.619 67 256s84.62 189 189.001 189S445 360.381 445 256 360.382 67 256.001 67zm0 361.481c-95.259 0-172.485-77.224-172.485-172.481 0-95.257 77.226-172.484 172.485-172.484 95.259 0 172.48 77.226 172.48 172.484 0 95.258-77.221 172.481-172.48 172.481z"/><path stroke="#E4EAF4" stroke-width="3" stroke-miterlimit="10" fill="none" d="M231.267 242.166l65.335-54.5m0 0L245.867 136.5m50.735 51.166l19.5-49.228m-84.835 103.728l-85.232-23.999m85.232 23.999l-50.7 70.334m50.7-70.334l56.6 63.4m0 0l72.334 24.301m-72.334-24.301l-34.564 63.967"/><defs><circle id="C" cx="231.267" cy="242.166" r="34.333"/></defs><clipPath id="D"><use xlink:href="#C" overflow="visible"/></clipPath><radialGradient id="E" cx="219.436" cy="230.335" r="51.497" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#D)" fill="url(#E)" cx="219.436" cy="230.335" r="51.498"/><radialGradient id="F" cx="228.484" cy="237.666" r="34.647" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F6FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4EBF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDBF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C7EF" stop-opacity=".712"/><stop offset="1" stop-color="#95B2E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#D)" fill="url(#F)" cx="229.934" cy="240.833" r="36.833"/><defs><circle id="G" cx="180.568" cy="312.5" r="24.033"/></defs><clipPath id="H"><use xlink:href="#G" overflow="visible"/></clipPath><radialGradient id="I" cx="172.285" cy="304.218" r="36.048" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#H)" fill="url(#I)" cx="172.285" cy="304.219" r="36.048"/><radialGradient id="J" cx="181.17" cy="304.201" r="24.252" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F6FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4EAF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CED9F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C4EF" stop-opacity=".712"/><stop offset="1" stop-color="#95AEE9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#H)" fill="url(#J)" cx="179.634" cy="311.566" r="25.783"/><defs><circle id="K" cx="288.801" cy="306.5" r="24.033"/></defs><clipPath id="L"><use xlink:href="#K" overflow="visible"/></clipPath><radialGradient id="M" cx="280.519" cy="298.218" r="36.048" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#L)" fill="url(#M)" cx="280.519" cy="298.219" r="36.048"/><radialGradient id="N" cx="282.978" cy="298.557" r="24.253" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F5FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4E7F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CED4F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2BBEF" stop-opacity=".712"/><stop offset="1" stop-color="#95A2E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#L)" fill="url(#N)" cx="287.867" cy="305.566" r="25.783"/><defs><circle id="O" cx="146.035" cy="218.167" r="17.167"/></defs><clipPath id="P"><use xlink:href="#O" overflow="visible"/></clipPath><radialGradient id="Q" cx="140.119" cy="212.251" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#P)" fill="url(#Q)" cx="140.119" cy="212.252" r="25.749"/><radialGradient id="R" cx="148.938" cy="215.719" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFEFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F9FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4F1F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEE5F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2D6EF" stop-opacity=".712"/><stop offset="1" stop-color="#95C7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#P)" fill="url(#R)" cx="145.368" cy="217.5" r="18.416"/><defs><circle id="S" cx="296.603" cy="187.667" r="17.167"/></defs><clipPath id="T"><use xlink:href="#S" overflow="visible"/></clipPath><radialGradient id="U" cx="290.687" cy="181.751" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#T)" fill="url(#U)" cx="290.687" cy="181.751" r="25.749"/><radialGradient id="V" cx="290.568" cy="187.029" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F7FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4ECF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDEF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2CBEF" stop-opacity=".712"/><stop offset="1" stop-color="#95B7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#T)" fill="url(#V)" cx="295.936" cy="187" r="18.416"/><defs><circle id="W" cx="253.304" cy="369.533" r="17.167"/></defs><clipPath id="X"><use xlink:href="#W" overflow="visible"/></clipPath><radialGradient id="Y" cx="247.388" cy="363.618" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#X)" fill="url(#Y)" cx="247.388" cy="363.619" r="25.749"/><radialGradient id="Z" cx="249.839" cy="358.1" r="17.323" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFCFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F3FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4E4F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CECFF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2B4EF" stop-opacity=".712"/><stop offset="1" stop-color="#9598E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#X)" fill="url(#Z)" cx="252.637" cy="368.867" r="18.416"/><defs><circle id="aa" cx="360.868" cy="330.533" r="17.167"/></defs><clipPath id="ab"><use xlink:href="#aa" overflow="visible"/></clipPath><radialGradient id="ac" cx="354.952" cy="324.618" r="25.749" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#ab)" fill="url(#ac)" cx="354.952" cy="324.619" r="25.749"/><radialGradient id="ad" cx="351.019" cy="321.415" r="17.322" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FDFCFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F5F3FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E9E4F9" stop-opacity=".487"/><stop offset=".755" stop-color="#D7CEF5" stop-opacity=".604"/><stop offset=".89" stop-color="#C0B2EF" stop-opacity=".712"/><stop offset="1" stop-color="#A995E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#ab)" fill="url(#ad)" cx="360.201" cy="329.867" r="18.416"/><defs><circle id="ae" cx="245.867" cy="136.5" r="13.733"/></defs><clipPath id="af"><use xlink:href="#ae" overflow="visible"/></clipPath><radialGradient id="ag" cx="241.135" cy="131.768" r="20.599" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#af)" fill="url(#ag)" cx="241.135" cy="131.768" r="20.599"/><radialGradient id="ah" cx="242.97" cy="139.026" r="13.859" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFEFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F9FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4F1F9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEE5F5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2D6EF" stop-opacity=".712"/><stop offset="1" stop-color="#95C7E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#af)" fill="url(#ah)" cx="245.334" cy="135.967" r="14.733"/><defs><circle id="ai" cx="316.102" cy="138.438" r="13.733"/></defs><clipPath id="aj"><use xlink:href="#ai" overflow="visible"/></clipPath><radialGradient id="ak" cx="311.369" cy="133.706" r="20.599" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#B8C4D1"/></radialGradient><circle clip-path="url(#aj)" fill="url(#ak)" cx="311.369" cy="133.707" r="20.599"/><radialGradient id="al" cx="309.035" cy="140.85" r="13.859" gradientTransform="translate(-12.968 -11.834) scale(1.063)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset=".265" stop-color="#FCFDFE" stop-opacity=".212"/><stop offset=".449" stop-color="#F3F7FD" stop-opacity=".359"/><stop offset=".609" stop-color="#E4ECF9" stop-opacity=".487"/><stop offset=".755" stop-color="#CEDDF5" stop-opacity=".604"/><stop offset=".89" stop-color="#B2C9EF" stop-opacity=".712"/><stop offset="1" stop-color="#95B5E9" stop-opacity=".8"/></radialGradient><circle clip-path="url(#aj)" fill="url(#al)" cx="315.568" cy="137.905" r="14.733"/></svg>
\ No newline at end of file
diff --git a/test/plugins/cleanupIDs.12.svg b/test/plugins/cleanupIDs.12.svg
new file mode 100644
index 0000000..1cb08f3
--- /dev/null
+++ b/test/plugins/cleanupIDs.12.svg
@@ -0,0 +1,19 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 230 120">
+    <circle id="garbage1" fill="red" cx="60" cy="60" r="50"/>
+    <rect id="garbage2" fill="blue" x="120" y="10" width="100" height="100"/>
+    <view id="xyzgarbage1" viewBox="0 0 120 120"/>
+    <view id="xyzgarbage2" viewBox="110 0 120 120"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 230 120">
+    <circle fill="red" cx="60" cy="60" r="50"/>
+    <rect fill="blue" x="120" y="10" width="100" height="100"/>
+    <view id="xyzgarbage1" viewBox="0 0 120 120"/>
+    <view id="xyzgarbage2" viewBox="110 0 120 120"/>
+</svg>
+
+@@@
+
+{"preservePrefixes": ["xyz"]}
diff --git a/test/plugins/cleanupIDs.13.svg b/test/plugins/cleanupIDs.13.svg
new file mode 100644
index 0000000..4349677
--- /dev/null
+++ b/test/plugins/cleanupIDs.13.svg
@@ -0,0 +1,22 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 120 120">
+    <style>
+        svg .hidden { display: none; }
+        svg .hidden:target { display: inline; }
+    </style>
+    <circle id="pre1_circle" class="hidden" fill="red" cx="60" cy="60" r="50"/>
+    <rect id="pre2_rect" class="hidden" fill="blue" x="10" y="10" width="100" height="100"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 120 120">
+    <style>
+        svg .hidden { display: none; } svg .hidden:target { display: inline; }
+    </style>
+    <circle id="pre1_circle" class="hidden" fill="red" cx="60" cy="60" r="50"/>
+    <rect id="pre2_rect" class="hidden" fill="blue" x="10" y="10" width="100" height="100"/>
+</svg>
+
+@@@
+
+{"force": true, "preservePrefixes": ["pre1_", "pre2_"]}
diff --git a/test/plugins/cleanupIDs.14.svg b/test/plugins/cleanupIDs.14.svg
new file mode 100644
index 0000000..ae8d80c
--- /dev/null
+++ b/test/plugins/cleanupIDs.14.svg
@@ -0,0 +1,34 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 120 120">
+    <style>
+        svg .hidden { display: none; }
+        svg .hidden:target { display: inline; }
+    </style>
+    <defs>
+        <circle id="circle" fill="red" cx="60" cy="60" r="50"/>
+        <rect id="rect" fill="blue" x="10" y="10" width="100" height="100"/>
+    </defs>
+    <g id="pre1_figure" class="hidden">
+        <use xlink:href="#circle"/>
+        <use href="#rect"/>
+    </g>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 120 120">
+    <style>
+        svg .hidden { display: none; } svg .hidden:target { display: inline; }
+    </style>
+    <defs>
+        <circle id="a" fill="red" cx="60" cy="60" r="50"/>
+        <rect id="b" fill="blue" x="10" y="10" width="100" height="100"/>
+    </defs>
+    <g id="pre1_figure" class="hidden">
+        <use xlink:href="#a"/>
+        <use href="#b"/>
+    </g>
+</svg>
+
+@@@
+
+{"force": true, "preservePrefixes": "pre1_"}
diff --git a/test/plugins/cleanupIDs.15.svg b/test/plugins/cleanupIDs.15.svg
new file mode 100644
index 0000000..ec0534f
--- /dev/null
+++ b/test/plugins/cleanupIDs.15.svg
@@ -0,0 +1,19 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 230 120">
+    <circle id="circle" fill="red" cx="60" cy="60" r="50"/>
+    <rect id="rect" fill="blue" x="120" y="10" width="100" height="100"/>
+    <view id="circle-suffix" viewBox="0 0 120 120"/>
+    <view id="rect-suffix" viewBox="110 0 120 120"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 230 120">
+    <circle id="circle" fill="red" cx="60" cy="60" r="50"/>
+    <rect id="rect" fill="blue" x="120" y="10" width="100" height="100"/>
+    <view viewBox="0 0 120 120"/>
+    <view id="rect-suffix" viewBox="110 0 120 120"/>
+</svg>
+
+@@@
+
+{"preserve": ["circle"], "preservePrefixes": ["suffix", "rect"]}
diff --git a/test/plugins/removeAttributesBySelector.01.svg b/test/plugins/removeAttributesBySelector.01.svg
new file mode 100644
index 0000000..cf47799
--- /dev/null
+++ b/test/plugins/removeAttributesBySelector.01.svg
@@ -0,0 +1,13 @@
+<svg id="test" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+    <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
+</svg>
+
+@@@
+
+<svg id="test" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+    <rect x="0" y="0" width="100" height="100" stroke="#00ff00"/>
+</svg>
+
+@@@
+
+{ "selector": "[fill='#00ff00']", "attributes": "fill" }
diff --git a/test/plugins/removeAttributesBySelector.02.svg b/test/plugins/removeAttributesBySelector.02.svg
new file mode 100644
index 0000000..a584eb7
--- /dev/null
+++ b/test/plugins/removeAttributesBySelector.02.svg
@@ -0,0 +1,13 @@
+<svg id="test" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+    <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
+</svg>
+
+@@@
+
+<svg id="test" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+    <rect x="0" y="0" width="100" height="100"/>
+</svg>
+
+@@@
+
+{ "selector": "[fill='#00ff00']", "attributes": ["fill", "stroke"] }
diff --git a/test/plugins/removeAttributesBySelector.03.svg b/test/plugins/removeAttributesBySelector.03.svg
new file mode 100644
index 0000000..d54f731
--- /dev/null
+++ b/test/plugins/removeAttributesBySelector.03.svg
@@ -0,0 +1,13 @@
+<svg id="test" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+    <rect id="remove" x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
+</svg>
+
+@@@
+
+<svg id="test" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+    <rect x="0" y="0" width="100" height="100"/>
+</svg>
+
+@@@
+
+{ "selectors": [{ "selector": "[fill='#00ff00']", "attributes": "fill" }, { "selector": "#remove", "attributes": ["stroke", "id"] }] }
diff --git a/test/plugins/removeAttrs.03.svg b/test/plugins/removeAttrs.03.svg
new file mode 100644
index 0000000..f4cf672
--- /dev/null
+++ b/test/plugins/removeAttrs.03.svg
@@ -0,0 +1,19 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+    <circle fill="currentColor" stroke-width="6" stroke-dashoffset="5" cx="60" cy="60" r="50"/>
+    <circle fill="red" stroke="#000" stroke-width="6" stroke-dashoffset="5" stroke-opacity="0" cx="60" cy="60" r="50"/>
+    <circle stroke="currentColor" stroke-width="6" stroke-dashoffset="5" stroke-opacity="0" cx="60" cy="60" r="50"/>
+    <path fill="red" stroke="red" d="M100,200 300,400 H100 V300 C100,100 250,100 250,200 S400,300 400,200 Q400,50 600,300 T1000,300 z"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg">
+    <circle fill="currentColor" stroke-width="6" stroke-dashoffset="5" cx="60" cy="60" r="50"/>
+    <circle stroke-width="6" stroke-dashoffset="5" stroke-opacity="0" cx="60" cy="60" r="50"/>
+    <circle stroke="currentColor" stroke-width="6" stroke-dashoffset="5" stroke-opacity="0" cx="60" cy="60" r="50"/>
+    <path d="M100,200 300,400 H100 V300 C100,100 250,100 250,200 S400,300 400,200 Q400,50 600,300 T1000,300 z"/>
+</svg>
+
+@@@
+
+{"attrs":"(fill|stroke)", "preserveCurrentColor": true}
diff --git a/test/plugins/removeOffCanvasPaths.01.svg b/test/plugins/removeOffCanvasPaths.01.svg
new file mode 100644
index 0000000..6bf8f43
--- /dev/null
+++ b/test/plugins/removeOffCanvasPaths.01.svg
@@ -0,0 +1,13 @@
+<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
+    <path d="M10 10 h 80 v 80 h -80 z"/>
+    <path d="M10 -90 h 80 v 80 h -80 z"/>
+    <path d="M110 10 h 80 v 80 h -80 z"/>
+    <path d="M10 110 h 80 v 80 h -80 z"/>
+    <path d="M-90 10 h 80 v 80 h -80 z"/>
+</svg>
+
+@@@
+
+<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
+    <path d="M10 10 h 80 v 80 h -80 z"/>
+</svg>
diff --git a/test/plugins/removeOffCanvasPaths.02.svg b/test/plugins/removeOffCanvasPaths.02.svg
new file mode 100644
index 0000000..3597831
--- /dev/null
+++ b/test/plugins/removeOffCanvasPaths.02.svg
@@ -0,0 +1,15 @@
+<svg height="1000" width="1000" xmlns="http://www.w3.org/2000/svg">
+    <path d="M10 10 h 80 v 80 h -80 z"/>
+    <path d="M10 -90 h 80 v 80 h -80 z"/>
+    <path d="M110 10 h 80 v 80 h -80 z"/>
+    <path d="M10 110 h 80 v 80 h -80 z"/>
+    <path d="M-90 10 h 80 v 80 h -80 z"/>
+</svg>
+
+@@@
+
+<svg height="1000" width="1000" xmlns="http://www.w3.org/2000/svg">
+    <path d="M10 10 h 80 v 80 h -80 z"/>
+    <path d="M110 10 h 80 v 80 h -80 z"/>
+    <path d="M10 110 h 80 v 80 h -80 z"/>
+</svg>
diff --git a/test/plugins/removeOffCanvasPaths.03.svg b/test/plugins/removeOffCanvasPaths.03.svg
new file mode 100644
index 0000000..c9a25d6
--- /dev/null
+++ b/test/plugins/removeOffCanvasPaths.03.svg
@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
+    <path d="M0 0h128v128H0z" fill="none" stroke="red"/>
+    <path d="M10.14 51.5c4.07 1.56 7.52 4.47 7.37 11.16" fill="none" stroke="#00f"/>
+    <path d="M100 200c4.07 1.56 7.52 4.47 7.37 11.16" fill="none" stroke="#00f"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
+    <path d="M0 0h128v128H0z" fill="none" stroke="red"/>
+    <path d="M10.14 51.5c4.07 1.56 7.52 4.47 7.37 11.16" fill="none" stroke="#00f"/>
+</svg>
diff --git a/test/plugins/removeOffCanvasPaths.04.svg b/test/plugins/removeOffCanvasPaths.04.svg
new file mode 100644
index 0000000..7ddb7f2
--- /dev/null
+++ b/test/plugins/removeOffCanvasPaths.04.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
+    <path d="M20.16 107.3l13.18-12.18m-1.6-5.41l-16.32 6.51M13 84.5h18m77 22.8L94.83 95.12m1.6-5.41l16.32 6.51M115 84.5H98" fill="none" stroke="#444" stroke-width="3"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
+    <path d="M20.16 107.3l13.18-12.18m-1.6-5.41l-16.32 6.51M13 84.5h18m77 22.8L94.83 95.12m1.6-5.41l16.32 6.51M115 84.5H98" fill="none" stroke="#444" stroke-width="3"/>
+</svg>
diff --git a/test/plugins/removeOffCanvasPaths.05.svg b/test/plugins/removeOffCanvasPaths.05.svg
new file mode 100644
index 0000000..1c76296
--- /dev/null
+++ b/test/plugins/removeOffCanvasPaths.05.svg
@@ -0,0 +1,15 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+    <path d="M-100-100h50v50h-50z" fill="red" transform="translate(100 100)"/>
+    <g transform="translate(150 150)">
+        <path d="M-100-100h50v50h-50z" fill="blue"/>
+    </g>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+    <path d="M-100-100h50v50h-50z" fill="red" transform="translate(100 100)"/>
+    <g transform="translate(150 150)">
+        <path d="M-100-100h50v50h-50z" fill="blue"/>
+    </g>
+</svg>
diff --git a/test/plugins/reusePaths.01.svg b/test/plugins/reusePaths.01.svg
new file mode 100644
index 0000000..3630385
--- /dev/null
+++ b/test/plugins/reusePaths.01.svg
@@ -0,0 +1,35 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+    <path id="test0" d="M 10,50 l 20,30 L 20,30"/>
+    <path transform="translate(10, 10)"
+          d="M 10,50 c 20,30 40,50 60,70 C 20,30 40,50 60,70"/>
+    <path transform="translate(20, 20)"
+          d="M 10,50 c 20,30 40,50 60,70 C 20,30 40,50 60,70"/>
+    <path d="M 10,50 c 20,30 40,50 60,70 C 20,30 40,50 60,70"/>
+    <path id="test1" d="M 10,50 l 20,30 L 20,30"/>
+    <path d="M 10,50 a 20,60 45 0,1 40,70 A 20,60 45 0,1 40,70"/>
+    <path d="M 20,30 a 20,60 45 0,1 40,70 A 20,60 45 0,1 40,70"/>
+    <g>
+      <path id="test2" d="M 10,50 l 20,30 L 20,30"/>
+    </g>
+    <path d="M 10,50 c 20,30 40,50 60,70 C 20,30 40,50 60,70"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg">
+    <defs>
+        <path id="test0" d="M 10,50 l 20,30 L 20,30"/>
+        <path d="M 10,50 c 20,30 40,50 60,70 C 20,30 40,50 60,70" id="reuse-0"/>
+    </defs>
+    <use xlink:href="#test0"/>
+    <use transform="translate(10, 10)" xlink:href="#reuse-0"/>
+    <use transform="translate(20, 20)" xlink:href="#reuse-0"/>
+    <use xlink:href="#reuse-0"/>
+    <use id="test1" xlink:href="#test0"/>
+    <path d="M 10,50 a 20,60 45 0,1 40,70 A 20,60 45 0,1 40,70"/>
+    <path d="M 20,30 a 20,60 45 0,1 40,70 A 20,60 45 0,1 40,70"/>
+    <g>
+        <use id="test2" xlink:href="#test0"/>
+    </g>
+    <use xlink:href="#reuse-0"/>
+</svg>
diff --git a/test/plugins/reusePaths.02.svg b/test/plugins/reusePaths.02.svg
new file mode 100644
index 0000000..45bfefd
--- /dev/null
+++ b/test/plugins/reusePaths.02.svg
@@ -0,0 +1,23 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+    <path id="test0" d="M 10,50 l 20,30 L 20,30"/>
+    <path id="test1" stroke="red" d="M 10,50 l 20,30 L 20,30"/>
+    <path id="test2" stroke="blue" d="M 10,50 l 20,30 L 20,30"/>
+    <path id="test3" d="M 10,50 l 20,30 L 20,30"/>
+    <path id="test4" stroke="blue" d="M 10,50 l 20,30 L 20,30"/>
+    <path id="test1" stroke="red" fill="green" d="M 10,50 l 20,30 L 20,30"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg">
+    <defs>
+        <path id="test2" stroke="blue" d="M 10,50 l 20,30 L 20,30"/>
+        <path id="test0" d="M 10,50 l 20,30 L 20,30"/>
+    </defs>
+    <use xlink:href="#test0"/>
+    <path id="test1" stroke="red" d="M 10,50 l 20,30 L 20,30"/>
+    <use xlink:href="#test2"/>
+    <use id="test3" xlink:href="#test0"/>
+    <use id="test4" xlink:href="#test2"/>
+    <path id="test1" stroke="red" fill="green" d="M 10,50 l 20,30 L 20,30"/>
+</svg>