url-sanitizer 4.1.4 → 4.2.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 +7 -4
- package/dist/url-sanitizer-wo-dompurify.min.js +1 -1
- package/dist/url-sanitizer-wo-dompurify.min.js.map +3 -3
- package/dist/url-sanitizer.min.js +3 -3
- package/dist/url-sanitizer.min.js.map +3 -3
- package/package.json +7 -8
- package/src/lib/iana/uri-schemes.json +1 -1
- package/src/mjs/dompurify.js +1 -1
- package/src/mjs/regexp.js +7 -0
- package/src/mjs/sanitizer.js +34 -34
- package/src/mjs/uri-util.js +15 -14
- package/types/mjs/dompurify.d.ts +1 -1
- package/types/mjs/regexp.d.ts +1 -0
package/package.json
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"esbuild": "^0.28.1",
|
|
40
40
|
"eslint": "^9.39.5",
|
|
41
41
|
"eslint-config-prettier": "^10.1.8",
|
|
42
|
-
"eslint-plugin-jsdoc": "^63.
|
|
42
|
+
"eslint-plugin-jsdoc": "^63.2.2",
|
|
43
43
|
"eslint-plugin-prettier": "^5.5.6",
|
|
44
44
|
"eslint-plugin-regexp": "^3.1.1",
|
|
45
45
|
"eslint-plugin-unicorn": "^64.0.0",
|
|
@@ -50,23 +50,22 @@
|
|
|
50
50
|
"mocha": "^11.7.6",
|
|
51
51
|
"neostandard": "^0.13.0",
|
|
52
52
|
"papaparse": "^5.5.4",
|
|
53
|
-
"prettier": "^3.9.
|
|
54
|
-
"sinon": "^22.
|
|
53
|
+
"prettier": "^3.9.6",
|
|
54
|
+
"sinon": "^22.1.0",
|
|
55
55
|
"strict-url-sanitise": "^0.0.1",
|
|
56
56
|
"typescript": "^7.0.2",
|
|
57
|
-
"undici": "^7.
|
|
57
|
+
"undici": "^7.29.0"
|
|
58
58
|
},
|
|
59
59
|
"overrides": {
|
|
60
60
|
"c8": {
|
|
61
61
|
"yargs": "^18.0.0"
|
|
62
62
|
},
|
|
63
63
|
"eslint": {
|
|
64
|
-
"
|
|
65
|
-
"js-yaml": "^4.2.0"
|
|
64
|
+
"js-yaml": "^4.3.0"
|
|
66
65
|
},
|
|
67
66
|
"mocha": {
|
|
68
67
|
"diff": "^8.0.3",
|
|
69
|
-
"js-yaml": "^4.
|
|
68
|
+
"js-yaml": "^4.3.0"
|
|
70
69
|
},
|
|
71
70
|
"serialize-javascript": "^7.0.4"
|
|
72
71
|
},
|
|
@@ -94,5 +93,5 @@
|
|
|
94
93
|
"engines": {
|
|
95
94
|
"node": ">=22.13"
|
|
96
95
|
},
|
|
97
|
-
"version": "4.
|
|
96
|
+
"version": "4.2.0"
|
|
98
97
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
["aaa","aaas","about","acap","acct","acd","acr","adiumxtra","adt","afp","afs","agtp","aim","amss","android","appdata","apt","ar","ari","ark","at","attachment","aw","barion","beshare","bitcoin","bitcoincash","bl","blob","bluetooth","bolo","brid","browserext","cabal","caip","calculator","callto","cap","cast","casts","chrome","chrome-extension","cid","coap","coaps","com-eventbrite-attendee","content","content-type","crid","cstr","cttps","cvs","dab","dat","data","dav","dhttp","diaspora","dict","did","dilithium3","dis","dlna-playcontainer","dlna-playsingle","dnp","dns","dntp","doi","donau","dpp","drm","dtmi","dtn","dvb","dvx","dweb","ed2k","eid","elsi","embedded","ens","esim","ethereum","example","ez","facetime","feed","feedready","fido","file","finger","first-run-pen-experience","fish","fm","ftp","fuchsia-pkg","geo","gg","git","gitoid","gizmoproject","go","gopher","graph","gtalk","h323","ham","hcap","hcp","hs20","http","https","hxxp","hxxps","hydrazone","hyper","i0","iax","ibi","ibi-","icap","icon","ilstring","im","imap","info","iotdisco","ipfs","ipn","ipns","ipp","ipps","irc","irc6","ircs","iris","iris.beep","iris.lwz","iris.xpc","iris.xpcs","isostore","itms","jabber","jar","jms","keyparc","lastfm","lbry","ldap","ldaps","leaptofrogans","lid","linkid","lorawan","lpa","lvlt","machineProvisioningProgressReporter","magnet","mailto","maps","market","matrix","mdoc","mdoc-openid4vp","message","microsoft.windows.camera","microsoft.windows.camera.multipicker","microsoft.windows.camera.picker","mid","mms","mongodb","moz","moz-extension","mqtt","mqtts","ms-access","ms-appinstaller","ms-browser-extension","ms-calculator","ms-drive-to","ms-enrollment","ms-excel","ms-eyecontrolspeech","ms-gamebarservices","ms-gamingoverlay","ms-getoffice","ms-help","ms-infopath","ms-inputapp","ms-launchremotedesktop","ms-lockscreencomponent-config","ms-media-stream-id","ms-meetnow","ms-mixedrealitycapture","ms-mobileplans","ms-newsandinterests","ms-officeapp","ms-people","ms-personacard","ms-powerpoint","ms-project","ms-publisher","ms-recall","ms-remotedesktop","ms-remotedesktop-launch","ms-restoretabcompanion","ms-screenclip","ms-screensketch","ms-search","ms-search-repair","ms-secondary-screen-controller","ms-secondary-screen-setup","ms-settings","ms-settings-airplanemode","ms-settings-bluetooth","ms-settings-camera","ms-settings-cellular","ms-settings-cloudstorage","ms-settings-connectabledevices","ms-settings-displays-topology","ms-settings-emailandaccounts","ms-settings-language","ms-settings-location","ms-settings-lock","ms-settings-nfctransactions","ms-settings-notifications","ms-settings-power","ms-settings-privacy","ms-settings-proximity","ms-settings-screenrotation","ms-settings-wifi","ms-settings-workplace","ms-spd","ms-stickers","ms-sttoverlay","ms-transit-to","ms-useractivityset","ms-uup","ms-virtualtouchpad","ms-visio","ms-walk-to","ms-whiteboard","ms-whiteboard-cmd","ms-widgetboard","ms-widgets","ms-word","msnim","msrp","msrps","mss","mt","mtqp","mtrust","mumble","mupdate","musik","mvn","mvrp","mvrps","news","nfs","ni","nih","nntp","notes","npamp","num","ocf","oid","onenote","onenote-cmd","opaquelocktoken","openid","openpgp4fpr","otpauth","palm","paparazzi","payto","pkcs11","platform","pop","pres","proxy","psyc","pttp","pwid","qb","query","quic-transport","redis","rediss","reload","res","resource","rmi","rsync","rtmfp","rtmp","rtsp","rtsps","rtspu","sarif","secondlife","secret-token","service","session","sftp","sgn","shc","shelter","sieve","simpleledger","simplex","sip","sips","skype","smb","smp","sms","smtp","snmp","soap.beep","soap.beeps","soldat","spacify","spiffe","spotify","ssb","ssh","sss","starknet","steam","stun","stuns","submit","svn","swh","swid","swidpath","tag","taler","teamspeak","teapot","teapots","tel","teliaeid","telnet","tftp","things","thismessage","tip","tn3270","tool","tttps","turn","turns","tv","udp","unreal","upn","urn","ut2004","uuaid","uuid-in-package","v-event","vemmi","ventrilo","ves","view-source","vnc","vscode","vscode-insiders","vsls","w3","wasm","wasm-js","wcr","web3","webcal","wifi","ws","wss","wtai","wyciwyg","xcompute","xcon","xcon-userid","xfire","xftp","xmlrpc.beep","xmlrpc.beeps","xmpp","xrcp","xri","ymsgr","z39.50r","z39.50s","ztdnaid"]
|
|
1
|
+
["aaa","aaas","about","acap","acct","acd","acr","adiumxtra","adt","afp","afs","agtp","aim","amss","android","appdata","apt","ar","ari","ark","at","attachment","aw","barion","beshare","bitcoin","bitcoincash","bl","blob","bluetooth","bolo","brid","browserext","cabal","caip","calculator","callto","cap","cast","casts","chrome","chrome-extension","cid","coap","coaps","com-eventbrite-attendee","content","content-type","crid","cstr","cttps","cvs","dab","dat","data","dav","dhttp","diaspora","dict","did","dilithium3","dis","dlna-playcontainer","dlna-playsingle","dnp","dns","dntp","doi","donau","dpp","drm","dtmi","dtn","dvb","dvx","dweb","ed2k","eid","elsi","embedded","ens","esim","ethereum","example","ez","facetime","feed","feedready","fido","file","finger","first-run-pen-experience","fish","fm","ftp","fuchsia-pkg","geo","gg","git","gitoid","gizmoproject","go","gopher","graph","gtalk","h323","ham","hcap","hcp","hs20","http","https","hxxp","hxxps","hydrazone","hyper","i0","iax","ibi","ibi-","icap","icon","ilstring","im","imap","info","iotdisco","ipfs","ipn","ipns","ipp","ipps","irc","irc6","ircs","iris","iris.beep","iris.lwz","iris.xpc","iris.xpcs","isostore","itms","jabber","jar","jms","keyparc","lastfm","lbry","ldap","ldaps","leaptofrogans","lid","linkid","lorawan","lpa","lvlt","machineProvisioningProgressReporter","magnet","mailto","maps","market","matrix","mdoc","mdoc-openid4vp","message","microsoft.windows.camera","microsoft.windows.camera.multipicker","microsoft.windows.camera.picker","mid","mms","mongodb","moz","moz-extension","mqtt","mqtts","ms-access","ms-appinstaller","ms-browser-extension","ms-calculator","ms-drive-to","ms-enrollment","ms-excel","ms-eyecontrolspeech","ms-gamebarservices","ms-gamingoverlay","ms-getoffice","ms-help","ms-infopath","ms-inputapp","ms-launchremotedesktop","ms-lockscreencomponent-config","ms-media-stream-id","ms-meetnow","ms-mixedrealitycapture","ms-mobileplans","ms-newsandinterests","ms-officeapp","ms-people","ms-personacard","ms-powerpoint","ms-project","ms-publisher","ms-recall","ms-remotedesktop","ms-remotedesktop-launch","ms-restoretabcompanion","ms-screenclip","ms-screensketch","ms-search","ms-search-repair","ms-secondary-screen-controller","ms-secondary-screen-setup","ms-settings","ms-settings-airplanemode","ms-settings-bluetooth","ms-settings-camera","ms-settings-cellular","ms-settings-cloudstorage","ms-settings-connectabledevices","ms-settings-displays-topology","ms-settings-emailandaccounts","ms-settings-language","ms-settings-location","ms-settings-lock","ms-settings-nfctransactions","ms-settings-notifications","ms-settings-power","ms-settings-privacy","ms-settings-proximity","ms-settings-screenrotation","ms-settings-wifi","ms-settings-workplace","ms-spd","ms-stickers","ms-sttoverlay","ms-transit-to","ms-useractivityset","ms-uup","ms-virtualtouchpad","ms-visio","ms-walk-to","ms-whiteboard","ms-whiteboard-cmd","ms-widgetboard","ms-widgets","ms-word","msnim","msrp","msrps","mss","mt","mtqp","mtrust","mumble","mupdate","musik","mvn","mvrp","mvrps","news","nfs","ni","nih","nntp","nostr","notes","npamp","num","ocf","oid","onenote","onenote-cmd","opaquelocktoken","openid","openpgp4fpr","otpauth","palm","paparazzi","payto","pkcs11","platform","pop","pres","proxy","psyc","pttp","pwid","qb","query","quic-transport","redis","rediss","reload","res","resource","rmi","rsync","rtmfp","rtmp","rtsp","rtsps","rtspu","sarif","secondlife","secret-token","service","session","sftp","sgn","shc","shelter","sieve","simpleledger","simplex","sip","sips","skype","smb","smp","sms","smtp","snmp","soap.beep","soap.beeps","soldat","spacify","spiffe","spotify","ssb","ssh","sss","starknet","steam","stun","stuns","submit","svn","swh","swid","swidpath","tag","taler","teamspeak","teapot","teapots","tel","teliaeid","telnet","tftp","things","thismessage","tip","tn3270","tool","tttps","turn","turns","tv","udp","unreal","upn","urn","ust","ut2004","uuaid","uuid-in-package","v-event","vemmi","ventrilo","ves","view-source","vnc","vscode","vscode-insiders","vsls","w3","wasm","wasm-js","wcr","web3","webcal","wifi","ws","wss","wtai","wyciwyg","xcompute","xcon","xcon-userid","xfire","xftp","xmlrpc.beep","xmlrpc.beeps","xmpp","xrcp","xri","ymsgr","z39.50r","z39.50s","ztdnaid"]
|
package/src/mjs/dompurify.js
CHANGED
|
@@ -10,6 +10,6 @@ const { window } = new JSDOM('');
|
|
|
10
10
|
/**
|
|
11
11
|
* An instance of DOMPurify initialized with a JSDOM window context.
|
|
12
12
|
* Used to sanitize HTML/SVG strings.
|
|
13
|
-
* @type {import('dompurify')}
|
|
13
|
+
* @type {import('dompurify').DOMPurify}
|
|
14
14
|
*/
|
|
15
15
|
export const domPurify = DOMPurify(window);
|
package/src/mjs/regexp.js
CHANGED
|
@@ -80,9 +80,16 @@ export const REG_URL_ENC = /^%[\dA-F]{2}$/i;
|
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
82
|
* Matches an ampersand-encoded character (&foo).
|
|
83
|
+
* @type {RegExp}
|
|
83
84
|
*/
|
|
84
85
|
export const REG_AMP_ENC = /&(?=[#a-z0-9])(?![a-z0-9]+=)/i;
|
|
85
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Match one or more consecutive URL percent-encoded sequences (%20, %E3%81%82).
|
|
89
|
+
* @type {RegExp}
|
|
90
|
+
*/
|
|
91
|
+
export const REG_PCT_ENC = /(?:%[\dA-F]{2})+/gi;
|
|
92
|
+
|
|
86
93
|
/**
|
|
87
94
|
* Validates relative URLs and flags invalid patterns.
|
|
88
95
|
* @type {RegExp}
|
package/src/mjs/sanitizer.js
CHANGED
|
@@ -126,10 +126,8 @@ class URLSanitizer extends URISchemes {
|
|
|
126
126
|
if (!sanitizer || !ctx) {
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
urlObj = new URL(evt.attrValue);
|
|
132
|
-
} catch {
|
|
129
|
+
const urlObj = URL.parse(evt.attrValue);
|
|
130
|
+
if (!urlObj) {
|
|
133
131
|
return;
|
|
134
132
|
}
|
|
135
133
|
if (urlObj.protocol === 'data:') {
|
|
@@ -357,10 +355,10 @@ class URLSanitizer extends URISchemes {
|
|
|
357
355
|
let relativeParsedPath = '';
|
|
358
356
|
// Handle Relative URLs
|
|
359
357
|
if (!isVerified && allowRelative && !REG_VERIFY_RELATIVE.test(url)) {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
358
|
+
const normUrl = url.normalize('NFKC');
|
|
359
|
+
const dummyUrl = URL.parse(url, 'http://dummy.local');
|
|
360
|
+
const dummyUrlNormalized = URL.parse(normUrl, 'http://dummy.local');
|
|
361
|
+
if (dummyUrl && dummyUrlNormalized) {
|
|
364
362
|
if (
|
|
365
363
|
dummyUrl.protocol === 'http:' &&
|
|
366
364
|
dummyUrl.hostname === 'dummy.local' &&
|
|
@@ -370,8 +368,8 @@ class URLSanitizer extends URISchemes {
|
|
|
370
368
|
isRelative = true;
|
|
371
369
|
relativeParsedPath = `${dummyUrl.pathname}${dummyUrl.search}${dummyUrl.hash}`;
|
|
372
370
|
}
|
|
373
|
-
}
|
|
374
|
-
logDebug(ctx.debug, 'Failed to parse relative URL.'
|
|
371
|
+
} else {
|
|
372
|
+
logDebug(ctx.debug, 'Failed to parse relative URL.');
|
|
375
373
|
}
|
|
376
374
|
}
|
|
377
375
|
if (!isVerified) {
|
|
@@ -388,7 +386,7 @@ class URLSanitizer extends URISchemes {
|
|
|
388
386
|
urlToSanitize: relativeParsedPath
|
|
389
387
|
};
|
|
390
388
|
}
|
|
391
|
-
const urlObj =
|
|
389
|
+
const urlObj = URL.parse(url);
|
|
392
390
|
const scheme = urlObj.protocol.replace(/:$/, '').normalize('NFKC');
|
|
393
391
|
const schemeParts = scheme.split('+');
|
|
394
392
|
return {
|
|
@@ -455,14 +453,18 @@ class URLSanitizer extends URISchemes {
|
|
|
455
453
|
const decodedData = parseURLEncodedNumCharRef(parsedData).trim();
|
|
456
454
|
const normalizedData = decodedData.normalize('NFKC');
|
|
457
455
|
const dummy = 'http://dummy.local';
|
|
458
|
-
const
|
|
456
|
+
const parsedUrl = URL.parse(normalizedData, dummy);
|
|
457
|
+
if (!parsedUrl) {
|
|
458
|
+
logDebug(ctx.debug, 'Failed to parse inner data URL protocol.');
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
const dataScheme = parsedUrl.protocol;
|
|
459
462
|
const dataSchemeParts = dataScheme.replace(/:$/, '').split('+');
|
|
460
463
|
if (dataSchemeParts.some(s => REG_SCRIPT_BLOB.test(s))) {
|
|
461
464
|
return null;
|
|
462
465
|
}
|
|
463
466
|
} catch (e) {
|
|
464
|
-
|
|
465
|
-
logDebug(ctx.debug, msg, e);
|
|
467
|
+
logDebug(ctx.debug, 'Failed to parse inner data URL protocol.', e);
|
|
466
468
|
return null;
|
|
467
469
|
}
|
|
468
470
|
if (!mediaType || REG_MIME_DOM.test(mediaType)) {
|
|
@@ -531,12 +533,11 @@ class URLSanitizer extends URISchemes {
|
|
|
531
533
|
!REG_TAG_QUOT.test(url) &&
|
|
532
534
|
!url.includes('data:')
|
|
533
535
|
) {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
return href.replace(/%26/g, escapeURLEncodedHTMLChars);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
logDebug(opt?.debug, msg, e);
|
|
536
|
+
const parsedUrl = URL.parse(url);
|
|
537
|
+
if (parsedUrl) {
|
|
538
|
+
return parsedUrl.href.replace(/%26/g, escapeURLEncodedHTMLChars);
|
|
539
|
+
} else {
|
|
540
|
+
logDebug(opt?.debug, `Failed to parse URL.`);
|
|
540
541
|
return null;
|
|
541
542
|
}
|
|
542
543
|
}
|
|
@@ -744,11 +745,11 @@ export const sanitizeURL = async (
|
|
|
744
745
|
let res;
|
|
745
746
|
if (url && isString(url)) {
|
|
746
747
|
let scheme;
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
scheme = protocol.replace(/:$/, '');
|
|
750
|
-
}
|
|
751
|
-
logDebug(isDebug, `Invalid URL input format: ${url}
|
|
748
|
+
const parsedUrl = URL.parse(url);
|
|
749
|
+
if (parsedUrl) {
|
|
750
|
+
scheme = parsedUrl.protocol.replace(/:$/, '');
|
|
751
|
+
} else {
|
|
752
|
+
logDebug(isDebug, `Invalid URL input format: ${url}`);
|
|
752
753
|
}
|
|
753
754
|
if (scheme === 'blob') {
|
|
754
755
|
const { allow, deny, only } = opt;
|
|
@@ -824,12 +825,11 @@ export const sanitizeURLSync = (
|
|
|
824
825
|
let res;
|
|
825
826
|
if (url && isString(url)) {
|
|
826
827
|
let scheme;
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
scheme = protocol.replace(/:$/, '');
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
logDebug(isDebug, msg, e);
|
|
828
|
+
const parsedUrl = URL.parse(url);
|
|
829
|
+
if (parsedUrl) {
|
|
830
|
+
scheme = parsedUrl.protocol.replace(/:$/, '');
|
|
831
|
+
} else {
|
|
832
|
+
logDebug(isDebug, `Invalid URL input format: ${url}`);
|
|
833
833
|
}
|
|
834
834
|
if (scheme === 'blob') {
|
|
835
835
|
if (opt?.revokeObjectURL) {
|
|
@@ -854,11 +854,11 @@ export const inspectURL = async url => {
|
|
|
854
854
|
};
|
|
855
855
|
|
|
856
856
|
/**
|
|
857
|
-
* @deprecated Use inspectURL instead.
|
|
857
|
+
* @deprecated Use {@link inspectURL} instead.
|
|
858
858
|
* @param {string} url - The URL string to inspect.
|
|
859
859
|
* @returns {Promise<InspectedURLResult>} A promise resolving to the inspected URL result.
|
|
860
860
|
*/
|
|
861
|
-
export const parseURL = url => inspectURL(url);
|
|
861
|
+
export const parseURL = async url => inspectURL(url);
|
|
862
862
|
|
|
863
863
|
/**
|
|
864
864
|
* Inspects, parses, and sanitizes the given URL synchronously.
|
|
@@ -868,7 +868,7 @@ export const parseURL = url => inspectURL(url);
|
|
|
868
868
|
export const inspectURLSync = url => urlSanitizer.inspect(url);
|
|
869
869
|
|
|
870
870
|
/**
|
|
871
|
-
* @deprecated Use inspectURLSync instead.
|
|
871
|
+
* @deprecated Use {@link inspectURLSync} instead.
|
|
872
872
|
* @param {string} url - The URL string to inspect.
|
|
873
873
|
* @returns {InspectedURLResult} The inspected URL result.
|
|
874
874
|
*/
|
package/src/mjs/uri-util.js
CHANGED
|
@@ -11,6 +11,7 @@ import { CHUNK_SIZE, DECI, HEX, MAX_BLOB_SIZE, MAX_NEST } from './constant.js';
|
|
|
11
11
|
import {
|
|
12
12
|
REG_HASH,
|
|
13
13
|
REG_NUM_REF,
|
|
14
|
+
REG_PCT_ENC,
|
|
14
15
|
REG_QUERY,
|
|
15
16
|
REG_SCHEME_EXT,
|
|
16
17
|
REG_SCRIPT,
|
|
@@ -88,18 +89,18 @@ export class URISchemes {
|
|
|
88
89
|
if (!isString(uri)) {
|
|
89
90
|
return false;
|
|
90
91
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
} catch {
|
|
92
|
+
const normalizedUri = uri.normalize('NFKC');
|
|
93
|
+
const parsedUrl = URL.parse(normalizedUri);
|
|
94
|
+
if (!parsedUrl) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const scheme = parsedUrl.protocol.replace(/:$/, '');
|
|
98
|
+
const parts = scheme.split('+');
|
|
99
|
+
const isScript = parts.some(s => REG_SCRIPT.test(s));
|
|
100
|
+
if (isScript) {
|
|
101
101
|
return false;
|
|
102
102
|
}
|
|
103
|
+
return REG_SCHEME_EXT.test(scheme) || parts.every(s => schemes.has(s));
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
|
|
@@ -113,11 +114,11 @@ export const getURLEncodedString = str => {
|
|
|
113
114
|
throw new TypeError(`Expected String but got ${getType(str)}.`);
|
|
114
115
|
}
|
|
115
116
|
const bytes = encoder.encode(str);
|
|
116
|
-
|
|
117
|
+
let encoded = '';
|
|
117
118
|
for (let i = 0; i < bytes.length; i++) {
|
|
118
|
-
encoded
|
|
119
|
+
encoded += HEX_TABLE[bytes[i]];
|
|
119
120
|
}
|
|
120
|
-
return encoded
|
|
121
|
+
return encoded;
|
|
121
122
|
};
|
|
122
123
|
|
|
123
124
|
/**
|
|
@@ -226,7 +227,7 @@ export const parseURLEncodedNumCharRef = (str, nest = 0) => {
|
|
|
226
227
|
res = decodeURIComponent(str);
|
|
227
228
|
} catch {
|
|
228
229
|
// Fallback: decode only valid multi-byte %XX sequences.
|
|
229
|
-
res = str.replace(
|
|
230
|
+
res = str.replace(REG_PCT_ENC, match => {
|
|
230
231
|
try {
|
|
231
232
|
return decodeURIComponent(match);
|
|
232
233
|
} catch {
|
package/types/mjs/dompurify.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const domPurify: import('dompurify');
|
|
1
|
+
export declare const domPurify: import('dompurify').DOMPurify;
|
package/types/mjs/regexp.d.ts
CHANGED
|
@@ -11,4 +11,5 @@ export declare const REG_SCRIPT_BLOB: RegExp;
|
|
|
11
11
|
export declare const REG_TAG_QUOT: RegExp;
|
|
12
12
|
export declare const REG_URL_ENC: RegExp;
|
|
13
13
|
export declare const REG_AMP_ENC: RegExp;
|
|
14
|
+
export declare const REG_PCT_ENC: RegExp;
|
|
14
15
|
export declare const REG_VERIFY_RELATIVE: RegExp;
|