Skip to content

Commit

Permalink
Changed the way ID are collected. All referenced IDs are collected an…
Browse files Browse the repository at this point in the history
…d mapped to uniqued IDs. Unreferenced IDs are removed in order to save space.
  • Loading branch information
Frank3K committed Jun 28, 2014
1 parent 75f0564 commit 7fc96d1
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 29 deletions.
9 changes: 9 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ module.exports = function(grunt) {
files: {
'tmp/cleanup.svg': ['test/fixtures/cleanup.svg']
}
},

removeunreferencedids: {
options: {
cleanup: true
},
files: {
'tmp/no_unref_ids.svg': ['test/fixtures/usingdef.svg']
}
}
},

Expand Down
47 changes: 27 additions & 20 deletions tasks/svgstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,46 +68,53 @@ module.exports = function (grunt) {
}).map(function (filepath) {
var filename = path.basename(filepath, '.svg');
var contentStr = grunt.file.read(filepath);
var uniqueId = md5(contentStr);
var $ = cheerio.load(contentStr, {
normalizeWhitespace: true,
xmlMode: true
});

// Map to store references from id to uniqueId + id;
// N.B.: only IDs that are referenced are mapped.
var mappedIds = {};

// Make IDs unique
$('[id]').each(function () {
var $elem = $(this);
var id = $elem.attr('id');
var newId = 'svgstore' + uniqueId + id;
mappedIds[id] = newId;
$elem.attr('id', newId);
});

// Search for an url() reference in every attribute of every tag
// replace the id with the unique one.
$('*').each(function () {
var $elem = $(this);
var attrs = $elem.attr();
Object.keys(attrs).forEach(function (key) {
var value = attrs[key];
var match;
while ((match = urlPattern.exec(value)) !== null) {
if (mappedIds[match[1]] !== undefined) {
value = value.replace(match[0], 'url(#' + mappedIds[match[1]] + ')');
} else {
grunt.log.warn('Can\'t reference to id "' + match[1] + '" from attribute "' + attr + '" in "' + this[0].name + '" because it is not defined.');
var refId = match[1];

// Add id mapping if not already present
if (!mappedIds[refId]) {
var uniqueId = md5(contentStr);
var newId = 'svgstore' + uniqueId + refId;
mappedIds[refId] = newId;
}

$elem.attr(key, value.replace(match[0], 'url(#' + mappedIds[refId] + ')'));
}

if (options.cleanup && key === 'style') {
value = null;
$elem.removeAttr(key);
}
$elem.attr(key, value);
});
});

// Apply ID mapping and remove unreferenced IDs
$('[id]').each(function () {
var $elem = $(this);
var id = $elem.attr('id');
var newId = mappedIds[id];
if (!newId) {
// ID is not refenced and can therefore be removed
$elem.removeAttr('id');
} else {
// Replace id by mapped id
$elem.attr('id', newId);
}
});

var $svg = $('svg');
var $title = $('title');
var $desc = $('desc');
Expand Down Expand Up @@ -150,7 +157,7 @@ module.exports = function (grunt) {
$symbol.prepend('<title>' + title + '</title>');
}

// Add viewBox (if present of SVG)
// Add viewBox (if present on SVG)
var viewBox = $svg.attr('viewBox');
if (viewBox) {
$symbol.attr('viewBox', viewBox);
Expand Down
2 changes: 1 addition & 1 deletion test/expected/cleanup.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions test/expected/includedemo-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</style>
<head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="width:0;height:0;visibility:hidden;"><defs> <lineargradient id="svgstore80ec02171da6cd7fecfaea37eb42d534grad1" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/> <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/> </lineargradient> </defs><symbol id="cleanup"><title>cleanup</title> <metadata id="svgstorea8f4356a420b8b730d9b8d0dc0a32b37metadata3320"> <rdf:rdf> <cc:work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> <dc:title/> </cc:work> </rdf:rdf> </metadata> <g transform="matrix(-1,0,0,-1,64.084221,73.450016)" id="svgstorea8f4356a420b8b730d9b8d0dc0a32b37layer3" style="fill:#000000;display:inline"> <path d="M 32.023548,13.911903 64.114266,44.069169 61.158286,47.02306 32.023548,19.819685 2.9238456,47.538113 -0.03004543,44.584221 z" id="svgstorea8f4356a420b8b730d9b8d0dc0a32b37path3317" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"/> </g> <g transform="matrix(-1,0,0,-1,64.047096,55.009338)" id="svgstorea8f4356a420b8b730d9b8d0dc0a32b37g5637" style="fill:#000000;display:inline"> <path d="M 32.023548,13.911903 64.114266,44.069169 61.158286,47.02306 32.023548,19.819685 2.9238456,47.538113 -0.03004543,44.584221 z" id="svgstorea8f4356a420b8b730d9b8d0dc0a32b37path5639" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"/> </g> </symbol><symbol viewBox="0 0 100 100" id="codepen"><title>Codepen Icon</title><desc>This is the offical Codepen icon</desc> <g> <path d="M50,0C22.385,0,0,22.385,0,50c0,27.615,22.385,50,50,50c27.614,0,50-22.385,50-50C100,22.385,77.615,0,50,0z M50,91.789
<svg xmlns="http://www.w3.org/2000/svg" style="width:0;height:0;visibility:hidden;"><defs> <lineargradient id="svgstoreed731f1dfc11607730fe18d714428949grad1" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/> <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/> </lineargradient> </defs><symbol id="cleanup"><title>cleanup</title> <metadata> <rdf:rdf> <cc:work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> <dc:title/> </cc:work> </rdf:rdf> </metadata> <g transform="matrix(-1,0,0,-1,64.084221,73.450016)" style="fill:#000000;display:inline"> <path d="M 32.023548,13.911903 64.114266,44.069169 61.158286,47.02306 32.023548,19.819685 2.9238456,47.538113 -0.03004543,44.584221 z" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"/> </g> <g transform="matrix(-1,0,0,-1,64.047096,55.009338)" style="fill:#000000;display:inline"> <path d="M 32.023548,13.911903 64.114266,44.069169 61.158286,47.02306 32.023548,19.819685 2.9238456,47.538113 -0.03004543,44.584221 z" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"/> </g> </symbol><symbol viewBox="0 0 100 100" id="codepen"><title>Codepen Icon</title><desc>This is the offical Codepen icon</desc> <g> <path d="M50,0C22.385,0,0,22.385,0,50c0,27.615,22.385,50,50,50c27.614,0,50-22.385,50-50C100,22.385,77.615,0,50,0z M50,91.789
C26.958,91.789,8.212,73.042,8.212,50C8.212,26.958,26.958,8.212,50,8.212c23.042,0,41.788,18.747,41.788,41.789
C91.788,73.042,73.042,91.789,50,91.789z"/> <path d="M80.893,40.234c-0.006-0.039-0.016-0.076-0.022-0.115c-0.013-0.075-0.027-0.15-0.046-0.223
c-0.012-0.044-0.028-0.086-0.042-0.128c-0.021-0.065-0.042-0.13-0.068-0.193c-0.018-0.044-0.039-0.088-0.059-0.13
Expand Down Expand Up @@ -97,7 +97,7 @@
c0,3.164,2.394,5.812,5.536,6.136C30.838,48.92,51.08,69.161,53.672,94.462c0.322,3.146,2.973,5.539,6.135,5.539h3.098
c1.74,0,3.398-0.732,4.566-2.023c1.168-1.286,1.738-3.009,1.571-4.74C65.841,60.349,39.65,34.158,6.764,30.957z"/> <path d="M99.986,93.431C96.732,43.428,56.568,3.268,6.565,0.012C6.432,0.005,6.298,0,6.166,0C4.604,0,3.095,0.593,1.95,1.667
C0.705,2.832,0,4.461,0,6.167v3.088c0,3.247,2.515,5.938,5.752,6.155c42.113,2.832,76.006,36.726,78.839,78.84
c0.22,3.235,2.907,5.75,6.151,5.75h3.091c1.706,0,3.335-0.706,4.5-1.95C99.498,96.805,100.098,95.135,99.986,93.431z"/> </g> </symbol><symbol viewBox="0 0 100 100" id="scissors"><title>scissors</title> <g id="svgstore9921d16b8577ede7241017be59c39cd8Captions"> </g> <g id="svgstore9921d16b8577ede7241017be59c39cd8Your_Icon"> <path d="M88.781,68.58c-4.819-6.068-13.189-8.268-20.355-6.131l-7.984-10.054L86.98,13.793c2.142-3.177,1.713-7.589-0.952-9.786
c0.22,3.235,2.907,5.75,6.151,5.75h3.091c1.706,0,3.335-0.706,4.5-1.95C99.498,96.805,100.098,95.135,99.986,93.431z"/> </g> </symbol><symbol viewBox="0 0 100 100" id="scissors"><title>scissors</title> <g> </g> <g> <path d="M88.781,68.58c-4.819-6.068-13.189-8.268-20.355-6.131l-7.984-10.054L86.98,13.793c2.142-3.177,1.713-7.589-0.952-9.786
C83.359,1.808,81.184,0,81.184,0L50.001,39.257L18.818,0c0,0-2.176,1.808-4.842,4.007c-2.665,2.197-3.095,6.609-0.954,9.786
l26.541,38.603l-7.987,10.054c-7.174-2.137-15.536,0.062-20.354,6.131c-3.182,3.998-4.641,9.024-4.117,14.147
c0.531,5.122,2.991,9.732,6.912,12.973c3.359,2.772,7.586,4.3,11.898,4.3c5.738,0,11.095-2.602,14.71-7.148
Expand All @@ -109,14 +109,14 @@
C34.712,82.125,34.046,84.411,32.61,86.229z M49.994,57.923c-2.849,0-5.159-2.355-5.159-5.258c0-2.905,2.31-5.261,5.159-5.261
c2.847,0,5.16,2.356,5.16,5.261C55.153,55.567,52.841,57.923,49.994,57.923z M79.488,87.521c-3.587,2.973-9.204,2.342-12.09-1.286
c-1.443-1.823-2.107-4.109-1.876-6.438c0.243-2.325,1.357-4.421,3.151-5.895c1.544-1.281,3.412-1.951,5.401-1.951
c2.603,0,5.045,1.177,6.685,3.251c1.449,1.815,2.114,4.103,1.87,6.431C82.391,83.961,81.276,86.056,79.488,87.521z"/> </g> </symbol><symbol viewBox="0 0 100 100" id="twitter"><title>twitter</title> <path id="svgstoreb5d29090de0329dd1548b3c12685706bshape-twitter" d="M100.001,17.942c-3.681,1.688-7.633,2.826-11.783,3.339
c2.603,0,5.045,1.177,6.685,3.251c1.449,1.815,2.114,4.103,1.87,6.431C82.391,83.961,81.276,86.056,79.488,87.521z"/> </g> </symbol><symbol viewBox="0 0 100 100" id="twitter"><title>twitter</title> <path d="M100.001,17.942c-3.681,1.688-7.633,2.826-11.783,3.339
c4.236-2.624,7.49-6.779,9.021-11.73c-3.965,2.432-8.354,4.193-13.026,5.146C80.47,10.575,75.138,8,69.234,8
c-11.33,0-20.518,9.494-20.518,21.205c0,1.662,0.183,3.281,0.533,4.833c-17.052-0.884-32.168-9.326-42.288-22.155
c-1.767,3.133-2.778,6.773-2.778,10.659c0,7.357,3.622,13.849,9.127,17.65c-3.363-0.109-6.525-1.064-9.293-2.651
c-0.002,0.089-0.002,0.178-0.002,0.268c0,10.272,7.072,18.845,16.458,20.793c-1.721,0.484-3.534,0.744-5.405,0.744
c-1.322,0-2.606-0.134-3.859-0.379c2.609,8.424,10.187,14.555,19.166,14.726c-7.021,5.688-15.867,9.077-25.48,9.077
c-1.656,0-3.289-0.102-4.895-0.297C9.08,88.491,19.865,92,31.449,92c37.737,0,58.374-32.312,58.374-60.336
c0-0.92-0.02-1.834-0.059-2.743C93.771,25.929,97.251,22.195,100.001,17.942L100.001,17.942z"/> </symbol><symbol viewBox="0 0 100 100" id="usingdef"><title>usingdef</title> <ellipse cx="50%" cy="50%" rx="50%" ry="25%" fill="url(#svgstore80ec02171da6cd7fecfaea37eb42d534grad1)"/> </symbol><symbol viewBox="0 0 100 100" id="youtube"><title>youtube</title> <g> <path d="M98.77,27.492c-1.225-5.064-5.576-8.799-10.811-9.354C75.561,16.818,63.01,15.993,50.514,16
c0-0.92-0.02-1.834-0.059-2.743C93.771,25.929,97.251,22.195,100.001,17.942L100.001,17.942z"/> </symbol><symbol viewBox="0 0 100 100" id="usingdef"><title>usingdef</title> <ellipse cx="50%" cy="50%" rx="50%" ry="25%" fill="url(#svgstoreed731f1dfc11607730fe18d714428949grad1)"/> </symbol><symbol viewBox="0 0 100 100" id="youtube"><title>youtube</title> <g> <path d="M98.77,27.492c-1.225-5.064-5.576-8.799-10.811-9.354C75.561,16.818,63.01,15.993,50.514,16
c-12.495-0.007-25.045,0.816-37.446,2.139c-5.235,0.557-9.583,4.289-10.806,9.354C0.522,34.704,0.5,42.574,0.5,50.001
c0,7.426,0,15.296,1.741,22.509c1.224,5.061,5.572,8.799,10.807,9.352c12.399,1.32,24.949,2.145,37.446,2.14
c12.494,0.005,25.047-0.817,37.443-2.14c5.234-0.555,9.586-4.291,10.81-9.352c1.741-7.213,1.753-15.083,1.753-22.509
Expand Down
4 changes: 2 additions & 2 deletions test/fixtures/usingdef.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions test/svgstore_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ exports.svgstore = {
test.equal(actual, expected, 'Name should be cut after the first dot');

test.done();
}
},

remove_unreferenced_ids: function(test){
test.expect(1);

};
var actual = grunt.file.read('tmp/no_unref_ids.svg');
var expected = grunt.file.read('test/expected/no_unref_ids.svg');
test.equal(actual, expected, 'Remove unreferenced IDs');

test.done();
}};

0 comments on commit 7fc96d1

Please sign in to comment.