var inverseXML = getInverseObj(require("../maps/xml.json")), xmlReplacer = getInverseReplacer(inverseXML); exports.XML = getInverse(inverseXML, xmlReplacer); var inverseHTML = getInverseObj(require("../maps/entities.json")), htmlReplacer = getInverseReplacer(inverseHTML); exports.HTML = getInverse(inverseHTML, htmlReplacer); function getInverseObj(obj){ return Object.keys(obj).sort().reduce(function(inverse, name){ inverse[obj[name]] = "&" + name + ";"; return inverse; }, {}); } function getInverseReplacer(inverse){ return new RegExp("\\" + Object.keys(inverse).sort().join("|\\"), "g"); } var re_nonASCII = /[^\0-\x7F]/g, re_astralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; function nonUTF8Replacer(c){ return "&#x" + c.charCodeAt(0).toString(16).toUpperCase() + ";"; } function astralReplacer(c){ // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae var high = c.charCodeAt(0); var low = c.charCodeAt(1); var codePoint = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000; return "&#x" + codePoint.toString(16).toUpperCase() + ";"; } function getInverse(inverse, re){ function func(name){ return inverse[name]; } return function(data){ return data .replace(re, func) .replace(re_astralSymbols, astralReplacer) .replace(re_nonASCII, nonUTF8Replacer); }; }