1
1
/**
2
2
* Helpers
3
3
*/
4
+ const escapeTest = / [ & < > " ' ] / ;
5
+ const escapeReplace = / [ & < > " ' ] / g;
6
+ const escapeTestNoEncode = / [ < > " ' ] | & (? ! # ? \w + ; ) / ;
7
+ const escapeReplaceNoEncode = / [ < > " ' ] | & (? ! # ? \w + ; ) / g;
8
+ const escapeReplacements = {
9
+ '&' : '&' ,
10
+ '<' : '<' ,
11
+ '>' : '>' ,
12
+ '"' : '"' ,
13
+ "'" : '''
14
+ } ;
15
+ const getEscapeReplacement = ( ch ) => escapeReplacements [ ch ] ;
4
16
function escape ( html , encode ) {
5
17
if ( encode ) {
6
- if ( escape . escapeTest . test ( html ) ) {
7
- return html . replace ( escape . escapeReplace , escape . getReplacement ) ;
18
+ if ( escapeTest . test ( html ) ) {
19
+ return html . replace ( escapeReplace , getEscapeReplacement ) ;
8
20
}
9
21
} else {
10
- if ( escape . escapeTestNoEncode . test ( html ) ) {
11
- return html . replace ( escape . escapeReplaceNoEncode , escape . getReplacement ) ;
22
+ if ( escapeTestNoEncode . test ( html ) ) {
23
+ return html . replace ( escapeReplaceNoEncode , getEscapeReplacement ) ;
12
24
}
13
25
}
14
26
15
27
return html ;
16
28
}
17
- escape . escapeTest = / [ & < > " ' ] / ;
18
- escape . escapeReplace = / [ & < > " ' ] / g;
19
- escape . escapeTestNoEncode = / [ < > " ' ] | & (? ! # ? \w + ; ) / ;
20
- escape . escapeReplaceNoEncode = / [ < > " ' ] | & (? ! # ? \w + ; ) / g;
21
- escape . replacements = {
22
- '&' : '&' ,
23
- '<' : '<' ,
24
- '>' : '>' ,
25
- '"' : '"' ,
26
- "'" : '''
27
- } ;
28
- escape . getReplacement = ( ch ) => escape . replacements [ ch ] ;
29
+
30
+ const unescapeTest = / & ( # (?: \d + ) | (?: # x [ 0 - 9 A - F a - f ] + ) | (?: \w + ) ) ; ? / ig;
29
31
30
32
function unescape ( html ) {
31
33
// explicitly match decimal, hex, and named HTML entities
32
- return html . replace ( unescape . unescapeTest , ( _ , n ) => {
34
+ return html . replace ( unescapeTest , ( _ , n ) => {
33
35
n = n . toLowerCase ( ) ;
34
36
if ( n === 'colon' ) return ':' ;
35
37
if ( n . charAt ( 0 ) === '#' ) {
@@ -40,15 +42,15 @@ function unescape(html) {
40
42
return '' ;
41
43
} ) ;
42
44
}
43
- unescape . unescapeTest = / & ( # (?: \d + ) | (?: # x [ 0 - 9 A - F a - f ] + ) | (?: \w + ) ) ; ? / ig;
44
45
46
+ const caret = / ( ^ | [ ^ \[ ] ) \^ / g;
45
47
function edit ( regex , opt ) {
46
48
regex = regex . source || regex ;
47
49
opt = opt || '' ;
48
50
const obj = {
49
51
replace : ( name , val ) => {
50
52
val = val . source || val ;
51
- val = val . replace ( edit . caret , '$1' ) ;
53
+ val = val . replace ( caret , '$1' ) ;
52
54
regex = regex . replace ( name , val ) ;
53
55
return obj ;
54
56
} ,
@@ -58,14 +60,15 @@ function edit(regex, opt) {
58
60
} ;
59
61
return obj ;
60
62
}
61
- edit . caret = / ( ^ | [ ^ \[ ] ) \^ / g;
62
63
64
+ const nonWordAndColonTest = / [ ^ \w : ] / g;
65
+ const originIndependentUrl = / ^ $ | ^ [ a - z ] [ a - z 0 - 9 + . - ] * : | ^ [ ? # ] / i;
63
66
function cleanUrl ( sanitize , base , href ) {
64
67
if ( sanitize ) {
65
68
let prot ;
66
69
try {
67
70
prot = decodeURIComponent ( unescape ( href ) )
68
- . replace ( cleanUrl . protocol , '' )
71
+ . replace ( nonWordAndColonTest , '' )
69
72
. toLowerCase ( ) ;
70
73
} catch ( e ) {
71
74
return null ;
@@ -74,7 +77,7 @@ function cleanUrl(sanitize, base, href) {
74
77
return null ;
75
78
}
76
79
}
77
- if ( base && ! cleanUrl . originIndependentUrl . test ( href ) ) {
80
+ if ( base && ! originIndependentUrl . test ( href ) ) {
78
81
href = resolveUrl ( base , href ) ;
79
82
}
80
83
try {
@@ -84,44 +87,42 @@ function cleanUrl(sanitize, base, href) {
84
87
}
85
88
return href ;
86
89
}
87
- cleanUrl . protocol = / [ ^ \w : ] / g;
88
- cleanUrl . originIndependentUrl = / ^ $ | ^ [ a - z ] [ a - z 0 - 9 + . - ] * : | ^ [ ? # ] / i;
90
+
91
+ const baseUrls = { } ;
92
+ const justDomain = / ^ [ ^ : ] + : \/ * [ ^ / ] * $ / ;
93
+ const protocol = / ^ ( [ ^ : ] + : ) [ \s \S ] * $ / ;
94
+ const domain = / ^ ( [ ^ : ] + : \/ * [ ^ / ] * ) [ \s \S ] * $ / ;
89
95
90
96
function resolveUrl ( base , href ) {
91
- if ( ! resolveUrl . baseUrls [ ' ' + base ] ) {
97
+ if ( ! baseUrls [ ' ' + base ] ) {
92
98
// we can ignore everything in base after the last slash of its path component,
93
99
// but we might need to add _that_
94
100
// https://tools.ietf.org/html/rfc3986#section-3
95
- if ( resolveUrl . justDomain . test ( base ) ) {
96
- resolveUrl . baseUrls [ ' ' + base ] = base + '/' ;
101
+ if ( justDomain . test ( base ) ) {
102
+ baseUrls [ ' ' + base ] = base + '/' ;
97
103
} else {
98
- resolveUrl . baseUrls [ ' ' + base ] = rtrim ( base , '/' , true ) ;
104
+ baseUrls [ ' ' + base ] = rtrim ( base , '/' , true ) ;
99
105
}
100
106
}
101
- base = resolveUrl . baseUrls [ ' ' + base ] ;
107
+ base = baseUrls [ ' ' + base ] ;
102
108
const relativeBase = base . indexOf ( ':' ) === - 1 ;
103
109
104
110
if ( href . substring ( 0 , 2 ) === '//' ) {
105
111
if ( relativeBase ) {
106
112
return href ;
107
113
}
108
- return base . replace ( resolveUrl . protocol , '$1' ) + href ;
114
+ return base . replace ( protocol , '$1' ) + href ;
109
115
} else if ( href . charAt ( 0 ) === '/' ) {
110
116
if ( relativeBase ) {
111
117
return href ;
112
118
}
113
- return base . replace ( resolveUrl . domain , '$1' ) + href ;
119
+ return base . replace ( domain , '$1' ) + href ;
114
120
} else {
115
121
return base + href ;
116
122
}
117
123
}
118
- resolveUrl . baseUrls = { } ;
119
- resolveUrl . justDomain = / ^ [ ^ : ] + : \/ * [ ^ / ] * $ / ;
120
- resolveUrl . protocol = / ^ ( [ ^ : ] + : ) [ \s \S ] * $ / ;
121
- resolveUrl . domain = / ^ ( [ ^ : ] + : \/ * [ ^ / ] * ) [ \s \S ] * $ / ;
122
124
123
- function noop ( ) { }
124
- noop . exec = noop ;
125
+ const noopTest = { exec : function noopTest ( ) { } } ;
125
126
126
127
function merge ( obj ) {
127
128
let i = 1 ,
@@ -233,7 +234,7 @@ module.exports = {
233
234
edit,
234
235
cleanUrl,
235
236
resolveUrl,
236
- noop ,
237
+ noopTest ,
237
238
merge,
238
239
splitCells,
239
240
rtrim,
0 commit comments