escape.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. 'use strict';
  2. // Declare internals
  3. const internals = {};
  4. exports.escapeJavaScript = function (input) {
  5. if (!input) {
  6. return '';
  7. }
  8. let escaped = '';
  9. for (let i = 0; i < input.length; ++i) {
  10. const charCode = input.charCodeAt(i);
  11. if (internals.isSafe(charCode)) {
  12. escaped += input[i];
  13. }
  14. else {
  15. escaped += internals.escapeJavaScriptChar(charCode);
  16. }
  17. }
  18. return escaped;
  19. };
  20. exports.escapeHtml = function (input) {
  21. if (!input) {
  22. return '';
  23. }
  24. let escaped = '';
  25. for (let i = 0; i < input.length; ++i) {
  26. const charCode = input.charCodeAt(i);
  27. if (internals.isSafe(charCode)) {
  28. escaped += input[i];
  29. }
  30. else {
  31. escaped += internals.escapeHtmlChar(charCode);
  32. }
  33. }
  34. return escaped;
  35. };
  36. exports.escapeJson = function (input) {
  37. if (!input) {
  38. return '';
  39. }
  40. const lessThan = 0x3C;
  41. const greaterThan = 0x3E;
  42. const andSymbol = 0x26;
  43. const lineSeperator = 0x2028;
  44. // replace method
  45. let charCode;
  46. return input.replace(/[<>&\u2028\u2029]/g, (match) => {
  47. charCode = match.charCodeAt(0);
  48. if (charCode === lessThan) {
  49. return '\\u003c';
  50. }
  51. else if (charCode === greaterThan) {
  52. return '\\u003e';
  53. }
  54. else if (charCode === andSymbol) {
  55. return '\\u0026';
  56. }
  57. else if (charCode === lineSeperator) {
  58. return '\\u2028';
  59. }
  60. return '\\u2029';
  61. });
  62. };
  63. internals.escapeJavaScriptChar = function (charCode) {
  64. if (charCode >= 256) {
  65. return '\\u' + internals.padLeft('' + charCode, 4);
  66. }
  67. const hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
  68. return '\\x' + internals.padLeft(hexValue, 2);
  69. };
  70. internals.escapeHtmlChar = function (charCode) {
  71. const namedEscape = internals.namedHtml[charCode];
  72. if (typeof namedEscape !== 'undefined') {
  73. return namedEscape;
  74. }
  75. if (charCode >= 256) {
  76. return '&#' + charCode + ';';
  77. }
  78. const hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
  79. return '&#x' + internals.padLeft(hexValue, 2) + ';';
  80. };
  81. internals.padLeft = function (str, len) {
  82. while (str.length < len) {
  83. str = '0' + str;
  84. }
  85. return str;
  86. };
  87. internals.isSafe = function (charCode) {
  88. return (typeof internals.safeCharCodes[charCode] !== 'undefined');
  89. };
  90. internals.namedHtml = {
  91. '38': '&amp;',
  92. '60': '&lt;',
  93. '62': '&gt;',
  94. '34': '&quot;',
  95. '160': '&nbsp;',
  96. '162': '&cent;',
  97. '163': '&pound;',
  98. '164': '&curren;',
  99. '169': '&copy;',
  100. '174': '&reg;'
  101. };
  102. internals.safeCharCodes = (function () {
  103. const safe = {};
  104. for (let i = 32; i < 123; ++i) {
  105. if ((i >= 97) || // a-z
  106. (i >= 65 && i <= 90) || // A-Z
  107. (i >= 48 && i <= 57) || // 0-9
  108. i === 32 || // space
  109. i === 46 || // .
  110. i === 44 || // ,
  111. i === 45 || // -
  112. i === 58 || // :
  113. i === 95) { // _
  114. safe[i] = null;
  115. }
  116. }
  117. return safe;
  118. }());