@@ -31,8 +31,12 @@ import {
31
31
* - `text` — use the text content of the matched element,
32
32
* - `[<attribute-name>]` copy the value from attribute `attribute-name` on the same element,
33
33
* - `?<parameter-name>` copy the value from URL parameter `parameter-name` of the same element's `href` attribute.
34
- * - `transform` — optional, defaults to no transforming:
34
+ * - `transform` — optional, defaults to no transforming. Possible values :
35
35
* - `base64decode` — decode the base64 string from specified attribute.
36
+ * - `removeHash` — remove the hash from the URL.
37
+ * - `removeParam[:<parameters>]` — remove the specified parameters from the URL,
38
+ * where `<parameters>` is a comma-separated list of parameter names;
39
+ * if no parameter is specified, remove all parameters.
36
40
*
37
41
* > Note that in the case where the discovered value does not correspond to a valid URL with the appropriate
38
42
* > http or https protocols, the value will not be set.
@@ -111,6 +115,60 @@ import {
111
115
* </div>
112
116
* ```
113
117
*
118
+ * 5. Remove the hash from the URL:
119
+ *
120
+ * ```adblock
121
+ * example.org#%#//scriptlet('href-sanitizer', 'a[href*="foo.com"]', '[href]', 'removeHash')
122
+ * ```
123
+ *
124
+ * ```html
125
+ * <!-- before -->
126
+ * <div>
127
+ * <a href="http://www.foo.com/out/#aHR0cDovL2V4YW1wbGUuY29tLz92PTEyMw=="></a>
128
+ * </div>
129
+ *
130
+ * <!-- after -->
131
+ * <div>
132
+ * <a href="http://www.foo.com/out/"></a>
133
+ * </div>
134
+ * ```
135
+ *
136
+ * 6. Remove the all parameter(s) from the URL:
137
+ *
138
+ * ```adblock
139
+ * example.org#%#//scriptlet('href-sanitizer', 'a[href*="foo.com"]', '[href]', 'removeParam')
140
+ * ```
141
+ *
142
+ * ```html
143
+ * <!-- before -->
144
+ * <div>
145
+ * <a href="https://foo.com/123123?utm_source=nova&utm_medium=tg&utm_campaign=main"></a>
146
+ * </div>
147
+ *
148
+ * <!-- after -->
149
+ * <div>
150
+ * <a href="https://foo.com/123123"></a>
151
+ * </div>
152
+ * ```
153
+ *
154
+ * 7. Remove the specified parameter(s) from the URL:
155
+ *
156
+ * ```adblock
157
+ * example.org#%#//scriptlet('href-sanitizer', 'a[href*="foo.com"]', '[href]', 'removeParam:utm_source,utm_medium')
158
+ * ```
159
+ *
160
+ * ```html
161
+ * <!-- before -->
162
+ * <div>
163
+ * <a href="https://foo.com/123123?utm_source=nova&utm_medium=tg&utm_campaign=main"></a>
164
+ * </div>
165
+ *
166
+ * <!-- after -->
167
+ * <div>
168
+ * <a href="https://foo.com/123123?utm_campaign=main"></a>
169
+ * </div>
170
+ * ```
171
+ *
114
172
* @added v1.10.25.
115
173
*/
116
174
@@ -125,7 +183,13 @@ export function hrefSanitizer(
125
183
return ;
126
184
}
127
185
128
- const BASE64_TRANSFORM_MARKER = 'base64decode' ;
186
+ // transform markers
187
+ const BASE64_DECODE_TRANSFORM_MARKER = 'base64decode' ;
188
+ const REMOVE_HASH_TRANSFORM_MARKER = 'removeHash' ;
189
+ const REMOVE_PARAM_TRANSFORM_MARKER = 'removeParam' ;
190
+ // separator markers
191
+ const MARKER_SEPARATOR = ':' ;
192
+ const COMMA = ',' ;
129
193
130
194
// Regular expression to find not valid characters at the beginning and at the end of the string,
131
195
// \x21-\x7e is a range that includes the ASCII characters from ! (hex 21) to ~ (hex 7E).
@@ -337,14 +401,64 @@ export function hrefSanitizer(
337
401
return validEncodedHash ? decodeBase64SeveralTimes ( validEncodedHash , DECODE_ATTEMPTS_NUMBER ) : '' ;
338
402
} ;
339
403
404
+ /**
405
+ * Removes the hash from the URL.
406
+ * @param url URL to remove the hash from
407
+ * @returns URL without the hash or empty string if no hash is found
408
+ */
409
+ const removeHash = ( url : string ) => {
410
+ const urlObj = new URL ( url , window . location . origin ) ;
411
+
412
+ if ( ! urlObj . hash ) {
413
+ return '' ;
414
+ }
415
+
416
+ urlObj . hash = '' ;
417
+ return urlObj . toString ( ) ;
418
+ } ;
419
+
420
+ /**
421
+ * Removes the specified parameter from the URL.
422
+ * @param url URL to remove the parameter from
423
+ * @param transformValue parameter value(s) to remove with marker
424
+ * @returns URL without the parameter(s) or empty string if no parameter is found
425
+ */
426
+ const removeParam = ( url : string , transformValue : string ) => {
427
+ const urlObj = new URL ( url , window . location . origin ) ;
428
+
429
+ // get the parameter values to remove
430
+ const paramNamesToRemoveStr = transformValue . split ( MARKER_SEPARATOR ) [ 1 ] ;
431
+
432
+ if ( ! paramNamesToRemoveStr ) {
433
+ urlObj . search = '' ;
434
+ return urlObj . toString ( ) ;
435
+ }
436
+
437
+ const initSearchParamsLength = urlObj . searchParams . toString ( ) . length ;
438
+
439
+ const removeParams = paramNamesToRemoveStr . split ( COMMA ) ;
440
+ removeParams . forEach ( ( param ) => {
441
+ if ( urlObj . searchParams . has ( param ) ) {
442
+ urlObj . searchParams . delete ( param ) ;
443
+ }
444
+ } ) ;
445
+
446
+ // if the parameter(s) is not found, return empty string
447
+ if ( initSearchParamsLength === urlObj . searchParams . toString ( ) . length ) {
448
+ return '' ;
449
+ }
450
+
451
+ return urlObj . toString ( ) ;
452
+ } ;
453
+
340
454
/**
341
455
* Extracts the base64 part from a string.
342
456
* If no base64 string is found, `null` is returned.
343
457
* @param url String to extract the base64 part from.
344
458
* @returns The base64 part of the string, or `null` if none is found.
345
459
*/
346
460
const decodeBase64URL = ( url : string ) => {
347
- const { search, hash } = new URL ( url ) ;
461
+ const { search, hash } = new URL ( url , document . location . href ) ;
348
462
349
463
if ( search . length > 0 ) {
350
464
return decodeSearchString ( search ) ;
@@ -394,13 +508,19 @@ export function hrefSanitizer(
394
508
return ;
395
509
}
396
510
let newHref = extractNewHref ( elem , attribute ) ;
397
-
398
511
// apply transform if specified
399
512
if ( transform ) {
400
- switch ( transform ) {
401
- case BASE64_TRANSFORM_MARKER :
513
+ switch ( true ) {
514
+ case transform === BASE64_DECODE_TRANSFORM_MARKER :
402
515
newHref = base64Decode ( newHref ) ;
403
516
break ;
517
+ case transform === REMOVE_HASH_TRANSFORM_MARKER :
518
+ newHref = removeHash ( newHref ) ;
519
+ break ;
520
+ case transform . startsWith ( REMOVE_PARAM_TRANSFORM_MARKER ) : {
521
+ newHref = removeParam ( newHref , transform ) ;
522
+ break ;
523
+ }
404
524
default :
405
525
logMessage ( source , `Invalid transform option: "${ transform } "` ) ;
406
526
return ;
0 commit comments