escape.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. export const xmlReplacer = /["$&'<>\u0080-\uFFFF]/g;
  2. const xmlCodeMap = new Map([
  3. [34, "&quot;"],
  4. [38, "&amp;"],
  5. [39, "&apos;"],
  6. [60, "&lt;"],
  7. [62, "&gt;"],
  8. ]);
  9. // For compatibility with node < 4, we wrap `codePointAt`
  10. export const getCodePoint =
  11. // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
  12. String.prototype.codePointAt == null
  13. ? (c, index) => (c.charCodeAt(index) & 64512) === 55296
  14. ? (c.charCodeAt(index) - 55296) * 1024 +
  15. c.charCodeAt(index + 1) -
  16. 56320 +
  17. 65536
  18. : c.charCodeAt(index)
  19. : // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
  20. (input, index) => input.codePointAt(index);
  21. /**
  22. * Encodes all non-ASCII characters, as well as characters not valid in XML
  23. * documents using XML entities.
  24. *
  25. * If a character has no equivalent entity, a
  26. * numeric hexadecimal reference (eg. `&#xfc;`) will be used.
  27. */
  28. export function encodeXML(input) {
  29. let returnValue = "";
  30. let lastIndex = 0;
  31. let match;
  32. while ((match = xmlReplacer.exec(input)) !== null) {
  33. const { index } = match;
  34. const char = input.charCodeAt(index);
  35. const next = xmlCodeMap.get(char);
  36. if (next === undefined) {
  37. returnValue += `${input.substring(lastIndex, index)}&#x${getCodePoint(input, index).toString(16)};`;
  38. // Increase by 1 if we have a surrogate pair
  39. lastIndex = xmlReplacer.lastIndex += Number((char & 64512) === 55296);
  40. }
  41. else {
  42. returnValue += input.substring(lastIndex, index) + next;
  43. lastIndex = index + 1;
  44. }
  45. }
  46. return returnValue + input.substr(lastIndex);
  47. }
  48. /**
  49. * Encodes all non-ASCII characters, as well as characters not valid in XML
  50. * documents using numeric hexadecimal reference (eg. `&#xfc;`).
  51. *
  52. * Have a look at `escapeUTF8` if you want a more concise output at the expense
  53. * of reduced transportability.
  54. *
  55. * @param data String to escape.
  56. */
  57. export const escape = encodeXML;
  58. /**
  59. * Creates a function that escapes all characters matched by the given regular
  60. * expression using the given map of characters to escape to their entities.
  61. *
  62. * @param regex Regular expression to match characters to escape.
  63. * @param map Map of characters to escape to their entities.
  64. *
  65. * @returns Function that escapes all characters matched by the given regular
  66. * expression using the given map of characters to escape to their entities.
  67. */
  68. function getEscaper(regex, map) {
  69. return function escape(data) {
  70. let match;
  71. let lastIndex = 0;
  72. let result = "";
  73. while ((match = regex.exec(data))) {
  74. if (lastIndex !== match.index) {
  75. result += data.substring(lastIndex, match.index);
  76. }
  77. // We know that this character will be in the map.
  78. result += map.get(match[0].charCodeAt(0));
  79. // Every match will be of length 1
  80. lastIndex = match.index + 1;
  81. }
  82. return result + data.substring(lastIndex);
  83. };
  84. }
  85. /**
  86. * Encodes all characters not valid in XML documents using XML entities.
  87. *
  88. * Note that the output will be character-set dependent.
  89. *
  90. * @param data String to escape.
  91. */
  92. export const escapeUTF8 = /* #__PURE__ */ getEscaper(/["&'<>]/g, xmlCodeMap);
  93. /**
  94. * Encodes all characters that have to be escaped in HTML attributes,
  95. * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
  96. *
  97. * @param data String to escape.
  98. */
  99. export const escapeAttribute =
  100. /* #__PURE__ */ getEscaper(/["&\u00A0]/g, new Map([
  101. [34, "&quot;"],
  102. [38, "&amp;"],
  103. [160, "&nbsp;"],
  104. ]));
  105. /**
  106. * Encodes all characters that have to be escaped in HTML text,
  107. * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
  108. *
  109. * @param data String to escape.
  110. */
  111. export const escapeText = /* #__PURE__ */ getEscaper(/[&<>\u00A0]/g, new Map([
  112. [38, "&amp;"],
  113. [60, "&lt;"],
  114. [62, "&gt;"],
  115. [160, "&nbsp;"],
  116. ]));
  117. //# sourceMappingURL=escape.js.map