escapeHtml.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. 'use strict';
  2. const internals = {};
  3. module.exports = function (input) {
  4. if (!input) {
  5. return '';
  6. }
  7. let escaped = '';
  8. for (let i = 0; i < input.length; ++i) {
  9. const charCode = input.charCodeAt(i);
  10. if (internals.isSafe(charCode)) {
  11. escaped += input[i];
  12. }
  13. else {
  14. escaped += internals.escapeHtmlChar(charCode);
  15. }
  16. }
  17. return escaped;
  18. };
  19. internals.escapeHtmlChar = function (charCode) {
  20. const namedEscape = internals.namedHtml.get(charCode);
  21. if (namedEscape) {
  22. return namedEscape;
  23. }
  24. if (charCode >= 256) {
  25. return '&#' + charCode + ';';
  26. }
  27. const hexValue = charCode.toString(16).padStart(2, '0');
  28. return `&#x${hexValue};`;
  29. };
  30. internals.isSafe = function (charCode) {
  31. return internals.safeCharCodes.has(charCode);
  32. };
  33. internals.namedHtml = new Map([
  34. [38, '&amp;'],
  35. [60, '&lt;'],
  36. [62, '&gt;'],
  37. [34, '&quot;'],
  38. [160, '&nbsp;'],
  39. [162, '&cent;'],
  40. [163, '&pound;'],
  41. [164, '&curren;'],
  42. [169, '&copy;'],
  43. [174, '&reg;']
  44. ]);
  45. internals.safeCharCodes = (function () {
  46. const safe = new Set();
  47. for (let i = 32; i < 123; ++i) {
  48. if ((i >= 97) || // a-z
  49. (i >= 65 && i <= 90) || // A-Z
  50. (i >= 48 && i <= 57) || // 0-9
  51. i === 32 || // space
  52. i === 46 || // .
  53. i === 44 || // ,
  54. i === 45 || // -
  55. i === 58 || // :
  56. i === 95) { // _
  57. safe.add(i);
  58. }
  59. }
  60. return safe;
  61. }());