Skip to content

Commit

Permalink
feat(labs/ssr): use RegExp.exec to escape HTML
Browse files Browse the repository at this point in the history
Switches from using `replace(pattern, fn)` to using the `exec` method of
a `RegExp` instead.
  • Loading branch information
43081j committed Apr 17, 2024
1 parent 700799b commit faab271
Showing 1 changed file with 49 additions and 14 deletions.
63 changes: 49 additions & 14 deletions packages/labs/ssr/src/lib/util/escape-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,57 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

const replacements = {
'&': '&',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
// Note &apos; was not defined in the HTML4 spec, and is not supported by very
// old browsers like IE8, so a codepoint entity is used instead.
"'": '&#39;',
};
const escapePattern = /[&<>"']/g;

/**
* Replaces characters which have special meaning in HTML (&<>"') with escaped
* HTML entities ("&amp;", "&lt;", etc.).
*/
export const escapeHtml = (str: string) =>
str.replace(
/[&<>"']/g,
(char) => replacements[char as keyof typeof replacements]
);
export const escapeHtml = (str: string) => {
let match = escapePattern.exec(str);

if (!match) {
return str;
}

let escapeStr;
let html = '';
let lastIndex = 0;

while (match) {
switch (str.charCodeAt(match.index)) {
// Character: "
case 34:
escapeStr = '&quot;';
break;
// Character: &
case 38:
escapeStr = '&amp;';
break;
// Character: '
// Note &apos; was not defined in the HTML4 spec, and is not supported by
// very old browsers like IE8, so a codepoint entity is used instead.
case 39:
escapeStr = '&#39;';
break;
// Character: <
case 60:
escapeStr = '&lt;';
break;
// Character: >
case 62:
escapeStr = '&gt;';
break;
}

html += str.substring(lastIndex, match.index) + escapeStr;
lastIndex = match.index + 1;
match = escapePattern.exec(str);
}

escapePattern.lastIndex = 0;

return lastIndex !== str.length - 1
? html + str.substring(lastIndex, str.length)
: html;
};

0 comments on commit faab271

Please sign in to comment.