@@ -8,7 +8,8 @@ const SCHEMA = '<SCHEMA>';
88const SUBDOMAIN = '<SUBDOMAIN>' ;
99const PATH = '<PATH>' ;
1010const QS_VALUE = '<QSVALUE>' ;
11- const QS_KVS = '<QSKVS>' ;
11+ const QS_KVS_1 = '<QSKVS1>' ;
12+ const QS_KVS_2 = '<QSKVS2>' ;
1213
1314
1415const KNOWN_REDIRECTS = [
@@ -93,7 +94,7 @@ const KNOWN_REDIRECTS = [
9394 {
9495 name : 'Tradedoubler' ,
9596 targetParam : 'url' ,
96- paramDelimiters : [ '&' , '( ' ] ,
97+ paramDelimiters : [ '&' , ') ' ] ,
9798 patterns : [
9899 `${ SCHEMA } ${ SUBDOMAIN } .tradedoubler.com/click?`
99100 ] ,
@@ -160,13 +161,12 @@ KNOWN_REDIRECTS.forEach(KNOWN_REDIRECT => {
160161 }
161162
162163 // Prep the Object if necessary
163- if ( ! ( REDIRECT_DATA_BY_TARGET_PARAM [ targetParam ] ) ) {
164- REDIRECT_DATA_BY_TARGET_PARAM [ targetParam ] = {
165- patterns : [ ] ,
166- regexes : [ ] ,
167- types : [ ] ,
168- } ;
169- }
164+ REDIRECT_DATA_BY_TARGET_PARAM [ targetParam ] = REDIRECT_DATA_BY_TARGET_PARAM [ targetParam ] || {
165+ paramDelimiters : [ ] ,
166+ patterns : [ ] ,
167+ regexes : [ ] ,
168+ types : [ ] ,
169+ } ;
170170
171171 // Go through every 'type' for this redirect
172172 types . forEach ( type => {
@@ -176,24 +176,38 @@ KNOWN_REDIRECTS.forEach(KNOWN_REDIRECT => {
176176 }
177177 } ) ;
178178
179+ paramDelimiters . forEach ( paramDelimiter => {
180+ if ( ! REDIRECT_DATA_BY_TARGET_PARAM [ targetParam ] . paramDelimiters . includes ( paramDelimiter ) ) {
181+ REDIRECT_DATA_BY_TARGET_PARAM [ targetParam ] . paramDelimiters . push ( paramDelimiter ) ;
182+ }
183+ } ) ;
184+
179185 const newPatterns = [ ] ;
180186 const newClipboardRegexes = [ ] ;
181187
182188 // Go through each of these patterns and create any combinations we need to
183189 orginalPatterns . forEach ( originalPattern => {
184-
185- // Create the key/value placeholder for the target param
186- const targetParamKv = `${ targetParam } =${ QS_VALUE } ` ;
187-
188- // We need to generate a few variations on this original pattern for URL matching
189- // 1) support the URL param as the first param
190- newPatterns . push ( replacePlaceholders ( `${ originalPattern } ${ targetParamKv } ` ) ) ;
191- // 2) support the URL param as a non-first param
192- newPatterns . push ( replacePlaceholders ( `${ originalPattern } ${ QS_KVS } ${ targetParamKv } ` ) ) ;
193-
194- // The regex only needs 1 variation which includes optional query string key/values
195- const regexPattern = replacePlaceholdersRegex ( `${ originalPattern } ${ QS_KVS } ${ targetParamKv } ` ) ;
196- newClipboardRegexes . push ( new RegExp ( regexPattern ) ) ;
190+ paramDelimiters . forEach ( paramDelimiter => {
191+ // For now we'll support query stryings that take one of 2 forms:
192+ // 1) key1=value1&key2=value2&key3=value3
193+ // 2) key1(value1)key2(value2)key3(value3)
194+ // So...base the key/value delimiter based on the param delimiter
195+ const kvDelimiter = paramDelimiter === '&' ? '=' : '(' ;
196+ const kvPlaceholder = paramDelimiter === '&' ? QS_KVS_1 : QS_KVS_2 ;
197+
198+ // Create the key/value placeholder for the target param
199+ const targetParamKv = `${ targetParam } ${ kvDelimiter } ${ QS_VALUE } ` ;
200+
201+ // We need to generate a few variations on this original pattern for URL matching
202+ // 1) support the URL param as the first param
203+ newPatterns . push ( replacePlaceholders ( `${ originalPattern } ${ targetParamKv } ` ) ) ;
204+ // 2) support the URL param as a non-first param
205+ newPatterns . push ( replacePlaceholders ( `${ originalPattern } ${ kvPlaceholder } ${ targetParamKv } ` ) ) ;
206+
207+ // The regex only needs 1 variation which includes optional query string key/values
208+ const regexPattern = replacePlaceholdersRegex ( `${ originalPattern } ${ kvPlaceholder } ${ targetParamKv } ` ) ;
209+ newClipboardRegexes . push ( new RegExp ( regexPattern ) ) ;
210+ } ) ;
197211 } ) ;
198212
199213 // Add these patterns to the array of patterns for this target param
@@ -203,9 +217,6 @@ KNOWN_REDIRECTS.forEach(KNOWN_REDIRECT => {
203217 REDIRECT_DATA_BY_TARGET_PARAM [ targetParam ] . regexes . push ( ...newClipboardRegexes ) ;
204218} ) ;
205219
206- console . log ( REDIRECT_DATA_BY_TARGET_PARAM ) ;
207-
208-
209220// Escape all of the literals
210221function escapeRegExp ( str ) {
211222 return str . replace ( / [ \- \[ \] \/ \{ \} \( \) \* \+ \? \. \\ \^ \$ \| ] / g, "\\$&" ) ;
@@ -217,7 +228,8 @@ function replacePlaceholders(pattern) {
217228 . replace ( SCHEMA , '*://' )
218229 . replace ( SUBDOMAIN , '*' )
219230 . replace ( PATH , '/*' )
220- . replace ( QS_KVS , '*&' )
231+ . replace ( QS_KVS_1 , '*&' )
232+ . replace ( QS_KVS_2 , '*)' )
221233 . replace ( QS_VALUE , '*' ) ;
222234}
223235
@@ -231,12 +243,14 @@ function replacePlaceholdersRegex(pattern) {
231243 // This one required text on either side of the '=' sign, when I've seen
232244 // some places build junk that would not match. Not sure if this is a good idea
233245 // to "fix" or not.
234- // pattern = pattern.replace(QS_KVS , '([\\w]+\\=[\\w]+\\&)*');
246+ // pattern = pattern.replace(QS_KVS_1 , '([\\w]+\\=[\\w]+\\&)*');
235247 // This would be the "fix" for the above. It allows blanks on either side of the
236248 // '=' sign.
237- // pattern = pattern.replace(QS_KVS , '([\\w*+\\=[\\w]*\\&)*');
249+ // pattern = pattern.replace(QS_KVS_1 , '([\\w*+\\=[\\w]*\\&)*');
238250 // OK, this one handles even more scenarios that are acceptable
239- . replace ( QS_KVS , '([\\w*+\\=?[\\w]*\\&)*' )
251+ . replace ( QS_KVS_1 , '([\\w*+\\=?[\\w]*\\&)*' )
252+ // foo(bar)baz(bop)...
253+ . replace ( QS_KVS_2 , '(\\w*\\(\\w*\\))*' )
240254 . replace ( QS_VALUE , '\\w' ) ;
241255}
242256
@@ -246,16 +260,16 @@ function replacePlaceholdersCreateExample(pattern) {
246260 . replace ( SCHEMA , 'https://' )
247261 . replace ( SUBDOMAIN , 'foo' )
248262 . replace ( PATH , '/path/to/whatever' )
249- . replace ( QS_KVS , '&' )
263+ . replace ( QS_KVS_1 , '&' )
250264 . replace ( QS_VALUE , 'foo' ) ;
251265}
252266
253267
254268// Extract the redirect target from a URL given the target parameter
255- function extractRedirectTarget ( url , targetParam = 'url' , paramDelimitters = [ '&' ] ) {
256- for ( let paramDelimitter of paramDelimitters ) {
269+ function extractRedirectTarget ( url , targetParam = 'url' , paramDelimiters = [ '&' ] ) {
270+ for ( let paramDelimiter of paramDelimiters ) {
257271 // See if we can find a target in the URL.
258- let target = findQueryParam ( targetParam , url , paramDelimitter ) ;
272+ let target = findQueryParam ( targetParam , url , paramDelimiter ) ;
259273
260274 if ( typeof target === 'string' && target . startsWith ( 'http' ) ) {
261275 return decodeURIComponent ( target ) ;
0 commit comments