@@ -2,10 +2,6 @@ import { encodeHTMLTrieRe, getCodePoint } from "./encode-trie";
22
33const htmlReplacer = / [ \t \n ! - , . / : - @ [ - ` \f { - } $ \x80 - \uFFFF ] / g;
44const xmlReplacer = / [ " & ' < > $ \x80 - \uFFFF ] / g;
5- const xmlInvalidChars = / [ & < > ' " ] / g;
6-
7- const textReplacer = / [ & < > \u00A0 ] / g;
8- const attrReplacer = / [ " & \u00A0 ] / g;
95
106const xmlCodeMap = new Map ( [
117 [ 34 , """ ] ,
@@ -15,14 +11,6 @@ const xmlCodeMap = new Map([
1511 [ 62 , ">" ] ,
1612] ) ;
1713
18- const htmlEscapeCodeMap = new Map ( [
19- [ 34 , """ ] ,
20- [ 38 , "&" ] ,
21- [ 60 , "<" ] ,
22- [ 62 , ">" ] ,
23- [ 160 , " " ] ,
24- ] ) ;
25-
2614/**
2715 * Encodes all non-ASCII characters, as well as characters not valid in XML
2816 * documents using XML entities.
@@ -93,55 +81,67 @@ export function encodeNonAsciiHTML(data: string): string {
9381 */
9482export const escape = encodeXML ;
9583
84+ function getEscaper (
85+ regex : RegExp ,
86+ map : Map < number , string >
87+ ) : ( data : string ) => string {
88+ return function escape ( data : string ) : string {
89+ let match ;
90+ let lastIdx = 0 ;
91+ let result = "" ;
92+
93+ while ( ( match = regex . exec ( data ) ) ) {
94+ if ( lastIdx !== match . index ) {
95+ result += data . substring ( lastIdx , match . index ) ;
96+ }
97+
98+ // We know that this chararcter will be in the map.
99+ result += map . get ( match [ 0 ] . charCodeAt ( 0 ) ) ! ;
100+
101+ // Every match will be of length 1
102+ lastIdx = match . index + 1 ;
103+ }
104+
105+ return result + data . substring ( lastIdx ) ;
106+ } ;
107+ }
108+
96109/**
97110 * Encodes all characters not valid in XML documents using XML entities.
98111 *
99112 * Note that the output will be character-set dependent.
100113 *
101114 * @param data String to escape.
102115 */
103- export function escapeUTF8 ( data : string ) : string {
104- let match ;
105- let lastIdx = 0 ;
106- let result = "" ;
107-
108- while ( ( match = xmlInvalidChars . exec ( data ) ) ) {
109- if ( lastIdx !== match . index ) {
110- result += data . substring ( lastIdx , match . index ) ;
111- }
112-
113- // We know that this chararcter will be in `inverseXML`
114- result += xmlCodeMap . get ( match [ 0 ] . charCodeAt ( 0 ) ) ! ;
115-
116- // Every match will be of length 1
117- lastIdx = match . index + 1 ;
118- }
119-
120- return result + data . substring ( lastIdx ) ;
121- }
116+ export const escapeUTF8 = getEscaper ( / [ & < > ' " ] / g, xmlCodeMap ) ;
122117
123118/**
124119 * Encodes all characters that have to be escaped in HTML attributes,
125120 * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
126121 *
127122 * @param data String to escape.
128123 */
129- export function escapeAttribute ( data : string ) : string {
130- return data . replace (
131- attrReplacer ,
132- ( match ) => htmlEscapeCodeMap . get ( match . charCodeAt ( 0 ) ) !
133- ) ;
134- }
124+ export const escapeAttribute = getEscaper (
125+ / [ " & \u00A0 ] / g,
126+ new Map ( [
127+ [ 34 , """ ] ,
128+ [ 38 , "&" ] ,
129+ [ 160 , " " ] ,
130+ ] )
131+ ) ;
135132
136133/**
137134 * Encodes all characters that have to be escaped in HTML text,
138135 * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
139136 *
140137 * @param data String to escape.
141138 */
142- export function escapeText ( data : string ) : string {
143- return data . replace (
144- textReplacer ,
145- ( match ) => htmlEscapeCodeMap . get ( match . charCodeAt ( 0 ) ) !
146- ) ;
147- }
139+ export const escapeText = getEscaper (
140+ / [ & < > \u00A0 ] / g,
141+ new Map ( [
142+ [ 38 , "&" ] ,
143+ [ 60 , "<" ] ,
144+ [ 62 , ">" ] ,
145+ [ 160 , " " ] ,
146+ ] )
147+ ) ;
0 commit comments