163 lines
3.2 KiB
JavaScript
163 lines
3.2 KiB
JavaScript
'use strict';
|
|
|
|
var SAX = require('sax'),
|
|
JSAPI = require('./jsAPI');
|
|
|
|
var config = {
|
|
strict: true,
|
|
trim: false,
|
|
normalize: true,
|
|
lowercase: true,
|
|
xmlns: true,
|
|
position: false
|
|
};
|
|
|
|
/**
|
|
* Convert SVG (XML) string to SVG-as-JS object.
|
|
*
|
|
* @param {String} data input data
|
|
* @param {Function} callback
|
|
*/
|
|
module.exports = function(data, callback) {
|
|
|
|
var sax = SAX.parser(config.strict, config),
|
|
root = new JSAPI({ elem: '#document' }),
|
|
current = root,
|
|
stack = [root],
|
|
textContext = null;
|
|
|
|
function pushToContent(content) {
|
|
|
|
content = new JSAPI(content, current);
|
|
|
|
(current.content = current.content || []).push(content);
|
|
|
|
return content;
|
|
|
|
}
|
|
|
|
sax.ondoctype = function(doctype) {
|
|
|
|
pushToContent({
|
|
doctype: doctype
|
|
});
|
|
|
|
};
|
|
|
|
sax.onprocessinginstruction = function(data) {
|
|
|
|
pushToContent({
|
|
processinginstruction: data
|
|
});
|
|
|
|
};
|
|
|
|
sax.oncomment = function(comment) {
|
|
|
|
pushToContent({
|
|
comment: comment.trim()
|
|
});
|
|
|
|
};
|
|
|
|
sax.oncdata = function(cdata) {
|
|
|
|
pushToContent({
|
|
cdata: cdata
|
|
});
|
|
|
|
};
|
|
|
|
sax.onopentag = function(data) {
|
|
|
|
var elem = {
|
|
elem: data.name,
|
|
prefix: data.prefix,
|
|
local: data.local
|
|
};
|
|
|
|
if (Object.keys(data.attributes).length) {
|
|
elem.attrs = {};
|
|
|
|
for (var name in data.attributes) {
|
|
elem.attrs[name] = {
|
|
name: name,
|
|
value: data.attributes[name].value,
|
|
prefix: data.attributes[name].prefix,
|
|
local: data.attributes[name].local
|
|
};
|
|
}
|
|
}
|
|
|
|
elem = pushToContent(elem);
|
|
current = elem;
|
|
|
|
// Save info about <text> tag to prevent trimming of meaningful whitespace
|
|
if (data.name == 'text' && !data.prefix) {
|
|
textContext = current;
|
|
}
|
|
|
|
stack.push(elem);
|
|
|
|
};
|
|
|
|
sax.ontext = function(text) {
|
|
|
|
if (/\S/.test(text) || textContext) {
|
|
|
|
if (!textContext)
|
|
text = text.trim();
|
|
|
|
pushToContent({
|
|
text: text
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
sax.onclosetag = function() {
|
|
|
|
var last = stack.pop();
|
|
|
|
// Trim text inside <text> tag.
|
|
if (last == textContext) {
|
|
trim(textContext);
|
|
textContext = null;
|
|
}
|
|
current = stack[stack.length - 1];
|
|
|
|
};
|
|
|
|
sax.onerror = function(e) {
|
|
|
|
callback({ error: 'Error in parsing: ' + e.message });
|
|
|
|
};
|
|
|
|
sax.onend = function() {
|
|
|
|
if (!this.error) callback(root);
|
|
|
|
};
|
|
|
|
sax.write(data).close();
|
|
|
|
function trim(elem) {
|
|
if (!elem.content) return elem;
|
|
|
|
var start = elem.content[0],
|
|
end = elem.content[elem.content.length - 1];
|
|
|
|
while (start && start.content && !start.text) start = start.content[0];
|
|
if (start && start.text) start.text = start.text.replace(/^\s+/, '');
|
|
|
|
while (end && end.content && !end.text) end = end.content[end.content.length - 1];
|
|
if (end && end.text) end.text = end.text.replace(/\s+$/, '');
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
};
|