url-sanitizer 0.4.4 → 0.5.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.
package/README.md CHANGED
@@ -8,6 +8,7 @@
8
8
  URL sanitizer for Node.js (>=18), browsers and web sites.
9
9
  **Experimental**
10
10
 
11
+
11
12
  ## Install
12
13
 
13
14
  ```shell
@@ -20,14 +21,16 @@ For browsers and web sites, standalone ESM builds are available in `dist/` direc
20
21
 
21
22
  Or, download them from [Releases](https://github.com/asamuzaK/urlSanitizer/releases).
22
23
 
24
+
23
25
  ## Usage
24
26
 
25
27
  ```javascript
26
28
  import urlSanitizer, {
27
- isURI, isURISync, sanitizeURL, sanitizeURLSync
29
+ isURI, isURISync, parseURL, parseURLSync, sanitizeURL, sanitizeURLSync
28
30
  } from 'url-sanitizer';
29
31
  ```
30
32
 
33
+
31
34
  ## sanitizeURL(url, opt)
32
35
 
33
36
  Sanitize the given URL.
@@ -37,38 +40,161 @@ Sanitize the given URL.
37
40
 
38
41
  * `url` **[string][1]** URL input.
39
42
  * `opt` **[object][3]** Options.
40
- * `opt.allow` **[Array][4]<[string][1]>** Array of allowed schemes, e.g. `['data']`.
41
- * `opt.deny` **[Array][4]<[string][1]>** Array of denied schemes, e.g. `['web+foo']`.
43
+ * `opt.allow` **[Array][4]<[string][1]>** Array of allowed schemes, e.g. `['data']`.
44
+ * `opt.deny` **[Array][4]<[string][1]>** Array of denied schemes, e.g. `['web+foo']`.
45
+ * `opt.only` **[Array][4]<[string][1]>** Array of specific schemes to allow, e.g. `['git', 'https']`.
46
+ `only` takes precedence over `allow` and `deny`.
42
47
 
43
48
  Returns **[Promise][5]<[string][1]?>** Sanitized URL, `null`able.
44
49
 
45
50
  ```javascript
46
51
  const res1 = await sanitizeURL('http://example.com/?<script>alert(1);</script>')
47
52
  .then(res => decodeURIComponent(res));
48
- // -> 'http://example.com/?&lt;script&gt;alert(1);&lt;/script&gt;'
53
+ // => 'http://example.com/?&lt;script&gt;alert(1);&lt;/script&gt;'
49
54
 
50
55
  const res2 = await sanitizeURL('data:text/html,<script>alert(1);</script>', {
51
56
  allow: ['data']
52
57
  }).then(res => decodeURIComponent(res));
53
- // -> 'data:text/html,&lt;script&gt;alert(1);&lt;/script&gt;'
58
+ // => 'data:text/html,&lt;script&gt;alert(1);&lt;/script&gt;'
54
59
 
55
60
  // Can parse and sanitize base64 encoded data
56
61
  const base64data3 = btoa('<script>alert(1);</script>');
57
62
  const res3 = await sanitizeURL(`data:text/html;base64,${base64data3}`, {
58
63
  allow: ['data']
59
64
  }).then(res => decodeURIComponent(res));
60
- // -> 'data:text/html,&lt;script&gt;alert(1);&lt;/script&gt;'
65
+ // => 'data:text/html,&lt;script&gt;alert(1);&lt;/script&gt;'
61
66
 
62
67
  const res4 = await sanitizeURL('web+foo://example.com', {
63
68
  deny: ['web+foo']
64
69
  });
65
- // -> null
70
+ // => null
71
+
72
+ const res5 = await sanitizeURL('http://example.com', {
73
+ only: ['data', 'git', 'https']
74
+ });
75
+ // => null
76
+
77
+ const res6 = await sanitizeURL('https://example.com/"onmouseover="alert(1)"', {
78
+ only: ['data', 'git', 'https']
79
+ }).then(res => decodeURIComponent(res));
80
+ // => https://example.com/&quot;onmouseover=&quot;alert(1)&quot;
81
+
82
+ const res7 = await sanitizeURL('data:text/html,<script>alert(1);</script>', {
83
+ only: ['data', 'git', 'https']
84
+ }).then(res => decodeURIComponent(res));
85
+ // => 'data:text/html,&lt;script&gt;alert(1);&lt;/script&gt;'
86
+
87
+ // `only` option also allows combinations of the specified schemes
88
+ const res8 = await sanitizeURL('git+https://example.com', {
89
+ only: ['data', 'git', 'https']
90
+ }).then(res => decodeURIComponent(res));;
91
+ // => git+https://example.com
66
92
  ```
67
93
 
94
+
68
95
  ## sanitizeURLSync
69
96
 
70
97
  Synchronous version of the [sanitizeURL()](#sanitizeurlurl-opt).
71
98
 
99
+
100
+ ## parseURL(url)
101
+
102
+ Parse the given URL.
103
+
104
+ ### Parameters
105
+
106
+ * `url` **[string][1]** URL input.
107
+
108
+ Returns **[Promise][5]<[ParsedURL](#parsedurl)>** Result.
109
+
110
+ ### ParsedURL
111
+
112
+ Object with extended properties based on [URL](https://developer.mozilla.org/ja/docs/Web/API/URL) API.
113
+
114
+ Type: [object][3]
115
+
116
+ #### Properties
117
+
118
+ * `input` **[string][1]** URL input.
119
+ * `valid` **[boolean][2]** Is valid URI.
120
+ * `data` **[object][3]** Parsed result of data URL, `null`able.
121
+ * `data.mime` **[string][1]** MIME type.
122
+ * `data.base64` **[boolean][2]** `true` if base64 encoded.
123
+ * `data.data` **[string][1]** Data part of the data URL.
124
+ * `href` **[string][1]** Same as URL API.
125
+ * `origin` **[string][1]** Same as URL API.
126
+ * `protocol` **[string][1]** Same as URL API.
127
+ * `username` **[string][1]** Same as URL API.
128
+ * `password` **[string][1]** Same as URL API.
129
+ * `host` **[string][1]** Same as URL API.
130
+ * `hostname` **[string][1]** Same as URL API.
131
+ * `port` **[string][1]** Same as URL API.
132
+ * `pathname` **[string][1]** Same as URL API.
133
+ * `search` **[string][1]** Same as URL API.
134
+ * `searchParams` **[object][3]** Same as URL API.
135
+ * `hash` **[string][1]** Same as URL API.
136
+
137
+ ```javascript
138
+ const res1 = await parseURL('javascript:alert(1)');
139
+ /* => {
140
+ input: 'javascript:alert(1)',
141
+ valid: false
142
+ } */
143
+
144
+ const res2 = await parseURL('https://example.com/?foo=bar#baz');
145
+ /* => {
146
+ input: 'https://www.example.com/?foo=bar#baz',
147
+ valid: true,
148
+ data: null,
149
+ href: 'https://www.example.com/?foo=bar#baz',
150
+ origin: 'https://www.example.com',
151
+ protocol: 'https:',
152
+ hostname: 'www.example.com',
153
+ pathname: '/',
154
+ search: '?foo=bar',
155
+ hash: '#baz',
156
+ ...
157
+ } */
158
+
159
+ // base64 encoded svg '<svg><g onload="alert(1)"/></svg>'
160
+ const res3 = await parseURL('data:image/svg+xml;base64,PHN2Zz48ZyBvbmxvYWQ9ImFsZXJ0KDEpIi8+PC9zdmc+');
161
+ /* => {
162
+ input: 'data:image/svg+xml;base64,PHN2Zz48ZyBvbmxvYWQ9ImFsZXJ0KDEpIi8+PC9zdmc+',
163
+ valid: true,
164
+ data: {
165
+ mime: 'image/svg+xml',
166
+ base64: false,
167
+ data: '%26lt;svg%26gt;%26lt;g%20onload=%26quot;alert(1)%26quot;/%26gt;%26lt;/svg%26gt;'
168
+ },
169
+ href: 'data:image/svg+xml,%26lt;svg%26gt;%26lt;g%20onload=%26quot;alert(1)%26quot;/%26gt;%26lt;/svg%26gt;',
170
+ protocol: 'data:',
171
+ pathname: 'image/svg+xml,%26lt;svg%26gt;%26lt;g%20onload=%26quot;alert(1)%26quot;/%26gt;%26lt;/svg%26gt;',
172
+ ...
173
+ } */
174
+
175
+ // base64 encoded png
176
+ const res4 = await parseURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==');
177
+ /* => {
178
+ input: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==',
179
+ valid: true,
180
+ data: {
181
+ mime: 'image/png',
182
+ base64: true,
183
+ data: 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='
184
+ },
185
+ href: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==',
186
+ protocol: 'data:',
187
+ pathname: 'image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==',
188
+ ...
189
+ } */
190
+ ```
191
+
192
+
193
+ ## parseURLSync(url)
194
+
195
+ Synchronous version of the [parseURL()](#parseURL).
196
+
197
+
72
198
  ## isURI(uri)
73
199
 
74
200
  Determines whether the given URI is valid.
@@ -78,26 +204,32 @@ Determines whether the given URI is valid.
78
204
  * `uri` **[string][1]** URI input.
79
205
 
80
206
  Returns **[Promise][5]<[boolean][2]>** Result.
81
- * Always `true` for `web+*` and `ext+*` schemes.
207
+ * Always `true` for `web+*` and `ext+*` schemes, except `web+javascript`, `web+vbscript`, `ext+javascript`, `ext+vbscript`.
82
208
 
83
209
  ```javascript
84
210
  const res1 = await isURI('https://example.com/foo');
85
- // -> true
211
+ // => true
86
212
 
87
213
  const res2 = await isURI('mailto:foo@example.com');
88
- // -> true
214
+ // => true
89
215
 
90
216
  const res3 = await isURI('foo:bar');
91
- // -> false
217
+ // => false
92
218
 
93
219
  const res4 = await isURI('web+foo:bar');
94
- // -> true
220
+ // => true
221
+
222
+ const res5 = await isURI('web+javascript:alert(1)');
223
+ // => false
95
224
  ```
96
225
 
226
+
97
227
  ## isURISync(uri)
98
228
 
99
229
  Synchronous version of the [isURI()](#isuriuri).
100
230
 
231
+ ---
232
+
101
233
  ## urlSanitizer
102
234
 
103
235
  Instance of the sanitizer.
@@ -112,7 +244,7 @@ Returns **[Array][4]<[string][1]>** Array of registered URI schemes.
112
244
 
113
245
  ```javascript
114
246
  const schemes = urlSanitizer.get();
115
- // -> ['aaa', 'aaas', 'about', 'acap', 'acct', ...];
247
+ // => ['aaa', 'aaas', 'about', 'acap', 'acct', ...];
116
248
  ```
117
249
 
118
250
  ### urlSanitizer.has(scheme)
@@ -127,10 +259,10 @@ Returns **[boolean][2]** Result.
127
259
 
128
260
  ```javascript
129
261
  const res1 = urlSanitizer.has('https');
130
- // -> true
262
+ // => true
131
263
 
132
264
  const res2 = urlSanitizer.has('foo');
133
- // -> false
265
+ // => false
134
266
  ```
135
267
 
136
268
  ### urlSanitizer.add(scheme)
@@ -146,13 +278,13 @@ Returns **[Array][4]<[string][1]>** Array of registered URI schemes.
146
278
 
147
279
  ```javascript
148
280
  console.log(isURISync('foo'));
149
- // -> false;
281
+ // => false;
150
282
 
151
283
  const res = urlSanitizer.add('foo');
152
- // -> ['aaa', 'aaas', 'about', 'acap', ... 'foo', ...];
284
+ // => ['aaa', 'aaas', 'about', 'acap', ... 'foo', ...];
153
285
 
154
286
  console.log(isURISync('foo'));
155
- // -> true;
287
+ // => true;
156
288
  ```
157
289
 
158
290
  ### urlSanitizer.remove(scheme)
@@ -168,16 +300,16 @@ Returns **[boolean][2]** Result.
168
300
 
169
301
  ```javascript
170
302
  console.log(isURISync('aaa'));
171
- // -> true;
303
+ // => true;
172
304
 
173
305
  const res1 = urlSanitizer.remove('aaa');
174
- // -> true
306
+ // => true
175
307
 
176
308
  console.log(isURISync('aaa'));
177
- // -> false;
309
+ // => false;
178
310
 
179
311
  const res2 = urlSanitizer.remove('foo');
180
- // -> false
312
+ // => false
181
313
  ```
182
314
 
183
315
  [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
@@ -792,16 +792,17 @@ var URLSanitizer = class extends URISchemes {
792
792
  * @param {object} opt - options
793
793
  * @param {Array.<string>} opt.allow - array of allowed schemes
794
794
  * @param {Array.<string>} opt.deny - array of denied schemes
795
+ * @param {Array.<string>} opt.only - array of specific schemes to allow
795
796
  * @returns {?string} - sanitized URL
796
797
  */
797
- sanitize(url, opt = { allow: [], deny: [] }) {
798
+ sanitize(url, opt = { allow: [], deny: [], only: [] }) {
798
799
  if (this.#nest > HEX) {
799
800
  this.#nest = 0;
800
801
  throw new Error("Data URLs nested too deeply.");
801
802
  }
802
803
  let sanitizedUrl;
803
804
  if (super.isURI(url)) {
804
- const { allow, deny } = opt ?? {};
805
+ const { allow, deny, only } = opt ?? {};
805
806
  const { hash, href, pathname, protocol, search } = new URL(url);
806
807
  const scheme = protocol.replace(/:$/, "");
807
808
  const schemeParts = scheme.split("+");
@@ -811,8 +812,12 @@ var URLSanitizer = class extends URISchemes {
811
812
  ["javascrpt", false],
812
813
  ["vbscript", false]
813
814
  ]);
814
- if (Array.isArray(allow) && allow.length) {
815
- const items = Object.values(allow);
815
+ if (Array.isArray(only) && only.length) {
816
+ const schemes = super.get();
817
+ for (const item of schemes) {
818
+ schemeMap.set(item, false);
819
+ }
820
+ const items = Object.values(only);
816
821
  for (let item of items) {
817
822
  if (isString(item)) {
818
823
  item = item.trim();
@@ -821,14 +826,26 @@ var URLSanitizer = class extends URISchemes {
821
826
  }
822
827
  }
823
828
  }
824
- }
825
- if (Array.isArray(deny) && deny.length) {
826
- const items = Object.values(deny);
827
- for (let item of items) {
828
- if (isString(item)) {
829
- item = item.trim();
830
- if (item) {
831
- schemeMap.set(item, false);
829
+ } else {
830
+ if (Array.isArray(allow) && allow.length) {
831
+ const items = Object.values(allow);
832
+ for (let item of items) {
833
+ if (isString(item)) {
834
+ item = item.trim();
835
+ if (!REG_SCRIPT.test(item)) {
836
+ schemeMap.set(item, true);
837
+ }
838
+ }
839
+ }
840
+ }
841
+ if (Array.isArray(deny) && deny.length) {
842
+ const items = Object.values(deny);
843
+ for (let item of items) {
844
+ if (isString(item)) {
845
+ item = item.trim();
846
+ if (item) {
847
+ schemeMap.set(item, false);
848
+ }
832
849
  }
833
850
  }
834
851
  }
@@ -919,6 +936,77 @@ var URLSanitizer = class extends URISchemes {
919
936
  }
920
937
  return sanitizedUrl || null;
921
938
  }
939
+ /**
940
+ * object with extended props based on URL API
941
+ *
942
+ * @typedef {object} ParsedURL
943
+ * @property {string} input - URL input
944
+ * @property {boolean} valid - is valid URI
945
+ * @property {object} data - parsed result of data URL, `null`able
946
+ * @property {string} data.mime - MIME type
947
+ * @property {boolean} data.base64 - `true` if base64 encoded
948
+ * @property {string} data.data - data part of the data URL
949
+ * @property {string} href - same as URL API
950
+ * @property {string} origin - same as URL API
951
+ * @property {string} protocol - same as URL API
952
+ * @property {string} username - same as URL API
953
+ * @property {string} password - same as URL API
954
+ * @property {string} host - same as URL API
955
+ * @property {string} hostname - same as URL API
956
+ * @property {string} port - same as URL API
957
+ * @property {string} pathname - same as URL API
958
+ * @property {string} search - same as URL API
959
+ * @property {object} searchParams - same as URL API
960
+ * @property {string} hash - same as URL API
961
+ */
962
+ /**
963
+ * parse sanitized URL
964
+ *
965
+ * @param {string} url - URL input
966
+ * @returns {ParsedURL} - result with extended props based on URL API
967
+ */
968
+ parse(url) {
969
+ if (!isString(url)) {
970
+ throw new TypeError(`Expected String but got ${getType(url)}.`);
971
+ }
972
+ const sanitizedUrl = this.sanitize(url, {
973
+ allow: ["data", "file"]
974
+ });
975
+ const parsedUrl = /* @__PURE__ */ new Map([
976
+ ["input", url]
977
+ ]);
978
+ if (sanitizedUrl) {
979
+ const urlObj = new URL(sanitizedUrl);
980
+ const { pathname, protocol } = urlObj;
981
+ const schemeParts = protocol.replace(/:$/, "").split("+");
982
+ parsedUrl.set("valid", true);
983
+ if (schemeParts.includes("data")) {
984
+ const dataUrl = /* @__PURE__ */ new Map();
985
+ const [head, ...body] = pathname.split(",");
986
+ const data = `${body.join(",")}`;
987
+ const mediaType = head.split(";");
988
+ const isBase64 = mediaType[mediaType.length - 1] === "base64";
989
+ if (isBase64) {
990
+ mediaType.pop();
991
+ }
992
+ dataUrl.set("mime", mediaType.join(";"));
993
+ dataUrl.set("base64", isBase64);
994
+ dataUrl.set("data", data);
995
+ parsedUrl.set("data", Object.fromEntries(dataUrl));
996
+ } else {
997
+ parsedUrl.set("data", null);
998
+ }
999
+ for (const key in urlObj) {
1000
+ const value = urlObj[key];
1001
+ if (typeof value !== "function") {
1002
+ parsedUrl.set(key, value);
1003
+ }
1004
+ }
1005
+ } else {
1006
+ parsedUrl.set("valid", false);
1007
+ }
1008
+ return Object.fromEntries(parsedUrl);
1009
+ }
922
1010
  };
923
1011
  var urlSanitizer = new URLSanitizer();
924
1012
  var isUri = (uri) => urlSanitizer.isURI(uri);
@@ -928,7 +1016,8 @@ var isURI = async (uri) => {
928
1016
  };
929
1017
  var sanitizeUrl = (url, opt) => urlSanitizer.sanitize(url, opt ?? {
930
1018
  allow: [],
931
- deny: []
1019
+ deny: [],
1020
+ only: []
932
1021
  });
933
1022
  var sanitizeURL = async (url, opt) => {
934
1023
  const res = await sanitizeUrl(url, opt);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/mjs/common.js", "../src/lib/file/text-chars.json", "../src/lib/iana/uri-schemes.json", "../src/mjs/uri-util.js"],
4
- "sourcesContent": ["/**\n * common.js\n */\n\n/* constants */\nconst TYPE_FROM = 8;\nconst TYPE_TO = -1;\n\n/**\n * get type\n *\n * @param {*} o - object to check\n * @returns {string} - type of object\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * is string\n *\n * @param {*} o - object to check\n * @returns {boolean} - result\n */\nexport const isString = o => typeof o === 'string' || o instanceof String;\n", "[\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13,\n 27,\n 32,\n 33,\n 34,\n 35,\n 36,\n 37,\n 38,\n 39,\n 40,\n 41,\n 42,\n 43,\n 44,\n 45,\n 46,\n 47,\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 55,\n 56,\n 57,\n 58,\n 59,\n 60,\n 61,\n 62,\n 63,\n 64,\n 65,\n 66,\n 67,\n 68,\n 69,\n 70,\n 71,\n 72,\n 73,\n 74,\n 75,\n 76,\n 77,\n 78,\n 79,\n 80,\n 81,\n 82,\n 83,\n 84,\n 85,\n 86,\n 87,\n 88,\n 89,\n 90,\n 91,\n 92,\n 93,\n 94,\n 95,\n 96,\n 97,\n 98,\n 99,\n 100,\n 101,\n 102,\n 103,\n 104,\n 105,\n 106,\n 107,\n 108,\n 109,\n 110,\n 111,\n 112,\n 113,\n 114,\n 115,\n 116,\n 117,\n 118,\n 119,\n 120,\n 121,\n 122,\n 123,\n 124,\n 125,\n 126,\n 128,\n 129,\n 130,\n 131,\n 132,\n 133,\n 134,\n 135,\n 136,\n 137,\n 138,\n 139,\n 140,\n 141,\n 142,\n 143,\n 144,\n 145,\n 146,\n 147,\n 148,\n 149,\n 150,\n 151,\n 152,\n 153,\n 154,\n 155,\n 156,\n 157,\n 158,\n 159,\n 160,\n 161,\n 162,\n 163,\n 164,\n 165,\n 166,\n 167,\n 168,\n 169,\n 170,\n 171,\n 172,\n 173,\n 174,\n 175,\n 176,\n 177,\n 178,\n 179,\n 180,\n 181,\n 182,\n 183,\n 184,\n 185,\n 186,\n 187,\n 188,\n 189,\n 190,\n 191,\n 192,\n 193,\n 194,\n 195,\n 196,\n 197,\n 198,\n 199,\n 200,\n 201,\n 202,\n 203,\n 204,\n 205,\n 206,\n 207,\n 208,\n 209,\n 210,\n 211,\n 212,\n 213,\n 214,\n 215,\n 216,\n 217,\n 218,\n 219,\n 220,\n 221,\n 222,\n 223,\n 224,\n 225,\n 226,\n 227,\n 228,\n 229,\n 230,\n 231,\n 232,\n 233,\n 234,\n 235,\n 236,\n 237,\n 238,\n 239,\n 240,\n 241,\n 242,\n 243,\n 244,\n 245,\n 246,\n 247,\n 248,\n 249,\n 250,\n 251,\n 252,\n 253,\n 254,\n 255\n]\n", "[\n \"aaa\",\n \"aaas\",\n \"about\",\n \"acap\",\n \"acct\",\n \"acd\",\n \"acr\",\n \"adiumxtra\",\n \"adt\",\n \"afp\",\n \"afs\",\n \"aim\",\n \"amss\",\n \"android\",\n \"appdata\",\n \"apt\",\n \"ar\",\n \"ark\",\n \"attachment\",\n \"aw\",\n \"barion\",\n \"beshare\",\n \"bitcoin\",\n \"bitcoincash\",\n \"blob\",\n \"bolo\",\n \"browserext\",\n \"cabal\",\n \"calculator\",\n \"callto\",\n \"cap\",\n \"cast\",\n \"casts\",\n \"chrome\",\n \"chrome-extension\",\n \"cid\",\n \"coap\",\n \"coaps\",\n \"com-eventbrite-attendee\",\n \"content\",\n \"content-type\",\n \"crid\",\n \"cstr\",\n \"cvs\",\n \"dab\",\n \"dat\",\n \"data\",\n \"dav\",\n \"diaspora\",\n \"dict\",\n \"did\",\n \"dis\",\n \"dlna-playcontainer\",\n \"dlna-playsingle\",\n \"dns\",\n \"dntp\",\n \"doi\",\n \"dpp\",\n \"drm\",\n \"dtmi\",\n \"dtn\",\n \"dvb\",\n \"dvx\",\n \"dweb\",\n \"ed2k\",\n \"eid\",\n \"elsi\",\n \"embedded\",\n \"ens\",\n \"ethereum\",\n \"example\",\n \"facetime\",\n \"feed\",\n \"feedready\",\n \"fido\",\n \"file\",\n \"finger\",\n \"first-run-pen-experience\",\n \"fish\",\n \"fm\",\n \"ftp\",\n \"fuchsia-pkg\",\n \"geo\",\n \"gg\",\n \"git\",\n \"gitoid\",\n \"gizmoproject\",\n \"go\",\n \"gopher\",\n \"graph\",\n \"gtalk\",\n \"h323\",\n \"ham\",\n \"hcap\",\n \"hcp\",\n \"http\",\n \"https\",\n \"hxxp\",\n \"hxxps\",\n \"hydrazone\",\n \"hyper\",\n \"iax\",\n \"icap\",\n \"icon\",\n \"im\",\n \"imap\",\n \"info\",\n \"iotdisco\",\n \"ipfs\",\n \"ipn\",\n \"ipns\",\n \"ipp\",\n \"ipps\",\n \"irc\",\n \"irc6\",\n \"ircs\",\n \"iris\",\n \"iris.beep\",\n \"iris.lwz\",\n \"iris.xpc\",\n \"iris.xpcs\",\n \"isostore\",\n \"itms\",\n \"jabber\",\n \"jar\",\n \"jms\",\n \"keyparc\",\n \"lastfm\",\n \"lbry\",\n \"ldap\",\n \"ldaps\",\n \"leaptofrogans\",\n \"lorawan\",\n \"lpa\",\n \"lvlt\",\n \"magnet\",\n \"mailto\",\n \"maps\",\n \"market\",\n \"matrix\",\n \"message\",\n \"microsoft.windows.camera\",\n \"microsoft.windows.camera.multipicker\",\n \"microsoft.windows.camera.picker\",\n \"mid\",\n \"mms\",\n \"mongodb\",\n \"moz\",\n \"moz-extension\",\n \"ms-access\",\n \"ms-appinstaller\",\n \"ms-browser-extension\",\n \"ms-calculator\",\n \"ms-drive-to\",\n \"ms-enrollment\",\n \"ms-excel\",\n \"ms-eyecontrolspeech\",\n \"ms-gamebarservices\",\n \"ms-gamingoverlay\",\n \"ms-getoffice\",\n \"ms-help\",\n \"ms-infopath\",\n \"ms-inputapp\",\n \"ms-lockscreencomponent-config\",\n \"ms-media-stream-id\",\n \"ms-meetnow\",\n \"ms-mixedrealitycapture\",\n \"ms-mobileplans\",\n \"ms-newsandinterests\",\n \"ms-officeapp\",\n \"ms-people\",\n \"ms-powerpoint\",\n \"ms-project\",\n \"ms-publisher\",\n \"ms-remotedesktop-launch\",\n \"ms-restoretabcompanion\",\n \"ms-screenclip\",\n \"ms-screensketch\",\n \"ms-search\",\n \"ms-search-repair\",\n \"ms-secondary-screen-controller\",\n \"ms-secondary-screen-setup\",\n \"ms-settings\",\n \"ms-settings-airplanemode\",\n \"ms-settings-bluetooth\",\n \"ms-settings-camera\",\n \"ms-settings-cellular\",\n \"ms-settings-cloudstorage\",\n \"ms-settings-connectabledevices\",\n \"ms-settings-displays-topology\",\n \"ms-settings-emailandaccounts\",\n \"ms-settings-language\",\n \"ms-settings-location\",\n \"ms-settings-lock\",\n \"ms-settings-nfctransactions\",\n \"ms-settings-notifications\",\n \"ms-settings-power\",\n \"ms-settings-privacy\",\n \"ms-settings-proximity\",\n \"ms-settings-screenrotation\",\n \"ms-settings-wifi\",\n \"ms-settings-workplace\",\n \"ms-spd\",\n \"ms-stickers\",\n \"ms-sttoverlay\",\n \"ms-transit-to\",\n \"ms-useractivityset\",\n \"ms-virtualtouchpad\",\n \"ms-visio\",\n \"ms-walk-to\",\n \"ms-whiteboard\",\n \"ms-whiteboard-cmd\",\n \"ms-word\",\n \"msnim\",\n \"msrp\",\n \"msrps\",\n \"mss\",\n \"mt\",\n \"mtqp\",\n \"mumble\",\n \"mupdate\",\n \"mvn\",\n \"news\",\n \"nfs\",\n \"ni\",\n \"nih\",\n \"nntp\",\n \"notes\",\n \"num\",\n \"ocf\",\n \"oid\",\n \"onenote\",\n \"onenote-cmd\",\n \"opaquelocktoken\",\n \"openpgp4fpr\",\n \"otpauth\",\n \"palm\",\n \"paparazzi\",\n \"payment\",\n \"payto\",\n \"pkcs11\",\n \"platform\",\n \"pop\",\n \"pres\",\n \"proxy\",\n \"psyc\",\n \"pttp\",\n \"pwid\",\n \"qb\",\n \"query\",\n \"quic-transport\",\n \"redis\",\n \"rediss\",\n \"reload\",\n \"res\",\n \"resource\",\n \"rmi\",\n \"rsync\",\n \"rtmfp\",\n \"rtmp\",\n \"rtsp\",\n \"rtsps\",\n \"rtspu\",\n \"sarif\",\n \"secondlife\",\n \"secret-token\",\n \"service\",\n \"session\",\n \"sftp\",\n \"sgn\",\n \"shc\",\n \"sieve\",\n \"simpleledger\",\n \"simplex\",\n \"sip\",\n \"sips\",\n \"skype\",\n \"smb\",\n \"smp\",\n \"sms\",\n \"smtp\",\n \"snmp\",\n \"soap.beep\",\n \"soap.beeps\",\n \"soldat\",\n \"spiffe\",\n \"spotify\",\n \"ssb\",\n \"ssh\",\n \"starknet\",\n \"steam\",\n \"stun\",\n \"stuns\",\n \"submit\",\n \"svn\",\n \"swh\",\n \"swid\",\n \"swidpath\",\n \"tag\",\n \"taler\",\n \"teamspeak\",\n \"tel\",\n \"teliaeid\",\n \"telnet\",\n \"tftp\",\n \"things\",\n \"thismessage\",\n \"tip\",\n \"tn3270\",\n \"tool\",\n \"turn\",\n \"turns\",\n \"tv\",\n \"udp\",\n \"unreal\",\n \"urn\",\n \"ut2004\",\n \"uuid-in-package\",\n \"v-event\",\n \"vemmi\",\n \"ventrilo\",\n \"ves\",\n \"view-source\",\n \"vnc\",\n \"vscode\",\n \"vscode-insiders\",\n \"vsls\",\n \"w3\",\n \"wcr\",\n \"web3\",\n \"webcal\",\n \"wifi\",\n \"ws\",\n \"wss\",\n \"wtai\",\n \"wyciwyg\",\n \"xcon\",\n \"xcon-userid\",\n \"xfire\",\n \"xmlrpc.beep\",\n \"xmlrpc.beeps\",\n \"xmpp\",\n \"xri\",\n \"ymsgr\",\n \"z39.50r\",\n \"z39.50s\"\n]\n", "/**\n * uri-util.js\n */\n\n/* shared */\nimport { getType, isString } from './common.js';\nimport textChars from '../lib/file/text-chars.json' assert { type: 'json' };\nimport uriSchemes from '../lib/iana/uri-schemes.json' assert { type: 'json' };\n\n/* constants */\nconst HEX = 16;\nconst REG_BASE64 = /^[\\da-z+/\\-_=]+$/i;\nconst REG_DATA_URL = /data:[^,]*,[^\"]+/g;\nconst REG_DATA_URL_BASE64 = /data:[^,]*;?base64,[\\da-z+/\\-_=]+/i;\nconst REG_HTML_SP = /[<>\"'\\s]/g;\nconst REG_HTML_SP_URL_ENC = /%(?:2(?:2|7)|3(?:C|E))/g;\nconst REG_NUM_REF = /&#(x(?:00)?[\\dA-F]{2}|0?\\d{1,3});?/ig;\nconst REG_SCHEME = /^[a-z][\\da-z+\\-.]*$/;\nconst REG_SCHEME_CUSTOM = /^(?:ext|web)\\+[a-z]+$/;\nconst REG_SCRIPT = /(?:java|vb)script/;\nconst REG_URL_ENC = /^%[\\dA-F]{2}$/i;\nconst REG_URL_ENC_AMP = /%26/g;\n\n/**\n * get URL encoded string\n *\n * @param {string} str - string\n * @returns {string} - URL encoded string\n */\nexport const getUrlEncodedString = str => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n const chars = [];\n for (const ch of str) {\n chars.push(`%${ch.charCodeAt(0).toString(HEX).toUpperCase()}`);\n }\n return chars.join('');\n};\n\n/**\n * escape URL encoded HTML special chars\n *\n * @param {string} ch - URL encoded (percent encoded) char\n * @returns {string} - escaped URL encoded HTML special char / URL encoded char\n */\nexport const escapeUrlEncodedHtmlChars = ch => {\n if (isString(ch)) {\n if (REG_URL_ENC.test(ch)) {\n ch = ch.toUpperCase();\n } else {\n throw new Error(`Invalid URL encoded character: ${ch}`);\n }\n } else {\n throw new TypeError(`Expected String but got ${getType(ch)}.`);\n }\n const [amp, num, lt, gt, quot, apos] =\n ['&', '#', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n let escapedChar;\n if (ch === amp) {\n escapedChar = `${amp}amp;`;\n } else if (ch === lt) {\n escapedChar = `${amp}lt;`;\n } else if (ch === gt) {\n escapedChar = `${amp}gt;`;\n } else if (ch === quot) {\n escapedChar = `${amp}quot;`;\n } else if (ch === apos) {\n escapedChar = `${amp}${num}39;`;\n } else {\n escapedChar = ch;\n }\n return escapedChar;\n};\n\n/**\n * parse base64 encoded data\n *\n * @param {string} data - base64 encoded data\n * @returns {string} - parsed text data / base64 encoded data if binary\n */\nexport const parseBase64 = data => {\n if (!isString(data)) {\n throw new TypeError(`Expected String but got ${getType(data)}.`);\n } else if (!REG_BASE64.test(data)) {\n throw new Error(`Invalid base64 data: ${data}`);\n }\n const bin = atob(data);\n const uint8arr = Uint8Array.from([...bin].map(c => c.charCodeAt(0)));\n const textCharCodes = new Set(textChars);\n let parsedData;\n if (uint8arr.every(c => textCharCodes.has(c))) {\n parsedData = bin.replace(/\\s/g, getUrlEncodedString);\n } else {\n parsedData = data;\n }\n return parsedData;\n};\n\n/**\n * parse URL encoded numeric character references in the range 0x00 to 0xFF\n *\n * @param {string} str - string\n * @param {number} nest - nest level\n * @returns {string} - parsed string\n */\nexport const parseUrlEncodedNumCharRef = (str, nest = 0) => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n if (!Number.isInteger(nest)) {\n throw new TypeError(`Expected Number but got ${getType(nest)}.`);\n } else if (nest > HEX) {\n throw new Error('Character references nested too deeply.');\n }\n let res = decodeURIComponent(str);\n if (/&#/.test(res)) {\n const textCharCodes = new Set(textChars);\n const items = [...res.matchAll(REG_NUM_REF)].reverse();\n for (const item of items) {\n const [numCharRef, value] = item;\n let num;\n if (/^x[\\dA-F]+/i.test(value)) {\n num = parseInt(`0${value}`, HEX);\n } else if (/^[\\d]+/.test(value)) {\n num = parseInt(value);\n }\n if (Number.isInteger(num)) {\n const { index } = item;\n const [preNum, postNum] = [\n res.substring(0, index),\n res.substring(index + numCharRef.length)\n ];\n if (textCharCodes.has(num)) {\n res = `${preNum}${String.fromCharCode(num)}${postNum}`;\n if (/#x?$/.test(preNum) || /^#(?:x(?:00)?[2-7]|\\d)/.test(postNum)) {\n res = parseUrlEncodedNumCharRef(res, ++nest);\n }\n } else if (num < HEX * HEX) {\n res = `${preNum}${postNum}`;\n }\n }\n }\n }\n return res;\n};\n\n/**\n * URI schemes\n *\n */\nexport class URISchemes {\n /* private fields */\n #schemes;\n\n /**\n * construct\n */\n constructor() {\n this.#schemes = new Set(uriSchemes);\n }\n\n /**\n * get schemes\n *\n * @see {@link https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml}\n * - Historical schemes omitted\n * - 'moz-extension' scheme added\n * @returns {Array.<string>} - array of schemes\n */\n get() {\n return [...this.#schemes];\n }\n\n /**\n * has scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n has(scheme) {\n return this.#schemes.has(scheme);\n }\n\n /**\n * add scheme\n * NOTE: `javascript` and/or `vbscript` schemes can not be registered\n *\n * @param {string} scheme - scheme\n * @returns {Array.<string>} - array of schemes\n */\n add(scheme) {\n if (!isString(scheme)) {\n throw new TypeError(`Expected String but got ${getType(scheme)}.`);\n } else if (REG_SCRIPT.test(scheme) || !REG_SCHEME.test(scheme)) {\n throw new Error(`Invalid scheme: ${scheme}`);\n }\n this.#schemes.add(scheme);\n return [...this.#schemes];\n }\n\n /**\n * remove scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n remove(scheme) {\n return this.#schemes.delete(scheme);\n }\n\n /**\n * is URI\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\n isURI(uri) {\n let res;\n if (isString(uri)) {\n try {\n const { protocol } = new URL(uri);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n res = (!REG_SCRIPT.test(scheme) && REG_SCHEME_CUSTOM.test(scheme)) ||\n schemeParts.every(s => this.#schemes.has(s));\n } catch (e) {\n res = false;\n }\n }\n return !!res;\n }\n};\n\n/* URL sanitizer */\nexport class URLSanitizer extends URISchemes {\n /* private fields */\n #nest;\n #recurse;\n\n /**\n * construct\n */\n constructor() {\n super();\n this.#nest = 0;\n this.#recurse = new Set();\n }\n\n /**\n * sanitize URL\n * NOTE: `data` and/or `file` schemes must be explicitly allowed\n * `javascript` and/or `vbscript` schemes can not be allowed\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @param {Array.<string>} opt.allow - array of allowed schemes\n * @param {Array.<string>} opt.deny - array of denied schemes\n * @returns {?string} - sanitized URL\n */\n sanitize(url, opt = { allow: [], deny: [] }) {\n if (this.#nest > HEX) {\n this.#nest = 0;\n throw new Error('Data URLs nested too deeply.');\n }\n let sanitizedUrl;\n if (super.isURI(url)) {\n const { allow, deny } = opt ?? {};\n const { hash, href, pathname, protocol, search } = new URL(url);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n const schemeMap = new Map([\n ['data', false],\n ['file', false],\n ['javascrpt', false],\n ['vbscript', false]\n ]);\n if (Array.isArray(allow) && allow.length) {\n const items = Object.values(allow);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (!REG_SCRIPT.test(item)) {\n schemeMap.set(item, true);\n }\n }\n }\n }\n if (Array.isArray(deny) && deny.length) {\n const items = Object.values(deny);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (item) {\n schemeMap.set(item, false);\n }\n }\n }\n }\n let bool;\n for (const [key, value] of schemeMap.entries()) {\n bool = value || (scheme !== key && schemeParts.every(s => s !== key));\n if (!bool) {\n break;\n }\n }\n if (bool) {\n let escapeHtml;\n let urlToSanitize = href;\n if (schemeParts.includes('data')) {\n const [head, ...body] = pathname.split(',');\n const data = `${body.join(',')}${search}${hash}`;\n const mediaType = head.split(';');\n let parsedData = data;\n if (mediaType[mediaType.length - 1] === 'base64') {\n mediaType.pop();\n parsedData = parseBase64(data);\n } else {\n try {\n const decodedData = parseUrlEncodedNumCharRef(parsedData);\n const { protocol: dataScheme } = new URL(decodedData.trim());\n const dataSchemeParts = dataScheme.replace(/:$/, '').split('+');\n if (dataSchemeParts.some(s => REG_SCRIPT.test(s))) {\n urlToSanitize = '';\n }\n } catch (e) {\n // fall through\n }\n }\n const containsDataUrl = /data:[^,]*,/.test(parsedData);\n if (parsedData !== data || containsDataUrl) {\n if (containsDataUrl) {\n const matchedDataUrls = parsedData.matchAll(REG_DATA_URL);\n const items = [...matchedDataUrls].reverse();\n for (const item of items) {\n let [dataUrl] = item;\n if (REG_DATA_URL_BASE64.test(dataUrl)) {\n [dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);\n }\n this.#nest++;\n this.#recurse.add(dataUrl);\n const parsedDataUrl = this.sanitize(dataUrl, {\n allow: ['data']\n });\n if (parsedDataUrl) {\n const { index } = item;\n const [preDataUrl, postDataUrl] = [\n parsedData.substring(0, index),\n parsedData.substring(index + dataUrl.length)\n ];\n parsedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;\n }\n }\n if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n urlToSanitize = `${scheme}:${mediaType.join(';')},${parsedData}`;\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else {\n escapeHtml = true;\n }\n if (urlToSanitize) {\n sanitizedUrl = urlToSanitize\n .replace(REG_HTML_SP, getUrlEncodedString)\n .replace(REG_URL_ENC_AMP, escapeUrlEncodedHtmlChars);\n if (escapeHtml) {\n sanitizedUrl = sanitizedUrl\n .replace(REG_HTML_SP_URL_ENC, escapeUrlEncodedHtmlChars);\n this.#nest = 0;\n }\n } else {\n sanitizedUrl = urlToSanitize;\n this.#nest = 0;\n }\n }\n }\n return sanitizedUrl || null;\n }\n};\n\n/* instance */\nconst urlSanitizer = new URLSanitizer();\n\n/* aliases and async wrappers */\n/**\n * is URI sync\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\nconst isUri = uri => urlSanitizer.isURI(uri);\n\n/**\n * is URI async\n *\n * @param {string} uri - URI input\n * @returns {Promise.<boolean>} - result\n */\nexport const isURI = async uri => {\n const res = await isUri(uri);\n return res;\n};\n\n/**\n * sanitize URL sync\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {?string} - sanitized URL\n */\nconst sanitizeUrl = (url, opt) => urlSanitizer.sanitize(url, opt ?? {\n allow: [],\n deny: []\n});\n\n/**\n * sanitize URL async\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {Promise.<?string>} - sanitized URL\n */\nexport const sanitizeURL = async (url, opt) => {\n const res = await sanitizeUrl(url, opt);\n return res;\n};\n\n/* export instance and aliases */\nexport {\n urlSanitizer as default,\n isUri as isURISync,\n sanitizeUrl as sanitizeURLSync\n};\n"],
5
- "mappings": ";AAKA,IAAM,YAAY;AAClB,IAAM,UAAU;AAQT,IAAM,UAAU,OACrB,OAAO,UAAU,SAAS,KAAK,CAAC,EAAE,MAAM,WAAW,OAAO;AAQrD,IAAM,WAAW,OAAK,OAAO,MAAM,YAAY,aAAa;;;ACvBnE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACxOA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACjVA,IAAM,MAAM;AACZ,IAAM,aAAa;AACnB,IAAM,eAAe;AACrB,IAAM,sBAA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",
4
+ "sourcesContent": ["/**\n * common.js\n */\n\n/* constants */\nconst TYPE_FROM = 8;\nconst TYPE_TO = -1;\n\n/**\n * get type\n *\n * @param {*} o - object to check\n * @returns {string} - type of object\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * is string\n *\n * @param {*} o - object to check\n * @returns {boolean} - result\n */\nexport const isString = o => typeof o === 'string' || o instanceof String;\n", "[\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13,\n 27,\n 32,\n 33,\n 34,\n 35,\n 36,\n 37,\n 38,\n 39,\n 40,\n 41,\n 42,\n 43,\n 44,\n 45,\n 46,\n 47,\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 55,\n 56,\n 57,\n 58,\n 59,\n 60,\n 61,\n 62,\n 63,\n 64,\n 65,\n 66,\n 67,\n 68,\n 69,\n 70,\n 71,\n 72,\n 73,\n 74,\n 75,\n 76,\n 77,\n 78,\n 79,\n 80,\n 81,\n 82,\n 83,\n 84,\n 85,\n 86,\n 87,\n 88,\n 89,\n 90,\n 91,\n 92,\n 93,\n 94,\n 95,\n 96,\n 97,\n 98,\n 99,\n 100,\n 101,\n 102,\n 103,\n 104,\n 105,\n 106,\n 107,\n 108,\n 109,\n 110,\n 111,\n 112,\n 113,\n 114,\n 115,\n 116,\n 117,\n 118,\n 119,\n 120,\n 121,\n 122,\n 123,\n 124,\n 125,\n 126,\n 128,\n 129,\n 130,\n 131,\n 132,\n 133,\n 134,\n 135,\n 136,\n 137,\n 138,\n 139,\n 140,\n 141,\n 142,\n 143,\n 144,\n 145,\n 146,\n 147,\n 148,\n 149,\n 150,\n 151,\n 152,\n 153,\n 154,\n 155,\n 156,\n 157,\n 158,\n 159,\n 160,\n 161,\n 162,\n 163,\n 164,\n 165,\n 166,\n 167,\n 168,\n 169,\n 170,\n 171,\n 172,\n 173,\n 174,\n 175,\n 176,\n 177,\n 178,\n 179,\n 180,\n 181,\n 182,\n 183,\n 184,\n 185,\n 186,\n 187,\n 188,\n 189,\n 190,\n 191,\n 192,\n 193,\n 194,\n 195,\n 196,\n 197,\n 198,\n 199,\n 200,\n 201,\n 202,\n 203,\n 204,\n 205,\n 206,\n 207,\n 208,\n 209,\n 210,\n 211,\n 212,\n 213,\n 214,\n 215,\n 216,\n 217,\n 218,\n 219,\n 220,\n 221,\n 222,\n 223,\n 224,\n 225,\n 226,\n 227,\n 228,\n 229,\n 230,\n 231,\n 232,\n 233,\n 234,\n 235,\n 236,\n 237,\n 238,\n 239,\n 240,\n 241,\n 242,\n 243,\n 244,\n 245,\n 246,\n 247,\n 248,\n 249,\n 250,\n 251,\n 252,\n 253,\n 254,\n 255\n]\n", "[\n \"aaa\",\n \"aaas\",\n \"about\",\n \"acap\",\n \"acct\",\n \"acd\",\n \"acr\",\n \"adiumxtra\",\n \"adt\",\n \"afp\",\n \"afs\",\n \"aim\",\n \"amss\",\n \"android\",\n \"appdata\",\n \"apt\",\n \"ar\",\n \"ark\",\n \"attachment\",\n \"aw\",\n \"barion\",\n \"beshare\",\n \"bitcoin\",\n \"bitcoincash\",\n \"blob\",\n \"bolo\",\n \"browserext\",\n \"cabal\",\n \"calculator\",\n \"callto\",\n \"cap\",\n \"cast\",\n \"casts\",\n \"chrome\",\n \"chrome-extension\",\n \"cid\",\n \"coap\",\n \"coaps\",\n \"com-eventbrite-attendee\",\n \"content\",\n \"content-type\",\n \"crid\",\n \"cstr\",\n \"cvs\",\n \"dab\",\n \"dat\",\n \"data\",\n \"dav\",\n \"diaspora\",\n \"dict\",\n \"did\",\n \"dis\",\n \"dlna-playcontainer\",\n \"dlna-playsingle\",\n \"dns\",\n \"dntp\",\n \"doi\",\n \"dpp\",\n \"drm\",\n \"dtmi\",\n \"dtn\",\n \"dvb\",\n \"dvx\",\n \"dweb\",\n \"ed2k\",\n \"eid\",\n \"elsi\",\n \"embedded\",\n \"ens\",\n \"ethereum\",\n \"example\",\n \"facetime\",\n \"feed\",\n \"feedready\",\n \"fido\",\n \"file\",\n \"finger\",\n \"first-run-pen-experience\",\n \"fish\",\n \"fm\",\n \"ftp\",\n \"fuchsia-pkg\",\n \"geo\",\n \"gg\",\n \"git\",\n \"gitoid\",\n \"gizmoproject\",\n \"go\",\n \"gopher\",\n \"graph\",\n \"gtalk\",\n \"h323\",\n \"ham\",\n \"hcap\",\n \"hcp\",\n \"http\",\n \"https\",\n \"hxxp\",\n \"hxxps\",\n \"hydrazone\",\n \"hyper\",\n \"iax\",\n \"icap\",\n \"icon\",\n \"im\",\n \"imap\",\n \"info\",\n \"iotdisco\",\n \"ipfs\",\n \"ipn\",\n \"ipns\",\n \"ipp\",\n \"ipps\",\n \"irc\",\n \"irc6\",\n \"ircs\",\n \"iris\",\n \"iris.beep\",\n \"iris.lwz\",\n \"iris.xpc\",\n \"iris.xpcs\",\n \"isostore\",\n \"itms\",\n \"jabber\",\n \"jar\",\n \"jms\",\n \"keyparc\",\n \"lastfm\",\n \"lbry\",\n \"ldap\",\n \"ldaps\",\n \"leaptofrogans\",\n \"lorawan\",\n \"lpa\",\n \"lvlt\",\n \"magnet\",\n \"mailto\",\n \"maps\",\n \"market\",\n \"matrix\",\n \"message\",\n \"microsoft.windows.camera\",\n \"microsoft.windows.camera.multipicker\",\n \"microsoft.windows.camera.picker\",\n \"mid\",\n \"mms\",\n \"mongodb\",\n \"moz\",\n \"moz-extension\",\n \"ms-access\",\n \"ms-appinstaller\",\n \"ms-browser-extension\",\n \"ms-calculator\",\n \"ms-drive-to\",\n \"ms-enrollment\",\n \"ms-excel\",\n \"ms-eyecontrolspeech\",\n \"ms-gamebarservices\",\n \"ms-gamingoverlay\",\n \"ms-getoffice\",\n \"ms-help\",\n \"ms-infopath\",\n \"ms-inputapp\",\n \"ms-lockscreencomponent-config\",\n \"ms-media-stream-id\",\n \"ms-meetnow\",\n \"ms-mixedrealitycapture\",\n \"ms-mobileplans\",\n \"ms-newsandinterests\",\n \"ms-officeapp\",\n \"ms-people\",\n \"ms-powerpoint\",\n \"ms-project\",\n \"ms-publisher\",\n \"ms-remotedesktop-launch\",\n \"ms-restoretabcompanion\",\n \"ms-screenclip\",\n \"ms-screensketch\",\n \"ms-search\",\n \"ms-search-repair\",\n \"ms-secondary-screen-controller\",\n \"ms-secondary-screen-setup\",\n \"ms-settings\",\n \"ms-settings-airplanemode\",\n \"ms-settings-bluetooth\",\n \"ms-settings-camera\",\n \"ms-settings-cellular\",\n \"ms-settings-cloudstorage\",\n \"ms-settings-connectabledevices\",\n \"ms-settings-displays-topology\",\n \"ms-settings-emailandaccounts\",\n \"ms-settings-language\",\n \"ms-settings-location\",\n \"ms-settings-lock\",\n \"ms-settings-nfctransactions\",\n \"ms-settings-notifications\",\n \"ms-settings-power\",\n \"ms-settings-privacy\",\n \"ms-settings-proximity\",\n \"ms-settings-screenrotation\",\n \"ms-settings-wifi\",\n \"ms-settings-workplace\",\n \"ms-spd\",\n \"ms-stickers\",\n \"ms-sttoverlay\",\n \"ms-transit-to\",\n \"ms-useractivityset\",\n \"ms-virtualtouchpad\",\n \"ms-visio\",\n \"ms-walk-to\",\n \"ms-whiteboard\",\n \"ms-whiteboard-cmd\",\n \"ms-word\",\n \"msnim\",\n \"msrp\",\n \"msrps\",\n \"mss\",\n \"mt\",\n \"mtqp\",\n \"mumble\",\n \"mupdate\",\n \"mvn\",\n \"news\",\n \"nfs\",\n \"ni\",\n \"nih\",\n \"nntp\",\n \"notes\",\n \"num\",\n \"ocf\",\n \"oid\",\n \"onenote\",\n \"onenote-cmd\",\n \"opaquelocktoken\",\n \"openpgp4fpr\",\n \"otpauth\",\n \"palm\",\n \"paparazzi\",\n \"payment\",\n \"payto\",\n \"pkcs11\",\n \"platform\",\n \"pop\",\n \"pres\",\n \"proxy\",\n \"psyc\",\n \"pttp\",\n \"pwid\",\n \"qb\",\n \"query\",\n \"quic-transport\",\n \"redis\",\n \"rediss\",\n \"reload\",\n \"res\",\n \"resource\",\n \"rmi\",\n \"rsync\",\n \"rtmfp\",\n \"rtmp\",\n \"rtsp\",\n \"rtsps\",\n \"rtspu\",\n \"sarif\",\n \"secondlife\",\n \"secret-token\",\n \"service\",\n \"session\",\n \"sftp\",\n \"sgn\",\n \"shc\",\n \"sieve\",\n \"simpleledger\",\n \"simplex\",\n \"sip\",\n \"sips\",\n \"skype\",\n \"smb\",\n \"smp\",\n \"sms\",\n \"smtp\",\n \"snmp\",\n \"soap.beep\",\n \"soap.beeps\",\n \"soldat\",\n \"spiffe\",\n \"spotify\",\n \"ssb\",\n \"ssh\",\n \"starknet\",\n \"steam\",\n \"stun\",\n \"stuns\",\n \"submit\",\n \"svn\",\n \"swh\",\n \"swid\",\n \"swidpath\",\n \"tag\",\n \"taler\",\n \"teamspeak\",\n \"tel\",\n \"teliaeid\",\n \"telnet\",\n \"tftp\",\n \"things\",\n \"thismessage\",\n \"tip\",\n \"tn3270\",\n \"tool\",\n \"turn\",\n \"turns\",\n \"tv\",\n \"udp\",\n \"unreal\",\n \"urn\",\n \"ut2004\",\n \"uuid-in-package\",\n \"v-event\",\n \"vemmi\",\n \"ventrilo\",\n \"ves\",\n \"view-source\",\n \"vnc\",\n \"vscode\",\n \"vscode-insiders\",\n \"vsls\",\n \"w3\",\n \"wcr\",\n \"web3\",\n \"webcal\",\n \"wifi\",\n \"ws\",\n \"wss\",\n \"wtai\",\n \"wyciwyg\",\n \"xcon\",\n \"xcon-userid\",\n \"xfire\",\n \"xmlrpc.beep\",\n \"xmlrpc.beeps\",\n \"xmpp\",\n \"xri\",\n \"ymsgr\",\n \"z39.50r\",\n \"z39.50s\"\n]\n", "/**\n * uri-util.js\n */\n\n/* shared */\nimport { getType, isString } from './common.js';\nimport textChars from '../lib/file/text-chars.json' assert { type: 'json' };\nimport uriSchemes from '../lib/iana/uri-schemes.json' assert { type: 'json' };\n\n/* constants */\nconst HEX = 16;\nconst REG_BASE64 = /^[\\da-z+/\\-_=]+$/i;\nconst REG_DATA_URL = /data:[^,]*,[^\"]+/g;\nconst REG_DATA_URL_BASE64 = /data:[^,]*;?base64,[\\da-z+/\\-_=]+/i;\nconst REG_HTML_SP = /[<>\"'\\s]/g;\nconst REG_HTML_SP_URL_ENC = /%(?:2(?:2|7)|3(?:C|E))/g;\nconst REG_NUM_REF = /&#(x(?:00)?[\\dA-F]{2}|0?\\d{1,3});?/ig;\nconst REG_SCHEME = /^[a-z][\\da-z+\\-.]*$/;\nconst REG_SCHEME_CUSTOM = /^(?:ext|web)\\+[a-z]+$/;\nconst REG_SCRIPT = /(?:java|vb)script/;\nconst REG_URL_ENC = /^%[\\dA-F]{2}$/i;\nconst REG_URL_ENC_AMP = /%26/g;\n\n/**\n * get URL encoded string\n *\n * @param {string} str - string\n * @returns {string} - URL encoded string\n */\nexport const getUrlEncodedString = str => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n const chars = [];\n for (const ch of str) {\n chars.push(`%${ch.charCodeAt(0).toString(HEX).toUpperCase()}`);\n }\n return chars.join('');\n};\n\n/**\n * escape URL encoded HTML special chars\n *\n * @param {string} ch - URL encoded (percent encoded) char\n * @returns {string} - escaped URL encoded HTML special char / URL encoded char\n */\nexport const escapeUrlEncodedHtmlChars = ch => {\n if (isString(ch)) {\n if (REG_URL_ENC.test(ch)) {\n ch = ch.toUpperCase();\n } else {\n throw new Error(`Invalid URL encoded character: ${ch}`);\n }\n } else {\n throw new TypeError(`Expected String but got ${getType(ch)}.`);\n }\n const [amp, num, lt, gt, quot, apos] =\n ['&', '#', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n let escapedChar;\n if (ch === amp) {\n escapedChar = `${amp}amp;`;\n } else if (ch === lt) {\n escapedChar = `${amp}lt;`;\n } else if (ch === gt) {\n escapedChar = `${amp}gt;`;\n } else if (ch === quot) {\n escapedChar = `${amp}quot;`;\n } else if (ch === apos) {\n escapedChar = `${amp}${num}39;`;\n } else {\n escapedChar = ch;\n }\n return escapedChar;\n};\n\n/**\n * parse base64 encoded data\n *\n * @param {string} data - base64 encoded data\n * @returns {string} - parsed text data / base64 encoded data if binary\n */\nexport const parseBase64 = data => {\n if (!isString(data)) {\n throw new TypeError(`Expected String but got ${getType(data)}.`);\n } else if (!REG_BASE64.test(data)) {\n throw new Error(`Invalid base64 data: ${data}`);\n }\n const bin = atob(data);\n const uint8arr = Uint8Array.from([...bin].map(c => c.charCodeAt(0)));\n const textCharCodes = new Set(textChars);\n let parsedData;\n if (uint8arr.every(c => textCharCodes.has(c))) {\n parsedData = bin.replace(/\\s/g, getUrlEncodedString);\n } else {\n parsedData = data;\n }\n return parsedData;\n};\n\n/**\n * parse URL encoded numeric character references in the range 0x00 to 0xFF\n *\n * @param {string} str - string\n * @param {number} nest - nest level\n * @returns {string} - parsed string\n */\nexport const parseUrlEncodedNumCharRef = (str, nest = 0) => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n if (!Number.isInteger(nest)) {\n throw new TypeError(`Expected Number but got ${getType(nest)}.`);\n } else if (nest > HEX) {\n throw new Error('Character references nested too deeply.');\n }\n let res = decodeURIComponent(str);\n if (/&#/.test(res)) {\n const textCharCodes = new Set(textChars);\n const items = [...res.matchAll(REG_NUM_REF)].reverse();\n for (const item of items) {\n const [numCharRef, value] = item;\n let num;\n if (/^x[\\dA-F]+/i.test(value)) {\n num = parseInt(`0${value}`, HEX);\n } else if (/^[\\d]+/.test(value)) {\n num = parseInt(value);\n }\n if (Number.isInteger(num)) {\n const { index } = item;\n const [preNum, postNum] = [\n res.substring(0, index),\n res.substring(index + numCharRef.length)\n ];\n if (textCharCodes.has(num)) {\n res = `${preNum}${String.fromCharCode(num)}${postNum}`;\n if (/#x?$/.test(preNum) || /^#(?:x(?:00)?[2-7]|\\d)/.test(postNum)) {\n res = parseUrlEncodedNumCharRef(res, ++nest);\n }\n } else if (num < HEX * HEX) {\n res = `${preNum}${postNum}`;\n }\n }\n }\n }\n return res;\n};\n\n/**\n * URI schemes\n *\n */\nexport class URISchemes {\n /* private fields */\n #schemes;\n\n /**\n * construct\n */\n constructor() {\n this.#schemes = new Set(uriSchemes);\n }\n\n /**\n * get schemes\n *\n * @see {@link https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml}\n * - Historical schemes omitted\n * - 'moz-extension' scheme added\n * @returns {Array.<string>} - array of schemes\n */\n get() {\n return [...this.#schemes];\n }\n\n /**\n * has scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n has(scheme) {\n return this.#schemes.has(scheme);\n }\n\n /**\n * add scheme\n * NOTE: `javascript` and/or `vbscript` schemes can not be registered\n *\n * @param {string} scheme - scheme\n * @returns {Array.<string>} - array of schemes\n */\n add(scheme) {\n if (!isString(scheme)) {\n throw new TypeError(`Expected String but got ${getType(scheme)}.`);\n } else if (REG_SCRIPT.test(scheme) || !REG_SCHEME.test(scheme)) {\n throw new Error(`Invalid scheme: ${scheme}`);\n }\n this.#schemes.add(scheme);\n return [...this.#schemes];\n }\n\n /**\n * remove scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n remove(scheme) {\n return this.#schemes.delete(scheme);\n }\n\n /**\n * is URI\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\n isURI(uri) {\n let res;\n if (isString(uri)) {\n try {\n const { protocol } = new URL(uri);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n res = (!REG_SCRIPT.test(scheme) && REG_SCHEME_CUSTOM.test(scheme)) ||\n schemeParts.every(s => this.#schemes.has(s));\n } catch (e) {\n res = false;\n }\n }\n return !!res;\n }\n};\n\n/* URL sanitizer */\nexport class URLSanitizer extends URISchemes {\n /* private fields */\n #nest;\n #recurse;\n\n /**\n * construct\n */\n constructor() {\n super();\n this.#nest = 0;\n this.#recurse = new Set();\n }\n\n /**\n * sanitize URL\n * NOTE: `data` and/or `file` schemes must be explicitly allowed\n * `javascript` and/or `vbscript` schemes can not be allowed\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @param {Array.<string>} opt.allow - array of allowed schemes\n * @param {Array.<string>} opt.deny - array of denied schemes\n * @param {Array.<string>} opt.only - array of specific schemes to allow\n * @returns {?string} - sanitized URL\n */\n sanitize(url, opt = { allow: [], deny: [], only: [] }) {\n if (this.#nest > HEX) {\n this.#nest = 0;\n throw new Error('Data URLs nested too deeply.');\n }\n let sanitizedUrl;\n if (super.isURI(url)) {\n const { allow, deny, only } = opt ?? {};\n const { hash, href, pathname, protocol, search } = new URL(url);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n const schemeMap = new Map([\n ['data', false],\n ['file', false],\n ['javascrpt', false],\n ['vbscript', false]\n ]);\n if (Array.isArray(only) && only.length) {\n const schemes = super.get();\n for (const item of schemes) {\n schemeMap.set(item, false);\n }\n const items = Object.values(only);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (!REG_SCRIPT.test(item)) {\n schemeMap.set(item, true);\n }\n }\n }\n } else {\n if (Array.isArray(allow) && allow.length) {\n const items = Object.values(allow);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (!REG_SCRIPT.test(item)) {\n schemeMap.set(item, true);\n }\n }\n }\n }\n if (Array.isArray(deny) && deny.length) {\n const items = Object.values(deny);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (item) {\n schemeMap.set(item, false);\n }\n }\n }\n }\n }\n let bool;\n for (const [key, value] of schemeMap.entries()) {\n bool = value || (scheme !== key && schemeParts.every(s => s !== key));\n if (!bool) {\n break;\n }\n }\n if (bool) {\n let escapeHtml;\n let urlToSanitize = href;\n if (schemeParts.includes('data')) {\n const [head, ...body] = pathname.split(',');\n const data = `${body.join(',')}${search}${hash}`;\n const mediaType = head.split(';');\n let parsedData = data;\n if (mediaType[mediaType.length - 1] === 'base64') {\n mediaType.pop();\n parsedData = parseBase64(data);\n } else {\n try {\n const decodedData = parseUrlEncodedNumCharRef(parsedData);\n const { protocol: dataScheme } = new URL(decodedData.trim());\n const dataSchemeParts = dataScheme.replace(/:$/, '').split('+');\n if (dataSchemeParts.some(s => REG_SCRIPT.test(s))) {\n urlToSanitize = '';\n }\n } catch (e) {\n // fall through\n }\n }\n const containsDataUrl = /data:[^,]*,/.test(parsedData);\n if (parsedData !== data || containsDataUrl) {\n if (containsDataUrl) {\n const matchedDataUrls = parsedData.matchAll(REG_DATA_URL);\n const items = [...matchedDataUrls].reverse();\n for (const item of items) {\n let [dataUrl] = item;\n if (REG_DATA_URL_BASE64.test(dataUrl)) {\n [dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);\n }\n this.#nest++;\n this.#recurse.add(dataUrl);\n const parsedDataUrl = this.sanitize(dataUrl, {\n allow: ['data']\n });\n if (parsedDataUrl) {\n const { index } = item;\n const [preDataUrl, postDataUrl] = [\n parsedData.substring(0, index),\n parsedData.substring(index + dataUrl.length)\n ];\n parsedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;\n }\n }\n if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n urlToSanitize = `${scheme}:${mediaType.join(';')},${parsedData}`;\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else {\n escapeHtml = true;\n }\n if (urlToSanitize) {\n sanitizedUrl = urlToSanitize\n .replace(REG_HTML_SP, getUrlEncodedString)\n .replace(REG_URL_ENC_AMP, escapeUrlEncodedHtmlChars);\n if (escapeHtml) {\n sanitizedUrl = sanitizedUrl\n .replace(REG_HTML_SP_URL_ENC, escapeUrlEncodedHtmlChars);\n this.#nest = 0;\n }\n } else {\n sanitizedUrl = urlToSanitize;\n this.#nest = 0;\n }\n }\n }\n return sanitizedUrl || null;\n }\n\n /**\n * object with extended props based on URL API\n *\n * @typedef {object} ParsedURL\n * @property {string} input - URL input\n * @property {boolean} valid - is valid URI\n * @property {object} data - parsed result of data URL, `null`able\n * @property {string} data.mime - MIME type\n * @property {boolean} data.base64 - `true` if base64 encoded\n * @property {string} data.data - data part of the data URL\n * @property {string} href - same as URL API\n * @property {string} origin - same as URL API\n * @property {string} protocol - same as URL API\n * @property {string} username - same as URL API\n * @property {string} password - same as URL API\n * @property {string} host - same as URL API\n * @property {string} hostname - same as URL API\n * @property {string} port - same as URL API\n * @property {string} pathname - same as URL API\n * @property {string} search - same as URL API\n * @property {object} searchParams - same as URL API\n * @property {string} hash - same as URL API\n */\n\n /**\n * parse sanitized URL\n *\n * @param {string} url - URL input\n * @returns {ParsedURL} - result with extended props based on URL API\n */\n parse(url) {\n if (!isString(url)) {\n throw new TypeError(`Expected String but got ${getType(url)}.`);\n }\n const sanitizedUrl = this.sanitize(url, {\n allow: ['data', 'file']\n });\n const parsedUrl = new Map([\n ['input', url]\n ]);\n if (sanitizedUrl) {\n const urlObj = new URL(sanitizedUrl);\n const { pathname, protocol } = urlObj;\n const schemeParts = protocol.replace(/:$/, '').split('+');\n parsedUrl.set('valid', true);\n if (schemeParts.includes('data')) {\n const dataUrl = new Map();\n const [head, ...body] = pathname.split(',');\n const data = `${body.join(',')}`;\n const mediaType = head.split(';');\n const isBase64 = mediaType[mediaType.length - 1] === 'base64';\n if (isBase64) {\n mediaType.pop();\n }\n dataUrl.set('mime', mediaType.join(';'));\n dataUrl.set('base64', isBase64);\n dataUrl.set('data', data);\n parsedUrl.set('data', Object.fromEntries(dataUrl));\n } else {\n parsedUrl.set('data', null);\n }\n for (const key in urlObj) {\n const value = urlObj[key];\n if (typeof value !== 'function') {\n parsedUrl.set(key, value);\n }\n }\n } else {\n parsedUrl.set('valid', false);\n }\n return Object.fromEntries(parsedUrl);\n }\n};\n\n/* instance */\nconst urlSanitizer = new URLSanitizer();\n\n/* aliases and async wrappers */\n/**\n * is URI sync\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\nconst isUri = uri => urlSanitizer.isURI(uri);\n\n/**\n * is URI async\n *\n * @param {string} uri - URI input\n * @returns {Promise.<boolean>} - result\n */\nexport const isURI = async uri => {\n const res = await isUri(uri);\n return res;\n};\n\n/**\n * sanitize URL sync\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {?string} - sanitized URL\n */\nconst sanitizeUrl = (url, opt) => urlSanitizer.sanitize(url, opt ?? {\n allow: [],\n deny: [],\n only: []\n});\n\n/**\n * sanitize URL async\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {Promise.<?string>} - sanitized URL\n */\nexport const sanitizeURL = async (url, opt) => {\n const res = await sanitizeUrl(url, opt);\n return res;\n};\n\n/**\n * parse URL sync\n *\n * @param {string} url - URL input\n * @returns {ParsedURL} - result with extended props based on URL API\n */\nconst parseUrl = url => urlSanitizer.parse(url);\n\n/**\n * parse URL async\n *\n * @param {string} url - URL input\n * @returns {Promise.<ParsedURL>} - result with extended props based on URL API\n */\nexport const parseURL = async url => {\n const res = await parseUrl(url);\n return res;\n};\n\n/* export instance and aliases */\nexport {\n urlSanitizer as default,\n isUri as isURISync,\n parseUrl as parseURLSync,\n sanitizeUrl as sanitizeURLSync\n};\n"],
5
+ "mappings": ";AAKA,IAAM,YAAY;AAClB,IAAM,UAAU;AAQT,IAAM,UAAU,OACrB,OAAO,UAAU,SAAS,KAAK,CAAC,EAAE,MAAM,WAAW,OAAO;AAQrD,IAAM,WAAW,OAAK,OAAO,MAAM,YAAY,aAAa;;;ACvBnE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACxOA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACjVA,IAAM,MAAM;AACZ,IAAM,aAAa;AACnB,IAAM,eAAe;AACrB,IAAM,sBAA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",
6
6
  "names": []
7
7
  }
@@ -1,2 +1,2 @@
1
- var g=t=>Object.prototype.toString.call(t).slice(8,-1),m=t=>typeof t=="string"||t instanceof String;var k=[7,8,9,10,11,12,13,27,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255];var P=["aaa","aaas","about","acap","acct","acd","acr","adiumxtra","adt","afp","afs","aim","amss","android","appdata","apt","ar","ark","attachment","aw","barion","beshare","bitcoin","bitcoincash","blob","bolo","browserext","cabal","calculator","callto","cap","cast","casts","chrome","chrome-extension","cid","coap","coaps","com-eventbrite-attendee","content","content-type","crid","cstr","cvs","dab","dat","data","dav","diaspora","dict","did","dis","dlna-playcontainer","dlna-playsingle","dns","dntp","doi","dpp","drm","dtmi","dtn","dvb","dvx","dweb","ed2k","eid","elsi","embedded","ens","ethereum","example","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","http","https","hxxp","hxxps","hydrazone","hyper","iax","icap","icon","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","lorawan","lpa","lvlt","magnet","mailto","maps","market","matrix","message","microsoft.windows.camera","microsoft.windows.camera.multipicker","microsoft.windows.camera.picker","mid","mms","mongodb","moz","moz-extension","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-lockscreencomponent-config","ms-media-stream-id","ms-meetnow","ms-mixedrealitycapture","ms-mobileplans","ms-newsandinterests","ms-officeapp","ms-people","ms-powerpoint","ms-project","ms-publisher","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-virtualtouchpad","ms-visio","ms-walk-to","ms-whiteboard","ms-whiteboard-cmd","ms-word","msnim","msrp","msrps","mss","mt","mtqp","mumble","mupdate","mvn","news","nfs","ni","nih","nntp","notes","num","ocf","oid","onenote","onenote-cmd","opaquelocktoken","openpgp4fpr","otpauth","palm","paparazzi","payment","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","sieve","simpleledger","simplex","sip","sips","skype","smb","smp","sms","smtp","snmp","soap.beep","soap.beeps","soldat","spiffe","spotify","ssb","ssh","starknet","steam","stun","stuns","submit","svn","swh","swid","swidpath","tag","taler","teamspeak","tel","teliaeid","telnet","tftp","things","thismessage","tip","tn3270","tool","turn","turns","tv","udp","unreal","urn","ut2004","uuid-in-package","v-event","vemmi","ventrilo","ves","view-source","vnc","vscode","vscode-insiders","vsls","w3","wcr","web3","webcal","wifi","ws","wss","wtai","wyciwyg","xcon","xcon-userid","xfire","xmlrpc.beep","xmlrpc.beeps","xmpp","xri","ymsgr","z39.50r","z39.50s"];var u=16,J=/^[\da-z+/\-_=]+$/i,K=/data:[^,]*,[^"]+/g,G=/data:[^,]*;?base64,[\da-z+/\-_=]+/i,Q=/[<>"'\s]/g,V=/%(?:2(?:2|7)|3(?:C|E))/g,W=/&#(x(?:00)?[\dA-F]{2}|0?\d{1,3});?/ig,Z=/^[a-z][\da-z+\-.]*$/,ee=/^(?:ext|web)\+[a-z]+$/,x=/(?:java|vb)script/,te=/^%[\dA-F]{2}$/i,se=/%26/g,T=t=>{if(!m(t))throw new TypeError(`Expected String but got ${g(t)}.`);let e=[];for(let s of t)e.push(`%${s.charCodeAt(0).toString(u).toUpperCase()}`);return e.join("")},M=t=>{if(m(t))if(te.test(t))t=t.toUpperCase();else throw new Error(`Invalid URL encoded character: ${t}`);else throw new TypeError(`Expected String but got ${g(t)}.`);let[e,s,a,i,o,f]=["&","#","<",">",'"',"'"].map(T),n;return t===e?n=`${e}amp;`:t===a?n=`${e}lt;`:t===i?n=`${e}gt;`:t===o?n=`${e}quot;`:t===f?n=`${e}${s}39;`:n=t,n},re=t=>{if(m(t)){if(!J.test(t))throw new Error(`Invalid base64 data: ${t}`)}else throw new TypeError(`Expected String but got ${g(t)}.`);let e=atob(t),s=Uint8Array.from([...e].map(o=>o.charCodeAt(0))),a=new Set(k),i;return s.every(o=>a.has(o))?i=e.replace(/\s/g,T):i=t,i},N=(t,e=0)=>{if(!m(t))throw new TypeError(`Expected String but got ${g(t)}.`);if(Number.isInteger(e)){if(e>u)throw new Error("Character references nested too deeply.")}else throw new TypeError(`Expected Number but got ${g(e)}.`);let s=decodeURIComponent(t);if(/&#/.test(s)){let a=new Set(k),i=[...s.matchAll(W)].reverse();for(let o of i){let[f,n]=o,l;if(/^x[\dA-F]+/i.test(n)?l=parseInt(`0${n}`,u):/^[\d]+/.test(n)&&(l=parseInt(n)),Number.isInteger(l)){let{index:b}=o,[w,h]=[s.substring(0,b),s.substring(b+f.length)];a.has(l)?(s=`${w}${String.fromCharCode(l)}${h}`,(/#x?$/.test(w)||/^#(?:x(?:00)?[2-7]|\d)/.test(h))&&(s=N(s,++e))):l<u*u&&(s=`${w}${h}`)}}}return s},C=class{#e;constructor(){this.#e=new Set(P)}get(){return[...this.#e]}has(e){return this.#e.has(e)}add(e){if(m(e)){if(x.test(e)||!Z.test(e))throw new Error(`Invalid scheme: ${e}`)}else throw new TypeError(`Expected String but got ${g(e)}.`);return this.#e.add(e),[...this.#e]}remove(e){return this.#e.delete(e)}isURI(e){let s;if(m(e))try{let{protocol:a}=new URL(e),i=a.replace(/:$/,""),o=i.split("+");s=!x.test(i)&&ee.test(i)||o.every(f=>this.#e.has(f))}catch{s=!1}return!!s}},z=class extends C{#e;#t;constructor(){super(),this.#e=0,this.#t=new Set}sanitize(e,s={allow:[],deny:[]}){if(this.#e>u)throw this.#e=0,new Error("Data URLs nested too deeply.");let a;if(super.isURI(e)){let{allow:i,deny:o}=s??{},{hash:f,href:n,pathname:l,protocol:b,search:w}=new URL(e),h=b.replace(/:$/,""),j=h.split("+"),v=new Map([["data",!1],["file",!1],["javascrpt",!1],["vbscript",!1]]);if(Array.isArray(i)&&i.length){let c=Object.values(i);for(let r of c)m(r)&&(r=r.trim(),x.test(r)||v.set(r,!0))}if(Array.isArray(o)&&o.length){let c=Object.values(o);for(let r of c)m(r)&&(r=r.trim(),r&&v.set(r,!1))}let E;for(let[c,r]of v.entries())if(E=r||h!==c&&j.every($=>$!==c),!E)break;if(E){let c,r=n;if(j.includes("data")){let[$,...H]=l.split(","),U=`${H.join(",")}${w}${f}`,y=$.split(";"),p=U;if(y[y.length-1]==="base64")y.pop(),p=re(U);else try{let R=N(p),{protocol:S}=new URL(R.trim());S.replace(/:$/,"").split("+").some(d=>x.test(d))&&(r="")}catch{}let I=/data:[^,]*,/.test(p);if(p!==U||I){if(I){let S=[...p.matchAll(K)].reverse();for(let _ of S){let[d]=_;G.test(d)&&([d]=G.exec(d)),this.#e++,this.#t.add(d);let L=this.sanitize(d,{allow:["data"]});if(L){let{index:D}=_,[F,Y]=[p.substring(0,D),p.substring(D+d.length)];p=`${F}${L}${Y}`}}this.#t.has(e)?this.#t.delete(e):c=!0}else this.#t.has(e)?this.#t.delete(e):c=!0;r=`${h}:${y.join(";")},${p}`}else this.#t.has(e)?this.#t.delete(e):c=!0}else c=!0;r?(a=r.replace(Q,T).replace(se,M),c&&(a=a.replace(V,M),this.#e=0)):(a=r,this.#e=0)}}return a||null}},A=new z,O=t=>A.isURI(t),ie=async t=>await O(t),q=(t,e)=>A.sanitize(t,e??{allow:[],deny:[]}),ae=async(t,e)=>await q(t,e);export{A as default,ie as isURI,O as isURISync,ae as sanitizeURL,q as sanitizeURLSync};
1
+ var w=t=>Object.prototype.toString.call(t).slice(8,-1),d=t=>typeof t=="string"||t instanceof String;var C=[7,8,9,10,11,12,13,27,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255];var D=["aaa","aaas","about","acap","acct","acd","acr","adiumxtra","adt","afp","afs","aim","amss","android","appdata","apt","ar","ark","attachment","aw","barion","beshare","bitcoin","bitcoincash","blob","bolo","browserext","cabal","calculator","callto","cap","cast","casts","chrome","chrome-extension","cid","coap","coaps","com-eventbrite-attendee","content","content-type","crid","cstr","cvs","dab","dat","data","dav","diaspora","dict","did","dis","dlna-playcontainer","dlna-playsingle","dns","dntp","doi","dpp","drm","dtmi","dtn","dvb","dvx","dweb","ed2k","eid","elsi","embedded","ens","ethereum","example","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","http","https","hxxp","hxxps","hydrazone","hyper","iax","icap","icon","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","lorawan","lpa","lvlt","magnet","mailto","maps","market","matrix","message","microsoft.windows.camera","microsoft.windows.camera.multipicker","microsoft.windows.camera.picker","mid","mms","mongodb","moz","moz-extension","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-lockscreencomponent-config","ms-media-stream-id","ms-meetnow","ms-mixedrealitycapture","ms-mobileplans","ms-newsandinterests","ms-officeapp","ms-people","ms-powerpoint","ms-project","ms-publisher","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-virtualtouchpad","ms-visio","ms-walk-to","ms-whiteboard","ms-whiteboard-cmd","ms-word","msnim","msrp","msrps","mss","mt","mtqp","mumble","mupdate","mvn","news","nfs","ni","nih","nntp","notes","num","ocf","oid","onenote","onenote-cmd","opaquelocktoken","openpgp4fpr","otpauth","palm","paparazzi","payment","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","sieve","simpleledger","simplex","sip","sips","skype","smb","smp","sms","smtp","snmp","soap.beep","soap.beeps","soldat","spiffe","spotify","ssb","ssh","starknet","steam","stun","stuns","submit","svn","swh","swid","swidpath","tag","taler","teamspeak","tel","teliaeid","telnet","tftp","things","thismessage","tip","tn3270","tool","turn","turns","tv","udp","unreal","urn","ut2004","uuid-in-package","v-event","vemmi","ventrilo","ves","view-source","vnc","vscode","vscode-insiders","vsls","w3","wcr","web3","webcal","wifi","ws","wss","wtai","wyciwyg","xcon","xcon-userid","xfire","xmlrpc.beep","xmlrpc.beeps","xmpp","xri","ymsgr","z39.50r","z39.50s"];var x=16,K=/^[\da-z+/\-_=]+$/i,Q=/data:[^,]*,[^"]+/g,O=/data:[^,]*;?base64,[\da-z+/\-_=]+/i,V=/[<>"'\s]/g,W=/%(?:2(?:2|7)|3(?:C|E))/g,Z=/&#(x(?:00)?[\dA-F]{2}|0?\d{1,3});?/ig,ee=/^[a-z][\da-z+\-.]*$/,te=/^(?:ext|web)\+[a-z]+$/,U=/(?:java|vb)script/,se=/^%[\dA-F]{2}$/i,re=/%26/g,A=t=>{if(!d(t))throw new TypeError(`Expected String but got ${w(t)}.`);let e=[];for(let s of t)e.push(`%${s.charCodeAt(0).toString(x).toUpperCase()}`);return e.join("")},G=t=>{if(d(t))if(se.test(t))t=t.toUpperCase();else throw new Error(`Invalid URL encoded character: ${t}`);else throw new TypeError(`Expected String but got ${w(t)}.`);let[e,s,r,i,o,l]=["&","#","<",">",'"',"'"].map(A),n;return t===e?n=`${e}amp;`:t===r?n=`${e}lt;`:t===i?n=`${e}gt;`:t===o?n=`${e}quot;`:t===l?n=`${e}${s}39;`:n=t,n},ae=t=>{if(d(t)){if(!K.test(t))throw new Error(`Invalid base64 data: ${t}`)}else throw new TypeError(`Expected String but got ${w(t)}.`);let e=atob(t),s=Uint8Array.from([...e].map(o=>o.charCodeAt(0))),r=new Set(C),i;return s.every(o=>r.has(o))?i=e.replace(/\s/g,A):i=t,i},N=(t,e=0)=>{if(!d(t))throw new TypeError(`Expected String but got ${w(t)}.`);if(Number.isInteger(e)){if(e>x)throw new Error("Character references nested too deeply.")}else throw new TypeError(`Expected Number but got ${w(e)}.`);let s=decodeURIComponent(t);if(/&#/.test(s)){let r=new Set(C),i=[...s.matchAll(Z)].reverse();for(let o of i){let[l,n]=o,c;if(/^x[\dA-F]+/i.test(n)?c=parseInt(`0${n}`,x):/^[\d]+/.test(n)&&(c=parseInt(n)),Number.isInteger(c)){let{index:f}=o,[y,b]=[s.substring(0,f),s.substring(f+l.length)];r.has(c)?(s=`${y}${String.fromCharCode(c)}${b}`,(/#x?$/.test(y)||/^#(?:x(?:00)?[2-7]|\d)/.test(b))&&(s=N(s,++e))):c<x*x&&(s=`${y}${b}`)}}}return s},T=class{#e;constructor(){this.#e=new Set(D)}get(){return[...this.#e]}has(e){return this.#e.has(e)}add(e){if(d(e)){if(U.test(e)||!ee.test(e))throw new Error(`Invalid scheme: ${e}`)}else throw new TypeError(`Expected String but got ${w(e)}.`);return this.#e.add(e),[...this.#e]}remove(e){return this.#e.delete(e)}isURI(e){let s;if(d(e))try{let{protocol:r}=new URL(e),i=r.replace(/:$/,""),o=i.split("+");s=!U.test(i)&&te.test(i)||o.every(l=>this.#e.has(l))}catch{s=!1}return!!s}},j=class extends T{#e;#t;constructor(){super(),this.#e=0,this.#t=new Set}sanitize(e,s={allow:[],deny:[],only:[]}){if(this.#e>x)throw this.#e=0,new Error("Data URLs nested too deeply.");let r;if(super.isURI(e)){let{allow:i,deny:o,only:l}=s??{},{hash:n,href:c,pathname:f,protocol:y,search:b}=new URL(e),g=y.replace(/:$/,""),v=g.split("+"),E=new Map([["data",!1],["file",!1],["javascrpt",!1],["vbscript",!1]]);if(Array.isArray(l)&&l.length){let p=super.get();for(let m of p)E.set(m,!1);let a=Object.values(l);for(let m of a)d(m)&&(m=m.trim(),U.test(m)||E.set(m,!0))}else{if(Array.isArray(i)&&i.length){let p=Object.values(i);for(let a of p)d(a)&&(a=a.trim(),U.test(a)||E.set(a,!0))}if(Array.isArray(o)&&o.length){let p=Object.values(o);for(let a of p)d(a)&&(a=a.trim(),a&&E.set(a,!1))}}let R;for(let[p,a]of E.entries())if(R=a||g!==p&&v.every(m=>m!==p),!R)break;if(R){let p,a=c;if(v.includes("data")){let[m,...F]=f.split(","),S=`${F.join(",")}${b}${n}`,$=m.split(";"),h=S;if($[$.length-1]==="base64")$.pop(),h=ae(S);else try{let _=N(h),{protocol:k}=new URL(_.trim());k.replace(/:$/,"").split("+").some(u=>U.test(u))&&(a="")}catch{}let I=/data:[^,]*,/.test(h);if(h!==S||I){if(I){let k=[...h.matchAll(Q)].reverse();for(let z of k){let[u]=z;O.test(u)&&([u]=O.exec(u)),this.#e++,this.#t.add(u);let M=this.sanitize(u,{allow:["data"]});if(M){let{index:P}=z,[B,Y]=[h.substring(0,P),h.substring(P+u.length)];h=`${B}${M}${Y}`}}this.#t.has(e)?this.#t.delete(e):p=!0}else this.#t.has(e)?this.#t.delete(e):p=!0;a=`${g}:${$.join(";")},${h}`}else this.#t.has(e)?this.#t.delete(e):p=!0}else p=!0;a?(r=a.replace(V,A).replace(re,G),p&&(r=r.replace(W,G),this.#e=0)):(r=a,this.#e=0)}}return r||null}parse(e){if(!d(e))throw new TypeError(`Expected String but got ${w(e)}.`);let s=this.sanitize(e,{allow:["data","file"]}),r=new Map([["input",e]]);if(s){let i=new URL(s),{pathname:o,protocol:l}=i,n=l.replace(/:$/,"").split("+");if(r.set("valid",!0),n.includes("data")){let c=new Map,[f,...y]=o.split(","),b=`${y.join(",")}`,g=f.split(";"),v=g[g.length-1]==="base64";v&&g.pop(),c.set("mime",g.join(";")),c.set("base64",v),c.set("data",b),r.set("data",Object.fromEntries(c))}else r.set("data",null);for(let c in i){let f=i[c];typeof f!="function"&&r.set(c,f)}}else r.set("valid",!1);return Object.fromEntries(r)}},L=new j,q=t=>L.isURI(t),ie=async t=>await q(t),H=(t,e)=>L.sanitize(t,e??{allow:[],deny:[],only:[]}),oe=async(t,e)=>await H(t,e);export{L as default,ie as isURI,q as isURISync,oe as sanitizeURL,H as sanitizeURLSync};
2
2
  //# sourceMappingURL=url-sanitizer.min.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/mjs/common.js", "../src/lib/file/text-chars.json", "../src/lib/iana/uri-schemes.json", "../src/mjs/uri-util.js"],
4
- "sourcesContent": ["/**\n * common.js\n */\n\n/* constants */\nconst TYPE_FROM = 8;\nconst TYPE_TO = -1;\n\n/**\n * get type\n *\n * @param {*} o - object to check\n * @returns {string} - type of object\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * is string\n *\n * @param {*} o - object to check\n * @returns {boolean} - result\n */\nexport const isString = o => typeof o === 'string' || o instanceof String;\n", "[\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13,\n 27,\n 32,\n 33,\n 34,\n 35,\n 36,\n 37,\n 38,\n 39,\n 40,\n 41,\n 42,\n 43,\n 44,\n 45,\n 46,\n 47,\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 55,\n 56,\n 57,\n 58,\n 59,\n 60,\n 61,\n 62,\n 63,\n 64,\n 65,\n 66,\n 67,\n 68,\n 69,\n 70,\n 71,\n 72,\n 73,\n 74,\n 75,\n 76,\n 77,\n 78,\n 79,\n 80,\n 81,\n 82,\n 83,\n 84,\n 85,\n 86,\n 87,\n 88,\n 89,\n 90,\n 91,\n 92,\n 93,\n 94,\n 95,\n 96,\n 97,\n 98,\n 99,\n 100,\n 101,\n 102,\n 103,\n 104,\n 105,\n 106,\n 107,\n 108,\n 109,\n 110,\n 111,\n 112,\n 113,\n 114,\n 115,\n 116,\n 117,\n 118,\n 119,\n 120,\n 121,\n 122,\n 123,\n 124,\n 125,\n 126,\n 128,\n 129,\n 130,\n 131,\n 132,\n 133,\n 134,\n 135,\n 136,\n 137,\n 138,\n 139,\n 140,\n 141,\n 142,\n 143,\n 144,\n 145,\n 146,\n 147,\n 148,\n 149,\n 150,\n 151,\n 152,\n 153,\n 154,\n 155,\n 156,\n 157,\n 158,\n 159,\n 160,\n 161,\n 162,\n 163,\n 164,\n 165,\n 166,\n 167,\n 168,\n 169,\n 170,\n 171,\n 172,\n 173,\n 174,\n 175,\n 176,\n 177,\n 178,\n 179,\n 180,\n 181,\n 182,\n 183,\n 184,\n 185,\n 186,\n 187,\n 188,\n 189,\n 190,\n 191,\n 192,\n 193,\n 194,\n 195,\n 196,\n 197,\n 198,\n 199,\n 200,\n 201,\n 202,\n 203,\n 204,\n 205,\n 206,\n 207,\n 208,\n 209,\n 210,\n 211,\n 212,\n 213,\n 214,\n 215,\n 216,\n 217,\n 218,\n 219,\n 220,\n 221,\n 222,\n 223,\n 224,\n 225,\n 226,\n 227,\n 228,\n 229,\n 230,\n 231,\n 232,\n 233,\n 234,\n 235,\n 236,\n 237,\n 238,\n 239,\n 240,\n 241,\n 242,\n 243,\n 244,\n 245,\n 246,\n 247,\n 248,\n 249,\n 250,\n 251,\n 252,\n 253,\n 254,\n 255\n]\n", "[\n \"aaa\",\n \"aaas\",\n \"about\",\n \"acap\",\n \"acct\",\n \"acd\",\n \"acr\",\n \"adiumxtra\",\n \"adt\",\n \"afp\",\n \"afs\",\n \"aim\",\n \"amss\",\n \"android\",\n \"appdata\",\n \"apt\",\n \"ar\",\n \"ark\",\n \"attachment\",\n \"aw\",\n \"barion\",\n \"beshare\",\n \"bitcoin\",\n \"bitcoincash\",\n \"blob\",\n \"bolo\",\n \"browserext\",\n \"cabal\",\n \"calculator\",\n \"callto\",\n \"cap\",\n \"cast\",\n \"casts\",\n \"chrome\",\n \"chrome-extension\",\n \"cid\",\n \"coap\",\n \"coaps\",\n \"com-eventbrite-attendee\",\n \"content\",\n \"content-type\",\n \"crid\",\n \"cstr\",\n \"cvs\",\n \"dab\",\n \"dat\",\n \"data\",\n \"dav\",\n \"diaspora\",\n \"dict\",\n \"did\",\n \"dis\",\n \"dlna-playcontainer\",\n \"dlna-playsingle\",\n \"dns\",\n \"dntp\",\n \"doi\",\n \"dpp\",\n \"drm\",\n \"dtmi\",\n \"dtn\",\n \"dvb\",\n \"dvx\",\n \"dweb\",\n \"ed2k\",\n \"eid\",\n \"elsi\",\n \"embedded\",\n \"ens\",\n \"ethereum\",\n \"example\",\n \"facetime\",\n \"feed\",\n \"feedready\",\n \"fido\",\n \"file\",\n \"finger\",\n \"first-run-pen-experience\",\n \"fish\",\n \"fm\",\n \"ftp\",\n \"fuchsia-pkg\",\n \"geo\",\n \"gg\",\n \"git\",\n \"gitoid\",\n \"gizmoproject\",\n \"go\",\n \"gopher\",\n \"graph\",\n \"gtalk\",\n \"h323\",\n \"ham\",\n \"hcap\",\n \"hcp\",\n \"http\",\n \"https\",\n \"hxxp\",\n \"hxxps\",\n \"hydrazone\",\n \"hyper\",\n \"iax\",\n \"icap\",\n \"icon\",\n \"im\",\n \"imap\",\n \"info\",\n \"iotdisco\",\n \"ipfs\",\n \"ipn\",\n \"ipns\",\n \"ipp\",\n \"ipps\",\n \"irc\",\n \"irc6\",\n \"ircs\",\n \"iris\",\n \"iris.beep\",\n \"iris.lwz\",\n \"iris.xpc\",\n \"iris.xpcs\",\n \"isostore\",\n \"itms\",\n \"jabber\",\n \"jar\",\n \"jms\",\n \"keyparc\",\n \"lastfm\",\n \"lbry\",\n \"ldap\",\n \"ldaps\",\n \"leaptofrogans\",\n \"lorawan\",\n \"lpa\",\n \"lvlt\",\n \"magnet\",\n \"mailto\",\n \"maps\",\n \"market\",\n \"matrix\",\n \"message\",\n \"microsoft.windows.camera\",\n \"microsoft.windows.camera.multipicker\",\n \"microsoft.windows.camera.picker\",\n \"mid\",\n \"mms\",\n \"mongodb\",\n \"moz\",\n \"moz-extension\",\n \"ms-access\",\n \"ms-appinstaller\",\n \"ms-browser-extension\",\n \"ms-calculator\",\n \"ms-drive-to\",\n \"ms-enrollment\",\n \"ms-excel\",\n \"ms-eyecontrolspeech\",\n \"ms-gamebarservices\",\n \"ms-gamingoverlay\",\n \"ms-getoffice\",\n \"ms-help\",\n \"ms-infopath\",\n \"ms-inputapp\",\n \"ms-lockscreencomponent-config\",\n \"ms-media-stream-id\",\n \"ms-meetnow\",\n \"ms-mixedrealitycapture\",\n \"ms-mobileplans\",\n \"ms-newsandinterests\",\n \"ms-officeapp\",\n \"ms-people\",\n \"ms-powerpoint\",\n \"ms-project\",\n \"ms-publisher\",\n \"ms-remotedesktop-launch\",\n \"ms-restoretabcompanion\",\n \"ms-screenclip\",\n \"ms-screensketch\",\n \"ms-search\",\n \"ms-search-repair\",\n \"ms-secondary-screen-controller\",\n \"ms-secondary-screen-setup\",\n \"ms-settings\",\n \"ms-settings-airplanemode\",\n \"ms-settings-bluetooth\",\n \"ms-settings-camera\",\n \"ms-settings-cellular\",\n \"ms-settings-cloudstorage\",\n \"ms-settings-connectabledevices\",\n \"ms-settings-displays-topology\",\n \"ms-settings-emailandaccounts\",\n \"ms-settings-language\",\n \"ms-settings-location\",\n \"ms-settings-lock\",\n \"ms-settings-nfctransactions\",\n \"ms-settings-notifications\",\n \"ms-settings-power\",\n \"ms-settings-privacy\",\n \"ms-settings-proximity\",\n \"ms-settings-screenrotation\",\n \"ms-settings-wifi\",\n \"ms-settings-workplace\",\n \"ms-spd\",\n \"ms-stickers\",\n \"ms-sttoverlay\",\n \"ms-transit-to\",\n \"ms-useractivityset\",\n \"ms-virtualtouchpad\",\n \"ms-visio\",\n \"ms-walk-to\",\n \"ms-whiteboard\",\n \"ms-whiteboard-cmd\",\n \"ms-word\",\n \"msnim\",\n \"msrp\",\n \"msrps\",\n \"mss\",\n \"mt\",\n \"mtqp\",\n \"mumble\",\n \"mupdate\",\n \"mvn\",\n \"news\",\n \"nfs\",\n \"ni\",\n \"nih\",\n \"nntp\",\n \"notes\",\n \"num\",\n \"ocf\",\n \"oid\",\n \"onenote\",\n \"onenote-cmd\",\n \"opaquelocktoken\",\n \"openpgp4fpr\",\n \"otpauth\",\n \"palm\",\n \"paparazzi\",\n \"payment\",\n \"payto\",\n \"pkcs11\",\n \"platform\",\n \"pop\",\n \"pres\",\n \"proxy\",\n \"psyc\",\n \"pttp\",\n \"pwid\",\n \"qb\",\n \"query\",\n \"quic-transport\",\n \"redis\",\n \"rediss\",\n \"reload\",\n \"res\",\n \"resource\",\n \"rmi\",\n \"rsync\",\n \"rtmfp\",\n \"rtmp\",\n \"rtsp\",\n \"rtsps\",\n \"rtspu\",\n \"sarif\",\n \"secondlife\",\n \"secret-token\",\n \"service\",\n \"session\",\n \"sftp\",\n \"sgn\",\n \"shc\",\n \"sieve\",\n \"simpleledger\",\n \"simplex\",\n \"sip\",\n \"sips\",\n \"skype\",\n \"smb\",\n \"smp\",\n \"sms\",\n \"smtp\",\n \"snmp\",\n \"soap.beep\",\n \"soap.beeps\",\n \"soldat\",\n \"spiffe\",\n \"spotify\",\n \"ssb\",\n \"ssh\",\n \"starknet\",\n \"steam\",\n \"stun\",\n \"stuns\",\n \"submit\",\n \"svn\",\n \"swh\",\n \"swid\",\n \"swidpath\",\n \"tag\",\n \"taler\",\n \"teamspeak\",\n \"tel\",\n \"teliaeid\",\n \"telnet\",\n \"tftp\",\n \"things\",\n \"thismessage\",\n \"tip\",\n \"tn3270\",\n \"tool\",\n \"turn\",\n \"turns\",\n \"tv\",\n \"udp\",\n \"unreal\",\n \"urn\",\n \"ut2004\",\n \"uuid-in-package\",\n \"v-event\",\n \"vemmi\",\n \"ventrilo\",\n \"ves\",\n \"view-source\",\n \"vnc\",\n \"vscode\",\n \"vscode-insiders\",\n \"vsls\",\n \"w3\",\n \"wcr\",\n \"web3\",\n \"webcal\",\n \"wifi\",\n \"ws\",\n \"wss\",\n \"wtai\",\n \"wyciwyg\",\n \"xcon\",\n \"xcon-userid\",\n \"xfire\",\n \"xmlrpc.beep\",\n \"xmlrpc.beeps\",\n \"xmpp\",\n \"xri\",\n \"ymsgr\",\n \"z39.50r\",\n \"z39.50s\"\n]\n", "/**\n * uri-util.js\n */\n\n/* shared */\nimport { getType, isString } from './common.js';\nimport textChars from '../lib/file/text-chars.json' assert { type: 'json' };\nimport uriSchemes from '../lib/iana/uri-schemes.json' assert { type: 'json' };\n\n/* constants */\nconst HEX = 16;\nconst REG_BASE64 = /^[\\da-z+/\\-_=]+$/i;\nconst REG_DATA_URL = /data:[^,]*,[^\"]+/g;\nconst REG_DATA_URL_BASE64 = /data:[^,]*;?base64,[\\da-z+/\\-_=]+/i;\nconst REG_HTML_SP = /[<>\"'\\s]/g;\nconst REG_HTML_SP_URL_ENC = /%(?:2(?:2|7)|3(?:C|E))/g;\nconst REG_NUM_REF = /&#(x(?:00)?[\\dA-F]{2}|0?\\d{1,3});?/ig;\nconst REG_SCHEME = /^[a-z][\\da-z+\\-.]*$/;\nconst REG_SCHEME_CUSTOM = /^(?:ext|web)\\+[a-z]+$/;\nconst REG_SCRIPT = /(?:java|vb)script/;\nconst REG_URL_ENC = /^%[\\dA-F]{2}$/i;\nconst REG_URL_ENC_AMP = /%26/g;\n\n/**\n * get URL encoded string\n *\n * @param {string} str - string\n * @returns {string} - URL encoded string\n */\nexport const getUrlEncodedString = str => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n const chars = [];\n for (const ch of str) {\n chars.push(`%${ch.charCodeAt(0).toString(HEX).toUpperCase()}`);\n }\n return chars.join('');\n};\n\n/**\n * escape URL encoded HTML special chars\n *\n * @param {string} ch - URL encoded (percent encoded) char\n * @returns {string} - escaped URL encoded HTML special char / URL encoded char\n */\nexport const escapeUrlEncodedHtmlChars = ch => {\n if (isString(ch)) {\n if (REG_URL_ENC.test(ch)) {\n ch = ch.toUpperCase();\n } else {\n throw new Error(`Invalid URL encoded character: ${ch}`);\n }\n } else {\n throw new TypeError(`Expected String but got ${getType(ch)}.`);\n }\n const [amp, num, lt, gt, quot, apos] =\n ['&', '#', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n let escapedChar;\n if (ch === amp) {\n escapedChar = `${amp}amp;`;\n } else if (ch === lt) {\n escapedChar = `${amp}lt;`;\n } else if (ch === gt) {\n escapedChar = `${amp}gt;`;\n } else if (ch === quot) {\n escapedChar = `${amp}quot;`;\n } else if (ch === apos) {\n escapedChar = `${amp}${num}39;`;\n } else {\n escapedChar = ch;\n }\n return escapedChar;\n};\n\n/**\n * parse base64 encoded data\n *\n * @param {string} data - base64 encoded data\n * @returns {string} - parsed text data / base64 encoded data if binary\n */\nexport const parseBase64 = data => {\n if (!isString(data)) {\n throw new TypeError(`Expected String but got ${getType(data)}.`);\n } else if (!REG_BASE64.test(data)) {\n throw new Error(`Invalid base64 data: ${data}`);\n }\n const bin = atob(data);\n const uint8arr = Uint8Array.from([...bin].map(c => c.charCodeAt(0)));\n const textCharCodes = new Set(textChars);\n let parsedData;\n if (uint8arr.every(c => textCharCodes.has(c))) {\n parsedData = bin.replace(/\\s/g, getUrlEncodedString);\n } else {\n parsedData = data;\n }\n return parsedData;\n};\n\n/**\n * parse URL encoded numeric character references in the range 0x00 to 0xFF\n *\n * @param {string} str - string\n * @param {number} nest - nest level\n * @returns {string} - parsed string\n */\nexport const parseUrlEncodedNumCharRef = (str, nest = 0) => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n if (!Number.isInteger(nest)) {\n throw new TypeError(`Expected Number but got ${getType(nest)}.`);\n } else if (nest > HEX) {\n throw new Error('Character references nested too deeply.');\n }\n let res = decodeURIComponent(str);\n if (/&#/.test(res)) {\n const textCharCodes = new Set(textChars);\n const items = [...res.matchAll(REG_NUM_REF)].reverse();\n for (const item of items) {\n const [numCharRef, value] = item;\n let num;\n if (/^x[\\dA-F]+/i.test(value)) {\n num = parseInt(`0${value}`, HEX);\n } else if (/^[\\d]+/.test(value)) {\n num = parseInt(value);\n }\n if (Number.isInteger(num)) {\n const { index } = item;\n const [preNum, postNum] = [\n res.substring(0, index),\n res.substring(index + numCharRef.length)\n ];\n if (textCharCodes.has(num)) {\n res = `${preNum}${String.fromCharCode(num)}${postNum}`;\n if (/#x?$/.test(preNum) || /^#(?:x(?:00)?[2-7]|\\d)/.test(postNum)) {\n res = parseUrlEncodedNumCharRef(res, ++nest);\n }\n } else if (num < HEX * HEX) {\n res = `${preNum}${postNum}`;\n }\n }\n }\n }\n return res;\n};\n\n/**\n * URI schemes\n *\n */\nexport class URISchemes {\n /* private fields */\n #schemes;\n\n /**\n * construct\n */\n constructor() {\n this.#schemes = new Set(uriSchemes);\n }\n\n /**\n * get schemes\n *\n * @see {@link https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml}\n * - Historical schemes omitted\n * - 'moz-extension' scheme added\n * @returns {Array.<string>} - array of schemes\n */\n get() {\n return [...this.#schemes];\n }\n\n /**\n * has scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n has(scheme) {\n return this.#schemes.has(scheme);\n }\n\n /**\n * add scheme\n * NOTE: `javascript` and/or `vbscript` schemes can not be registered\n *\n * @param {string} scheme - scheme\n * @returns {Array.<string>} - array of schemes\n */\n add(scheme) {\n if (!isString(scheme)) {\n throw new TypeError(`Expected String but got ${getType(scheme)}.`);\n } else if (REG_SCRIPT.test(scheme) || !REG_SCHEME.test(scheme)) {\n throw new Error(`Invalid scheme: ${scheme}`);\n }\n this.#schemes.add(scheme);\n return [...this.#schemes];\n }\n\n /**\n * remove scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n remove(scheme) {\n return this.#schemes.delete(scheme);\n }\n\n /**\n * is URI\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\n isURI(uri) {\n let res;\n if (isString(uri)) {\n try {\n const { protocol } = new URL(uri);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n res = (!REG_SCRIPT.test(scheme) && REG_SCHEME_CUSTOM.test(scheme)) ||\n schemeParts.every(s => this.#schemes.has(s));\n } catch (e) {\n res = false;\n }\n }\n return !!res;\n }\n};\n\n/* URL sanitizer */\nexport class URLSanitizer extends URISchemes {\n /* private fields */\n #nest;\n #recurse;\n\n /**\n * construct\n */\n constructor() {\n super();\n this.#nest = 0;\n this.#recurse = new Set();\n }\n\n /**\n * sanitize URL\n * NOTE: `data` and/or `file` schemes must be explicitly allowed\n * `javascript` and/or `vbscript` schemes can not be allowed\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @param {Array.<string>} opt.allow - array of allowed schemes\n * @param {Array.<string>} opt.deny - array of denied schemes\n * @returns {?string} - sanitized URL\n */\n sanitize(url, opt = { allow: [], deny: [] }) {\n if (this.#nest > HEX) {\n this.#nest = 0;\n throw new Error('Data URLs nested too deeply.');\n }\n let sanitizedUrl;\n if (super.isURI(url)) {\n const { allow, deny } = opt ?? {};\n const { hash, href, pathname, protocol, search } = new URL(url);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n const schemeMap = new Map([\n ['data', false],\n ['file', false],\n ['javascrpt', false],\n ['vbscript', false]\n ]);\n if (Array.isArray(allow) && allow.length) {\n const items = Object.values(allow);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (!REG_SCRIPT.test(item)) {\n schemeMap.set(item, true);\n }\n }\n }\n }\n if (Array.isArray(deny) && deny.length) {\n const items = Object.values(deny);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (item) {\n schemeMap.set(item, false);\n }\n }\n }\n }\n let bool;\n for (const [key, value] of schemeMap.entries()) {\n bool = value || (scheme !== key && schemeParts.every(s => s !== key));\n if (!bool) {\n break;\n }\n }\n if (bool) {\n let escapeHtml;\n let urlToSanitize = href;\n if (schemeParts.includes('data')) {\n const [head, ...body] = pathname.split(',');\n const data = `${body.join(',')}${search}${hash}`;\n const mediaType = head.split(';');\n let parsedData = data;\n if (mediaType[mediaType.length - 1] === 'base64') {\n mediaType.pop();\n parsedData = parseBase64(data);\n } else {\n try {\n const decodedData = parseUrlEncodedNumCharRef(parsedData);\n const { protocol: dataScheme } = new URL(decodedData.trim());\n const dataSchemeParts = dataScheme.replace(/:$/, '').split('+');\n if (dataSchemeParts.some(s => REG_SCRIPT.test(s))) {\n urlToSanitize = '';\n }\n } catch (e) {\n // fall through\n }\n }\n const containsDataUrl = /data:[^,]*,/.test(parsedData);\n if (parsedData !== data || containsDataUrl) {\n if (containsDataUrl) {\n const matchedDataUrls = parsedData.matchAll(REG_DATA_URL);\n const items = [...matchedDataUrls].reverse();\n for (const item of items) {\n let [dataUrl] = item;\n if (REG_DATA_URL_BASE64.test(dataUrl)) {\n [dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);\n }\n this.#nest++;\n this.#recurse.add(dataUrl);\n const parsedDataUrl = this.sanitize(dataUrl, {\n allow: ['data']\n });\n if (parsedDataUrl) {\n const { index } = item;\n const [preDataUrl, postDataUrl] = [\n parsedData.substring(0, index),\n parsedData.substring(index + dataUrl.length)\n ];\n parsedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;\n }\n }\n if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n urlToSanitize = `${scheme}:${mediaType.join(';')},${parsedData}`;\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else {\n escapeHtml = true;\n }\n if (urlToSanitize) {\n sanitizedUrl = urlToSanitize\n .replace(REG_HTML_SP, getUrlEncodedString)\n .replace(REG_URL_ENC_AMP, escapeUrlEncodedHtmlChars);\n if (escapeHtml) {\n sanitizedUrl = sanitizedUrl\n .replace(REG_HTML_SP_URL_ENC, escapeUrlEncodedHtmlChars);\n this.#nest = 0;\n }\n } else {\n sanitizedUrl = urlToSanitize;\n this.#nest = 0;\n }\n }\n }\n return sanitizedUrl || null;\n }\n};\n\n/* instance */\nconst urlSanitizer = new URLSanitizer();\n\n/* aliases and async wrappers */\n/**\n * is URI sync\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\nconst isUri = uri => urlSanitizer.isURI(uri);\n\n/**\n * is URI async\n *\n * @param {string} uri - URI input\n * @returns {Promise.<boolean>} - result\n */\nexport const isURI = async uri => {\n const res = await isUri(uri);\n return res;\n};\n\n/**\n * sanitize URL sync\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {?string} - sanitized URL\n */\nconst sanitizeUrl = (url, opt) => urlSanitizer.sanitize(url, opt ?? {\n allow: [],\n deny: []\n});\n\n/**\n * sanitize URL async\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {Promise.<?string>} - sanitized URL\n */\nexport const sanitizeURL = async (url, opt) => {\n const res = await sanitizeUrl(url, opt);\n return res;\n};\n\n/* export instance and aliases */\nexport {\n urlSanitizer as default,\n isUri as isURISync,\n sanitizeUrl as sanitizeURLSync\n};\n"],
5
- "mappings": "AAcO,IAAMA,EAAUC,GACrB,OAAO,UAAU,SAAS,KAAKA,CAAC,EAAE,MAAM,EAAW,EAAO,EAQ/CC,EAAWD,GAAK,OAAOA,GAAM,UAAYA,aAAa,OCvBnE,IAAAE,EAAA,CACE,EACA,EACA,EACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,GACF,ECxOA,IAAAC,EAAA,CACE,MACA,OACA,QACA,OACA,OACA,MACA,MACA,YACA,MACA,MACA,MACA,MACA,OACA,UACA,UACA,MACA,KACA,MACA,aACA,KACA,SACA,UACA,UACA,cACA,OACA,OACA,aACA,QACA,aACA,SACA,MACA,OACA,QACA,SACA,mBACA,MACA,OACA,QACA,0BACA,UACA,eACA,OACA,OACA,MACA,MACA,MACA,OACA,MACA,WACA,OACA,MACA,MACA,qBACA,kBACA,MACA,OACA,MACA,MACA,MACA,OACA,MACA,MACA,MACA,OACA,OACA,MACA,OACA,WACA,MACA,WACA,UACA,WACA,OACA,YACA,OACA,OACA,SACA,2BACA,OACA,KACA,MACA,cACA,MACA,KACA,MACA,SACA,eACA,KACA,SACA,QACA,QACA,OACA,MACA,OACA,MACA,OACA,QACA,OACA,QACA,YACA,QACA,MACA,OACA,OACA,KACA,OACA,OACA,WACA,OACA,MACA,OACA,MACA,OACA,MACA,OACA,OACA,OACA,YACA,WACA,WACA,YACA,WACA,OACA,SACA,MACA,MACA,UACA,SACA,OACA,OACA,QACA,gBACA,UACA,MACA,OACA,SACA,SACA,OACA,SACA,SACA,UACA,2BACA,uCACA,kCACA,MACA,MACA,UACA,MACA,gBACA,YACA,kBACA,uBACA,gBACA,cACA,gBACA,WACA,sBACA,qBACA,mBACA,eACA,UACA,cACA,cACA,gCACA,qBACA,aACA,yBACA,iBACA,sBACA,eACA,YACA,gBACA,aACA,eACA,0BACA,yBACA,gBACA,kBACA,YACA,mBACA,iCACA,4BACA,cACA,2BACA,wBACA,qBACA,uBACA,2BACA,iCACA,gCACA,+BACA,uBACA,uBACA,mBACA,8BACA,4BACA,oBACA,sBACA,wBACA,6BACA,mBACA,wBACA,SACA,cACA,gBACA,gBACA,qBACA,qBACA,WACA,aACA,gBACA,oBACA,UACA,QACA,OACA,QACA,MACA,KACA,OACA,SACA,UACA,MACA,OACA,MACA,KACA,MACA,OACA,QACA,MACA,MACA,MACA,UACA,cACA,kBACA,cACA,UACA,OACA,YACA,UACA,QACA,SACA,WACA,MACA,OACA,QACA,OACA,OACA,OACA,KACA,QACA,iBACA,QACA,SACA,SACA,MACA,WACA,MACA,QACA,QACA,OACA,OACA,QACA,QACA,QACA,aACA,eACA,UACA,UACA,OACA,MACA,MACA,QACA,eACA,UACA,MACA,OACA,QACA,MACA,MACA,MACA,OACA,OACA,YACA,aACA,SACA,SACA,UACA,MACA,MACA,WACA,QACA,OACA,QACA,SACA,MACA,MACA,OACA,WACA,MACA,QACA,YACA,MACA,WACA,SACA,OACA,SACA,cACA,MACA,SACA,OACA,OACA,QACA,KACA,MACA,SACA,MACA,SACA,kBACA,UACA,QACA,WACA,MACA,cACA,MACA,SACA,kBACA,OACA,KACA,MACA,OACA,SACA,OACA,KACA,MACA,OACA,UACA,OACA,cACA,QACA,cACA,eACA,OACA,MACA,QACA,UACA,SACF,ECjVA,IAAMC,EAAM,GACNC,EAAa,oBACbC,EAAe,oBACfC,EAAsB,qCACtBC,EAAc,YACdC,EAAsB,0BACtBC,EAAc,uCACdC,EAAa,sBACbC,GAAoB,wBACpBC,EAAa,oBACbC,GAAc,iBACdC,GAAkB,OAQXC,EAAsBC,GAAO,CACxC,GAAI,CAACC,EAASD,CAAG,EACf,MAAM,IAAI,UAAU,2BAA2BE,EAAQF,CAAG,IAAI,EAEhE,IAAMG,EAAQ,CAAC,EACf,QAAWC,KAAMJ,EACfG,EAAM,KAAK,IAAIC,EAAG,WAAW,CAAC,EAAE,SAASjB,CAAG,EAAE,YAAY,GAAG,EAE/D,OAAOgB,EAAM,KAAK,EAAE,CACtB,EAQaE,EAA4BD,GAAM,CAC7C,GAAIH,EAASG,CAAE,EACb,GAAIP,GAAY,KAAKO,CAAE,EACrBA,EAAKA,EAAG,YAAY,MAEpB,OAAM,IAAI,MAAM,kCAA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",
6
- "names": ["getType", "o", "isString", "text_chars_default", "uri_schemes_default", "HEX", "REG_BASE64", "REG_DATA_URL", "REG_DATA_URL_BASE64", "REG_HTML_SP", "REG_HTML_SP_URL_ENC", "REG_NUM_REF", "REG_SCHEME", "REG_SCHEME_CUSTOM", "REG_SCRIPT", "REG_URL_ENC", "REG_URL_ENC_AMP", "getUrlEncodedString", "str", "isString", "getType", "chars", "ch", "escapeUrlEncodedHtmlChars", "amp", "num", "lt", "gt", "quot", "apos", "escapedChar", "parseBase64", "data", "bin", "uint8arr", "c", "textCharCodes", "text_chars_default", "parsedData", "parseUrlEncodedNumCharRef", "nest", "res", "items", "item", "numCharRef", "value", "index", "preNum", "postNum", "URISchemes", "#schemes", "uri_schemes_default", "scheme", "uri", "protocol", "schemeParts", "s", "URLSanitizer", "#nest", "#recurse", "url", "opt", "sanitizedUrl", "allow", "deny", "hash", "href", "pathname", "search", "schemeMap", "bool", "key", "escapeHtml", "urlToSanitize", "head", "body", "mediaType", "decodedData", "dataScheme", "containsDataUrl", "dataUrl", "parsedDataUrl", "preDataUrl", "postDataUrl", "urlSanitizer", "isUri", "isURI", "sanitizeUrl", "sanitizeURL"]
4
+ "sourcesContent": ["/**\n * common.js\n */\n\n/* constants */\nconst TYPE_FROM = 8;\nconst TYPE_TO = -1;\n\n/**\n * get type\n *\n * @param {*} o - object to check\n * @returns {string} - type of object\n */\nexport const getType = o =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * is string\n *\n * @param {*} o - object to check\n * @returns {boolean} - result\n */\nexport const isString = o => typeof o === 'string' || o instanceof String;\n", "[\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13,\n 27,\n 32,\n 33,\n 34,\n 35,\n 36,\n 37,\n 38,\n 39,\n 40,\n 41,\n 42,\n 43,\n 44,\n 45,\n 46,\n 47,\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 55,\n 56,\n 57,\n 58,\n 59,\n 60,\n 61,\n 62,\n 63,\n 64,\n 65,\n 66,\n 67,\n 68,\n 69,\n 70,\n 71,\n 72,\n 73,\n 74,\n 75,\n 76,\n 77,\n 78,\n 79,\n 80,\n 81,\n 82,\n 83,\n 84,\n 85,\n 86,\n 87,\n 88,\n 89,\n 90,\n 91,\n 92,\n 93,\n 94,\n 95,\n 96,\n 97,\n 98,\n 99,\n 100,\n 101,\n 102,\n 103,\n 104,\n 105,\n 106,\n 107,\n 108,\n 109,\n 110,\n 111,\n 112,\n 113,\n 114,\n 115,\n 116,\n 117,\n 118,\n 119,\n 120,\n 121,\n 122,\n 123,\n 124,\n 125,\n 126,\n 128,\n 129,\n 130,\n 131,\n 132,\n 133,\n 134,\n 135,\n 136,\n 137,\n 138,\n 139,\n 140,\n 141,\n 142,\n 143,\n 144,\n 145,\n 146,\n 147,\n 148,\n 149,\n 150,\n 151,\n 152,\n 153,\n 154,\n 155,\n 156,\n 157,\n 158,\n 159,\n 160,\n 161,\n 162,\n 163,\n 164,\n 165,\n 166,\n 167,\n 168,\n 169,\n 170,\n 171,\n 172,\n 173,\n 174,\n 175,\n 176,\n 177,\n 178,\n 179,\n 180,\n 181,\n 182,\n 183,\n 184,\n 185,\n 186,\n 187,\n 188,\n 189,\n 190,\n 191,\n 192,\n 193,\n 194,\n 195,\n 196,\n 197,\n 198,\n 199,\n 200,\n 201,\n 202,\n 203,\n 204,\n 205,\n 206,\n 207,\n 208,\n 209,\n 210,\n 211,\n 212,\n 213,\n 214,\n 215,\n 216,\n 217,\n 218,\n 219,\n 220,\n 221,\n 222,\n 223,\n 224,\n 225,\n 226,\n 227,\n 228,\n 229,\n 230,\n 231,\n 232,\n 233,\n 234,\n 235,\n 236,\n 237,\n 238,\n 239,\n 240,\n 241,\n 242,\n 243,\n 244,\n 245,\n 246,\n 247,\n 248,\n 249,\n 250,\n 251,\n 252,\n 253,\n 254,\n 255\n]\n", "[\n \"aaa\",\n \"aaas\",\n \"about\",\n \"acap\",\n \"acct\",\n \"acd\",\n \"acr\",\n \"adiumxtra\",\n \"adt\",\n \"afp\",\n \"afs\",\n \"aim\",\n \"amss\",\n \"android\",\n \"appdata\",\n \"apt\",\n \"ar\",\n \"ark\",\n \"attachment\",\n \"aw\",\n \"barion\",\n \"beshare\",\n \"bitcoin\",\n \"bitcoincash\",\n \"blob\",\n \"bolo\",\n \"browserext\",\n \"cabal\",\n \"calculator\",\n \"callto\",\n \"cap\",\n \"cast\",\n \"casts\",\n \"chrome\",\n \"chrome-extension\",\n \"cid\",\n \"coap\",\n \"coaps\",\n \"com-eventbrite-attendee\",\n \"content\",\n \"content-type\",\n \"crid\",\n \"cstr\",\n \"cvs\",\n \"dab\",\n \"dat\",\n \"data\",\n \"dav\",\n \"diaspora\",\n \"dict\",\n \"did\",\n \"dis\",\n \"dlna-playcontainer\",\n \"dlna-playsingle\",\n \"dns\",\n \"dntp\",\n \"doi\",\n \"dpp\",\n \"drm\",\n \"dtmi\",\n \"dtn\",\n \"dvb\",\n \"dvx\",\n \"dweb\",\n \"ed2k\",\n \"eid\",\n \"elsi\",\n \"embedded\",\n \"ens\",\n \"ethereum\",\n \"example\",\n \"facetime\",\n \"feed\",\n \"feedready\",\n \"fido\",\n \"file\",\n \"finger\",\n \"first-run-pen-experience\",\n \"fish\",\n \"fm\",\n \"ftp\",\n \"fuchsia-pkg\",\n \"geo\",\n \"gg\",\n \"git\",\n \"gitoid\",\n \"gizmoproject\",\n \"go\",\n \"gopher\",\n \"graph\",\n \"gtalk\",\n \"h323\",\n \"ham\",\n \"hcap\",\n \"hcp\",\n \"http\",\n \"https\",\n \"hxxp\",\n \"hxxps\",\n \"hydrazone\",\n \"hyper\",\n \"iax\",\n \"icap\",\n \"icon\",\n \"im\",\n \"imap\",\n \"info\",\n \"iotdisco\",\n \"ipfs\",\n \"ipn\",\n \"ipns\",\n \"ipp\",\n \"ipps\",\n \"irc\",\n \"irc6\",\n \"ircs\",\n \"iris\",\n \"iris.beep\",\n \"iris.lwz\",\n \"iris.xpc\",\n \"iris.xpcs\",\n \"isostore\",\n \"itms\",\n \"jabber\",\n \"jar\",\n \"jms\",\n \"keyparc\",\n \"lastfm\",\n \"lbry\",\n \"ldap\",\n \"ldaps\",\n \"leaptofrogans\",\n \"lorawan\",\n \"lpa\",\n \"lvlt\",\n \"magnet\",\n \"mailto\",\n \"maps\",\n \"market\",\n \"matrix\",\n \"message\",\n \"microsoft.windows.camera\",\n \"microsoft.windows.camera.multipicker\",\n \"microsoft.windows.camera.picker\",\n \"mid\",\n \"mms\",\n \"mongodb\",\n \"moz\",\n \"moz-extension\",\n \"ms-access\",\n \"ms-appinstaller\",\n \"ms-browser-extension\",\n \"ms-calculator\",\n \"ms-drive-to\",\n \"ms-enrollment\",\n \"ms-excel\",\n \"ms-eyecontrolspeech\",\n \"ms-gamebarservices\",\n \"ms-gamingoverlay\",\n \"ms-getoffice\",\n \"ms-help\",\n \"ms-infopath\",\n \"ms-inputapp\",\n \"ms-lockscreencomponent-config\",\n \"ms-media-stream-id\",\n \"ms-meetnow\",\n \"ms-mixedrealitycapture\",\n \"ms-mobileplans\",\n \"ms-newsandinterests\",\n \"ms-officeapp\",\n \"ms-people\",\n \"ms-powerpoint\",\n \"ms-project\",\n \"ms-publisher\",\n \"ms-remotedesktop-launch\",\n \"ms-restoretabcompanion\",\n \"ms-screenclip\",\n \"ms-screensketch\",\n \"ms-search\",\n \"ms-search-repair\",\n \"ms-secondary-screen-controller\",\n \"ms-secondary-screen-setup\",\n \"ms-settings\",\n \"ms-settings-airplanemode\",\n \"ms-settings-bluetooth\",\n \"ms-settings-camera\",\n \"ms-settings-cellular\",\n \"ms-settings-cloudstorage\",\n \"ms-settings-connectabledevices\",\n \"ms-settings-displays-topology\",\n \"ms-settings-emailandaccounts\",\n \"ms-settings-language\",\n \"ms-settings-location\",\n \"ms-settings-lock\",\n \"ms-settings-nfctransactions\",\n \"ms-settings-notifications\",\n \"ms-settings-power\",\n \"ms-settings-privacy\",\n \"ms-settings-proximity\",\n \"ms-settings-screenrotation\",\n \"ms-settings-wifi\",\n \"ms-settings-workplace\",\n \"ms-spd\",\n \"ms-stickers\",\n \"ms-sttoverlay\",\n \"ms-transit-to\",\n \"ms-useractivityset\",\n \"ms-virtualtouchpad\",\n \"ms-visio\",\n \"ms-walk-to\",\n \"ms-whiteboard\",\n \"ms-whiteboard-cmd\",\n \"ms-word\",\n \"msnim\",\n \"msrp\",\n \"msrps\",\n \"mss\",\n \"mt\",\n \"mtqp\",\n \"mumble\",\n \"mupdate\",\n \"mvn\",\n \"news\",\n \"nfs\",\n \"ni\",\n \"nih\",\n \"nntp\",\n \"notes\",\n \"num\",\n \"ocf\",\n \"oid\",\n \"onenote\",\n \"onenote-cmd\",\n \"opaquelocktoken\",\n \"openpgp4fpr\",\n \"otpauth\",\n \"palm\",\n \"paparazzi\",\n \"payment\",\n \"payto\",\n \"pkcs11\",\n \"platform\",\n \"pop\",\n \"pres\",\n \"proxy\",\n \"psyc\",\n \"pttp\",\n \"pwid\",\n \"qb\",\n \"query\",\n \"quic-transport\",\n \"redis\",\n \"rediss\",\n \"reload\",\n \"res\",\n \"resource\",\n \"rmi\",\n \"rsync\",\n \"rtmfp\",\n \"rtmp\",\n \"rtsp\",\n \"rtsps\",\n \"rtspu\",\n \"sarif\",\n \"secondlife\",\n \"secret-token\",\n \"service\",\n \"session\",\n \"sftp\",\n \"sgn\",\n \"shc\",\n \"sieve\",\n \"simpleledger\",\n \"simplex\",\n \"sip\",\n \"sips\",\n \"skype\",\n \"smb\",\n \"smp\",\n \"sms\",\n \"smtp\",\n \"snmp\",\n \"soap.beep\",\n \"soap.beeps\",\n \"soldat\",\n \"spiffe\",\n \"spotify\",\n \"ssb\",\n \"ssh\",\n \"starknet\",\n \"steam\",\n \"stun\",\n \"stuns\",\n \"submit\",\n \"svn\",\n \"swh\",\n \"swid\",\n \"swidpath\",\n \"tag\",\n \"taler\",\n \"teamspeak\",\n \"tel\",\n \"teliaeid\",\n \"telnet\",\n \"tftp\",\n \"things\",\n \"thismessage\",\n \"tip\",\n \"tn3270\",\n \"tool\",\n \"turn\",\n \"turns\",\n \"tv\",\n \"udp\",\n \"unreal\",\n \"urn\",\n \"ut2004\",\n \"uuid-in-package\",\n \"v-event\",\n \"vemmi\",\n \"ventrilo\",\n \"ves\",\n \"view-source\",\n \"vnc\",\n \"vscode\",\n \"vscode-insiders\",\n \"vsls\",\n \"w3\",\n \"wcr\",\n \"web3\",\n \"webcal\",\n \"wifi\",\n \"ws\",\n \"wss\",\n \"wtai\",\n \"wyciwyg\",\n \"xcon\",\n \"xcon-userid\",\n \"xfire\",\n \"xmlrpc.beep\",\n \"xmlrpc.beeps\",\n \"xmpp\",\n \"xri\",\n \"ymsgr\",\n \"z39.50r\",\n \"z39.50s\"\n]\n", "/**\n * uri-util.js\n */\n\n/* shared */\nimport { getType, isString } from './common.js';\nimport textChars from '../lib/file/text-chars.json' assert { type: 'json' };\nimport uriSchemes from '../lib/iana/uri-schemes.json' assert { type: 'json' };\n\n/* constants */\nconst HEX = 16;\nconst REG_BASE64 = /^[\\da-z+/\\-_=]+$/i;\nconst REG_DATA_URL = /data:[^,]*,[^\"]+/g;\nconst REG_DATA_URL_BASE64 = /data:[^,]*;?base64,[\\da-z+/\\-_=]+/i;\nconst REG_HTML_SP = /[<>\"'\\s]/g;\nconst REG_HTML_SP_URL_ENC = /%(?:2(?:2|7)|3(?:C|E))/g;\nconst REG_NUM_REF = /&#(x(?:00)?[\\dA-F]{2}|0?\\d{1,3});?/ig;\nconst REG_SCHEME = /^[a-z][\\da-z+\\-.]*$/;\nconst REG_SCHEME_CUSTOM = /^(?:ext|web)\\+[a-z]+$/;\nconst REG_SCRIPT = /(?:java|vb)script/;\nconst REG_URL_ENC = /^%[\\dA-F]{2}$/i;\nconst REG_URL_ENC_AMP = /%26/g;\n\n/**\n * get URL encoded string\n *\n * @param {string} str - string\n * @returns {string} - URL encoded string\n */\nexport const getUrlEncodedString = str => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n const chars = [];\n for (const ch of str) {\n chars.push(`%${ch.charCodeAt(0).toString(HEX).toUpperCase()}`);\n }\n return chars.join('');\n};\n\n/**\n * escape URL encoded HTML special chars\n *\n * @param {string} ch - URL encoded (percent encoded) char\n * @returns {string} - escaped URL encoded HTML special char / URL encoded char\n */\nexport const escapeUrlEncodedHtmlChars = ch => {\n if (isString(ch)) {\n if (REG_URL_ENC.test(ch)) {\n ch = ch.toUpperCase();\n } else {\n throw new Error(`Invalid URL encoded character: ${ch}`);\n }\n } else {\n throw new TypeError(`Expected String but got ${getType(ch)}.`);\n }\n const [amp, num, lt, gt, quot, apos] =\n ['&', '#', '<', '>', '\"', \"'\"].map(getUrlEncodedString);\n let escapedChar;\n if (ch === amp) {\n escapedChar = `${amp}amp;`;\n } else if (ch === lt) {\n escapedChar = `${amp}lt;`;\n } else if (ch === gt) {\n escapedChar = `${amp}gt;`;\n } else if (ch === quot) {\n escapedChar = `${amp}quot;`;\n } else if (ch === apos) {\n escapedChar = `${amp}${num}39;`;\n } else {\n escapedChar = ch;\n }\n return escapedChar;\n};\n\n/**\n * parse base64 encoded data\n *\n * @param {string} data - base64 encoded data\n * @returns {string} - parsed text data / base64 encoded data if binary\n */\nexport const parseBase64 = data => {\n if (!isString(data)) {\n throw new TypeError(`Expected String but got ${getType(data)}.`);\n } else if (!REG_BASE64.test(data)) {\n throw new Error(`Invalid base64 data: ${data}`);\n }\n const bin = atob(data);\n const uint8arr = Uint8Array.from([...bin].map(c => c.charCodeAt(0)));\n const textCharCodes = new Set(textChars);\n let parsedData;\n if (uint8arr.every(c => textCharCodes.has(c))) {\n parsedData = bin.replace(/\\s/g, getUrlEncodedString);\n } else {\n parsedData = data;\n }\n return parsedData;\n};\n\n/**\n * parse URL encoded numeric character references in the range 0x00 to 0xFF\n *\n * @param {string} str - string\n * @param {number} nest - nest level\n * @returns {string} - parsed string\n */\nexport const parseUrlEncodedNumCharRef = (str, nest = 0) => {\n if (!isString(str)) {\n throw new TypeError(`Expected String but got ${getType(str)}.`);\n }\n if (!Number.isInteger(nest)) {\n throw new TypeError(`Expected Number but got ${getType(nest)}.`);\n } else if (nest > HEX) {\n throw new Error('Character references nested too deeply.');\n }\n let res = decodeURIComponent(str);\n if (/&#/.test(res)) {\n const textCharCodes = new Set(textChars);\n const items = [...res.matchAll(REG_NUM_REF)].reverse();\n for (const item of items) {\n const [numCharRef, value] = item;\n let num;\n if (/^x[\\dA-F]+/i.test(value)) {\n num = parseInt(`0${value}`, HEX);\n } else if (/^[\\d]+/.test(value)) {\n num = parseInt(value);\n }\n if (Number.isInteger(num)) {\n const { index } = item;\n const [preNum, postNum] = [\n res.substring(0, index),\n res.substring(index + numCharRef.length)\n ];\n if (textCharCodes.has(num)) {\n res = `${preNum}${String.fromCharCode(num)}${postNum}`;\n if (/#x?$/.test(preNum) || /^#(?:x(?:00)?[2-7]|\\d)/.test(postNum)) {\n res = parseUrlEncodedNumCharRef(res, ++nest);\n }\n } else if (num < HEX * HEX) {\n res = `${preNum}${postNum}`;\n }\n }\n }\n }\n return res;\n};\n\n/**\n * URI schemes\n *\n */\nexport class URISchemes {\n /* private fields */\n #schemes;\n\n /**\n * construct\n */\n constructor() {\n this.#schemes = new Set(uriSchemes);\n }\n\n /**\n * get schemes\n *\n * @see {@link https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml}\n * - Historical schemes omitted\n * - 'moz-extension' scheme added\n * @returns {Array.<string>} - array of schemes\n */\n get() {\n return [...this.#schemes];\n }\n\n /**\n * has scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n has(scheme) {\n return this.#schemes.has(scheme);\n }\n\n /**\n * add scheme\n * NOTE: `javascript` and/or `vbscript` schemes can not be registered\n *\n * @param {string} scheme - scheme\n * @returns {Array.<string>} - array of schemes\n */\n add(scheme) {\n if (!isString(scheme)) {\n throw new TypeError(`Expected String but got ${getType(scheme)}.`);\n } else if (REG_SCRIPT.test(scheme) || !REG_SCHEME.test(scheme)) {\n throw new Error(`Invalid scheme: ${scheme}`);\n }\n this.#schemes.add(scheme);\n return [...this.#schemes];\n }\n\n /**\n * remove scheme\n *\n * @param {string} scheme - scheme\n * @returns {boolean} - result\n */\n remove(scheme) {\n return this.#schemes.delete(scheme);\n }\n\n /**\n * is URI\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\n isURI(uri) {\n let res;\n if (isString(uri)) {\n try {\n const { protocol } = new URL(uri);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n res = (!REG_SCRIPT.test(scheme) && REG_SCHEME_CUSTOM.test(scheme)) ||\n schemeParts.every(s => this.#schemes.has(s));\n } catch (e) {\n res = false;\n }\n }\n return !!res;\n }\n};\n\n/* URL sanitizer */\nexport class URLSanitizer extends URISchemes {\n /* private fields */\n #nest;\n #recurse;\n\n /**\n * construct\n */\n constructor() {\n super();\n this.#nest = 0;\n this.#recurse = new Set();\n }\n\n /**\n * sanitize URL\n * NOTE: `data` and/or `file` schemes must be explicitly allowed\n * `javascript` and/or `vbscript` schemes can not be allowed\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @param {Array.<string>} opt.allow - array of allowed schemes\n * @param {Array.<string>} opt.deny - array of denied schemes\n * @param {Array.<string>} opt.only - array of specific schemes to allow\n * @returns {?string} - sanitized URL\n */\n sanitize(url, opt = { allow: [], deny: [], only: [] }) {\n if (this.#nest > HEX) {\n this.#nest = 0;\n throw new Error('Data URLs nested too deeply.');\n }\n let sanitizedUrl;\n if (super.isURI(url)) {\n const { allow, deny, only } = opt ?? {};\n const { hash, href, pathname, protocol, search } = new URL(url);\n const scheme = protocol.replace(/:$/, '');\n const schemeParts = scheme.split('+');\n const schemeMap = new Map([\n ['data', false],\n ['file', false],\n ['javascrpt', false],\n ['vbscript', false]\n ]);\n if (Array.isArray(only) && only.length) {\n const schemes = super.get();\n for (const item of schemes) {\n schemeMap.set(item, false);\n }\n const items = Object.values(only);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (!REG_SCRIPT.test(item)) {\n schemeMap.set(item, true);\n }\n }\n }\n } else {\n if (Array.isArray(allow) && allow.length) {\n const items = Object.values(allow);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (!REG_SCRIPT.test(item)) {\n schemeMap.set(item, true);\n }\n }\n }\n }\n if (Array.isArray(deny) && deny.length) {\n const items = Object.values(deny);\n for (let item of items) {\n if (isString(item)) {\n item = item.trim();\n if (item) {\n schemeMap.set(item, false);\n }\n }\n }\n }\n }\n let bool;\n for (const [key, value] of schemeMap.entries()) {\n bool = value || (scheme !== key && schemeParts.every(s => s !== key));\n if (!bool) {\n break;\n }\n }\n if (bool) {\n let escapeHtml;\n let urlToSanitize = href;\n if (schemeParts.includes('data')) {\n const [head, ...body] = pathname.split(',');\n const data = `${body.join(',')}${search}${hash}`;\n const mediaType = head.split(';');\n let parsedData = data;\n if (mediaType[mediaType.length - 1] === 'base64') {\n mediaType.pop();\n parsedData = parseBase64(data);\n } else {\n try {\n const decodedData = parseUrlEncodedNumCharRef(parsedData);\n const { protocol: dataScheme } = new URL(decodedData.trim());\n const dataSchemeParts = dataScheme.replace(/:$/, '').split('+');\n if (dataSchemeParts.some(s => REG_SCRIPT.test(s))) {\n urlToSanitize = '';\n }\n } catch (e) {\n // fall through\n }\n }\n const containsDataUrl = /data:[^,]*,/.test(parsedData);\n if (parsedData !== data || containsDataUrl) {\n if (containsDataUrl) {\n const matchedDataUrls = parsedData.matchAll(REG_DATA_URL);\n const items = [...matchedDataUrls].reverse();\n for (const item of items) {\n let [dataUrl] = item;\n if (REG_DATA_URL_BASE64.test(dataUrl)) {\n [dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);\n }\n this.#nest++;\n this.#recurse.add(dataUrl);\n const parsedDataUrl = this.sanitize(dataUrl, {\n allow: ['data']\n });\n if (parsedDataUrl) {\n const { index } = item;\n const [preDataUrl, postDataUrl] = [\n parsedData.substring(0, index),\n parsedData.substring(index + dataUrl.length)\n ];\n parsedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;\n }\n }\n if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n urlToSanitize = `${scheme}:${mediaType.join(';')},${parsedData}`;\n } else if (this.#recurse.has(url)) {\n this.#recurse.delete(url);\n } else {\n escapeHtml = true;\n }\n } else {\n escapeHtml = true;\n }\n if (urlToSanitize) {\n sanitizedUrl = urlToSanitize\n .replace(REG_HTML_SP, getUrlEncodedString)\n .replace(REG_URL_ENC_AMP, escapeUrlEncodedHtmlChars);\n if (escapeHtml) {\n sanitizedUrl = sanitizedUrl\n .replace(REG_HTML_SP_URL_ENC, escapeUrlEncodedHtmlChars);\n this.#nest = 0;\n }\n } else {\n sanitizedUrl = urlToSanitize;\n this.#nest = 0;\n }\n }\n }\n return sanitizedUrl || null;\n }\n\n /**\n * object with extended props based on URL API\n *\n * @typedef {object} ParsedURL\n * @property {string} input - URL input\n * @property {boolean} valid - is valid URI\n * @property {object} data - parsed result of data URL, `null`able\n * @property {string} data.mime - MIME type\n * @property {boolean} data.base64 - `true` if base64 encoded\n * @property {string} data.data - data part of the data URL\n * @property {string} href - same as URL API\n * @property {string} origin - same as URL API\n * @property {string} protocol - same as URL API\n * @property {string} username - same as URL API\n * @property {string} password - same as URL API\n * @property {string} host - same as URL API\n * @property {string} hostname - same as URL API\n * @property {string} port - same as URL API\n * @property {string} pathname - same as URL API\n * @property {string} search - same as URL API\n * @property {object} searchParams - same as URL API\n * @property {string} hash - same as URL API\n */\n\n /**\n * parse sanitized URL\n *\n * @param {string} url - URL input\n * @returns {ParsedURL} - result with extended props based on URL API\n */\n parse(url) {\n if (!isString(url)) {\n throw new TypeError(`Expected String but got ${getType(url)}.`);\n }\n const sanitizedUrl = this.sanitize(url, {\n allow: ['data', 'file']\n });\n const parsedUrl = new Map([\n ['input', url]\n ]);\n if (sanitizedUrl) {\n const urlObj = new URL(sanitizedUrl);\n const { pathname, protocol } = urlObj;\n const schemeParts = protocol.replace(/:$/, '').split('+');\n parsedUrl.set('valid', true);\n if (schemeParts.includes('data')) {\n const dataUrl = new Map();\n const [head, ...body] = pathname.split(',');\n const data = `${body.join(',')}`;\n const mediaType = head.split(';');\n const isBase64 = mediaType[mediaType.length - 1] === 'base64';\n if (isBase64) {\n mediaType.pop();\n }\n dataUrl.set('mime', mediaType.join(';'));\n dataUrl.set('base64', isBase64);\n dataUrl.set('data', data);\n parsedUrl.set('data', Object.fromEntries(dataUrl));\n } else {\n parsedUrl.set('data', null);\n }\n for (const key in urlObj) {\n const value = urlObj[key];\n if (typeof value !== 'function') {\n parsedUrl.set(key, value);\n }\n }\n } else {\n parsedUrl.set('valid', false);\n }\n return Object.fromEntries(parsedUrl);\n }\n};\n\n/* instance */\nconst urlSanitizer = new URLSanitizer();\n\n/* aliases and async wrappers */\n/**\n * is URI sync\n *\n * @param {string} uri - URI input\n * @returns {boolean} - result\n */\nconst isUri = uri => urlSanitizer.isURI(uri);\n\n/**\n * is URI async\n *\n * @param {string} uri - URI input\n * @returns {Promise.<boolean>} - result\n */\nexport const isURI = async uri => {\n const res = await isUri(uri);\n return res;\n};\n\n/**\n * sanitize URL sync\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {?string} - sanitized URL\n */\nconst sanitizeUrl = (url, opt) => urlSanitizer.sanitize(url, opt ?? {\n allow: [],\n deny: [],\n only: []\n});\n\n/**\n * sanitize URL async\n *\n * @param {string} url - URL input\n * @param {object} opt - options\n * @returns {Promise.<?string>} - sanitized URL\n */\nexport const sanitizeURL = async (url, opt) => {\n const res = await sanitizeUrl(url, opt);\n return res;\n};\n\n/**\n * parse URL sync\n *\n * @param {string} url - URL input\n * @returns {ParsedURL} - result with extended props based on URL API\n */\nconst parseUrl = url => urlSanitizer.parse(url);\n\n/**\n * parse URL async\n *\n * @param {string} url - URL input\n * @returns {Promise.<ParsedURL>} - result with extended props based on URL API\n */\nexport const parseURL = async url => {\n const res = await parseUrl(url);\n return res;\n};\n\n/* export instance and aliases */\nexport {\n urlSanitizer as default,\n isUri as isURISync,\n parseUrl as parseURLSync,\n sanitizeUrl as sanitizeURLSync\n};\n"],
5
+ "mappings": "AAcO,IAAMA,EAAUC,GACrB,OAAO,UAAU,SAAS,KAAKA,CAAC,EAAE,MAAM,EAAW,EAAO,EAQ/CC,EAAWD,GAAK,OAAOA,GAAM,UAAYA,aAAa,OCvBnE,IAAAE,EAAA,CACE,EACA,EACA,EACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,GACF,ECxOA,IAAAC,EAAA,CACE,MACA,OACA,QACA,OACA,OACA,MACA,MACA,YACA,MACA,MACA,MACA,MACA,OACA,UACA,UACA,MACA,KACA,MACA,aACA,KACA,SACA,UACA,UACA,cACA,OACA,OACA,aACA,QACA,aACA,SACA,MACA,OACA,QACA,SACA,mBACA,MACA,OACA,QACA,0BACA,UACA,eACA,OACA,OACA,MACA,MACA,MACA,OACA,MACA,WACA,OACA,MACA,MACA,qBACA,kBACA,MACA,OACA,MACA,MACA,MACA,OACA,MACA,MACA,MACA,OACA,OACA,MACA,OACA,WACA,MACA,WACA,UACA,WACA,OACA,YACA,OACA,OACA,SACA,2BACA,OACA,KACA,MACA,cACA,MACA,KACA,MACA,SACA,eACA,KACA,SACA,QACA,QACA,OACA,MACA,OACA,MACA,OACA,QACA,OACA,QACA,YACA,QACA,MACA,OACA,OACA,KACA,OACA,OACA,WACA,OACA,MACA,OACA,MACA,OACA,MACA,OACA,OACA,OACA,YACA,WACA,WACA,YACA,WACA,OACA,SACA,MACA,MACA,UACA,SACA,OACA,OACA,QACA,gBACA,UACA,MACA,OACA,SACA,SACA,OACA,SACA,SACA,UACA,2BACA,uCACA,kCACA,MACA,MACA,UACA,MACA,gBACA,YACA,kBACA,uBACA,gBACA,cACA,gBACA,WACA,sBACA,qBACA,mBACA,eACA,UACA,cACA,cACA,gCACA,qBACA,aACA,yBACA,iBACA,sBACA,eACA,YACA,gBACA,aACA,eACA,0BACA,yBACA,gBACA,kBACA,YACA,mBACA,iCACA,4BACA,cACA,2BACA,wBACA,qBACA,uBACA,2BACA,iCACA,gCACA,+BACA,uBACA,uBACA,mBACA,8BACA,4BACA,oBACA,sBACA,wBACA,6BACA,mBACA,wBACA,SACA,cACA,gBACA,gBACA,qBACA,qBACA,WACA,aACA,gBACA,oBACA,UACA,QACA,OACA,QACA,MACA,KACA,OACA,SACA,UACA,MACA,OACA,MACA,KACA,MACA,OACA,QACA,MACA,MACA,MACA,UACA,cACA,kBACA,cACA,UACA,OACA,YACA,UACA,QACA,SACA,WACA,MACA,OACA,QACA,OACA,OACA,OACA,KACA,QACA,iBACA,QACA,SACA,SACA,MACA,WACA,MACA,QACA,QACA,OACA,OACA,QACA,QACA,QACA,aACA,eACA,UACA,UACA,OACA,MACA,MACA,QACA,eACA,UACA,MACA,OACA,QACA,MACA,MACA,MACA,OACA,OACA,YACA,aACA,SACA,SACA,UACA,MACA,MACA,WACA,QACA,OACA,QACA,SACA,MACA,MACA,OACA,WACA,MACA,QACA,YACA,MACA,WACA,SACA,OACA,SACA,cACA,MACA,SACA,OACA,OACA,QACA,KACA,MACA,SACA,MACA,SACA,kBACA,UACA,QACA,WACA,MACA,cACA,MACA,SACA,kBACA,OACA,KACA,MACA,OACA,SACA,OACA,KACA,MACA,OACA,UACA,OACA,cACA,QACA,cACA,eACA,OACA,MACA,QACA,UACA,SACF,ECjVA,IAAMC,EAAM,GACNC,EAAa,oBACbC,EAAe,oBACfC,EAAsB,qCACtBC,EAAc,YACdC,EAAsB,0BACtBC,EAAc,uCACdC,GAAa,sBACbC,GAAoB,wBACpBC,EAAa,oBACbC,GAAc,iBACdC,GAAkB,OAQXC,EAAsBC,GAAO,CACxC,GAAI,CAACC,EAASD,CAAG,EACf,MAAM,IAAI,UAAU,2BAA2BE,EAAQF,CAAG,IAAI,EAEhE,IAAMG,EAAQ,CAAC,EACf,QAAWC,KAAMJ,EACfG,EAAM,KAAK,IAAIC,EAAG,WAAW,CAAC,EAAE,SAASjB,CAAG,EAAE,YAAY,GAAG,EAE/D,OAAOgB,EAAM,KAAK,EAAE,CACtB,EAQaE,EAA4BD,GAAM,CAC7C,GAAIH,EAASG,CAAE,EACb,GAAIP,GAAY,KAAKO,CAAE,EACrBA,EAAKA,EAAG,YAAY,MAEpB,OAAM,IAAI,MAAM,kCAAkCA,GAAI,MAGxD,OAAM,IAAI,UAAU,2BAA2BF,EAAQE,CAAE,IAAI,EAE/D,GAAM,CAACE,EAAKC,EAAKC,EAAIC,EAAIC,EAAMC,CAAI,EACjC,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EAAE,IAAIZ,CAAmB,EACpDa,EACJ,OAAIR,IAAOE,EACTM,EAAc,GAAGN,QACRF,IAAOI,EAChBI,EAAc,GAAGN,OACRF,IAAOK,EAChBG,EAAc,GAAGN,OACRF,IAAOM,EAChBE,EAAc,GAAGN,SACRF,IAAOO,EAChBC,EAAc,GAAGN,IAAMC,OAEvBK,EAAcR,EAETQ,CACT,EAQaC,GAAcC,GAAQ,CACjC,GAAKb,EAASa,CAAI,GAEX,GAAI,CAAC1B,EAAW,KAAK0B,CAAI,EAC9B,MAAM,IAAI,MAAM,wBAAwBA,GAAM,MAF9C,OAAM,IAAI,UAAU,2BAA2BZ,EAAQY,CAAI,IAAI,EAIjE,IAAMC,EAAM,KAAKD,CAAI,EACfE,EAAW,WAAW,KAAK,CAAC,GAAGD,CAAG,EAAE,IAAIE,GAAKA,EAAE,WAAW,CAAC,CAAC,CAAC,EAC7DC,EAAgB,IAAI,IAAIC,CAAS,EACnCC,EACJ,OAAIJ,EAAS,MAAMC,GAAKC,EAAc,IAAID,CAAC,CAAC,EAC1CG,EAAaL,EAAI,QAAQ,MAAOhB,CAAmB,EAEnDqB,EAAaN,EAERM,CACT,EASaC,EAA4B,CAACrB,EAAKsB,EAAO,IAAM,CAC1D,GAAI,CAACrB,EAASD,CAAG,EACf,MAAM,IAAI,UAAU,2BAA2BE,EAAQF,CAAG,IAAI,EAEhE,GAAK,OAAO,UAAUsB,CAAI,GAEnB,GAAIA,EAAOnC,EAChB,MAAM,IAAI,MAAM,yCAAyC,MAFzD,OAAM,IAAI,UAAU,2BAA2Be,EAAQoB,CAAI,IAAI,EAIjE,IAAIC,EAAM,mBAAmBvB,CAAG,EAChC,GAAI,KAAK,KAAKuB,CAAG,EAAG,CAClB,IAAML,EAAgB,IAAI,IAAIC,CAAS,EACjCK,EAAQ,CAAC,GAAGD,EAAI,SAAS9B,CAAW,CAAC,EAAE,QAAQ,EACrD,QAAWgC,KAAQD,EAAO,CACxB,GAAM,CAACE,EAAYC,CAAK,EAAIF,EACxBlB,EAMJ,GALI,cAAc,KAAKoB,CAAK,EAC1BpB,EAAM,SAAS,IAAIoB,IAASxC,CAAG,EACtB,SAAS,KAAKwC,CAAK,IAC5BpB,EAAM,SAASoB,CAAK,GAElB,OAAO,UAAUpB,CAAG,EAAG,CACzB,GAAM,CAAE,MAAAqB,CAAM,EAAIH,EACZ,CAACI,EAAQC,CAAO,EAAI,CACxBP,EAAI,UAAU,EAAGK,CAAK,EACtBL,EAAI,UAAUK,EAAQF,EAAW,MAAM,CACzC,EACIR,EAAc,IAAIX,CAAG,GACvBgB,EAAM,GAAGM,IAAS,OAAO,aAAatB,CAAG,IAAIuB,KACzC,OAAO,KAAKD,CAAM,GAAK,yBAAyB,KAAKC,CAAO,KAC9DP,EAAMF,EAA0BE,EAAK,EAAED,CAAI,IAEpCf,EAAMpB,EAAMA,IACrBoC,EAAM,GAAGM,IAASC,IAEtB,CACF,CACF,CACA,OAAOP,CACT,EAMaQ,EAAN,KAAiB,CAEtBC,GAKA,aAAc,CACZ,KAAKA,GAAW,IAAI,IAAIC,CAAU,CACpC,CAUA,KAAM,CACJ,MAAO,CAAC,GAAG,KAAKD,EAAQ,CAC1B,CAQA,IAAIE,EAAQ,CACV,OAAO,KAAKF,GAAS,IAAIE,CAAM,CACjC,CASA,IAAIA,EAAQ,CACV,GAAKjC,EAASiC,CAAM,GAEb,GAAItC,EAAW,KAAKsC,CAAM,GAAK,CAACxC,GAAW,KAAKwC,CAAM,EAC3D,MAAM,IAAI,MAAM,mBAAmBA,GAAQ,MAF3C,OAAM,IAAI,UAAU,2BAA2BhC,EAAQgC,CAAM,IAAI,EAInE,YAAKF,GAAS,IAAIE,CAAM,EACjB,CAAC,GAAG,KAAKF,EAAQ,CAC1B,CAQA,OAAOE,EAAQ,CACb,OAAO,KAAKF,GAAS,OAAOE,CAAM,CACpC,CAQA,MAAMC,EAAK,CACT,IAAIZ,EACJ,GAAItB,EAASkC,CAAG,EACd,GAAI,CACF,GAAM,CAAE,SAAAC,CAAS,EAAI,IAAI,IAAID,CAAG,EAC1BD,EAASE,EAAS,QAAQ,KAAM,EAAE,EAClCC,EAAcH,EAAO,MAAM,GAAG,EACpCX,EAAO,CAAC3B,EAAW,KAAKsC,CAAM,GAAKvC,GAAkB,KAAKuC,CAAM,GAC1DG,EAAY,MAAMC,GAAK,KAAKN,GAAS,IAAIM,CAAC,CAAC,CACnD,MAAE,CACAf,EAAM,EACR,CAEF,MAAO,CAAC,CAACA,CACX,CACF,EAGagB,EAAN,cAA2BR,CAAW,CAE3CS,GACAC,GAKA,aAAc,CACZ,MAAM,EACN,KAAKD,GAAQ,EACb,KAAKC,GAAW,IAAI,GACtB,CAcA,SAASC,EAAKC,EAAM,CAAE,MAAO,CAAC,EAAG,KAAM,CAAC,EAAG,KAAM,CAAC,CAAE,EAAG,CACrD,GAAI,KAAKH,GAAQrD,EACf,WAAKqD,GAAQ,EACP,IAAI,MAAM,8BAA8B,EAEhD,IAAII,EACJ,GAAI,MAAM,MAAMF,CAAG,EAAG,CACpB,GAAM,CAAE,MAAAG,EAAO,KAAAC,EAAM,KAAAC,CAAK,EAAIJ,GAAO,CAAC,EAChC,CAAE,KAAAK,EAAM,KAAAC,EAAM,SAAAC,EAAU,SAAAd,EAAU,OAAAe,CAAO,EAAI,IAAI,IAAIT,CAAG,EACxDR,EAASE,EAAS,QAAQ,KAAM,EAAE,EAClCC,EAAcH,EAAO,MAAM,GAAG,EAC9BkB,EAAY,IAAI,IAAI,CACxB,CAAC,OAAQ,EAAK,EACd,CAAC,OAAQ,EAAK,EACd,CAAC,YAAa,EAAK,EACnB,CAAC,WAAY,EAAK,CACpB,CAAC,EACD,GAAI,MAAM,QAAQL,CAAI,GAAKA,EAAK,OAAQ,CACtC,IAAMM,EAAU,MAAM,IAAI,EAC1B,QAAW5B,KAAQ4B,EACjBD,EAAU,IAAI3B,EAAM,EAAK,EAE3B,IAAMD,EAAQ,OAAO,OAAOuB,CAAI,EAChC,QAAStB,KAAQD,EACXvB,EAASwB,CAAI,IACfA,EAAOA,EAAK,KAAK,EACZ7B,EAAW,KAAK6B,CAAI,GACvB2B,EAAU,IAAI3B,EAAM,EAAI,EAIhC,KAAO,CACL,GAAI,MAAM,QAAQoB,CAAK,GAAKA,EAAM,OAAQ,CACxC,IAAMrB,EAAQ,OAAO,OAAOqB,CAAK,EACjC,QAASpB,KAAQD,EACXvB,EAASwB,CAAI,IACfA,EAAOA,EAAK,KAAK,EACZ7B,EAAW,KAAK6B,CAAI,GACvB2B,EAAU,IAAI3B,EAAM,EAAI,EAIhC,CACA,GAAI,MAAM,QAAQqB,CAAI,GAAKA,EAAK,OAAQ,CACtC,IAAMtB,EAAQ,OAAO,OAAOsB,CAAI,EAChC,QAASrB,KAAQD,EACXvB,EAASwB,CAAI,IACfA,EAAOA,EAAK,KAAK,EACbA,GACF2B,EAAU,IAAI3B,EAAM,EAAK,EAIjC,CACF,CACA,IAAI6B,EACJ,OAAW,CAACC,EAAK5B,CAAK,IAAKyB,EAAU,QAAQ,EAE3C,GADAE,EAAO3B,GAAUO,IAAWqB,GAAOlB,EAAY,MAAMC,GAAKA,IAAMiB,CAAG,EAC/D,CAACD,EACH,MAGJ,GAAIA,EAAM,CACR,IAAIE,EACAC,EAAgBR,EACpB,GAAIZ,EAAY,SAAS,MAAM,EAAG,CAChC,GAAM,CAACqB,EAAM,GAAGC,CAAI,EAAIT,EAAS,MAAM,GAAG,EACpCpC,EAAO,GAAG6C,EAAK,KAAK,GAAG,IAAIR,IAASH,IACpCY,EAAYF,EAAK,MAAM,GAAG,EAC5BtC,EAAaN,EACjB,GAAI8C,EAAUA,EAAU,OAAS,CAAC,IAAM,SACtCA,EAAU,IAAI,EACdxC,EAAaP,GAAYC,CAAI,MAE7B,IAAI,CACF,IAAM+C,EAAcxC,EAA0BD,CAAU,EAClD,CAAE,SAAU0C,CAAW,EAAI,IAAI,IAAID,EAAY,KAAK,CAAC,EACnCC,EAAW,QAAQ,KAAM,EAAE,EAAE,MAAM,GAAG,EAC1C,KAAKxB,GAAK1C,EAAW,KAAK0C,CAAC,CAAC,IAC9CmB,EAAgB,GAEpB,MAAE,CAEF,CAEF,IAAMM,EAAkB,cAAc,KAAK3C,CAAU,EACrD,GAAIA,IAAeN,GAAQiD,EAAiB,CAC1C,GAAIA,EAAiB,CAEnB,IAAMvC,EAAQ,CAAC,GADSJ,EAAW,SAAS/B,CAAY,CACvB,EAAE,QAAQ,EAC3C,QAAWoC,KAAQD,EAAO,CACxB,GAAI,CAACwC,CAAO,EAAIvC,EACZnC,EAAoB,KAAK0E,CAAO,IAClC,CAACA,CAAO,EAAI1E,EAAoB,KAAK0E,CAAO,GAE9C,KAAKxB,KACL,KAAKC,GAAS,IAAIuB,CAAO,EACzB,IAAMC,EAAgB,KAAK,SAASD,EAAS,CAC3C,MAAO,CAAC,MAAM,CAChB,CAAC,EACD,GAAIC,EAAe,CACjB,GAAM,CAAE,MAAArC,CAAM,EAAIH,EACZ,CAACyC,EAAYC,CAAW,EAAI,CAChC/C,EAAW,UAAU,EAAGQ,CAAK,EAC7BR,EAAW,UAAUQ,EAAQoC,EAAQ,MAAM,CAC7C,EACA5C,EAAa,GAAG8C,IAAaD,IAAgBE,GAC/C,CACF,CACI,KAAK1B,GAAS,IAAIC,CAAG,EACvB,KAAKD,GAAS,OAAOC,CAAG,EAExBc,EAAa,EAEjB,MAAW,KAAKf,GAAS,IAAIC,CAAG,EAC9B,KAAKD,GAAS,OAAOC,CAAG,EAExBc,EAAa,GAEfC,EAAgB,GAAGvB,KAAU0B,EAAU,KAAK,GAAG,KAAKxC,GACtD,MAAW,KAAKqB,GAAS,IAAIC,CAAG,EAC9B,KAAKD,GAAS,OAAOC,CAAG,EAExBc,EAAa,EAEjB,MACEA,EAAa,GAEXC,GACFb,EAAea,EACZ,QAAQlE,EAAaQ,CAAmB,EACxC,QAAQD,GAAiBO,CAAyB,EACjDmD,IACFZ,EAAeA,EACZ,QAAQpD,EAAqBa,CAAyB,EACzD,KAAKmC,GAAQ,KAGfI,EAAea,EACf,KAAKjB,GAAQ,EAEjB,CACF,CACA,OAAOI,GAAgB,IACzB,CAgCA,MAAMF,EAAK,CACT,GAAI,CAACzC,EAASyC,CAAG,EACf,MAAM,IAAI,UAAU,2BAA2BxC,EAAQwC,CAAG,IAAI,EAEhE,IAAME,EAAe,KAAK,SAASF,EAAK,CACtC,MAAO,CAAC,OAAQ,MAAM,CACxB,CAAC,EACK0B,EAAY,IAAI,IAAI,CACxB,CAAC,QAAS1B,CAAG,CACf,CAAC,EACD,GAAIE,EAAc,CAChB,IAAMyB,EAAS,IAAI,IAAIzB,CAAY,EAC7B,CAAE,SAAAM,EAAU,SAAAd,CAAS,EAAIiC,EACzBhC,EAAcD,EAAS,QAAQ,KAAM,EAAE,EAAE,MAAM,GAAG,EAExD,GADAgC,EAAU,IAAI,QAAS,EAAI,EACvB/B,EAAY,SAAS,MAAM,EAAG,CAChC,IAAM2B,EAAU,IAAI,IACd,CAACN,EAAM,GAAGC,CAAI,EAAIT,EAAS,MAAM,GAAG,EACpCpC,EAAO,GAAG6C,EAAK,KAAK,GAAG,IACvBC,EAAYF,EAAK,MAAM,GAAG,EAC1BY,EAAWV,EAAUA,EAAU,OAAS,CAAC,IAAM,SACjDU,GACFV,EAAU,IAAI,EAEhBI,EAAQ,IAAI,OAAQJ,EAAU,KAAK,GAAG,CAAC,EACvCI,EAAQ,IAAI,SAAUM,CAAQ,EAC9BN,EAAQ,IAAI,OAAQlD,CAAI,EACxBsD,EAAU,IAAI,OAAQ,OAAO,YAAYJ,CAAO,CAAC,CACnD,MACEI,EAAU,IAAI,OAAQ,IAAI,EAE5B,QAAWb,KAAOc,EAAQ,CACxB,IAAM1C,EAAQ0C,EAAOd,CAAG,EACpB,OAAO5B,GAAU,YACnByC,EAAU,IAAIb,EAAK5B,CAAK,CAE5B,CACF,MACEyC,EAAU,IAAI,QAAS,EAAK,EAE9B,OAAO,OAAO,YAAYA,CAAS,CACrC,CACF,EAGMG,EAAe,IAAIhC,EASnBiC,EAAQrC,GAAOoC,EAAa,MAAMpC,CAAG,EAQ9BsC,GAAQ,MAAMtC,GACb,MAAMqC,EAAMrC,CAAG,EAWvBuC,EAAc,CAAChC,EAAKC,IAAQ4B,EAAa,SAAS7B,EAAKC,GAAO,CAClE,MAAO,CAAC,EACR,KAAM,CAAC,EACP,KAAM,CAAC,CACT,CAAC,EASYgC,GAAc,MAAOjC,EAAKC,IACzB,MAAM+B,EAAYhC,EAAKC,CAAG",
6
+ "names": ["getType", "o", "isString", "text_chars_default", "uri_schemes_default", "HEX", "REG_BASE64", "REG_DATA_URL", "REG_DATA_URL_BASE64", "REG_HTML_SP", "REG_HTML_SP_URL_ENC", "REG_NUM_REF", "REG_SCHEME", "REG_SCHEME_CUSTOM", "REG_SCRIPT", "REG_URL_ENC", "REG_URL_ENC_AMP", "getUrlEncodedString", "str", "isString", "getType", "chars", "ch", "escapeUrlEncodedHtmlChars", "amp", "num", "lt", "gt", "quot", "apos", "escapedChar", "parseBase64", "data", "bin", "uint8arr", "c", "textCharCodes", "text_chars_default", "parsedData", "parseUrlEncodedNumCharRef", "nest", "res", "items", "item", "numCharRef", "value", "index", "preNum", "postNum", "URISchemes", "#schemes", "uri_schemes_default", "scheme", "uri", "protocol", "schemeParts", "s", "URLSanitizer", "#nest", "#recurse", "url", "opt", "sanitizedUrl", "allow", "deny", "only", "hash", "href", "pathname", "search", "schemeMap", "schemes", "bool", "key", "escapeHtml", "urlToSanitize", "head", "body", "mediaType", "decodedData", "dataScheme", "containsDataUrl", "dataUrl", "parsedDataUrl", "preDataUrl", "postDataUrl", "parsedUrl", "urlObj", "isBase64", "urlSanitizer", "isUri", "isURI", "sanitizeUrl", "sanitizeURL"]
7
7
  }
package/package.json CHANGED
@@ -50,5 +50,5 @@
50
50
  "sinon": "^15.0.1",
51
51
  "undici": "^5.16.0"
52
52
  },
53
- "version": "0.4.4"
53
+ "version": "0.5.1"
54
54
  }
@@ -256,16 +256,17 @@ export class URLSanitizer extends URISchemes {
256
256
  * @param {object} opt - options
257
257
  * @param {Array.<string>} opt.allow - array of allowed schemes
258
258
  * @param {Array.<string>} opt.deny - array of denied schemes
259
+ * @param {Array.<string>} opt.only - array of specific schemes to allow
259
260
  * @returns {?string} - sanitized URL
260
261
  */
261
- sanitize(url, opt = { allow: [], deny: [] }) {
262
+ sanitize(url, opt = { allow: [], deny: [], only: [] }) {
262
263
  if (this.#nest > HEX) {
263
264
  this.#nest = 0;
264
265
  throw new Error('Data URLs nested too deeply.');
265
266
  }
266
267
  let sanitizedUrl;
267
268
  if (super.isURI(url)) {
268
- const { allow, deny } = opt ?? {};
269
+ const { allow, deny, only } = opt ?? {};
269
270
  const { hash, href, pathname, protocol, search } = new URL(url);
270
271
  const scheme = protocol.replace(/:$/, '');
271
272
  const schemeParts = scheme.split('+');
@@ -275,8 +276,12 @@ export class URLSanitizer extends URISchemes {
275
276
  ['javascrpt', false],
276
277
  ['vbscript', false]
277
278
  ]);
278
- if (Array.isArray(allow) && allow.length) {
279
- const items = Object.values(allow);
279
+ if (Array.isArray(only) && only.length) {
280
+ const schemes = super.get();
281
+ for (const item of schemes) {
282
+ schemeMap.set(item, false);
283
+ }
284
+ const items = Object.values(only);
280
285
  for (let item of items) {
281
286
  if (isString(item)) {
282
287
  item = item.trim();
@@ -285,14 +290,26 @@ export class URLSanitizer extends URISchemes {
285
290
  }
286
291
  }
287
292
  }
288
- }
289
- if (Array.isArray(deny) && deny.length) {
290
- const items = Object.values(deny);
291
- for (let item of items) {
292
- if (isString(item)) {
293
- item = item.trim();
294
- if (item) {
295
- schemeMap.set(item, false);
293
+ } else {
294
+ if (Array.isArray(allow) && allow.length) {
295
+ const items = Object.values(allow);
296
+ for (let item of items) {
297
+ if (isString(item)) {
298
+ item = item.trim();
299
+ if (!REG_SCRIPT.test(item)) {
300
+ schemeMap.set(item, true);
301
+ }
302
+ }
303
+ }
304
+ }
305
+ if (Array.isArray(deny) && deny.length) {
306
+ const items = Object.values(deny);
307
+ for (let item of items) {
308
+ if (isString(item)) {
309
+ item = item.trim();
310
+ if (item) {
311
+ schemeMap.set(item, false);
312
+ }
296
313
  }
297
314
  }
298
315
  }
@@ -387,6 +404,79 @@ export class URLSanitizer extends URISchemes {
387
404
  }
388
405
  return sanitizedUrl || null;
389
406
  }
407
+
408
+ /**
409
+ * object with extended props based on URL API
410
+ *
411
+ * @typedef {object} ParsedURL
412
+ * @property {string} input - URL input
413
+ * @property {boolean} valid - is valid URI
414
+ * @property {object} data - parsed result of data URL, `null`able
415
+ * @property {string} data.mime - MIME type
416
+ * @property {boolean} data.base64 - `true` if base64 encoded
417
+ * @property {string} data.data - data part of the data URL
418
+ * @property {string} href - same as URL API
419
+ * @property {string} origin - same as URL API
420
+ * @property {string} protocol - same as URL API
421
+ * @property {string} username - same as URL API
422
+ * @property {string} password - same as URL API
423
+ * @property {string} host - same as URL API
424
+ * @property {string} hostname - same as URL API
425
+ * @property {string} port - same as URL API
426
+ * @property {string} pathname - same as URL API
427
+ * @property {string} search - same as URL API
428
+ * @property {object} searchParams - same as URL API
429
+ * @property {string} hash - same as URL API
430
+ */
431
+
432
+ /**
433
+ * parse sanitized URL
434
+ *
435
+ * @param {string} url - URL input
436
+ * @returns {ParsedURL} - result with extended props based on URL API
437
+ */
438
+ parse(url) {
439
+ if (!isString(url)) {
440
+ throw new TypeError(`Expected String but got ${getType(url)}.`);
441
+ }
442
+ const sanitizedUrl = this.sanitize(url, {
443
+ allow: ['data', 'file']
444
+ });
445
+ const parsedUrl = new Map([
446
+ ['input', url]
447
+ ]);
448
+ if (sanitizedUrl) {
449
+ const urlObj = new URL(sanitizedUrl);
450
+ const { pathname, protocol } = urlObj;
451
+ const schemeParts = protocol.replace(/:$/, '').split('+');
452
+ parsedUrl.set('valid', true);
453
+ if (schemeParts.includes('data')) {
454
+ const dataUrl = new Map();
455
+ const [head, ...body] = pathname.split(',');
456
+ const data = `${body.join(',')}`;
457
+ const mediaType = head.split(';');
458
+ const isBase64 = mediaType[mediaType.length - 1] === 'base64';
459
+ if (isBase64) {
460
+ mediaType.pop();
461
+ }
462
+ dataUrl.set('mime', mediaType.join(';'));
463
+ dataUrl.set('base64', isBase64);
464
+ dataUrl.set('data', data);
465
+ parsedUrl.set('data', Object.fromEntries(dataUrl));
466
+ } else {
467
+ parsedUrl.set('data', null);
468
+ }
469
+ for (const key in urlObj) {
470
+ const value = urlObj[key];
471
+ if (typeof value !== 'function') {
472
+ parsedUrl.set(key, value);
473
+ }
474
+ }
475
+ } else {
476
+ parsedUrl.set('valid', false);
477
+ }
478
+ return Object.fromEntries(parsedUrl);
479
+ }
390
480
  };
391
481
 
392
482
  /* instance */
@@ -421,7 +511,8 @@ export const isURI = async uri => {
421
511
  */
422
512
  const sanitizeUrl = (url, opt) => urlSanitizer.sanitize(url, opt ?? {
423
513
  allow: [],
424
- deny: []
514
+ deny: [],
515
+ only: []
425
516
  });
426
517
 
427
518
  /**
@@ -436,9 +527,29 @@ export const sanitizeURL = async (url, opt) => {
436
527
  return res;
437
528
  };
438
529
 
530
+ /**
531
+ * parse URL sync
532
+ *
533
+ * @param {string} url - URL input
534
+ * @returns {ParsedURL} - result with extended props based on URL API
535
+ */
536
+ const parseUrl = url => urlSanitizer.parse(url);
537
+
538
+ /**
539
+ * parse URL async
540
+ *
541
+ * @param {string} url - URL input
542
+ * @returns {Promise.<ParsedURL>} - result with extended props based on URL API
543
+ */
544
+ export const parseURL = async url => {
545
+ const res = await parseUrl(url);
546
+ return res;
547
+ };
548
+
439
549
  /* export instance and aliases */
440
550
  export {
441
551
  urlSanitizer as default,
442
552
  isUri as isURISync,
553
+ parseUrl as parseURLSync,
443
554
  sanitizeUrl as sanitizeURLSync
444
555
  };