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

Use maps in cleanupIDs. Fixes #562

This commit is contained in:
GreLI
2016-08-25 22:03:37 +03:00
parent 6e9854a046
commit d9e670c210
3 changed files with 60 additions and 35 deletions

View File

@@ -64,7 +64,7 @@
"coveralls": "~2.11.12" "coveralls": "~2.11.12"
}, },
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.12.0"
}, },
"license": "MIT" "license": "MIT"
} }

View File

@@ -12,7 +12,7 @@ exports.params = {
prefix: '' prefix: ''
}; };
var referencesProps = require('./_collections').referencesProps, var referencesProps = new Set(require('./_collections').referencesProps),
regReferencesUrl = /\burl\(("|')?#(.+?)\1\)/, regReferencesUrl = /\burl\(("|')?#(.+?)\1\)/,
regReferencesHref = /^#(.+?)$/, regReferencesHref = /^#(.+?)$/,
regReferencesBegin = /^(\w+?)\./, regReferencesBegin = /^(\w+?)\./,
@@ -36,8 +36,8 @@ exports.fn = function(data, params) {
var currentID, var currentID,
currentIDstring, currentIDstring,
IDs = Object.create(null), IDs = new Map(),
referencesIDs = Object.create(null), referencesIDs = new Map(),
idPrefix = 'id-', // prefix IDs so that values like '__proto__' don't break the work idPrefix = 'id-', // prefix IDs so that values like '__proto__' don't break the work
hasStyleOrScript = false; hasStyleOrScript = false;
@@ -67,24 +67,24 @@ exports.fn = function(data, params) {
var key; var key;
// save IDs // save IDs
if (attr.name === 'id') { if (attr.name === 'id') {
key = idPrefix + attr.value; key = attr.value;
if (key in IDs) { if (IDs.has(key)) {
item.removeAttr('id'); item.removeAttr('id');
} else { } else {
IDs[key] = item; IDs.set(key, item);
} }
} }
// save IDs url() references // save IDs url() references
else if (referencesProps.indexOf(attr.name) > -1) { else if (referencesProps.has(attr.name)) {
match = attr.value.match(regReferencesUrl); match = attr.value.match(regReferencesUrl);
if (match) { if (match) {
key = idPrefix + match[2]; key = match[2];
if (referencesIDs[key]) { if (referencesIDs.has(key)) {
referencesIDs[key].push(attr); referencesIDs.get(key).push(attr);
} else { } else {
referencesIDs[key] = [attr]; referencesIDs.set(key, [attr]);
} }
} }
} }
@@ -94,11 +94,11 @@ exports.fn = function(data, params) {
attr.local === 'href' && (match = attr.value.match(regReferencesHref)) || attr.local === 'href' && (match = attr.value.match(regReferencesHref)) ||
attr.name === 'begin' && (match = attr.value.match(regReferencesBegin)) attr.name === 'begin' && (match = attr.value.match(regReferencesBegin))
) { ) {
key = idPrefix + match[1]; key = match[1];
if (referencesIDs[key]) { if (referencesIDs.has(key)) {
referencesIDs[key].push(attr); referencesIDs.get(key).push(attr);
} else { } else {
referencesIDs[key] = [attr]; referencesIDs.set(key, [attr]);
} }
} }
}); });
@@ -121,37 +121,34 @@ exports.fn = function(data, params) {
return data; return data;
} }
var idKey; for (var ID of referencesIDs) {
for (var k in referencesIDs) { var key = ID[0],
if (IDs[k]) { references = ID[1];
idKey = k;
if (IDs.has(key)) {
// replace referenced IDs with the minified ones // replace referenced IDs with the minified ones
if (params.minify) { if (params.minify) {
currentIDstring = getIDstring(currentID = generateID(currentID), params); currentIDstring = getIDstring(currentID = generateID(currentID), params);
IDs[k].attr('id').value = currentIDstring; IDs.get(key).attr('id').value = currentIDstring;
referencesIDs[k].forEach(function(attr) { references.forEach(function(attr) {
k = k.replace(idPrefix, ''); // console.log(key)
attr.value = attr.value attr.value = attr.value
.replace('#' + k, '#' + currentIDstring) .replace('#' + key, '#' + currentIDstring)
.replace(k + '.', currentIDstring + '.'); .replace(key + '.', currentIDstring + '.');
}); });
idKey = idPrefix + k;
} }
// don't remove referenced IDs // don't remove referenced IDs
delete IDs[idKey]; IDs.delete(key);
} }
} }
// remove non-referenced IDs attributes from elements // remove non-referenced IDs attributes from elements
if (params.remove) { if (params.remove) {
for(var keyElem of IDs) {
for(var ID in IDs) { keyElem[1].removeAttr('id');
IDs[ID].removeAttr('id');
} }
} }
return data; return data;

View File

@@ -1,11 +1,39 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:x="http://www.w3.org/1999/xlink"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:x="http://www.w3.org/1999/xlink">
<defs>
<g id="mid-line"/>
<g id="line-plus">
<use x:href="#mid-line"/>
<use x:href="#plus"/>
</g>
<g id="plus"/>
<g id="line-circle">
<use x:href="#mid-line"/>
<use x:href="#circle"/>
</g>
<g id="circle"/>
</defs>
<path d="M0 0" id="a"/> <path d="M0 0" id="a"/>
<use x:href="#a" x="50" y="50"/> <use x:href="#a" x="50" y="50"/>
<use x:href="#line-plus"/>
</svg> </svg>
@@@ @@@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:x="http://www.w3.org/1999/xlink"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:x="http://www.w3.org/1999/xlink">
<path d="M0 0" id="a"/> <defs>
<use x:href="#a" x="50" y="50"/> <g id="a"/>
<g id="e">
<use x:href="#a"/>
<use x:href="#b"/>
</g>
<g id="b"/>
<g>
<use x:href="#a"/>
<use x:href="#c"/>
</g>
<g id="c"/>
</defs>
<path d="M0 0" id="d"/>
<use x:href="#d" x="50" y="50"/>
<use x:href="#e"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 310 B

After

Width:  |  Height:  |  Size: 954 B