| | 'use strict'; |
| |
|
| | const internals = {}; |
| |
|
| |
|
| | module.exports = function (input) { |
| |
|
| | if (!input) { |
| | return ''; |
| | } |
| |
|
| | let escaped = ''; |
| |
|
| | for (let i = 0; i < input.length; ++i) { |
| |
|
| | const charCode = input.charCodeAt(i); |
| |
|
| | if (internals.isSafe(charCode)) { |
| | escaped += input[i]; |
| | } |
| | else { |
| | escaped += internals.escapeHtmlChar(charCode); |
| | } |
| | } |
| |
|
| | return escaped; |
| | }; |
| |
|
| |
|
| | internals.escapeHtmlChar = function (charCode) { |
| |
|
| | const namedEscape = internals.namedHtml.get(charCode); |
| | if (namedEscape) { |
| | return namedEscape; |
| | } |
| |
|
| | if (charCode >= 256) { |
| | return '&#' + charCode + ';'; |
| | } |
| |
|
| | const hexValue = charCode.toString(16).padStart(2, '0'); |
| | return `&#x${hexValue};`; |
| | }; |
| |
|
| |
|
| | internals.isSafe = function (charCode) { |
| |
|
| | return internals.safeCharCodes.has(charCode); |
| | }; |
| |
|
| |
|
| | internals.namedHtml = new Map([ |
| | [38, '&'], |
| | [60, '<'], |
| | [62, '>'], |
| | [34, '"'], |
| | [160, ' '], |
| | [162, '¢'], |
| | [163, '£'], |
| | [164, '¤'], |
| | [169, '©'], |
| | [174, '®'] |
| | ]); |
| |
|
| |
|
| | internals.safeCharCodes = (function () { |
| |
|
| | const safe = new Set(); |
| |
|
| | for (let i = 32; i < 123; ++i) { |
| |
|
| | if ((i >= 97) || |
| | (i >= 65 && i <= 90) || |
| | (i >= 48 && i <= 57) || |
| | i === 32 || |
| | i === 46 || |
| | i === 44 || |
| | i === 45 || |
| | i === 58 || |
| | i === 95) { |
| |
|
| | safe.add(i); |
| | } |
| | } |
| |
|
| | return safe; |
| | }()); |
| |
|