Skip to content

Instantly share code, notes, and snippets.

@kmxz
Created May 31, 2016 11:53
Show Gist options
  • Save kmxz/c355c4a0aae961653244ae83f996554a to your computer and use it in GitHub Desktop.
Save kmxz/c355c4a0aae961653244ae83f996554a to your computer and use it in GitHub Desktop.
Reduce the size of SVG files exported from Sketch
#!/usr/bin/env node
var DOMParser = require('xmldom').DOMParser;
var fs = require("fs");
var file = fs.readFileSync(process.argv[2], 'utf-8');
var doc = new DOMParser().parseFromString(file, 'text/xml');
var regex = /^\s*translate\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\)\s*$/;
// pass 1: remove IDs
var recursiveRemoveId = function (element) {
if (element.nodeType === 1) {
if (element.hasAttribute('id')) {
element.removeAttribute('id');
}
}
Array.prototype.forEach.call(element.childNodes || [], recursiveRemoveId.bind(null));
};
recursiveRemoveId(doc);
// pass 2: merge stacked translates
var recursive = function (element) {
var thisTransform, childTransform, childCount;
if (element.nodeType === 1) {
if (element.hasAttribute('transform')) {
while (true) {
thisTransform = element.getAttribute('transform').match(regex);
childCount = Array.prototype.filter.call(element.childNodes || [], function (ct) { return ct.nodeType === 1; });
if ((childCount.length === 1) && (childCount[0].attributes.length === 1) && childCount[0].hasAttribute('transform')) {
childTransform = childCount[0].getAttribute('transform').match(regex);
element.setAttribute('transform', 'translate(' + (parseFloat(thisTransform[1]) + parseFloat(childTransform[1])) + ',' + (parseFloat(thisTransform[2]) + parseFloat(childTransform[2])) + ')');
Array.prototype.forEach.call(childCount[0].childNodes, function (cn) {
element.appendChild(cn.cloneNode(true));
});
element.removeChild(childCount[0]);
} else {
break;
}
}
}
}
Array.prototype.forEach.call(element.childNodes || [], recursive.bind(null));
};
recursive(doc);
// pass 3: remove spaces and comments
var recursiveTrimSpace = function (element) {
Array.prototype.forEach.call(element.childNodes || [], function (n) {
if (n.nodeType === 3) { // text
element.replaceChild(doc.createTextNode(n.data.trim()), n);
} else if (n.nodeType === 8) { // comment
element.removeChild(n);
} else {
recursiveTrimSpace(n);
}
});
};
recursiveTrimSpace(doc);
fs.writeFileSync('thin-' + process.argv[2], doc.toString());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment