1
0
mirror of https://github.com/svg/svgo.git synced 2025-07-31 07:44:22 +03:00

Refactor removeUnusedNS plugin (#1559)

- covered with types
- migrated to visitor plugin api
- dropped traverse utility which is replaced by visitor
This commit is contained in:
Bogdan Chadkin
2021-09-10 20:30:34 +03:00
committed by GitHub
parent d9102930ca
commit 6eb4524aef
3 changed files with 44 additions and 86 deletions

View File

@ -55,26 +55,6 @@ const closestByName = (node, name) => {
}; };
exports.closestByName = closestByName; exports.closestByName = closestByName;
const traverseBreak = Symbol();
exports.traverseBreak = traverseBreak;
/**
* @type {(node: any, fn: any) => any}
*/
const traverse = (node, fn) => {
if (fn(node) === traverseBreak) {
return traverseBreak;
}
if (node.type === 'root' || node.type === 'element') {
for (const child of node.children) {
if (traverse(child, fn) === traverseBreak) {
return traverseBreak;
}
}
}
};
exports.traverse = traverse;
const visitSkip = Symbol(); const visitSkip = Symbol();
exports.visitSkip = visitSkip; exports.visitSkip = visitSkip;

View File

@ -1,82 +1,61 @@
'use strict'; 'use strict';
const { traverse } = require('../lib/xast.js'); exports.type = 'visitor';
const { parseName } = require('../lib/svgo/tools.js');
exports.name = 'removeUnusedNS'; exports.name = 'removeUnusedNS';
exports.type = 'full';
exports.active = true; exports.active = true;
exports.description = 'removes unused namespaces declaration'; exports.description = 'removes unused namespaces declaration';
/** /**
* Remove unused namespaces declaration. * Remove unused namespaces declaration from svg element
* * which are not used in elements or attributes
* @param {Object} item current iteration item
* @return {Boolean} if false, item will be filtered out
* *
* @author Kir Belevich * @author Kir Belevich
*
* @type {import('../lib/types').Plugin<void>}
*/ */
exports.fn = function (root) { exports.fn = () => {
let svgElem;
const xmlnsCollection = [];
/** /**
* Remove namespace from collection. * @type {Set<string>}
*
* @param {String} ns namescape name
*/ */
function removeNSfromCollection(ns) { const unusedNamespaces = new Set();
const pos = xmlnsCollection.indexOf(ns); return {
element: {
// if found - remove ns from the namespaces collection enter: (node, parentNode) => {
if (pos > -1) { // collect all namespaces from svg element
xmlnsCollection.splice(pos, 1); // (such as xmlns:xlink="http://www.w3.org/1999/xlink")
} if (node.name === 'svg' && parentNode.type === 'root') {
} for (const name of Object.keys(node.attributes)) {
if (name.startsWith('xmlns:')) {
traverse(root, (node) => { const local = name.slice('xmlns:'.length);
if (node.type === 'element') { unusedNamespaces.add(local);
if (node.name === 'svg') { }
for (const name of Object.keys(node.attributes)) {
const { prefix, local } = parseName(name);
// collect namespaces
if (prefix === 'xmlns' && local) {
xmlnsCollection.push(local);
} }
} }
if (unusedNamespaces.size !== 0) {
// if svg element has ns-attr // preserve namespace used in nested elements names
if (xmlnsCollection.length) { if (node.name.includes(':')) {
// save svg element const [ns] = node.name.split(':');
svgElem = node; if (unusedNamespaces.has(ns)) {
unusedNamespaces.delete(ns);
}
}
// preserve namespace used in nested elements attributes
for (const name of Object.keys(node.attributes)) {
if (name.includes(':')) {
const [ns] = name.split(':');
unusedNamespaces.delete(ns);
}
}
} }
} },
exit: (node, parentNode) => {
if (xmlnsCollection.length) { // remove unused namespace attributes from svg element
const { prefix } = parseName(node.name); if (node.name === 'svg' && parentNode.type === 'root') {
// check node for the ns-attrs for (const name of unusedNamespaces) {
if (prefix) { delete node.attributes[`xmlns:${name}`];
removeNSfromCollection(prefix); }
} }
},
// check each attr for the ns-attrs },
for (const name of Object.keys(node.attributes)) { };
const { prefix } = parseName(name);
removeNSfromCollection(prefix);
}
}
}
});
// remove svg element ns-attributes if they are not used even once
if (xmlnsCollection.length) {
for (const name of xmlnsCollection) {
delete svgElem.attributes['xmlns:' + name];
}
}
return root;
}; };

View File

@ -24,7 +24,6 @@
"plugins/removeDimensions.js", "plugins/removeDimensions.js",
"plugins/removeEmptyAttrs.js", "plugins/removeEmptyAttrs.js",
"plugins/removeNonInheritableGroupAttrs.js", "plugins/removeNonInheritableGroupAttrs.js",
"plugins/removeUnusedNS.js",
"plugins/removeXMLNS.js", "plugins/removeXMLNS.js",
"plugins/sortAttrs.js", "plugins/sortAttrs.js",
"plugins/removeEmptyContainers.js", "plugins/removeEmptyContainers.js",