@url-sanitize/core 0.1.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -4
- package/dist/index.d.ts +657 -1
- package/dist/index.js +258 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,16 +5,16 @@ Pure TypeScript implementation for removing tracking parameters and unwrapping t
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
npm install @url-sanitize/core @url-sanitize/
|
|
8
|
+
npm install @url-sanitize/core @url-sanitize/merged
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
14
|
import { compileSanitizer } from '@url-sanitize/core';
|
|
15
|
-
import {
|
|
15
|
+
import { mergedCatalog } from '@url-sanitize/merged';
|
|
16
16
|
|
|
17
|
-
const sanitize = compileSanitizer(
|
|
17
|
+
const sanitize = compileSanitizer(mergedCatalog, {
|
|
18
18
|
stripReferralMarketing: false,
|
|
19
19
|
unwrapRedirects: true,
|
|
20
20
|
domainBlocking: false
|
|
@@ -38,10 +38,29 @@ type SanitizeResult =
|
|
|
38
38
|
|
|
39
39
|
- Zero runtime dependencies.
|
|
40
40
|
- Pure function; no I/O.
|
|
41
|
-
- Catalog-agnostic: any source (ClearURLs, AdGuard, custom) that produces a `SanitizerCatalog` works.
|
|
41
|
+
- Catalog-agnostic: any source (ClearURLs, AdGuard, Brave, Firefox, custom) that produces a `SanitizerCatalog` works.
|
|
42
42
|
- Factory pattern (`compileSanitizer(catalog)`) — no module-level cache, no singletons.
|
|
43
43
|
- Discriminated union return type — exhaustive `switch (result.kind)`.
|
|
44
44
|
|
|
45
|
+
## Custom catalogs
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { defineCatalog, mergeCatalogs, sanitizerCatalogJsonSchema } from '@url-sanitize/core';
|
|
49
|
+
|
|
50
|
+
const custom = defineCatalog({
|
|
51
|
+
version: 'custom-1',
|
|
52
|
+
generatedAt: new Date().toISOString(),
|
|
53
|
+
sources: [{ name: 'custom' }],
|
|
54
|
+
rules: [{ kind: 'strip-param', source: 'custom', provider: 'local', paramPattern: 'utm_.+' }]
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const merged = mergeCatalogs(custom);
|
|
58
|
+
console.log(sanitizerCatalogJsonSchema.$id);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`mergeCatalogs()` preserves input order and concatenates sources/rules. It does
|
|
62
|
+
not dedupe, reorder, or apply source precedence.
|
|
63
|
+
|
|
45
64
|
## License
|
|
46
65
|
|
|
47
66
|
MIT.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
type RuleSource = 'clearurls' | 'adguard' | 'brave' | 'firefox' | 'custom';
|
|
2
|
+
type RedirectMatchPart = 'url' | 'pathname';
|
|
3
|
+
type RedirectTargetEncoding = 'percent' | 'base64';
|
|
4
|
+
type RedirectPrependScheme = 'http' | 'https';
|
|
2
5
|
type SanitizerRule = {
|
|
3
6
|
kind: 'strip-param';
|
|
4
7
|
source: RuleSource;
|
|
5
8
|
provider: string;
|
|
6
9
|
urlPattern?: string;
|
|
7
10
|
paramPattern: string;
|
|
11
|
+
valuePattern?: string;
|
|
8
12
|
exceptions?: string[];
|
|
9
13
|
isReferralMarketing?: boolean;
|
|
10
14
|
} | {
|
|
@@ -22,6 +26,10 @@ type SanitizerRule = {
|
|
|
22
26
|
urlPattern?: string;
|
|
23
27
|
pattern: string;
|
|
24
28
|
captureGroup: number;
|
|
29
|
+
matchPart?: RedirectMatchPart;
|
|
30
|
+
targetEncoding?: RedirectTargetEncoding;
|
|
31
|
+
prependScheme?: RedirectPrependScheme;
|
|
32
|
+
targetTemplate?: string;
|
|
25
33
|
exceptions?: string[];
|
|
26
34
|
} | {
|
|
27
35
|
kind: 'block-domain';
|
|
@@ -73,7 +81,655 @@ interface SanitizerOptions {
|
|
|
73
81
|
domainBlocking?: boolean;
|
|
74
82
|
}
|
|
75
83
|
|
|
84
|
+
declare function defineCatalog(catalog: SanitizerCatalog): SanitizerCatalog;
|
|
85
|
+
declare function mergeCatalogs(first: SanitizerCatalog, ...rest: SanitizerCatalog[]): SanitizerCatalog;
|
|
86
|
+
|
|
76
87
|
type Sanitizer = (input: string) => SanitizeResult;
|
|
77
88
|
declare function compileSanitizer(catalog: SanitizerCatalog, options?: SanitizerOptions): Sanitizer;
|
|
78
89
|
|
|
79
|
-
|
|
90
|
+
declare const sanitizerOptionsJsonSchema: {
|
|
91
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
92
|
+
readonly $id: "https://url-sanitize.dev/schema/v1/options.json";
|
|
93
|
+
readonly title: "url-sanitize options";
|
|
94
|
+
readonly type: "object";
|
|
95
|
+
readonly additionalProperties: false;
|
|
96
|
+
readonly properties: {
|
|
97
|
+
readonly stripReferralMarketing: {
|
|
98
|
+
readonly type: "boolean";
|
|
99
|
+
};
|
|
100
|
+
readonly unwrapRedirects: {
|
|
101
|
+
readonly type: "boolean";
|
|
102
|
+
};
|
|
103
|
+
readonly domainBlocking: {
|
|
104
|
+
readonly type: "boolean";
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
declare const sanitizerCatalogJsonSchema: {
|
|
109
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
110
|
+
readonly $id: "https://url-sanitize.dev/schema/v1/catalog.json";
|
|
111
|
+
readonly title: "url-sanitize catalog";
|
|
112
|
+
readonly type: "object";
|
|
113
|
+
readonly required: readonly ["version", "generatedAt", "sources", "rules"];
|
|
114
|
+
readonly additionalProperties: false;
|
|
115
|
+
readonly properties: {
|
|
116
|
+
readonly version: {
|
|
117
|
+
readonly type: "string";
|
|
118
|
+
};
|
|
119
|
+
readonly generatedAt: {
|
|
120
|
+
readonly type: "string";
|
|
121
|
+
};
|
|
122
|
+
readonly sources: {
|
|
123
|
+
readonly type: "array";
|
|
124
|
+
readonly items: {
|
|
125
|
+
readonly type: "object";
|
|
126
|
+
readonly required: readonly ["name"];
|
|
127
|
+
readonly additionalProperties: false;
|
|
128
|
+
readonly properties: {
|
|
129
|
+
readonly name: {
|
|
130
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
131
|
+
};
|
|
132
|
+
readonly version: {
|
|
133
|
+
readonly type: "string";
|
|
134
|
+
};
|
|
135
|
+
readonly hash: {
|
|
136
|
+
readonly type: "string";
|
|
137
|
+
};
|
|
138
|
+
readonly license: {
|
|
139
|
+
readonly type: "string";
|
|
140
|
+
};
|
|
141
|
+
readonly upstream: {
|
|
142
|
+
readonly type: "string";
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
readonly rules: {
|
|
148
|
+
readonly type: "array";
|
|
149
|
+
readonly items: {
|
|
150
|
+
readonly oneOf: readonly [{
|
|
151
|
+
readonly type: "object";
|
|
152
|
+
readonly required: readonly ["kind", "source", "provider", "paramPattern"];
|
|
153
|
+
readonly additionalProperties: false;
|
|
154
|
+
readonly properties: {
|
|
155
|
+
readonly kind: {
|
|
156
|
+
readonly const: "strip-param";
|
|
157
|
+
};
|
|
158
|
+
readonly paramPattern: {
|
|
159
|
+
readonly type: "string";
|
|
160
|
+
};
|
|
161
|
+
readonly valuePattern: {
|
|
162
|
+
readonly type: "string";
|
|
163
|
+
};
|
|
164
|
+
readonly isReferralMarketing: {
|
|
165
|
+
readonly type: "boolean";
|
|
166
|
+
};
|
|
167
|
+
readonly source: {
|
|
168
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
169
|
+
};
|
|
170
|
+
readonly provider: {
|
|
171
|
+
readonly type: "string";
|
|
172
|
+
};
|
|
173
|
+
readonly urlPattern: {
|
|
174
|
+
readonly type: "string";
|
|
175
|
+
};
|
|
176
|
+
readonly exceptions: {
|
|
177
|
+
readonly type: "array";
|
|
178
|
+
readonly items: {
|
|
179
|
+
readonly type: "string";
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
}, {
|
|
184
|
+
readonly type: "object";
|
|
185
|
+
readonly required: readonly ["kind", "source", "provider", "pattern", "replacement"];
|
|
186
|
+
readonly additionalProperties: false;
|
|
187
|
+
readonly properties: {
|
|
188
|
+
readonly kind: {
|
|
189
|
+
readonly const: "raw-replace";
|
|
190
|
+
};
|
|
191
|
+
readonly pattern: {
|
|
192
|
+
readonly type: "string";
|
|
193
|
+
};
|
|
194
|
+
readonly replacement: {
|
|
195
|
+
readonly type: "string";
|
|
196
|
+
};
|
|
197
|
+
readonly source: {
|
|
198
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
199
|
+
};
|
|
200
|
+
readonly provider: {
|
|
201
|
+
readonly type: "string";
|
|
202
|
+
};
|
|
203
|
+
readonly urlPattern: {
|
|
204
|
+
readonly type: "string";
|
|
205
|
+
};
|
|
206
|
+
readonly exceptions: {
|
|
207
|
+
readonly type: "array";
|
|
208
|
+
readonly items: {
|
|
209
|
+
readonly type: "string";
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
}, {
|
|
214
|
+
readonly type: "object";
|
|
215
|
+
readonly required: readonly ["kind", "source", "provider", "pattern", "captureGroup"];
|
|
216
|
+
readonly additionalProperties: false;
|
|
217
|
+
readonly properties: {
|
|
218
|
+
readonly kind: {
|
|
219
|
+
readonly const: "unwrap-redirect";
|
|
220
|
+
};
|
|
221
|
+
readonly pattern: {
|
|
222
|
+
readonly type: "string";
|
|
223
|
+
};
|
|
224
|
+
readonly captureGroup: {
|
|
225
|
+
readonly type: "integer";
|
|
226
|
+
readonly minimum: 0;
|
|
227
|
+
};
|
|
228
|
+
readonly matchPart: {
|
|
229
|
+
readonly enum: readonly ["url", "pathname"];
|
|
230
|
+
};
|
|
231
|
+
readonly targetEncoding: {
|
|
232
|
+
readonly enum: readonly ["percent", "base64"];
|
|
233
|
+
};
|
|
234
|
+
readonly prependScheme: {
|
|
235
|
+
readonly enum: readonly ["http", "https"];
|
|
236
|
+
};
|
|
237
|
+
readonly targetTemplate: {
|
|
238
|
+
readonly type: "string";
|
|
239
|
+
};
|
|
240
|
+
readonly source: {
|
|
241
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
242
|
+
};
|
|
243
|
+
readonly provider: {
|
|
244
|
+
readonly type: "string";
|
|
245
|
+
};
|
|
246
|
+
readonly urlPattern: {
|
|
247
|
+
readonly type: "string";
|
|
248
|
+
};
|
|
249
|
+
readonly exceptions: {
|
|
250
|
+
readonly type: "array";
|
|
251
|
+
readonly items: {
|
|
252
|
+
readonly type: "string";
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
}, {
|
|
257
|
+
readonly type: "object";
|
|
258
|
+
readonly required: readonly ["kind", "source", "provider", "urlPattern"];
|
|
259
|
+
readonly additionalProperties: false;
|
|
260
|
+
readonly properties: {
|
|
261
|
+
readonly kind: {
|
|
262
|
+
readonly const: "block-domain";
|
|
263
|
+
};
|
|
264
|
+
readonly source: {
|
|
265
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
266
|
+
};
|
|
267
|
+
readonly provider: {
|
|
268
|
+
readonly type: "string";
|
|
269
|
+
};
|
|
270
|
+
readonly urlPattern: {
|
|
271
|
+
readonly type: "string";
|
|
272
|
+
};
|
|
273
|
+
readonly exceptions: {
|
|
274
|
+
readonly type: "array";
|
|
275
|
+
readonly items: {
|
|
276
|
+
readonly type: "string";
|
|
277
|
+
};
|
|
278
|
+
};
|
|
279
|
+
};
|
|
280
|
+
}];
|
|
281
|
+
};
|
|
282
|
+
};
|
|
283
|
+
};
|
|
284
|
+
};
|
|
285
|
+
declare const sanitizeResultJsonSchema: {
|
|
286
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
287
|
+
readonly $id: "https://url-sanitize.dev/schema/v1/result.json";
|
|
288
|
+
readonly title: "url-sanitize result";
|
|
289
|
+
readonly oneOf: readonly [{
|
|
290
|
+
readonly type: "object";
|
|
291
|
+
readonly required: readonly ["kind", "url"];
|
|
292
|
+
readonly additionalProperties: false;
|
|
293
|
+
readonly properties: {
|
|
294
|
+
readonly kind: {
|
|
295
|
+
readonly const: "unchanged";
|
|
296
|
+
};
|
|
297
|
+
readonly url: {
|
|
298
|
+
readonly type: "string";
|
|
299
|
+
};
|
|
300
|
+
};
|
|
301
|
+
}, {
|
|
302
|
+
readonly type: "object";
|
|
303
|
+
readonly required: readonly ["kind", "original", "url", "strippedParams", "matchedRules"];
|
|
304
|
+
readonly additionalProperties: false;
|
|
305
|
+
readonly properties: {
|
|
306
|
+
readonly kind: {
|
|
307
|
+
readonly const: "cleaned";
|
|
308
|
+
};
|
|
309
|
+
readonly original: {
|
|
310
|
+
readonly type: "string";
|
|
311
|
+
};
|
|
312
|
+
readonly url: {
|
|
313
|
+
readonly type: "string";
|
|
314
|
+
};
|
|
315
|
+
readonly strippedParams: {
|
|
316
|
+
readonly type: "array";
|
|
317
|
+
readonly items: {
|
|
318
|
+
readonly type: "string";
|
|
319
|
+
};
|
|
320
|
+
};
|
|
321
|
+
readonly matchedRules: {
|
|
322
|
+
readonly type: "array";
|
|
323
|
+
readonly items: {
|
|
324
|
+
readonly type: "object";
|
|
325
|
+
readonly required: readonly ["source", "provider", "kind"];
|
|
326
|
+
readonly additionalProperties: false;
|
|
327
|
+
readonly properties: {
|
|
328
|
+
readonly source: {
|
|
329
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
330
|
+
};
|
|
331
|
+
readonly provider: {
|
|
332
|
+
readonly type: "string";
|
|
333
|
+
};
|
|
334
|
+
readonly kind: {
|
|
335
|
+
readonly enum: readonly ["strip-param", "raw-replace", "unwrap-redirect", "block-domain"];
|
|
336
|
+
};
|
|
337
|
+
readonly detail: {
|
|
338
|
+
readonly type: "string";
|
|
339
|
+
};
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
};
|
|
344
|
+
}, {
|
|
345
|
+
readonly type: "object";
|
|
346
|
+
readonly required: readonly ["kind", "original", "url", "via"];
|
|
347
|
+
readonly additionalProperties: false;
|
|
348
|
+
readonly properties: {
|
|
349
|
+
readonly kind: {
|
|
350
|
+
readonly const: "redirected";
|
|
351
|
+
};
|
|
352
|
+
readonly original: {
|
|
353
|
+
readonly type: "string";
|
|
354
|
+
};
|
|
355
|
+
readonly url: {
|
|
356
|
+
readonly type: "string";
|
|
357
|
+
};
|
|
358
|
+
readonly via: {
|
|
359
|
+
readonly type: "object";
|
|
360
|
+
readonly required: readonly ["source", "provider", "kind"];
|
|
361
|
+
readonly additionalProperties: false;
|
|
362
|
+
readonly properties: {
|
|
363
|
+
readonly source: {
|
|
364
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
365
|
+
};
|
|
366
|
+
readonly provider: {
|
|
367
|
+
readonly type: "string";
|
|
368
|
+
};
|
|
369
|
+
readonly kind: {
|
|
370
|
+
readonly enum: readonly ["strip-param", "raw-replace", "unwrap-redirect", "block-domain"];
|
|
371
|
+
};
|
|
372
|
+
readonly detail: {
|
|
373
|
+
readonly type: "string";
|
|
374
|
+
};
|
|
375
|
+
};
|
|
376
|
+
};
|
|
377
|
+
};
|
|
378
|
+
}, {
|
|
379
|
+
readonly type: "object";
|
|
380
|
+
readonly required: readonly ["kind", "original", "via"];
|
|
381
|
+
readonly additionalProperties: false;
|
|
382
|
+
readonly properties: {
|
|
383
|
+
readonly kind: {
|
|
384
|
+
readonly const: "blocked";
|
|
385
|
+
};
|
|
386
|
+
readonly original: {
|
|
387
|
+
readonly type: "string";
|
|
388
|
+
};
|
|
389
|
+
readonly via: {
|
|
390
|
+
readonly type: "object";
|
|
391
|
+
readonly required: readonly ["source", "provider", "kind"];
|
|
392
|
+
readonly additionalProperties: false;
|
|
393
|
+
readonly properties: {
|
|
394
|
+
readonly source: {
|
|
395
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
396
|
+
};
|
|
397
|
+
readonly provider: {
|
|
398
|
+
readonly type: "string";
|
|
399
|
+
};
|
|
400
|
+
readonly kind: {
|
|
401
|
+
readonly enum: readonly ["strip-param", "raw-replace", "unwrap-redirect", "block-domain"];
|
|
402
|
+
};
|
|
403
|
+
readonly detail: {
|
|
404
|
+
readonly type: "string";
|
|
405
|
+
};
|
|
406
|
+
};
|
|
407
|
+
};
|
|
408
|
+
};
|
|
409
|
+
}];
|
|
410
|
+
};
|
|
411
|
+
declare const urlSanitizeJsonSchemas: {
|
|
412
|
+
readonly catalog: {
|
|
413
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
414
|
+
readonly $id: "https://url-sanitize.dev/schema/v1/catalog.json";
|
|
415
|
+
readonly title: "url-sanitize catalog";
|
|
416
|
+
readonly type: "object";
|
|
417
|
+
readonly required: readonly ["version", "generatedAt", "sources", "rules"];
|
|
418
|
+
readonly additionalProperties: false;
|
|
419
|
+
readonly properties: {
|
|
420
|
+
readonly version: {
|
|
421
|
+
readonly type: "string";
|
|
422
|
+
};
|
|
423
|
+
readonly generatedAt: {
|
|
424
|
+
readonly type: "string";
|
|
425
|
+
};
|
|
426
|
+
readonly sources: {
|
|
427
|
+
readonly type: "array";
|
|
428
|
+
readonly items: {
|
|
429
|
+
readonly type: "object";
|
|
430
|
+
readonly required: readonly ["name"];
|
|
431
|
+
readonly additionalProperties: false;
|
|
432
|
+
readonly properties: {
|
|
433
|
+
readonly name: {
|
|
434
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
435
|
+
};
|
|
436
|
+
readonly version: {
|
|
437
|
+
readonly type: "string";
|
|
438
|
+
};
|
|
439
|
+
readonly hash: {
|
|
440
|
+
readonly type: "string";
|
|
441
|
+
};
|
|
442
|
+
readonly license: {
|
|
443
|
+
readonly type: "string";
|
|
444
|
+
};
|
|
445
|
+
readonly upstream: {
|
|
446
|
+
readonly type: "string";
|
|
447
|
+
};
|
|
448
|
+
};
|
|
449
|
+
};
|
|
450
|
+
};
|
|
451
|
+
readonly rules: {
|
|
452
|
+
readonly type: "array";
|
|
453
|
+
readonly items: {
|
|
454
|
+
readonly oneOf: readonly [{
|
|
455
|
+
readonly type: "object";
|
|
456
|
+
readonly required: readonly ["kind", "source", "provider", "paramPattern"];
|
|
457
|
+
readonly additionalProperties: false;
|
|
458
|
+
readonly properties: {
|
|
459
|
+
readonly kind: {
|
|
460
|
+
readonly const: "strip-param";
|
|
461
|
+
};
|
|
462
|
+
readonly paramPattern: {
|
|
463
|
+
readonly type: "string";
|
|
464
|
+
};
|
|
465
|
+
readonly valuePattern: {
|
|
466
|
+
readonly type: "string";
|
|
467
|
+
};
|
|
468
|
+
readonly isReferralMarketing: {
|
|
469
|
+
readonly type: "boolean";
|
|
470
|
+
};
|
|
471
|
+
readonly source: {
|
|
472
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
473
|
+
};
|
|
474
|
+
readonly provider: {
|
|
475
|
+
readonly type: "string";
|
|
476
|
+
};
|
|
477
|
+
readonly urlPattern: {
|
|
478
|
+
readonly type: "string";
|
|
479
|
+
};
|
|
480
|
+
readonly exceptions: {
|
|
481
|
+
readonly type: "array";
|
|
482
|
+
readonly items: {
|
|
483
|
+
readonly type: "string";
|
|
484
|
+
};
|
|
485
|
+
};
|
|
486
|
+
};
|
|
487
|
+
}, {
|
|
488
|
+
readonly type: "object";
|
|
489
|
+
readonly required: readonly ["kind", "source", "provider", "pattern", "replacement"];
|
|
490
|
+
readonly additionalProperties: false;
|
|
491
|
+
readonly properties: {
|
|
492
|
+
readonly kind: {
|
|
493
|
+
readonly const: "raw-replace";
|
|
494
|
+
};
|
|
495
|
+
readonly pattern: {
|
|
496
|
+
readonly type: "string";
|
|
497
|
+
};
|
|
498
|
+
readonly replacement: {
|
|
499
|
+
readonly type: "string";
|
|
500
|
+
};
|
|
501
|
+
readonly source: {
|
|
502
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
503
|
+
};
|
|
504
|
+
readonly provider: {
|
|
505
|
+
readonly type: "string";
|
|
506
|
+
};
|
|
507
|
+
readonly urlPattern: {
|
|
508
|
+
readonly type: "string";
|
|
509
|
+
};
|
|
510
|
+
readonly exceptions: {
|
|
511
|
+
readonly type: "array";
|
|
512
|
+
readonly items: {
|
|
513
|
+
readonly type: "string";
|
|
514
|
+
};
|
|
515
|
+
};
|
|
516
|
+
};
|
|
517
|
+
}, {
|
|
518
|
+
readonly type: "object";
|
|
519
|
+
readonly required: readonly ["kind", "source", "provider", "pattern", "captureGroup"];
|
|
520
|
+
readonly additionalProperties: false;
|
|
521
|
+
readonly properties: {
|
|
522
|
+
readonly kind: {
|
|
523
|
+
readonly const: "unwrap-redirect";
|
|
524
|
+
};
|
|
525
|
+
readonly pattern: {
|
|
526
|
+
readonly type: "string";
|
|
527
|
+
};
|
|
528
|
+
readonly captureGroup: {
|
|
529
|
+
readonly type: "integer";
|
|
530
|
+
readonly minimum: 0;
|
|
531
|
+
};
|
|
532
|
+
readonly matchPart: {
|
|
533
|
+
readonly enum: readonly ["url", "pathname"];
|
|
534
|
+
};
|
|
535
|
+
readonly targetEncoding: {
|
|
536
|
+
readonly enum: readonly ["percent", "base64"];
|
|
537
|
+
};
|
|
538
|
+
readonly prependScheme: {
|
|
539
|
+
readonly enum: readonly ["http", "https"];
|
|
540
|
+
};
|
|
541
|
+
readonly targetTemplate: {
|
|
542
|
+
readonly type: "string";
|
|
543
|
+
};
|
|
544
|
+
readonly source: {
|
|
545
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
546
|
+
};
|
|
547
|
+
readonly provider: {
|
|
548
|
+
readonly type: "string";
|
|
549
|
+
};
|
|
550
|
+
readonly urlPattern: {
|
|
551
|
+
readonly type: "string";
|
|
552
|
+
};
|
|
553
|
+
readonly exceptions: {
|
|
554
|
+
readonly type: "array";
|
|
555
|
+
readonly items: {
|
|
556
|
+
readonly type: "string";
|
|
557
|
+
};
|
|
558
|
+
};
|
|
559
|
+
};
|
|
560
|
+
}, {
|
|
561
|
+
readonly type: "object";
|
|
562
|
+
readonly required: readonly ["kind", "source", "provider", "urlPattern"];
|
|
563
|
+
readonly additionalProperties: false;
|
|
564
|
+
readonly properties: {
|
|
565
|
+
readonly kind: {
|
|
566
|
+
readonly const: "block-domain";
|
|
567
|
+
};
|
|
568
|
+
readonly source: {
|
|
569
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
570
|
+
};
|
|
571
|
+
readonly provider: {
|
|
572
|
+
readonly type: "string";
|
|
573
|
+
};
|
|
574
|
+
readonly urlPattern: {
|
|
575
|
+
readonly type: "string";
|
|
576
|
+
};
|
|
577
|
+
readonly exceptions: {
|
|
578
|
+
readonly type: "array";
|
|
579
|
+
readonly items: {
|
|
580
|
+
readonly type: "string";
|
|
581
|
+
};
|
|
582
|
+
};
|
|
583
|
+
};
|
|
584
|
+
}];
|
|
585
|
+
};
|
|
586
|
+
};
|
|
587
|
+
};
|
|
588
|
+
};
|
|
589
|
+
readonly options: {
|
|
590
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
591
|
+
readonly $id: "https://url-sanitize.dev/schema/v1/options.json";
|
|
592
|
+
readonly title: "url-sanitize options";
|
|
593
|
+
readonly type: "object";
|
|
594
|
+
readonly additionalProperties: false;
|
|
595
|
+
readonly properties: {
|
|
596
|
+
readonly stripReferralMarketing: {
|
|
597
|
+
readonly type: "boolean";
|
|
598
|
+
};
|
|
599
|
+
readonly unwrapRedirects: {
|
|
600
|
+
readonly type: "boolean";
|
|
601
|
+
};
|
|
602
|
+
readonly domainBlocking: {
|
|
603
|
+
readonly type: "boolean";
|
|
604
|
+
};
|
|
605
|
+
};
|
|
606
|
+
};
|
|
607
|
+
readonly result: {
|
|
608
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
609
|
+
readonly $id: "https://url-sanitize.dev/schema/v1/result.json";
|
|
610
|
+
readonly title: "url-sanitize result";
|
|
611
|
+
readonly oneOf: readonly [{
|
|
612
|
+
readonly type: "object";
|
|
613
|
+
readonly required: readonly ["kind", "url"];
|
|
614
|
+
readonly additionalProperties: false;
|
|
615
|
+
readonly properties: {
|
|
616
|
+
readonly kind: {
|
|
617
|
+
readonly const: "unchanged";
|
|
618
|
+
};
|
|
619
|
+
readonly url: {
|
|
620
|
+
readonly type: "string";
|
|
621
|
+
};
|
|
622
|
+
};
|
|
623
|
+
}, {
|
|
624
|
+
readonly type: "object";
|
|
625
|
+
readonly required: readonly ["kind", "original", "url", "strippedParams", "matchedRules"];
|
|
626
|
+
readonly additionalProperties: false;
|
|
627
|
+
readonly properties: {
|
|
628
|
+
readonly kind: {
|
|
629
|
+
readonly const: "cleaned";
|
|
630
|
+
};
|
|
631
|
+
readonly original: {
|
|
632
|
+
readonly type: "string";
|
|
633
|
+
};
|
|
634
|
+
readonly url: {
|
|
635
|
+
readonly type: "string";
|
|
636
|
+
};
|
|
637
|
+
readonly strippedParams: {
|
|
638
|
+
readonly type: "array";
|
|
639
|
+
readonly items: {
|
|
640
|
+
readonly type: "string";
|
|
641
|
+
};
|
|
642
|
+
};
|
|
643
|
+
readonly matchedRules: {
|
|
644
|
+
readonly type: "array";
|
|
645
|
+
readonly items: {
|
|
646
|
+
readonly type: "object";
|
|
647
|
+
readonly required: readonly ["source", "provider", "kind"];
|
|
648
|
+
readonly additionalProperties: false;
|
|
649
|
+
readonly properties: {
|
|
650
|
+
readonly source: {
|
|
651
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
652
|
+
};
|
|
653
|
+
readonly provider: {
|
|
654
|
+
readonly type: "string";
|
|
655
|
+
};
|
|
656
|
+
readonly kind: {
|
|
657
|
+
readonly enum: readonly ["strip-param", "raw-replace", "unwrap-redirect", "block-domain"];
|
|
658
|
+
};
|
|
659
|
+
readonly detail: {
|
|
660
|
+
readonly type: "string";
|
|
661
|
+
};
|
|
662
|
+
};
|
|
663
|
+
};
|
|
664
|
+
};
|
|
665
|
+
};
|
|
666
|
+
}, {
|
|
667
|
+
readonly type: "object";
|
|
668
|
+
readonly required: readonly ["kind", "original", "url", "via"];
|
|
669
|
+
readonly additionalProperties: false;
|
|
670
|
+
readonly properties: {
|
|
671
|
+
readonly kind: {
|
|
672
|
+
readonly const: "redirected";
|
|
673
|
+
};
|
|
674
|
+
readonly original: {
|
|
675
|
+
readonly type: "string";
|
|
676
|
+
};
|
|
677
|
+
readonly url: {
|
|
678
|
+
readonly type: "string";
|
|
679
|
+
};
|
|
680
|
+
readonly via: {
|
|
681
|
+
readonly type: "object";
|
|
682
|
+
readonly required: readonly ["source", "provider", "kind"];
|
|
683
|
+
readonly additionalProperties: false;
|
|
684
|
+
readonly properties: {
|
|
685
|
+
readonly source: {
|
|
686
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
687
|
+
};
|
|
688
|
+
readonly provider: {
|
|
689
|
+
readonly type: "string";
|
|
690
|
+
};
|
|
691
|
+
readonly kind: {
|
|
692
|
+
readonly enum: readonly ["strip-param", "raw-replace", "unwrap-redirect", "block-domain"];
|
|
693
|
+
};
|
|
694
|
+
readonly detail: {
|
|
695
|
+
readonly type: "string";
|
|
696
|
+
};
|
|
697
|
+
};
|
|
698
|
+
};
|
|
699
|
+
};
|
|
700
|
+
}, {
|
|
701
|
+
readonly type: "object";
|
|
702
|
+
readonly required: readonly ["kind", "original", "via"];
|
|
703
|
+
readonly additionalProperties: false;
|
|
704
|
+
readonly properties: {
|
|
705
|
+
readonly kind: {
|
|
706
|
+
readonly const: "blocked";
|
|
707
|
+
};
|
|
708
|
+
readonly original: {
|
|
709
|
+
readonly type: "string";
|
|
710
|
+
};
|
|
711
|
+
readonly via: {
|
|
712
|
+
readonly type: "object";
|
|
713
|
+
readonly required: readonly ["source", "provider", "kind"];
|
|
714
|
+
readonly additionalProperties: false;
|
|
715
|
+
readonly properties: {
|
|
716
|
+
readonly source: {
|
|
717
|
+
readonly enum: readonly ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
718
|
+
};
|
|
719
|
+
readonly provider: {
|
|
720
|
+
readonly type: "string";
|
|
721
|
+
};
|
|
722
|
+
readonly kind: {
|
|
723
|
+
readonly enum: readonly ["strip-param", "raw-replace", "unwrap-redirect", "block-domain"];
|
|
724
|
+
};
|
|
725
|
+
readonly detail: {
|
|
726
|
+
readonly type: "string";
|
|
727
|
+
};
|
|
728
|
+
};
|
|
729
|
+
};
|
|
730
|
+
};
|
|
731
|
+
}];
|
|
732
|
+
};
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
export { type MatchedRule, type RedirectMatchPart, type RedirectPrependScheme, type RedirectTargetEncoding, type RuleSource, type SanitizeResult, type Sanitizer, type SanitizerCatalog, type SanitizerOptions, type SanitizerRule, compileSanitizer, defineCatalog, mergeCatalogs, sanitizeResultJsonSchema, sanitizerCatalogJsonSchema, sanitizerOptionsJsonSchema, urlSanitizeJsonSchemas };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
// src/catalog.ts
|
|
2
|
+
function defineCatalog(catalog) {
|
|
3
|
+
return catalog;
|
|
4
|
+
}
|
|
5
|
+
function mergeCatalogs(first, ...rest) {
|
|
6
|
+
const catalogs = [first, ...rest];
|
|
7
|
+
return {
|
|
8
|
+
version: catalogs.length === 1 ? first.version : `merged(${catalogs.map((catalog) => catalog.version).join(",")})`,
|
|
9
|
+
generatedAt: latestGeneratedAt(catalogs),
|
|
10
|
+
sources: catalogs.flatMap((catalog) => catalog.sources.map((source) => ({ ...source }))),
|
|
11
|
+
rules: catalogs.flatMap((catalog) => catalog.rules.map(cloneRule))
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function latestGeneratedAt(catalogs) {
|
|
15
|
+
return catalogs.map((catalog) => catalog.generatedAt).reduce((latest, generatedAt) => generatedAt > latest ? generatedAt : latest);
|
|
16
|
+
}
|
|
17
|
+
function cloneRule(rule) {
|
|
18
|
+
return rule.exceptions ? { ...rule, exceptions: [...rule.exceptions] } : { ...rule };
|
|
19
|
+
}
|
|
20
|
+
|
|
1
21
|
// src/sanitize.ts
|
|
2
22
|
function safeRegex(pattern, flags = "") {
|
|
3
23
|
try {
|
|
@@ -20,6 +40,8 @@ function compileRule(rule) {
|
|
|
20
40
|
case "strip-param": {
|
|
21
41
|
const paramPattern = safeRegex(`^(?:${rule.paramPattern})$`, "i");
|
|
22
42
|
if (!paramPattern) return null;
|
|
43
|
+
const valuePattern = rule.valuePattern ? safeRegex(`^(?:${rule.valuePattern})$`, "i") : null;
|
|
44
|
+
if (rule.valuePattern && !valuePattern) return null;
|
|
23
45
|
const urlPattern = rule.urlPattern ? safeRegex(rule.urlPattern, "i") : null;
|
|
24
46
|
if (rule.urlPattern && !urlPattern) return null;
|
|
25
47
|
return {
|
|
@@ -28,6 +50,7 @@ function compileRule(rule) {
|
|
|
28
50
|
provider: rule.provider,
|
|
29
51
|
urlPattern,
|
|
30
52
|
paramPattern,
|
|
53
|
+
valuePattern,
|
|
31
54
|
exceptions: compileExceptions(rule.exceptions),
|
|
32
55
|
isReferralMarketing: rule.isReferralMarketing ?? false
|
|
33
56
|
};
|
|
@@ -59,6 +82,10 @@ function compileRule(rule) {
|
|
|
59
82
|
urlPattern,
|
|
60
83
|
pattern,
|
|
61
84
|
captureGroup: rule.captureGroup,
|
|
85
|
+
matchPart: rule.matchPart ?? "url",
|
|
86
|
+
targetEncoding: rule.targetEncoding ?? "percent",
|
|
87
|
+
prependScheme: rule.prependScheme,
|
|
88
|
+
targetTemplate: rule.targetTemplate,
|
|
62
89
|
exceptions: compileExceptions(rule.exceptions)
|
|
63
90
|
};
|
|
64
91
|
}
|
|
@@ -82,6 +109,29 @@ function safeDecode(value) {
|
|
|
82
109
|
return value;
|
|
83
110
|
}
|
|
84
111
|
}
|
|
112
|
+
function safeBase64Decode(value) {
|
|
113
|
+
try {
|
|
114
|
+
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
115
|
+
const padded = normalized.padEnd(normalized.length + (4 - normalized.length % 4) % 4, "=");
|
|
116
|
+
const binary = globalThis.atob(padded);
|
|
117
|
+
const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
|
118
|
+
return new TextDecoder().decode(bytes);
|
|
119
|
+
} catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function templateTarget(template, match) {
|
|
124
|
+
return template.replace(/\$([1-9])/g, (_, index) => match[Number(index)] ?? "");
|
|
125
|
+
}
|
|
126
|
+
function targetWithPrependedScheme(target, scheme) {
|
|
127
|
+
if (!scheme) return target;
|
|
128
|
+
try {
|
|
129
|
+
new URL(target);
|
|
130
|
+
return target;
|
|
131
|
+
} catch {
|
|
132
|
+
return `${scheme}://${target.replace(/^\/+/, "")}`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
85
135
|
function matchesAny(url, patterns) {
|
|
86
136
|
return patterns.some((re) => re.test(url));
|
|
87
137
|
}
|
|
@@ -128,10 +178,22 @@ function compileSanitizer(catalog, options = {}) {
|
|
|
128
178
|
}
|
|
129
179
|
case "unwrap-redirect": {
|
|
130
180
|
if (!unwrapRedirects) continue;
|
|
131
|
-
|
|
132
|
-
|
|
181
|
+
let matchInput = current;
|
|
182
|
+
if (rule.matchPart === "pathname") {
|
|
183
|
+
try {
|
|
184
|
+
matchInput = new URL(current).pathname;
|
|
185
|
+
} catch {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const m = rule.pattern.exec(matchInput);
|
|
190
|
+
if (!m) continue;
|
|
191
|
+
const captured = rule.targetTemplate ? templateTarget(rule.targetTemplate, m) : m[rule.captureGroup];
|
|
133
192
|
if (typeof captured === "string" && captured.length > 0) {
|
|
134
|
-
const
|
|
193
|
+
const decodedTarget = rule.targetEncoding === "base64" ? safeBase64Decode(safeDecode(captured)) : safeDecode(captured);
|
|
194
|
+
if (!decodedTarget) continue;
|
|
195
|
+
const target = targetWithPrependedScheme(decodedTarget, rule.prependScheme);
|
|
196
|
+
if (!target) continue;
|
|
135
197
|
try {
|
|
136
198
|
const targetUrl = new URL(target);
|
|
137
199
|
return {
|
|
@@ -165,8 +227,8 @@ function compileSanitizer(catalog, options = {}) {
|
|
|
165
227
|
} catch {
|
|
166
228
|
continue;
|
|
167
229
|
}
|
|
168
|
-
const search = stripFromQueryString(urlObj.search, rule.paramPattern);
|
|
169
|
-
const hash = stripFromQueryString(urlObj.hash, rule.paramPattern);
|
|
230
|
+
const search = stripFromQueryString(urlObj.search, rule.paramPattern, rule.valuePattern);
|
|
231
|
+
const hash = stripFromQueryString(urlObj.hash, rule.paramPattern, rule.valuePattern);
|
|
170
232
|
const removed = [...search.removed, ...hash.removed];
|
|
171
233
|
if (removed.length === 0) continue;
|
|
172
234
|
urlObj.search = search.result;
|
|
@@ -193,7 +255,7 @@ function compileSanitizer(catalog, options = {}) {
|
|
|
193
255
|
};
|
|
194
256
|
};
|
|
195
257
|
}
|
|
196
|
-
function stripFromQueryString(searchOrHash, paramPattern) {
|
|
258
|
+
function stripFromQueryString(searchOrHash, paramPattern, valuePattern) {
|
|
197
259
|
if (!searchOrHash) return { result: searchOrHash, removed: [] };
|
|
198
260
|
const prefix = searchOrHash.charAt(0);
|
|
199
261
|
const body = prefix === "?" || prefix === "#" ? searchOrHash.slice(1) : searchOrHash;
|
|
@@ -204,7 +266,8 @@ function stripFromQueryString(searchOrHash, paramPattern) {
|
|
|
204
266
|
for (const pair of pairs) {
|
|
205
267
|
const eqIdx = pair.indexOf("=");
|
|
206
268
|
const name = eqIdx === -1 ? pair : pair.slice(0, eqIdx);
|
|
207
|
-
|
|
269
|
+
const value = eqIdx === -1 ? "" : pair.slice(eqIdx + 1);
|
|
270
|
+
if (paramPattern.test(name) && (!valuePattern || valuePattern.test(value))) {
|
|
208
271
|
removed.push(name);
|
|
209
272
|
} else {
|
|
210
273
|
kept.push(pair);
|
|
@@ -214,6 +277,193 @@ function stripFromQueryString(searchOrHash, paramPattern) {
|
|
|
214
277
|
if (kept.length === 0) return { result: "", removed };
|
|
215
278
|
return { result: prefix + kept.join("&"), removed };
|
|
216
279
|
}
|
|
280
|
+
|
|
281
|
+
// src/schemas.ts
|
|
282
|
+
var ruleSourceValues = ["clearurls", "adguard", "brave", "firefox", "custom"];
|
|
283
|
+
var ruleKindValues = ["strip-param", "raw-replace", "unwrap-redirect", "block-domain"];
|
|
284
|
+
var redirectMatchPartValues = ["url", "pathname"];
|
|
285
|
+
var redirectTargetEncodingValues = ["percent", "base64"];
|
|
286
|
+
var redirectPrependSchemeValues = ["http", "https"];
|
|
287
|
+
var catalogSourceSchema = {
|
|
288
|
+
type: "object",
|
|
289
|
+
required: ["name"],
|
|
290
|
+
additionalProperties: false,
|
|
291
|
+
properties: {
|
|
292
|
+
name: { enum: ruleSourceValues },
|
|
293
|
+
version: { type: "string" },
|
|
294
|
+
hash: { type: "string" },
|
|
295
|
+
license: { type: "string" },
|
|
296
|
+
upstream: { type: "string" }
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
var ruleBaseProperties = {
|
|
300
|
+
source: { enum: ruleSourceValues },
|
|
301
|
+
provider: { type: "string" },
|
|
302
|
+
urlPattern: { type: "string" },
|
|
303
|
+
exceptions: {
|
|
304
|
+
type: "array",
|
|
305
|
+
items: { type: "string" }
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
var matchedRuleSchema = {
|
|
309
|
+
type: "object",
|
|
310
|
+
required: ["source", "provider", "kind"],
|
|
311
|
+
additionalProperties: false,
|
|
312
|
+
properties: {
|
|
313
|
+
source: { enum: ruleSourceValues },
|
|
314
|
+
provider: { type: "string" },
|
|
315
|
+
kind: { enum: ruleKindValues },
|
|
316
|
+
detail: { type: "string" }
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
var sanitizerOptionsJsonSchema = {
|
|
320
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
321
|
+
$id: "https://url-sanitize.dev/schema/v1/options.json",
|
|
322
|
+
title: "url-sanitize options",
|
|
323
|
+
type: "object",
|
|
324
|
+
additionalProperties: false,
|
|
325
|
+
properties: {
|
|
326
|
+
stripReferralMarketing: { type: "boolean" },
|
|
327
|
+
unwrapRedirects: { type: "boolean" },
|
|
328
|
+
domainBlocking: { type: "boolean" }
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
var sanitizerCatalogJsonSchema = {
|
|
332
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
333
|
+
$id: "https://url-sanitize.dev/schema/v1/catalog.json",
|
|
334
|
+
title: "url-sanitize catalog",
|
|
335
|
+
type: "object",
|
|
336
|
+
required: ["version", "generatedAt", "sources", "rules"],
|
|
337
|
+
additionalProperties: false,
|
|
338
|
+
properties: {
|
|
339
|
+
version: { type: "string" },
|
|
340
|
+
generatedAt: { type: "string" },
|
|
341
|
+
sources: {
|
|
342
|
+
type: "array",
|
|
343
|
+
items: catalogSourceSchema
|
|
344
|
+
},
|
|
345
|
+
rules: {
|
|
346
|
+
type: "array",
|
|
347
|
+
items: {
|
|
348
|
+
oneOf: [
|
|
349
|
+
{
|
|
350
|
+
type: "object",
|
|
351
|
+
required: ["kind", "source", "provider", "paramPattern"],
|
|
352
|
+
additionalProperties: false,
|
|
353
|
+
properties: {
|
|
354
|
+
...ruleBaseProperties,
|
|
355
|
+
kind: { const: "strip-param" },
|
|
356
|
+
paramPattern: { type: "string" },
|
|
357
|
+
valuePattern: { type: "string" },
|
|
358
|
+
isReferralMarketing: { type: "boolean" }
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
type: "object",
|
|
363
|
+
required: ["kind", "source", "provider", "pattern", "replacement"],
|
|
364
|
+
additionalProperties: false,
|
|
365
|
+
properties: {
|
|
366
|
+
...ruleBaseProperties,
|
|
367
|
+
kind: { const: "raw-replace" },
|
|
368
|
+
pattern: { type: "string" },
|
|
369
|
+
replacement: { type: "string" }
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
type: "object",
|
|
374
|
+
required: ["kind", "source", "provider", "pattern", "captureGroup"],
|
|
375
|
+
additionalProperties: false,
|
|
376
|
+
properties: {
|
|
377
|
+
...ruleBaseProperties,
|
|
378
|
+
kind: { const: "unwrap-redirect" },
|
|
379
|
+
pattern: { type: "string" },
|
|
380
|
+
captureGroup: { type: "integer", minimum: 0 },
|
|
381
|
+
matchPart: { enum: redirectMatchPartValues },
|
|
382
|
+
targetEncoding: { enum: redirectTargetEncodingValues },
|
|
383
|
+
prependScheme: { enum: redirectPrependSchemeValues },
|
|
384
|
+
targetTemplate: { type: "string" }
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
type: "object",
|
|
389
|
+
required: ["kind", "source", "provider", "urlPattern"],
|
|
390
|
+
additionalProperties: false,
|
|
391
|
+
properties: {
|
|
392
|
+
...ruleBaseProperties,
|
|
393
|
+
kind: { const: "block-domain" }
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
]
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
var sanitizeResultJsonSchema = {
|
|
402
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
403
|
+
$id: "https://url-sanitize.dev/schema/v1/result.json",
|
|
404
|
+
title: "url-sanitize result",
|
|
405
|
+
oneOf: [
|
|
406
|
+
{
|
|
407
|
+
type: "object",
|
|
408
|
+
required: ["kind", "url"],
|
|
409
|
+
additionalProperties: false,
|
|
410
|
+
properties: {
|
|
411
|
+
kind: { const: "unchanged" },
|
|
412
|
+
url: { type: "string" }
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
type: "object",
|
|
417
|
+
required: ["kind", "original", "url", "strippedParams", "matchedRules"],
|
|
418
|
+
additionalProperties: false,
|
|
419
|
+
properties: {
|
|
420
|
+
kind: { const: "cleaned" },
|
|
421
|
+
original: { type: "string" },
|
|
422
|
+
url: { type: "string" },
|
|
423
|
+
strippedParams: {
|
|
424
|
+
type: "array",
|
|
425
|
+
items: { type: "string" }
|
|
426
|
+
},
|
|
427
|
+
matchedRules: {
|
|
428
|
+
type: "array",
|
|
429
|
+
items: matchedRuleSchema
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
type: "object",
|
|
435
|
+
required: ["kind", "original", "url", "via"],
|
|
436
|
+
additionalProperties: false,
|
|
437
|
+
properties: {
|
|
438
|
+
kind: { const: "redirected" },
|
|
439
|
+
original: { type: "string" },
|
|
440
|
+
url: { type: "string" },
|
|
441
|
+
via: matchedRuleSchema
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
type: "object",
|
|
446
|
+
required: ["kind", "original", "via"],
|
|
447
|
+
additionalProperties: false,
|
|
448
|
+
properties: {
|
|
449
|
+
kind: { const: "blocked" },
|
|
450
|
+
original: { type: "string" },
|
|
451
|
+
via: matchedRuleSchema
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
]
|
|
455
|
+
};
|
|
456
|
+
var urlSanitizeJsonSchemas = {
|
|
457
|
+
catalog: sanitizerCatalogJsonSchema,
|
|
458
|
+
options: sanitizerOptionsJsonSchema,
|
|
459
|
+
result: sanitizeResultJsonSchema
|
|
460
|
+
};
|
|
217
461
|
export {
|
|
218
|
-
compileSanitizer
|
|
462
|
+
compileSanitizer,
|
|
463
|
+
defineCatalog,
|
|
464
|
+
mergeCatalogs,
|
|
465
|
+
sanitizeResultJsonSchema,
|
|
466
|
+
sanitizerCatalogJsonSchema,
|
|
467
|
+
sanitizerOptionsJsonSchema,
|
|
468
|
+
urlSanitizeJsonSchemas
|
|
219
469
|
};
|