Files
react-native-devtools-frontend/node_modules/svgo/plugins/reusePaths.js
T
Tim van der Lippe 706ec965fb Add packages to optimize svgs dynamically
These packages will be used to dynamically optimize SVG images
during the build.

R=jacktfranklin@chromium.org

Bug: 1216402
Change-Id: I04e95aa7d79c9d67beaf8a7861182c52b16b7d0f
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2939992
Reviewed-by: Jack Franklin <jacktfranklin@chromium.org>
Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org>
2021-06-04 13:32:16 +00:00

93 lines
2.4 KiB
JavaScript

'use strict';
const { traverse } = require('../lib/xast.js');
const JSAPI = require('../lib/svgo/jsAPI');
exports.type = 'full';
exports.active = false;
exports.description =
'Finds <path> elements with the same d, fill, and ' +
'stroke, and converts them to <use> elements ' +
'referencing a single <path> def.';
/**
* Finds <path> elements with the same d, fill, and stroke, and converts them to
* <use> elements referencing a single <path> def.
*
* @author Jacob Howcroft
*/
exports.fn = function (root) {
const seen = new Map();
let count = 0;
const defs = [];
traverse(root, (node) => {
if (
node.type !== 'element' ||
node.name !== 'path' ||
node.attributes.d == null
) {
return;
}
const d = node.attributes.d;
const fill = node.attributes.fill || '';
const stroke = node.attributes.stroke || '';
const key = d + ';s:' + stroke + ';f:' + fill;
const hasSeen = seen.get(key);
if (!hasSeen) {
seen.set(key, { elem: node, reused: false });
return;
}
if (!hasSeen.reused) {
hasSeen.reused = true;
if (hasSeen.elem.attributes.id == null) {
hasSeen.elem.attributes.id = 'reuse-' + count++;
}
defs.push(hasSeen.elem);
}
convertToUse(node, hasSeen.elem.attributes.id);
});
if (defs.length > 0) {
const defsTag = new JSAPI(
{
type: 'element',
name: 'defs',
attributes: {},
children: [],
},
root
);
root.children[0].spliceContent(0, 0, defsTag);
for (let def of defs) {
// Remove class and style before copying to avoid circular refs in
// JSON.stringify. This is fine because we don't actually want class or
// style information to be copied.
const style = def.style;
const defClass = def.class;
delete def.style;
delete def.class;
const defClone = def.clone();
def.style = style;
def.class = defClass;
delete defClone.attributes.transform;
defsTag.spliceContent(0, 0, defClone);
// Convert the original def to a use so the first usage isn't duplicated.
def = convertToUse(def, defClone.attributes.id);
delete def.attributes.id;
}
}
return root;
};
/** */
function convertToUse(item, href) {
item.renameElem('use');
delete item.attributes.d;
delete item.attributes.stroke;
delete item.attributes.fill;
item.attributes['xlink:href'] = '#' + href;
delete item.pathJS;
return item;
}