Repository: svg/svgo
Pull request #979 (2018-06-09 05:29:41)

Add removeOffCanvasPaths plugin
The plugin is rudimentary: it compares each `<path>` to the viewBox using `intersects()` and removes those that don't. The plugin is disabled by default.

JoshyPHP: I have tested this plugin on various SVGs and while it works well enough for most, there are many edge cases that are difficult to handle. For instance, items whose geometry is modified by a transformation matrix.

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..f4bd0c9 100644
--- a/.svgo.yml
+++ b/.svgo.yml
@@ -55,11 +55,13 @@ plugins:
   - removeDesc
   - removeDimensions
   - removeAttrs
+  - removeAttributesBySelector
   - removeElementsByAttr
   - addClassesToSVGElement
   - removeStyleElement
   - removeScriptElement
   - addAttributesToSVGElement
+  - removeOffCanvasPaths
 
 # configure the indent (default 4 spaces) used by `--pretty` here:
 #
diff --git a/README.md b/README.md
index 66a254a..4dfcefc 100644
--- a/README.md
+++ b/README.md
@@ -58,6 +58,7 @@ 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) |
diff --git a/lib/svgo/coa.js b/lib/svgo/coa.js
index 012b51e..c63338f 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);
@@ -358,13 +370,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 +468,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 +532,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 +555,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/js2svg.js b/lib/svgo/js2svg.js
index 2480d8b..0a52c6b 100644
--- a/lib/svgo/js2svg.js
+++ b/lib/svgo/js2svg.js
@@ -57,7 +57,7 @@ function JS2SVG(config) {
     if (config) {
         this.config = Object.assign({}, defaults, config);
     } else {
-        this.config = defaults;
+        this.config = Object.assign({}, defaults);
     }
 
     var indent = this.config.indent;
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/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/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;
+}


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/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/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>