var XSON = { stringify: function (obj, replacer, space, type) { if (replacer) { throw new Exception('Replacer is not supported'); } function rec(obj, level) { function indent(str) { if (space === undefined) { return str; } return '\n' + Array(level + 1).join(space) + str; } function encode(str) { return str .replace(/\\/g, '\\\\') .replace(/[\u0000-\u0008\u000b-\u001f&<>"\n\t]/g, function(c) { var hex = c.charCodeAt(0).toString(16); while (hex.length < 4) { hex = '0' + hex; } return '\\u' + hex; }); } if (typeof obj === 'string') { if (!obj.length) { return indent(type === 'html' ? '' : ''); } return indent('' + encode(obj) + ''); } if (obj === null || obj === undefined) { return indent(type === 'html' ? '' : ''); } if (typeof obj === 'boolean') { if (obj) { return indent(type === 'html' ? '' : ''); } return indent(type === 'html' ? '' : ''); } if (typeof obj === 'number') { if (obj !== obj) { return indent(type === 'html' ? '' : ''); } return indent('' + obj + ''); } if ('slice' in obj) { if (!obj.length) { return indent(type === 'html' ? '' : ''); } return indent('') + obj.map(function (obj) { return rec(obj, level + 1); }).join('') + indent(''); } var elements = []; for (var key in obj) { var element = rec(obj[key], level + 1); var pos = space === undefined ? 2 : space.length * (level + 1) + 3; elements.push(element.substr(0, pos) + ' k="' + encode(key) + '"' + element.substr(pos)); } if (!elements.length) { return indent(type === 'html' ? '' : ''); } return indent('') + elements.join('') + indent(''); } return rec(obj, 0).substr(space === undefined ? 0 : 1); }, parse: function (str) { var element = new DOMParser().parseFromString(str, 'text/xml'); function childrenToArray(element) { return Array.prototype.slice.apply(element.childNodes) .filter(function (child) { return child.nodeType !== 3; }); } function decode(str) { return str .replace(/(\\*)\\u([0-9a-f]{4})/g, function(_, backslash, n) { if (backslash.length % 2 === 0) { return backslash + String.fromCharCode(parseInt(n, 16)); } return backslash + '\\u' + n; }) .replace(/\\\\/g, '\\'); } function rec(element) { if (element.tagName === 's') { return decode(element.textContent); } if (element.tagName === 't') { return true; } if (element.tagName === 'f') { return false; } if (element.tagName === 'l') { return null; } if (element.tagName === 'n') { return parseFloat(element.textContent); } if (element.tagName === 'a') { return childrenToArray(element).map(rec); } if (element.tagName === 'o') { var result = {}; childrenToArray(element).forEach(function (child) { result[decode(child.getAttribute('k'))] = rec(child); }); return result; } throw new 'Invalid tag: ' + element.tagName; } return rec(element.firstChild); } }; if (typeof exports !== 'undefined') { exports.stringify = XSON.stringify; exports.parse = XSON.parse; }