url-sanitizer 4.2.2 → 5.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.
@@ -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,122 @@ 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);
81
103
  }
82
- return this.#schemes.has(scheme.trim().toLowerCase());
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;
116
+ }
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);
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
+ * @returns {boolean} True if the parsed URL is valid and permitted.
160
+ */
161
+ verifyParsed(parsedUrl, schemes) {
162
+ if (!parsedUrl || !parsedUrl.protocol) {
98
163
  return false;
99
164
  }
100
- const scheme = parsedUrl.protocol.replace(/:$/, '');
165
+ const scheme = parsedUrl.protocol.toLowerCase().replace(/:$/, '');
101
166
  const parts = scheme.split('+');
102
167
  const isScript = parts.some(s => REG_SCRIPT.test(s));
103
168
  if (isScript) {
104
169
  return false;
105
170
  }
106
- return REG_SCHEME_EXT.test(scheme) || parts.every(s => schemes.has(s));
171
+ if (!schemes) {
172
+ schemes = this.#schemes;
173
+ }
174
+ return (
175
+ schemes.has(scheme) ||
176
+ REG_SCHEME_EXT.test(scheme) ||
177
+ parts.every(s => schemes.has(s))
178
+ );
107
179
  }
108
180
  }
109
181
 
182
+ /**
183
+ * Extracts an array of schemes.
184
+ * @param {string} protocol - The URL protocol (e.g., "data:", "git+https:").
185
+ * @returns {string[]} An array of scheme parts.
186
+ */
187
+ export const getSchemeParts = protocol => {
188
+ if (!isString(protocol)) {
189
+ return [];
190
+ }
191
+ return protocol.replace(/:$/, '').split('+');
192
+ };
193
+
110
194
  /**
111
195
  * Gets the URL-encoded representation of a given string.
112
196
  * @param {string} str - The target string.
@@ -117,11 +201,11 @@ export const getURLEncodedString = str => {
117
201
  throw new TypeError(`Expected String but got ${getType(str)}.`);
118
202
  }
119
203
  const bytes = encoder.encode(str);
120
- let encoded = '';
204
+ const encoded = new Array(bytes.length);
121
205
  for (let i = 0; i < bytes.length; i++) {
122
- encoded += HEX_TABLE[bytes[i]];
206
+ encoded[i] = HEX_TABLE[bytes[i]];
123
207
  }
124
- return encoded;
208
+ return encoded.join('');
125
209
  };
126
210
 
127
211
  /**
@@ -129,7 +213,6 @@ export const getURLEncodedString = str => {
129
213
  * @param {string} ch - A URL-encoded (percent-encoded) character.
130
214
  * @returns {string} The escaped HTML special character, or the given character.
131
215
  */
132
-
133
216
  export const escapeURLEncodedHTMLChars = ch => {
134
217
  if (!isString(ch)) {
135
218
  return ch;
@@ -139,65 +222,15 @@ export const escapeURLEncodedHTMLChars = ch => {
139
222
  };
140
223
 
141
224
  /**
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.
225
+ * Truncate URL string.
226
+ * @param {string|unknown} url - A URL string
227
+ * @returns {string} - The truncated string
185
228
  */
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;
229
+ export const truncateURL = url => {
230
+ const str = isString(url) ? url : String(url);
231
+ const truncated =
232
+ str.length > TRUNCATE_LENGTH ? `${str.slice(0, TRUNCATE_LENGTH)}...` : str;
233
+ return truncated;
201
234
  };
202
235
 
203
236
  /**
@@ -213,7 +246,30 @@ export const trimTrailingEmptyQueryAndHash = url => {
213
246
  };
214
247
 
215
248
  /**
216
- * Parses URL-encoded numeric character references in the range 0x00 to 0xFF.
249
+ * Replaces URL-encoded numeric character references.
250
+ * @param {string} match - The matched substring.
251
+ * @param {string} value - The captured numeric value.
252
+ * @returns {string} The resolved character or the original match.
253
+ */
254
+ export const replaceNumCharRef = (match, value) => {
255
+ const num = /^x/i.test(value)
256
+ ? Number.parseInt(value.slice(1), HEX)
257
+ : Number.parseInt(value, DECI);
258
+ if (!Number.isInteger(num) || num < 0 || num >= BYTE_RANGE) {
259
+ return match;
260
+ }
261
+ if (NON_TEXT_CHAR_CODES.has(num)) {
262
+ return '';
263
+ }
264
+ if (TEXT_CHAR_CODES.has(num)) {
265
+ return String.fromCharCode(num);
266
+ }
267
+ const codePoint = WINDOWS1252_TO_UNICODE.get(num);
268
+ return String.fromCodePoint(codePoint);
269
+ };
270
+
271
+ /**
272
+ * Parses URL-encoded numeric character references.
217
273
  * @param {string} str - The target string to parse.
218
274
  * @param {number} [nest] - The current nesting depth for recursive parsing.
219
275
  * @returns {string} The decoded and parsed string.
@@ -238,84 +294,84 @@ export const parseURLEncodedNumCharRef = (str, nest = 0) => {
238
294
  }
239
295
  });
240
296
  }
241
- res = res.replace(REG_CTRL_CHARS, '');
297
+ res = res.replace(REG_NON_TEXT_G, '');
242
298
  let depth = 0;
243
- for (; depth + nest <= MAX_NEST; depth++) {
299
+ for (; depth + nest < MAX_NEST; depth++) {
244
300
  const previousRes = res;
245
301
  // Decode '&amp;' before decoding numeric references.
246
- res = res.replace(/&amp;/gi, '&').replace(REG_NUM_REF, replaceNumCharRef);
302
+ res = res.replace(REG_AMP, '&').replace(REG_NUM_REF, replaceNumCharRef);
247
303
  if (res === previousRes) {
248
304
  break;
249
305
  }
250
306
  }
251
- if (depth + nest > MAX_NEST && /&#/.test(res)) {
307
+ if (depth + nest >= MAX_NEST && /&#/.test(res)) {
252
308
  throw new Error('Character references nested too deeply.');
253
309
  }
254
310
  return res;
255
311
  };
256
312
 
257
313
  /**
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.
275
- */
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.
314
+ * Extracts the components of a parsed Data URL.
315
+ * @param {string} pathname - The pathname of the URL.
316
+ * @param {string} [search] - The search (query) string of the URL.
317
+ * @param {string} [hash] - The hash (fragment) of the URL.
318
+ * @returns {object} An object containing the media type, parsed media types array, data string, and a boolean indicating if it is base64-encoded.
290
319
  */
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)));
320
+ export const extractDataUrlComponents = (pathname, search = '', hash = '') => {
321
+ if (!isString(pathname)) {
322
+ return { mediaType: '', mediaTypes: [], data: '', isBase64: false };
323
+ }
324
+ const comma = pathname.indexOf(',');
325
+ if (comma === -1) {
326
+ return {
327
+ mediaType: pathname,
328
+ mediaTypes: pathname.split(';'),
329
+ data: '',
330
+ isBase64: false
331
+ };
298
332
  }
299
- return `data:${mimeStr},${btoa(chunks.join(''))}`;
333
+ const mediaType = pathname.slice(0, comma);
334
+ const data = `${pathname.slice(comma + 1)}${search}${hash}`;
335
+ const mediaTypes = mediaType.split(';');
336
+ const isBase64 = /^base64$/i.test(mediaTypes.at(-1));
337
+ return { mediaType, mediaTypes, data, isBase64 };
300
338
  };
301
339
 
302
340
  /**
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.
341
+ * Parses base64-encoded data.
342
+ * @param {string} data - The base64-encoded string.
343
+ * @returns {string} The parsed text, or the original base64 if binary.
307
344
  */
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');
345
+ export const parseBase64 = data => {
346
+ if (!isString(data)) {
347
+ throw new TypeError(`Expected String but got ${getType(data)}.`);
314
348
  }
349
+ const cleanData = data.replace(/\s/g, '');
350
+ let binStr;
351
+ try {
352
+ binStr = atob(cleanData);
353
+ } catch {
354
+ throw new Error(`Invalid base64 data: ${truncateURL(data)}`);
355
+ }
356
+ let bytes;
315
357
  if (IS_NODE && globalThis.Buffer) {
316
- return convertFromBuffer(blob);
317
- } else if (globalThis.FileReader) {
318
- return convertFromFileReader(blob);
358
+ // Use 'latin1' to correctly map the binary string directly to bytes.
359
+ // @see https://nodejs.org/docs/latest/api/buffer.html#buffers-and-character-encodings
360
+ bytes = globalThis.Buffer.from(binStr, 'latin1');
361
+ } else {
362
+ const len = binStr.length;
363
+ bytes = new Uint8Array(len);
364
+ for (let i = 0; i < len; i++) {
365
+ bytes[i] = binStr.charCodeAt(i);
366
+ }
367
+ }
368
+ try {
369
+ const text = decoder.decode(bytes);
370
+ if (REG_NON_TEXT.test(text)) {
371
+ return cleanData;
372
+ }
373
+ return text;
374
+ } catch {
375
+ return cleanData;
319
376
  }
320
- return convertFromBtoa(blob);
321
377
  };
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;
@@ -21,8 +21,18 @@ export type InspectedURLResult = {
21
21
  search?: string;
22
22
  hash?: string;
23
23
  };
24
- export declare const logDebug: (isDebug: boolean, message: string, error?: Error) => void;
25
- declare class URLSanitizer extends URISchemes {
24
+ export declare const logDebug: (message: string, error?: Error) => void;
25
+ export declare class SanitizeContext {
26
+ debug: boolean;
27
+ domPurify: object;
28
+ nest: number;
29
+ recurse: Set<any>;
30
+ schemeMap: Map<string, boolean>;
31
+ constructor(opt: object, domPurifyInstance: object);
32
+ enter(url: string): boolean;
33
+ leave(url: string): void;
34
+ }
35
+ export declare class URLSanitizer extends URISchemes {
26
36
  #private;
27
37
  private static #uponSanitizeAttribute;
28
38
  constructor();
@@ -34,6 +44,7 @@ declare class URLSanitizer extends URISchemes {
34
44
  private #isSchemeAllowed;
35
45
  private #sanitizeDataURL;
36
46
  private #sanitizeStandardURL;
47
+ private #executeSanitize;
37
48
  sanitize(url: string, opt?: {
38
49
  allow?: string[];
39
50
  deny?: string[];
@@ -43,7 +54,7 @@ declare class URLSanitizer extends URISchemes {
43
54
  maxBlobSize?: number;
44
55
  maxLength?: number;
45
56
  }): string | null;
46
- inspect(url: string, opt?: object): InspectedURLResult;
57
+ inspect(url: string): InspectedURLResult;
47
58
  get(): string[];
48
59
  has(scheme: string): boolean;
49
60
  add(scheme: string): string[];
@@ -51,7 +62,6 @@ declare class URLSanitizer extends URISchemes {
51
62
  reset(): void;
52
63
  verify(uri: string, schemes?: Set<string>): boolean;
53
64
  }
54
- export { URLSanitizer };
55
65
  declare const urlSanitizer: URLSanitizer;
56
66
  export declare const sanitizeURL: (url: string, opt?: {
57
67
  allow?: string[];
@@ -73,9 +83,6 @@ export declare const sanitizeURLSync: (url: string, opt?: {
73
83
  maxLength?: number;
74
84
  }) => string | null;
75
85
  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>;
86
+ export declare const isValidURI: (uri: string) => boolean;
80
87
  export declare const isURISync: (uri: string) => boolean;
81
88
  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>): 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;