mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-01 01:38:07 +08:00
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>
93 lines
2.4 KiB
JavaScript
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;
|
|
}
|