Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
subzey committed Apr 28, 2016
0 parents commit 3803a52
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.gitignore
10 changes: 10 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

var svgStr = require('./lib/svgstr');
var signleQuoteStr = require('./lib/single-quote-str');

module.exports = function svgloader(content) {
this.cacheable();
var str = svgStr(content);
return "module.exports = " + signleQuoteStr(str) + ';';
};
26 changes: 26 additions & 0 deletions lib/single-quote-str.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

function escapeStr(str){
return str.replace(/'|\r|\n|\t|\\|\u2028|\u2029/g, function(c){
switch (c){
case "'":
return "\\'";
case '\r':
return '\\r';
case '\n':
return '\\n';
case '\t':
return '\\t';
case '\\':
return '\\\\';
case '\u2028':
return '\\u2028';
case '\u2029':
return '\\u2029';
}
});
}

module.exports = function singleQuoteStr(str) {
return "'" + escapeStr(str) + "'";
};
161 changes: 161 additions & 0 deletions lib/svgstr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
function escape(str) {
return str
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}

var attrOrder = ['xmlns', 'viewBox', 'width', 'height', /^fill/, /^stroke/, /^[cr]?[xy]$/, '*', 'id', 'class', 'style'];

function _getOrder(str) {
var defaultOrder = Infinity;
for (var i = 0; i < attrOrder.length; i++) {
var pattern = attrOrder[i];
if (pattern === '*') {
defaultOrder = i;
continue;
}
if (pattern instanceof RegExp) {
if (pattern.test(str)) {
return i;
}
} else {
if (pattern === str) {
return i;
}
}
}
return defaultOrder;
}

function attrSorter(a, b) {
var aLocal = a.local || a.prefix;
var bLocal = b.local || b.prefix;
// Try predefined order
var aOrder = _getOrder(aLocal);
var bOrder = _getOrder(bLocal);
if (aOrder !== bOrder) {
return aOrder - bOrder;
}
// Sort alphanumeric
if (aLocal < bLocal) {
return -1;
} else if (aLocal > bLocal) {
return 1;
}
// Okay, names are the same. Try prefix
if (a.prefix < b.prefix) {
return -1;
} else if (a.prefix > b.prefix) {
return 1;
}
return 0;
}

module.exports = function SvgStr(inStr) {
var sax = require('sax').parser(true, {
xmlns: true,
trim: true,
normalize: true
});

var retVal = '';
var isSvg = false;
var _unclosedTag = false;
var finished = false;


function write(str) {
if (_unclosedTag) {
str = '>' + str;
_unclosedTag = false;
}

if (!finished) {
retVal += str;
}
}

sax.onerror = function(e) {
if (!finished) {
// Re-emit errors
throw e;
}

// We don't care about errors happened after we've finished
};

sax.ontext = function(text) {
write(escape(text));
};

sax.processinginstruction = function(e) {
if (e.name === 'xml') {
// XML declaration is ignored
return;
}
write('<?' + e.name + ' ' + e.body + '?>');
};

// 'doctype' is intentionally ignored

// 'sgmldeclaration' is ignored

sax.onopentag = function(e) {
if (!isSvg) {
if (e.local !== 'svg') {
throw new Error('Not an SVG format');
} else {
isSvg = true;
}
}

var str = '<' + (e.prefix ? (e.prefix + ':') : '') + e.local;
var attrs = Object.keys(e.attributes).map(function(key) {return e.attributes[key];}).sort(attrSorter);

for (var i=0; i<attrs.length; i++) {
var attr = attrs[i];
var local = attr.local;
var prefix = attr.prefix;
if (prefix && !local) {
local = prefix;
prefix = '';
}
str += ' ' + (prefix ? (prefix + ':') : '') + local + '="' + escape(attr.value) + '"';
}

write(str);
_unclosedTag = true;
};

sax.onclosetag = function(tagname) {
if (_unclosedTag) {
_unclosedTag = false;
write('/>');
return;
}
write('</' + tagname + '>');
};

sax.onopencdata = function() {
write('<![CDATA[');
};

sax.oncdata = function(text) {
write(text);
};

sax.onclosecdata = function() {
write(']]>');
};

sax.onend = function() {
finished = true;
write(''); // flush unclosed tag
};

sax.write(inStr).close();

return retVal;
};
29 changes: 29 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "tv-webpack-svg-loader",
"version": "1.0.0-alpha.1",
"description": "TV webpack SVG loader",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"tv",
"svg",
"webpack",
"loader"
],
"author": "Anton Khlynovskiy <[email protected]>",
"license": "WTFPL",
"dependencies": {
"sax": "^1.2.1"
},
"devDependencies": {},
"repository": {
"type": "git",
"url": "git+https://github.com/multicharts/tv-webpack-svg-loader.git"
},
"bugs": {
"url": "https://github.com/multicharts/tv-webpack-svg-loader/issues"
},
"homepage": "https://github.com/multicharts/tv-webpack-svg-loader#readme"
}

0 comments on commit 3803a52

Please sign in to comment.