Repository: svg/svgo
Pull request #1000 (2018-07-11 22:39:35)

Add the preserveCurrentColor option to the removeAttrs plugin.
Hello, I just coded this up as a follow up for the issue I just logged https://github.com/svg/svgo/issues/999 .. I've added some explanations in my diff to hopefully make it easy to review.

Also, nothing output when I ran: `npm run lint` and `npm test` returns `  307 passing (1s)`. Let me know if you like this and/or if there's any conventions I missed. Thanks for your time!


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/removeAttrs.js b/plugins/removeAttrs.js
index c8968c2..0ee35f2 100644
--- a/plugins/removeAttrs.js
+++ b/plugins/removeAttrs.js
@@ -10,6 +10,7 @@ exports.description = 'removes specified attributes';
 
 exports.params = {
     elemSeparator: DEFAULT_SEPARATOR,
+    preserveCurrentColor: false,
     attrs: []
 };
 
@@ -19,6 +20,9 @@ exports.params = {
  * @param elemSeparator
  *   format: string
  *
+ * @param preserveCurrentColor
+ *   format: boolean
+ *
  * @param attrs:
  *
  *   format: [ element* : attribute* ]
@@ -69,7 +73,6 @@ exports.params = {
  * @author Benny Schudel
  */
 exports.fn = function(item, params) {
-
         // wrap into an array if params is not
     if (!Array.isArray(params.attrs)) {
         params.attrs = [params.attrs];
@@ -77,6 +80,7 @@ exports.fn = function(item, params) {
 
     if (item.isElem()) {
         var elemSeparator = typeof params.elemSeparator == 'string' ? params.elemSeparator : DEFAULT_SEPARATOR;
+        var preserveCurrentColor = typeof params.preserveCurrentColor == 'boolean' ? params.preserveCurrentColor : false;
 
             // prepare patterns
         var patterns = params.attrs.map(function(pattern) {
@@ -107,10 +111,15 @@ exports.fn = function(item, params) {
                     // loop attributes
                 item.eachAttr(function(attr) {
                     var name = attr.name;
+                    var value = attr.value;
+                    var isFillCurrentColor = preserveCurrentColor && name == 'fill' && value == 'currentColor';
+                    var isStrokeCurrentColor = preserveCurrentColor && name == 'stroke' && value == 'currentColor';
 
+                    if (!(isFillCurrentColor || isStrokeCurrentColor)) {
                         // matches attribute name
-                    if (pattern[1].test(name)) {
-                        item.removeAttr(name);
+                        if (pattern[1].test(name)) {
+                            item.removeAttr(name);
+                        }
                     }
 
                 });
diff --git a/plugins/removeOffCanvasPaths.js b/plugins/removeOffCanvasPaths.js
new file mode 100644
index 0000000..5bcb9a1
--- /dev/null
+++ b/plugins/removeOffCanvasPaths.js
@@ -0,0 +1,133 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes elements that are drawn outside of the viewbox (disabled by default)';
+
+var SVGO       = require('../lib/svgo.js'),
+	_path      = require('./_path.js'),
+	intersects = _path.intersects,
+	path2js    = _path.path2js,
+	viewBox,
+	viewBoxJS;
+
+/**
+ * Remove elements that are drawn outside of the viewbox.
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author JoshyPHP
+ */
+exports.fn = function(item) {
+
+	if (item.isElem('path') && item.hasAttr('d') && typeof viewBox !== 'undefined')
+	{
+		// Consider that any item with a transform attribute or a M instruction
+		// within the viewBox is visible
+		if (hasTransform(item) || pathMovesWithinViewBox(item.attr('d').value))
+		{
+			return true;
+		}
+
+		var pathJS = path2js(item);
+		if (pathJS.length === 2)
+		{
+			// Use a closed clone of the path if it's too short for intersects()
+			pathJS = JSON.parse(JSON.stringify(pathJS));
+			pathJS.push({ instruction: 'z' });
+		}
+
+		return intersects(viewBoxJS, pathJS);
+	}
+	if (item.isElem('svg'))
+	{
+		parseViewBox(item);
+	}
+
+	return true;
+};
+
+/**
+ * Test whether given item or any of its ancestors has a transform attribute.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ */
+function hasTransform(item)
+{
+	return item.hasAttr('transform') || (item.parentNode && hasTransform(item.parentNode));
+}
+
+/**
+ * Parse the viewBox coordinates and compute the JS representation of its path.
+ *
+ * @param {Object} svg svg element item
+ */
+function parseViewBox(svg)
+{
+	var viewBoxData = '';
+	if (svg.hasAttr('viewBox'))
+	{
+		// Remove commas and plus signs, normalize and trim whitespace
+		viewBoxData = svg.attr('viewBox').value;
+	}
+	else if (svg.hasAttr('height') && svg.hasAttr('width'))
+	{
+		viewBoxData = '0 0 ' + svg.attr('width').value + ' ' + svg.attr('height').value;
+	}
+
+	// Remove commas and plus signs, normalize and trim whitespace
+	viewBoxData = viewBoxData.replace(/[,+]|px/g, ' ').replace(/\s+/g, ' ').replace(/^\s*|\s*$/g, '');
+
+	// Ensure that the dimensions are 4 values separated by space
+	var m = /^(-?\d*\.?\d+) (-?\d*\.?\d+) (\d*\.?\d+) (\d*\.?\d+)$/.exec(viewBoxData);
+	if (!m)
+	{
+		return;
+	}
+
+	// Store the viewBox boundaries
+	viewBox = {
+		left:   parseFloat(m[1]),
+		top:    parseFloat(m[2]),
+		right:  parseFloat(m[1]) + parseFloat(m[3]),
+		bottom: parseFloat(m[2]) + parseFloat(m[4])
+	};
+
+	var path = new SVGO().createContentItem({
+		elem:   'path',
+		prefix: '',
+		local:  'path'
+	});
+	path.addAttr({
+		name:   'd',
+		prefix: '',
+		local:  'd',
+		value:  'M' + m[1] + ' ' + m[2] + 'h' + m[3] + 'v' + m[4] + 'H' + m[1] + 'z'
+	});
+
+	viewBoxJS = path2js(path);
+}
+
+/**
+ * Test whether given path has a M instruction with coordinates within the viewBox.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ */
+function pathMovesWithinViewBox(path)
+{
+	var regexp = /M\s*(-?\d*\.?\d+)(?!\d)\s*(-?\d*\.?\d+)/g, m;
+	while (null !== (m = regexp.exec(path)))
+	{
+		if (m[1] >= viewBox.left && m[1] <= viewBox.right && m[2] >= viewBox.top && m[2] <= viewBox.bottom)
+		{
+			return true;
+		}
+	}
+
+	return false;
+}


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/removeAttrs.03.svg b/test/plugins/removeAttrs.03.svg
new file mode 100644
index 0000000..f4cf672
--- /dev/null
+++ b/test/plugins/removeAttrs.03.svg
@@ -0,0 +1,19 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+    <circle fill="currentColor" stroke-width="6" stroke-dashoffset="5" cx="60" cy="60" r="50"/>
+    <circle fill="red" stroke="#000" stroke-width="6" stroke-dashoffset="5" stroke-opacity="0" cx="60" cy="60" r="50"/>
+    <circle stroke="currentColor" stroke-width="6" stroke-dashoffset="5" stroke-opacity="0" cx="60" cy="60" r="50"/>
+    <path fill="red" stroke="red" d="M100,200 300,400 H100 V300 C100,100 250,100 250,200 S400,300 400,200 Q400,50 600,300 T1000,300 z"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg">
+    <circle fill="currentColor" stroke-width="6" stroke-dashoffset="5" cx="60" cy="60" r="50"/>
+    <circle stroke-width="6" stroke-dashoffset="5" stroke-opacity="0" cx="60" cy="60" r="50"/>
+    <circle stroke="currentColor" stroke-width="6" stroke-dashoffset="5" stroke-opacity="0" cx="60" cy="60" r="50"/>
+    <path d="M100,200 300,400 H100 V300 C100,100 250,100 250,200 S400,300 400,200 Q400,50 600,300 T1000,300 z"/>
+</svg>
+
+@@@
+
+{"attrs":"(fill|stroke)", "preserveCurrentColor": true}
diff --git a/test/plugins/removeOffCanvasPaths.01.svg b/test/plugins/removeOffCanvasPaths.01.svg
new file mode 100644
index 0000000..6bf8f43
--- /dev/null
+++ b/test/plugins/removeOffCanvasPaths.01.svg
@@ -0,0 +1,13 @@
+<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
+    <path d="M10 10 h 80 v 80 h -80 z"/>
+    <path d="M10 -90 h 80 v 80 h -80 z"/>
+    <path d="M110 10 h 80 v 80 h -80 z"/>
+    <path d="M10 110 h 80 v 80 h -80 z"/>
+    <path d="M-90 10 h 80 v 80 h -80 z"/>
+</svg>
+
+@@@
+
+<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
+    <path d="M10 10 h 80 v 80 h -80 z"/>
+</svg>
diff --git a/test/plugins/removeOffCanvasPaths.02.svg b/test/plugins/removeOffCanvasPaths.02.svg
new file mode 100644
index 0000000..3597831
--- /dev/null
+++ b/test/plugins/removeOffCanvasPaths.02.svg
@@ -0,0 +1,15 @@
+<svg height="1000" width="1000" xmlns="http://www.w3.org/2000/svg">
+    <path d="M10 10 h 80 v 80 h -80 z"/>
+    <path d="M10 -90 h 80 v 80 h -80 z"/>
+    <path d="M110 10 h 80 v 80 h -80 z"/>
+    <path d="M10 110 h 80 v 80 h -80 z"/>
+    <path d="M-90 10 h 80 v 80 h -80 z"/>
+</svg>
+
+@@@
+
+<svg height="1000" width="1000" xmlns="http://www.w3.org/2000/svg">
+    <path d="M10 10 h 80 v 80 h -80 z"/>
+    <path d="M110 10 h 80 v 80 h -80 z"/>
+    <path d="M10 110 h 80 v 80 h -80 z"/>
+</svg>
diff --git a/test/plugins/removeOffCanvasPaths.03.svg b/test/plugins/removeOffCanvasPaths.03.svg
new file mode 100644
index 0000000..c9a25d6
--- /dev/null
+++ b/test/plugins/removeOffCanvasPaths.03.svg
@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
+    <path d="M0 0h128v128H0z" fill="none" stroke="red"/>
+    <path d="M10.14 51.5c4.07 1.56 7.52 4.47 7.37 11.16" fill="none" stroke="#00f"/>
+    <path d="M100 200c4.07 1.56 7.52 4.47 7.37 11.16" fill="none" stroke="#00f"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
+    <path d="M0 0h128v128H0z" fill="none" stroke="red"/>
+    <path d="M10.14 51.5c4.07 1.56 7.52 4.47 7.37 11.16" fill="none" stroke="#00f"/>
+</svg>
diff --git a/test/plugins/removeOffCanvasPaths.04.svg b/test/plugins/removeOffCanvasPaths.04.svg
new file mode 100644
index 0000000..7ddb7f2
--- /dev/null
+++ b/test/plugins/removeOffCanvasPaths.04.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
+    <path d="M20.16 107.3l13.18-12.18m-1.6-5.41l-16.32 6.51M13 84.5h18m77 22.8L94.83 95.12m1.6-5.41l16.32 6.51M115 84.5H98" fill="none" stroke="#444" stroke-width="3"/>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
+    <path d="M20.16 107.3l13.18-12.18m-1.6-5.41l-16.32 6.51M13 84.5h18m77 22.8L94.83 95.12m1.6-5.41l16.32 6.51M115 84.5H98" fill="none" stroke="#444" stroke-width="3"/>
+</svg>
diff --git a/test/plugins/removeOffCanvasPaths.05.svg b/test/plugins/removeOffCanvasPaths.05.svg
new file mode 100644
index 0000000..1c76296
--- /dev/null
+++ b/test/plugins/removeOffCanvasPaths.05.svg
@@ -0,0 +1,15 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+    <path d="M-100-100h50v50h-50z" fill="red" transform="translate(100 100)"/>
+    <g transform="translate(150 150)">
+        <path d="M-100-100h50v50h-50z" fill="blue"/>
+    </g>
+</svg>
+
+@@@
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+    <path d="M-100-100h50v50h-50z" fill="red" transform="translate(100 100)"/>
+    <g transform="translate(150 150)">
+        <path d="M-100-100h50v50h-50z" fill="blue"/>
+    </g>
+</svg>