url-sanitizer 4.2.2 → 5.0.1

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.
@@ -4,7 +4,7 @@
4
4
 
5
5
  /* shared */
6
6
  import textChars from '../lib/file/text-chars.json' with { type: 'json' };
7
- import { HEX } from './constant.js';
7
+ import { BYTE_RANGE, HEX } from './constant.js';
8
8
 
9
9
  /**
10
10
  * A set of valid text character codes.
@@ -47,13 +47,13 @@ export const WINDOWS1252_TO_UNICODE = new Map([
47
47
  ]);
48
48
 
49
49
  /**
50
- * Generates control character codes in hex.
50
+ * Generates hexadecimal escape strings for non-text characters.
51
51
  * @private
52
52
  * @returns {Map<number, string>} Generated control char codes.
53
53
  */
54
- const generateCtrlCharCodes = () => {
54
+ const generateNonTextCharCodes = () => {
55
55
  const charCodes = new Map();
56
- for (let i = 0; i < HEX * HEX; i++) {
56
+ for (let i = 0; i < BYTE_RANGE; i++) {
57
57
  if (!TEXT_CHAR_CODES.has(i) && !WINDOWS1252_TO_UNICODE.has(i)) {
58
58
  charCodes.set(i, `\\x${i.toString(HEX).padStart(2, '0').toUpperCase()}`);
59
59
  }
@@ -62,7 +62,7 @@ const generateCtrlCharCodes = () => {
62
62
  };
63
63
 
64
64
  /**
65
- * A mapping of control character codes to their hexadecimal escape strings.
65
+ * A mapping of non-text character codes to their hexadecimal escape strings.
66
66
  * @type {Map<number, string>}
67
67
  */
68
- export const CTRL_CHAR_CODES = generateCtrlCharCodes();
68
+ export const NON_TEXT_CHAR_CODES = generateNonTextCharCodes();
@@ -7,8 +7,15 @@ import uriSchemes from '../lib/iana/uri-schemes.json' with { type: 'json' };
7
7
  import { getType, isString } from './common.js';
8
8
 
9
9
  /* constants */
10
- import { CHUNK_SIZE, DECI, HEX, MAX_BLOB_SIZE, MAX_NEST } from './constant.js';
11
10
  import {
11
+ BYTE_RANGE,
12
+ DECI,
13
+ HEX,
14
+ MAX_NEST,
15
+ TRUNCATE_LENGTH
16
+ } from './constant.js';
17
+ import {
18
+ REG_AMP,
12
19
  REG_HASH,
13
20
  REG_NUM_REF,
14
21
  REG_PCT_ENC,
@@ -18,7 +25,7 @@ import {
18
25
  REG_URL_ENC
19
26
  } from './regexp.js';
20
27
  import {
21
- CTRL_CHAR_CODES,
28
+ NON_TEXT_CHAR_CODES,
22
29
  TEXT_CHAR_CODES,
23
30
  WINDOWS1252_TO_UNICODE
24
31
  } from './text-chars.js';
@@ -38,15 +45,13 @@ const ESCAPE_MAP = {
38
45
  [ENC_APOS]: `${ENC_AMP}${ENC_NUM}39;`
39
46
  };
40
47
  const HEX_TABLE = Array.from(
41
- { length: HEX * HEX },
48
+ { length: BYTE_RANGE },
42
49
  (_, i) => `%${i.toString(HEX).padStart(2, '0').toUpperCase()}`
43
50
  );
44
51
  const IS_NODE = globalThis.process?.versions?.node !== undefined;
45
- const REG_BINARY = new RegExp(`[${[...CTRL_CHAR_CODES.values()].join('')}]`);
46
- const REG_CTRL_CHARS = new RegExp(
47
- `[${[...CTRL_CHAR_CODES.values()].join('')}]`,
48
- 'g'
49
- );
52
+ const NON_TEXT_PATTERN = `[${[...NON_TEXT_CHAR_CODES.values()].join('')}]`;
53
+ const REG_NON_TEXT = new RegExp(NON_TEXT_PATTERN);
54
+ const REG_NON_TEXT_G = new RegExp(NON_TEXT_PATTERN, 'g');
50
55
 
51
56
  /* encoder / decoder */
52
57
  const encoder = new TextEncoder();
@@ -70,43 +75,128 @@ export class URISchemes {
70
75
  return [...this.#schemes];
71
76
  }
72
77
 
78
+ /**
79
+ * Extracts the scheme from URI.
80
+ * @param {string} uri - The URI string.
81
+ * @returns {string|null} The extracted scheme, or null.
82
+ */
83
+ getScheme(uri) {
84
+ if (!isString(uri)) {
85
+ return null;
86
+ }
87
+ const parsed = this.parse(uri);
88
+ if (parsed) {
89
+ return parsed.protocol.replace(/:$/, '');
90
+ }
91
+ return null;
92
+ }
93
+
73
94
  /**
74
95
  * Checks if the specified scheme is currently registered.
75
96
  * @param {string} scheme - The target scheme.
76
97
  * @returns {boolean} True if the scheme is registered.
77
98
  */
78
99
  has(scheme) {
79
- if (!isString(scheme)) {
80
- return false;
100
+ const normalized = this.normalize(scheme, true);
101
+ if (normalized) {
102
+ return this.#schemes.has(normalized);
103
+ }
104
+ return false;
105
+ }
106
+
107
+ /**
108
+ * Normalizes the URI string using NFKC.
109
+ * @param {string} uri - The URL to normalize.
110
+ * @param {boolean} [isScheme] - True if uri is a scheme.
111
+ * @returns {string|null} The normalized URI string, or null.
112
+ */
113
+ normalize(uri, isScheme = false) {
114
+ if (!isString(uri)) {
115
+ return null;
81
116
  }
82
- return this.#schemes.has(scheme.trim().toLowerCase());
117
+ const normalized = uri.normalize('NFKC');
118
+ if (isScheme) {
119
+ return normalized.trim().toLowerCase();
120
+ }
121
+ return normalized;
122
+ }
123
+
124
+ /**
125
+ * Parse the URI string.
126
+ * @param {string} uri - The URI string.
127
+ * @param {string} [base] - The base URI string.
128
+ * @returns {URL|null} The parsed URL object, or null.
129
+ */
130
+ parse(uri, base) {
131
+ if (!isString(uri)) {
132
+ return null;
133
+ }
134
+ const normalized = this.normalize(uri);
135
+ if (base && isString(base)) {
136
+ return URL.parse(normalized, this.normalize(base));
137
+ }
138
+ return URL.parse(normalized);
83
139
  }
84
140
 
85
141
  /**
86
142
  * Verifies if the given URI is valid and its scheme is allowed.
87
143
  * @param {string} uri - The URI string to verify.
88
144
  * @param {Set<string>} [schemes] - The set of allowed schemes.
89
- * @returns {boolean} True if the URI is syntactically valid and permitted.
145
+ * @returns {boolean} True if the URI is valid and permitted.
90
146
  */
91
- verify(uri, schemes = this.#schemes) {
147
+ verify(uri, schemes) {
92
148
  if (!isString(uri)) {
93
149
  return false;
94
150
  }
95
- const normalizedUri = uri.normalize('NFKC');
96
- const parsedUrl = URL.parse(normalizedUri);
97
- if (!parsedUrl) {
151
+ const parsedUrl = this.parse(uri);
152
+ return this.verifyParsed(parsedUrl, schemes, true);
153
+ }
154
+
155
+ /**
156
+ * Verifies if the pre-parsed URL object is valid and its scheme is allowed.
157
+ * @param {URL} parsedUrl - The parsed URL object to verify.
158
+ * @param {Set<string>} [schemes] - The set of allowed schemes.
159
+ * @param {boolean} [allowCustom] - True if web+*, ext+* schemes are allowed.
160
+ * @returns {boolean} True if the parsed URL is valid and permitted.
161
+ */
162
+ verifyParsed(parsedUrl, schemes, allowCustom = false) {
163
+ if (!parsedUrl || !parsedUrl.protocol) {
98
164
  return false;
99
165
  }
100
- const scheme = parsedUrl.protocol.replace(/:$/, '');
166
+ const scheme = parsedUrl.protocol.toLowerCase().replace(/:$/, '');
101
167
  const parts = scheme.split('+');
102
168
  const isScript = parts.some(s => REG_SCRIPT.test(s));
103
169
  if (isScript) {
104
170
  return false;
105
171
  }
106
- return REG_SCHEME_EXT.test(scheme) || parts.every(s => schemes.has(s));
172
+ if (!schemes) {
173
+ schemes = this.#schemes;
174
+ }
175
+ if (schemes.has(scheme)) {
176
+ return true;
177
+ }
178
+ if (parts.length > 1) {
179
+ return (
180
+ (allowCustom && REG_SCHEME_EXT.test(scheme)) ||
181
+ parts.every(s => schemes.has(s))
182
+ );
183
+ }
184
+ return false;
107
185
  }
108
186
  }
109
187
 
188
+ /**
189
+ * Extracts an array of schemes.
190
+ * @param {string} protocol - The URL protocol (e.g., "data:", "git+https:").
191
+ * @returns {string[]} An array of scheme parts.
192
+ */
193
+ export const getSchemeParts = protocol => {
194
+ if (!isString(protocol)) {
195
+ return [];
196
+ }
197
+ return protocol.replace(/:$/, '').split('+');
198
+ };
199
+
110
200
  /**
111
201
  * Gets the URL-encoded representation of a given string.
112
202
  * @param {string} str - The target string.
@@ -117,11 +207,11 @@ export const getURLEncodedString = str => {
117
207
  throw new TypeError(`Expected String but got ${getType(str)}.`);
118
208
  }
119
209
  const bytes = encoder.encode(str);
120
- let encoded = '';
210
+ const encoded = new Array(bytes.length);
121
211
  for (let i = 0; i < bytes.length; i++) {
122
- encoded += HEX_TABLE[bytes[i]];
212
+ encoded[i] = HEX_TABLE[bytes[i]];
123
213
  }
124
- return encoded;
214
+ return encoded.join('');
125
215
  };
126
216
 
127
217
  /**
@@ -129,7 +219,6 @@ export const getURLEncodedString = str => {
129
219
  * @param {string} ch - A URL-encoded (percent-encoded) character.
130
220
  * @returns {string} The escaped HTML special character, or the given character.
131
221
  */
132
-
133
222
  export const escapeURLEncodedHTMLChars = ch => {
134
223
  if (!isString(ch)) {
135
224
  return ch;
@@ -139,65 +228,15 @@ export const escapeURLEncodedHTMLChars = ch => {
139
228
  };
140
229
 
141
230
  /**
142
- * Parses base64-encoded data.
143
- * @param {string} data - The base64-encoded string.
144
- * @returns {string} The parsed text, or the original base64 if binary.
145
- */
146
- export const parseBase64 = data => {
147
- if (!isString(data)) {
148
- throw new TypeError(`Expected String but got ${getType(data)}.`);
149
- }
150
- const cleanData = data.replace(/\s/g, '');
151
- let binStr;
152
- try {
153
- binStr = atob(cleanData);
154
- } catch {
155
- throw new Error(`Invalid base64 data: ${data}`);
156
- }
157
- let bytes;
158
- if (IS_NODE && globalThis.Buffer) {
159
- // Use 'latin1' to correctly map the binary string directly to bytes.
160
- // @see https://nodejs.org/docs/latest/api/buffer.html#buffers-and-character-encodings
161
- bytes = globalThis.Buffer.from(binStr, 'latin1');
162
- } else {
163
- const len = binStr.length;
164
- bytes = new Uint8Array(len);
165
- for (let i = 0; i < len; i++) {
166
- bytes[i] = binStr.charCodeAt(i);
167
- }
168
- }
169
- try {
170
- const text = decoder.decode(bytes);
171
- if (REG_BINARY.test(text)) {
172
- return cleanData;
173
- }
174
- return text;
175
- } catch {
176
- return cleanData;
177
- }
178
- };
179
-
180
- /**
181
- * Replaces URL-encoded numeric character references.
182
- * @param {string} match - The matched substring.
183
- * @param {string} value - The captured numeric value.
184
- * @returns {string} The resolved character or the original match.
231
+ * Truncate URL string.
232
+ * @param {string|unknown} url - A URL string
233
+ * @returns {string} - The truncated string
185
234
  */
186
- export const replaceNumCharRef = (match, value) => {
187
- const num = /x/i.test(value[0])
188
- ? parseInt(value.substring(1), HEX)
189
- : parseInt(value, DECI);
190
- if (Number.isInteger(num)) {
191
- if (TEXT_CHAR_CODES.has(num)) {
192
- return String.fromCharCode(num);
193
- } else if (WINDOWS1252_TO_UNICODE.has(num)) {
194
- const codePoint = WINDOWS1252_TO_UNICODE.get(num);
195
- return String.fromCodePoint(codePoint);
196
- } else if (CTRL_CHAR_CODES.has(num)) {
197
- return '';
198
- }
199
- }
200
- return match;
235
+ export const truncateURL = url => {
236
+ const str = isString(url) ? url : String(url);
237
+ const truncated =
238
+ str.length > TRUNCATE_LENGTH ? `${str.slice(0, TRUNCATE_LENGTH)}...` : str;
239
+ return truncated;
201
240
  };
202
241
 
203
242
  /**
@@ -213,7 +252,30 @@ export const trimTrailingEmptyQueryAndHash = url => {
213
252
  };
214
253
 
215
254
  /**
216
- * Parses URL-encoded numeric character references in the range 0x00 to 0xFF.
255
+ * Replaces URL-encoded numeric character references.
256
+ * @param {string} match - The matched substring.
257
+ * @param {string} value - The captured numeric value.
258
+ * @returns {string} The resolved character or the original match.
259
+ */
260
+ export const replaceNumCharRef = (match, value) => {
261
+ const num = /^x/i.test(value)
262
+ ? Number.parseInt(value.slice(1), HEX)
263
+ : Number.parseInt(value, DECI);
264
+ if (!Number.isInteger(num) || num < 0 || num >= BYTE_RANGE) {
265
+ return match;
266
+ }
267
+ if (NON_TEXT_CHAR_CODES.has(num)) {
268
+ return '';
269
+ }
270
+ if (TEXT_CHAR_CODES.has(num)) {
271
+ return String.fromCharCode(num);
272
+ }
273
+ const codePoint = WINDOWS1252_TO_UNICODE.get(num);
274
+ return String.fromCodePoint(codePoint);
275
+ };
276
+
277
+ /**
278
+ * Parses URL-encoded numeric character references.
217
279
  * @param {string} str - The target string to parse.
218
280
  * @param {number} [nest] - The current nesting depth for recursive parsing.
219
281
  * @returns {string} The decoded and parsed string.
@@ -238,84 +300,84 @@ export const parseURLEncodedNumCharRef = (str, nest = 0) => {
238
300
  }
239
301
  });
240
302
  }
241
- res = res.replace(REG_CTRL_CHARS, '');
303
+ res = res.replace(REG_NON_TEXT_G, '');
242
304
  let depth = 0;
243
- for (; depth + nest <= MAX_NEST; depth++) {
305
+ for (; depth + nest < MAX_NEST; depth++) {
244
306
  const previousRes = res;
245
307
  // Decode '&amp;' before decoding numeric references.
246
- res = res.replace(/&amp;/gi, '&').replace(REG_NUM_REF, replaceNumCharRef);
308
+ res = res.replace(REG_AMP, '&').replace(REG_NUM_REF, replaceNumCharRef);
247
309
  if (res === previousRes) {
248
310
  break;
249
311
  }
250
312
  }
251
- if (depth + nest > MAX_NEST && /&#/.test(res)) {
313
+ if (depth + nest >= MAX_NEST && /&#/.test(res)) {
252
314
  throw new Error('Character references nested too deeply.');
253
315
  }
254
316
  return res;
255
317
  };
256
318
 
257
319
  /**
258
- * Converts Blob to data URL from Buffer.
259
- * @private
260
- * @param {Blob} blob - The target Blob object.
261
- * @returns {Promise<string|null>} A promise resolving to the data URL, or null.
262
- */
263
- const convertFromBuffer = async blob => {
264
- const mimeStr = blob.type ? `${blob.type};base64` : 'base64';
265
- const buffer = await blob.arrayBuffer();
266
- const base64 = globalThis.Buffer.from(buffer).toString('base64');
267
- return `data:${mimeStr},${base64}`;
268
- };
269
-
270
- /**
271
- * Converts Blob to data URL from FileReader.
272
- * @private
273
- * @param {Blob} blob - The target Blob object.
274
- * @returns {Promise<string|null>} A promise resolving to the data URL, or null.
320
+ * Extracts the components of a parsed Data URL.
321
+ * @param {string} pathname - The pathname of the URL.
322
+ * @param {string} [search] - The search (query) string of the URL.
323
+ * @param {string} [hash] - The hash (fragment) of the URL.
324
+ * @returns {object} An object containing the media type, parsed media types array, data string, and a boolean indicating if it is base64-encoded.
275
325
  */
276
- const convertFromFileReader = blob =>
277
- new Promise((resolve, reject) => {
278
- const reader = new globalThis.FileReader();
279
- reader.addEventListener('error', () => reject(reader.error));
280
- reader.addEventListener('abort', () => resolve(null));
281
- reader.addEventListener('load', () => resolve(reader.result));
282
- reader.readAsDataURL(blob);
283
- });
284
-
285
- /**
286
- * Converts Blob to data URL from btoa.
287
- * @private
288
- * @param {Blob} blob - The target Blob object.
289
- * @returns {Promise<string|null>} A promise resolving to the data URL, or null.
290
- */
291
- const convertFromBtoa = async blob => {
292
- const mimeStr = blob.type ? `${blob.type};base64` : 'base64';
293
- const buffer = await blob.arrayBuffer();
294
- const uint8arr = new Uint8Array(buffer);
295
- const chunks = [];
296
- for (let i = 0; i < uint8arr.length; i += CHUNK_SIZE) {
297
- chunks.push(String.fromCharCode(...uint8arr.subarray(i, i + CHUNK_SIZE)));
326
+ export const extractDataUrlComponents = (pathname, search = '', hash = '') => {
327
+ if (!isString(pathname)) {
328
+ return { mediaType: '', mediaTypes: [], data: '', isBase64: false };
329
+ }
330
+ const comma = pathname.indexOf(',');
331
+ if (comma === -1) {
332
+ return {
333
+ mediaType: pathname,
334
+ mediaTypes: pathname.split(';'),
335
+ data: '',
336
+ isBase64: false
337
+ };
298
338
  }
299
- return `data:${mimeStr},${btoa(chunks.join(''))}`;
339
+ const mediaType = pathname.slice(0, comma);
340
+ const data = `${pathname.slice(comma + 1)}${search}${hash}`;
341
+ const mediaTypes = mediaType.split(';');
342
+ const isBase64 = /^base64$/i.test(mediaTypes.at(-1));
343
+ return { mediaType, mediaTypes, data, isBase64 };
300
344
  };
301
345
 
302
346
  /**
303
- * Converts a Blob to a data URL.
304
- * @param {Blob} blob - The target Blob object.
305
- * @param {number} [maxSize] - The maximum allowed blob size.
306
- * @returns {Promise<string|null>} A promise resolving to the data URL, or null.
347
+ * Parses base64-encoded data.
348
+ * @param {string} data - The base64-encoded string.
349
+ * @returns {string} The parsed text, or the original base64 if binary.
307
350
  */
308
- export const convertBlobToDataURL = async (blob, maxSize = MAX_BLOB_SIZE) => {
309
- if (!Number.isInteger(blob?.size)) {
310
- return null;
311
- } else if (Number.isInteger(maxSize) && blob.size > maxSize) {
312
- const msg = `Blob size (${blob.size} bytes) exceeds max (${maxSize} bytes).`;
313
- throw new DOMException(msg, 'NotReadableError');
351
+ export const parseBase64 = data => {
352
+ if (!isString(data)) {
353
+ throw new TypeError(`Expected String but got ${getType(data)}.`);
314
354
  }
355
+ const cleanData = data.replace(/\s/g, '');
356
+ let binStr;
357
+ try {
358
+ binStr = atob(cleanData);
359
+ } catch {
360
+ throw new Error(`Invalid base64 data: ${truncateURL(data)}`);
361
+ }
362
+ let bytes;
315
363
  if (IS_NODE && globalThis.Buffer) {
316
- return convertFromBuffer(blob);
317
- } else if (globalThis.FileReader) {
318
- return convertFromFileReader(blob);
364
+ // Use 'latin1' to correctly map the binary string directly to bytes.
365
+ // @see https://nodejs.org/docs/latest/api/buffer.html#buffers-and-character-encodings
366
+ bytes = globalThis.Buffer.from(binStr, 'latin1');
367
+ } else {
368
+ const len = binStr.length;
369
+ bytes = new Uint8Array(len);
370
+ for (let i = 0; i < len; i++) {
371
+ bytes[i] = binStr.charCodeAt(i);
372
+ }
373
+ }
374
+ try {
375
+ const text = decoder.decode(bytes);
376
+ if (REG_NON_TEXT.test(text)) {
377
+ return cleanData;
378
+ }
379
+ return text;
380
+ } catch {
381
+ return cleanData;
319
382
  }
320
- return convertFromBtoa(blob);
321
383
  };
package/types/index.d.ts CHANGED
@@ -5,4 +5,4 @@
5
5
  * @copyright asamuzaK (Kazz)
6
6
  * @see {@link https://github.com/asamuzaK/urlSanitizer/blob/main/LICENSE}
7
7
  */
8
- export { default, inspectURL, inspectURLSync, isURI, isURISync, parseURL, parseURLSync, sanitizeURL, sanitizeURLSync } from './mjs/sanitizer.js';
8
+ export { default, inspectURL, isURISync, isValidURI, sanitizeURL, sanitizeURLSync } from './mjs/sanitizer.js';
@@ -1,7 +1,10 @@
1
+ export declare const BYTE_RANGE: number;
1
2
  export declare const CHUNK_SIZE: number;
2
3
  export declare const DECI: number;
3
4
  export declare const HEX: number;
4
5
  export declare const MAX_BLOB_SIZE: number;
5
6
  export declare const MAX_NEST: number;
7
+ export declare const MAX_URL_LENGTH: number;
8
+ export declare const TRUNCATE_LENGTH: number;
6
9
  export declare const TYPE_FROM: number;
7
10
  export declare const TYPE_TO: number;
@@ -7,9 +7,10 @@ export declare const REG_QUERY: RegExp;
7
7
  export declare const REG_SCHEME: RegExp;
8
8
  export declare const REG_SCHEME_EXT: RegExp;
9
9
  export declare const REG_SCRIPT: RegExp;
10
- export declare const REG_SCRIPT_BLOB: RegExp;
10
+ export declare const REG_SCRIPT_OR_BLOB: RegExp;
11
11
  export declare const REG_TAG_QUOT: RegExp;
12
12
  export declare const REG_URL_ENC: RegExp;
13
- export declare const REG_AMP_ENC: RegExp;
14
13
  export declare const REG_PCT_ENC: RegExp;
14
+ export declare const REG_AMP: RegExp;
15
+ export declare const REG_AMP_ENC: RegExp;
15
16
  export declare const REG_VERIFY_RELATIVE: RegExp;
@@ -7,6 +7,7 @@ export type InspectedDataURL = {
7
7
  export type InspectedURLResult = {
8
8
  input: string;
9
9
  valid: boolean;
10
+ relative?: boolean;
10
11
  reason?: string;
11
12
  data?: InspectedDataURL | null;
12
13
  href?: string;
@@ -21,18 +22,30 @@ export type InspectedURLResult = {
21
22
  search?: string;
22
23
  hash?: string;
23
24
  };
24
- export declare const logDebug: (isDebug: boolean, message: string, error?: Error) => void;
25
- declare class URLSanitizer extends URISchemes {
25
+ export declare const logDebug: (message: string, error?: Error) => void;
26
+ export declare class SanitizeContext {
27
+ debug: boolean;
28
+ domPurify: object;
29
+ nest: number;
30
+ recurse: Set<any>;
31
+ schemeMap: Map<string, boolean>;
32
+ constructor(opt: object, domPurifyInstance: object);
33
+ enter(url: string): boolean;
34
+ leave(url: string): void;
35
+ }
36
+ export declare class URLSanitizer extends URISchemes {
26
37
  #private;
27
- private static #uponSanitizeAttribute;
28
38
  constructor();
29
- private #registerScheme;
30
- private #purify;
39
+ private #executeSanitize;
31
40
  private #process;
32
41
  private #resolveSchemeRules;
42
+ private #registerScheme;
43
+ private #isValidScheme;
33
44
  private #parseAndVerifyURL;
34
45
  private #isSchemeAllowed;
35
46
  private #sanitizeDataURL;
47
+ private #purify;
48
+ private #handleSanitizeAttribute;
36
49
  private #sanitizeStandardURL;
37
50
  sanitize(url: string, opt?: {
38
51
  allow?: string[];
@@ -43,7 +56,7 @@ declare class URLSanitizer extends URISchemes {
43
56
  maxBlobSize?: number;
44
57
  maxLength?: number;
45
58
  }): string | null;
46
- inspect(url: string, opt?: object): InspectedURLResult;
59
+ inspect(url: string): InspectedURLResult;
47
60
  get(): string[];
48
61
  has(scheme: string): boolean;
49
62
  add(scheme: string): string[];
@@ -51,7 +64,6 @@ declare class URLSanitizer extends URISchemes {
51
64
  reset(): void;
52
65
  verify(uri: string, schemes?: Set<string>): boolean;
53
66
  }
54
- export { URLSanitizer };
55
67
  declare const urlSanitizer: URLSanitizer;
56
68
  export declare const sanitizeURL: (url: string, opt?: {
57
69
  allow?: string[];
@@ -73,9 +85,6 @@ export declare const sanitizeURLSync: (url: string, opt?: {
73
85
  maxLength?: number;
74
86
  }) => string | null;
75
87
  export declare const inspectURL: (url: string) => Promise<InspectedURLResult>;
76
- export declare const parseURL: (url: string) => Promise<InspectedURLResult>;
77
- export declare const inspectURLSync: (url: string) => InspectedURLResult;
78
- export declare const parseURLSync: (url: string) => InspectedURLResult;
79
- export declare const isURI: (uri: string) => Promise<boolean>;
88
+ export declare const isValidURI: (uri: string) => boolean;
80
89
  export declare const isURISync: (uri: string) => boolean;
81
90
  export default urlSanitizer;
@@ -1,3 +1,3 @@
1
1
  export declare const TEXT_CHAR_CODES: Set<number>;
2
2
  export declare const WINDOWS1252_TO_UNICODE: Map<number, number>;
3
- export declare const CTRL_CHAR_CODES: Map<number, string>;
3
+ export declare const NON_TEXT_CHAR_CODES: Map<number, string>;
@@ -1,13 +1,19 @@
1
1
  export declare class URISchemes {
2
2
  #private;
3
3
  get(): string[];
4
+ getScheme(uri: string): string | null;
4
5
  has(scheme: string): boolean;
6
+ normalize(uri: string, isScheme?: boolean): string | null;
7
+ parse(uri: string, base?: string): URL | null;
5
8
  verify(uri: string, schemes?: Set<string>): boolean;
9
+ verifyParsed(parsedUrl: URL, schemes?: Set<string>, allowCustom?: boolean): boolean;
6
10
  }
11
+ export declare const getSchemeParts: (protocol: string) => string[];
7
12
  export declare const getURLEncodedString: (str: string) => string;
8
13
  export declare const escapeURLEncodedHTMLChars: (ch: string) => string;
9
- export declare const parseBase64: (data: string) => string;
10
- export declare const replaceNumCharRef: (match: string, value: string) => string;
14
+ export declare const truncateURL: (url: string | unknown) => string;
11
15
  export declare const trimTrailingEmptyQueryAndHash: (url: string) => string;
16
+ export declare const replaceNumCharRef: (match: string, value: string) => string;
12
17
  export declare const parseURLEncodedNumCharRef: (str: string, nest?: number) => string;
13
- export declare const convertBlobToDataURL: (blob: Blob, maxSize?: number) => Promise<string | null>;
18
+ export declare const extractDataUrlComponents: (pathname: string, search?: string, hash?: string) => object;
19
+ export declare const parseBase64: (data: string) => string;