decode.js 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. var entityMap = require("../maps/entities.json"),
  2. legacyMap = require("../maps/legacy.json"),
  3. xmlMap = require("../maps/xml.json"),
  4. decodeCodePoint = require("./decode_codepoint.js");
  5. var decodeXMLStrict = getStrictDecoder(xmlMap),
  6. decodeHTMLStrict = getStrictDecoder(entityMap);
  7. function getStrictDecoder(map){
  8. var keys = Object.keys(map).join("|"),
  9. replace = getReplacer(map);
  10. keys += "|#[xX][\\da-fA-F]+|#\\d+";
  11. var re = new RegExp("&(?:" + keys + ");", "g");
  12. return function(str){
  13. return String(str).replace(re, replace);
  14. };
  15. }
  16. var decodeHTML = (function(){
  17. var legacy = Object.keys(legacyMap)
  18. .sort(sorter);
  19. var keys = Object.keys(entityMap)
  20. .sort(sorter);
  21. for(var i = 0, j = 0; i < keys.length; i++){
  22. if(legacy[j] === keys[i]){
  23. keys[i] += ";?";
  24. j++;
  25. } else {
  26. keys[i] += ";";
  27. }
  28. }
  29. var re = new RegExp("&(?:" + keys.join("|") + "|#[xX][\\da-fA-F]+;?|#\\d+;?)", "g"),
  30. replace = getReplacer(entityMap);
  31. function replacer(str){
  32. if(str.substr(-1) !== ";") str += ";";
  33. return replace(str);
  34. }
  35. //TODO consider creating a merged map
  36. return function(str){
  37. return String(str).replace(re, replacer);
  38. };
  39. }());
  40. function sorter(a, b){
  41. return a < b ? 1 : -1;
  42. }
  43. function getReplacer(map){
  44. return function replace(str){
  45. if(str.charAt(1) === "#"){
  46. if(str.charAt(2) === "X" || str.charAt(2) === "x"){
  47. return decodeCodePoint(parseInt(str.substr(3), 16));
  48. }
  49. return decodeCodePoint(parseInt(str.substr(2), 10));
  50. }
  51. return map[str.slice(1, -1)];
  52. };
  53. }
  54. module.exports = {
  55. XML: decodeXMLStrict,
  56. HTML: decodeHTML,
  57. HTMLStrict: decodeHTMLStrict
  58. };