diff --git a/.svgo.yml b/.svgo.yml index 313bf7c68..f3c425cfe 100644 --- a/.svgo.yml +++ b/.svgo.yml @@ -41,6 +41,7 @@ plugins: - removeHiddenElems - removeEmptyText - convertShapeToPath + - removeOffCanvasPaths - moveElemsAttrsToGroup - moveGroupAttrsToElems - collapseGroups diff --git a/plugins/removeOffCanvasPaths.js b/plugins/removeOffCanvasPaths.js new file mode 100644 index 000000000..30fba2870 --- /dev/null +++ b/plugins/removeOffCanvasPaths.js @@ -0,0 +1,79 @@ +'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, + 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') && typeof viewBoxJS !== 'undefined') + { + return intersects(viewBoxJS, path2js(item)); + } + if (item.isElem('svg')) + { + viewBoxJS = getViewBoxJS(item); + } + + return true; +}; + +/** + * Compute the JS representation of the viewbox's path. + * + * @param {Object} svg svg element item + * @return {Object} JS representation, or undefined + */ +function getViewBoxJS(svg) +{ + var viewbox = ''; + if (svg.hasAttr('viewBox')) + { + // Remove commas and plus signs, normalize and trim whitespace + viewbox = svg.attr('viewBox').value; + } + else if (svg.hasAttr('height') && svg.hasAttr('width')) + { + viewbox = '0 0 ' + svg.attr('width').value + ' ' + svg.attr('height').value; + } + + // Remove commas and plus signs, normalize and trim whitespace + viewbox = viewbox.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(viewbox); + if (!m) + { + return undefined; + } + + 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' + }); + + return path2js(path); +} diff --git a/test/plugins/removeOffCanvasPaths.01.svg b/test/plugins/removeOffCanvasPaths.01.svg new file mode 100644 index 000000000..6bf8f4318 --- /dev/null +++ b/test/plugins/removeOffCanvasPaths.01.svg @@ -0,0 +1,13 @@ + + + + + + + + +@@@ + + + + diff --git a/test/plugins/removeOffCanvasPaths.02.svg b/test/plugins/removeOffCanvasPaths.02.svg new file mode 100644 index 000000000..3597831a4 --- /dev/null +++ b/test/plugins/removeOffCanvasPaths.02.svg @@ -0,0 +1,15 @@ + + + + + + + + +@@@ + + + + + +