url-sanitizer 0.7.3 → 0.7.5

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
@@ -35,7 +35,7 @@ import urlSanitizer, {
35
35
  ## sanitizeURL(url, opt)
36
36
 
37
37
  Sanitize the given URL.
38
- * `data` and `file` schemes must be explicitly allowed.
38
+ * `blob`, `data` and `file` schemes must be explicitly allowed.
39
39
 
40
40
  ### Parameters
41
41
 
@@ -61,7 +61,7 @@ console.log(decodeURIComponent(res1));
61
61
  const res2 = await sanitizeURL('data:text/html,<div><script>alert(1);</script></div><p onclick="alert(2)"></p>', {
62
62
  allow: ['data']
63
63
  })
64
- // -> 'data:text/html,%3Cdiv%3E%3C%2Fdiv%3E%3Cp%3E%3C%2Fp%3E'
64
+ // -> 'data:text/html,%3Cdiv%3E%3C/div%3E%3Cp%3E%3C/p%3E'
65
65
 
66
66
  console.log(decodeURIComponent(res2));
67
67
  // => 'data:text/html,<div></div><p></p>'
@@ -71,14 +71,14 @@ const base64data3 = btoa('<div><script>alert(1);</script></div>');
71
71
  const res3 = await sanitizeURL(`data:text/html;base64,${base64data3}`, {
72
72
  allow: ['data']
73
73
  })
74
- // => 'data:text/html,%3Cdiv%3E%3C%2Fdiv%3E'
74
+ // => 'data:text/html,%3Cdiv%3E%3C/div%3E'
75
75
 
76
76
  console.log(decodeURIComponent(res3));
77
77
  // => 'data:text/html,<div></div>'
78
78
 
79
79
  const base64data4 = btoa('<div><img src="javascript:alert(1)"></div>');
80
80
  const res4 = await sanitizeURL(`data:text/html;base64,${base64data4}`);
81
- // => 'data:text/html,%3Cdiv%3E%3Cimg%3E%3C%2Fdiv%3E'
81
+ // => 'data:text/html,%3Cdiv%3E%3Cimg%3E%3C/div%3E'
82
82
 
83
83
  console.log(decodeURIComponent(res4));
84
84
  // => 'data:text/html,<div><img></div>'
@@ -152,7 +152,7 @@ Type: [object][3]
152
152
  * `valid` **[boolean][2]** Is valid URI.
153
153
  * `data` **[object][3]** Parsed result of data URL, `null`able.
154
154
  * `data.mime` **[string][1]** MIME type.
155
- * `data.base64` **[boolean][2]** `true` if base64 encoded.
155
+ * `data.base64` **[boolean][2]** Is base64 encoded.
156
156
  * `data.data` **[string][1]** Data part of the data URL.
157
157
  * `href` **[string][1]** Sanitized URL input.
158
158
  * `origin` **[string][1]** Scheme, domain and port of the sanitized URL.
@@ -196,12 +196,12 @@ const res3 = await parseURL('data:image/svg+xml;base64,PHN2Zz48ZyBvbmNsaWNrPSJhb
196
196
  data: {
197
197
  mime: 'image/svg+xml',
198
198
  base64: false,
199
- data: '%3Csvg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
199
+ data: '%3Csvg%3E%3Cg%3E%3C/g%3E%3C/svg%3E'
200
200
  },
201
- href: 'data:image/svg+xml,%3Csvg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E',
201
+ href: 'data:image/svg+xml,%3Csvg%3E%3Cg%3E%3C/g%3E%3C/svg%3E',
202
202
  origin: 'null',
203
203
  protocol: 'data:',
204
- pathname: 'image/svg+xml,%3Csvg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E',
204
+ pathname: 'image/svg+xml,%3Csvg%3E%3Cg%3E%3C/g%3E%3C/svg%3E',
205
205
  ...
206
206
  } */
207
207
 
@@ -231,7 +231,7 @@ Synchronous version of the [parseURL()](#parseURL).
231
231
 
232
232
  ## isURI(uri)
233
233
 
234
- Verify if the given URI is valid.
234
+ Verify if the given URI is valid and registered.
235
235
 
236
236
  ### Parameters
237
237
 
@@ -239,6 +239,7 @@ Verify if the given URI is valid.
239
239
 
240
240
  Returns **[Promise][5]<[boolean][2]>** Result.
241
241
  * Always `true` for `web+*` and `ext+*` schemes, except `web+javascript`, `web+vbscript`, `ext+javascript`, `ext+vbscript`.
242
+ * `false` for `javascript` and `vbscript` schemes.
242
243
 
243
244
  ```javascript
244
245
  const res1 = await isURI('https://example.com/foo');
@@ -1595,19 +1595,26 @@ var uri_schemes_default = [
1595
1595
  // bundle/mjs/uri-util.js
1596
1596
  var HEX = 16;
1597
1597
  var REG_BASE64 = /^[\da-z+/\-_=]+$/i;
1598
- var REG_DATA_URL = /data:[^,]*,[^"]+/g;
1598
+ var REG_DATA_URL = /data:[^,]*,/;
1599
1599
  var REG_DATA_URL_BASE64 = /data:[^,]*;?base64,[\da-z+/\-_=]+/i;
1600
+ var REG_DATA_URL_G = /data:[^,]*,[^"]+/g;
1601
+ var REG_END_COLON = /:$/;
1602
+ var REG_END_NUM = /(?:#|%23)$/;
1603
+ var REG_END_QUEST = /(?<!(?:#|%23).*)(?:\?|%3F)$/;
1600
1604
  var REG_HTML_SP = /[<>"'\s]/g;
1601
- var REG_HTML_SP_URL_ENC = /%(?:2(?:2|7)|3(?:C|E))/g;
1602
- var REG_HTML_SP_URL_ENC_SHORT = /%(?:2(?:2|7)|3(?:C|E))+?/;
1605
+ var REG_HTML_URL_ENC = /%(?:2(?:2|7)|3(?:C|E))/g;
1606
+ var REG_HTML_URL_ENC_SHORT = /%(?:2(?:2|7)|3(?:C|E))+?/;
1603
1607
  var REG_MIME_DOM = /^(?:text\/(?:ht|x)ml|application\/(?:xhtml\+)?xml|image\/svg\+xml)/;
1608
+ var REG_NUM_DECI = /^\d+/;
1609
+ var REG_NUM_HEAD = /#x?$/;
1610
+ var REG_NUM_HEAD_ASCII = /^#(?:x(?:00)?[2-7]|\d)/;
1611
+ var REG_NUM_HEX = /^x[\dA-F]+/i;
1604
1612
  var REG_NUM_REF = /&#(x(?:00)?[\dA-F]{2}|0?\d{1,3});?/ig;
1605
1613
  var REG_SCHEME = /^[a-z][\da-z+\-.]*$/;
1606
1614
  var REG_SCHEME_CUSTOM = /^(?:ext|web)\+[a-z]+$/;
1607
1615
  var REG_SCRIPT = /(?:java|vb)script/;
1608
1616
  var REG_URL_ENC = /^%[\dA-F]{2}$/i;
1609
1617
  var REG_URL_ENC_AMP = /%26/g;
1610
- var REG_URL_ENC_HTML_SP = /%26(?:(?:l|g|quo)t|%2339);?/g;
1611
1618
  var getURLEncodedString = (str) => {
1612
1619
  if (!isString(str)) {
1613
1620
  throw new TypeError(`Expected String but got ${getType(str)}.`);
@@ -1639,21 +1646,6 @@ var escapeURLEncodedHTMLChars = (ch) => {
1639
1646
  }
1640
1647
  return escapedChar;
1641
1648
  };
1642
- var unescapeURLEncodedHTMLChars = (ch) => {
1643
- let unescapedChar;
1644
- if (/%26lt;?/.test(ch)) {
1645
- unescapedChar = "<";
1646
- } else if (/%26gt;?/.test(ch)) {
1647
- unescapedChar = ">";
1648
- } else if (/%26quot;?/.test(ch)) {
1649
- unescapedChar = '"';
1650
- } else if (/%26%2339;?/.test(ch)) {
1651
- unescapedChar = "'";
1652
- } else {
1653
- unescapedChar = ch;
1654
- }
1655
- return unescapedChar;
1656
- };
1657
1649
  var parseBase64 = (data) => {
1658
1650
  if (!isString(data)) {
1659
1651
  throw new TypeError(`Expected String but got ${getType(data)}.`);
@@ -1687,9 +1679,9 @@ var parseURLEncodedNumCharRef = (str, nest = 0) => {
1687
1679
  for (const item of items) {
1688
1680
  const [numCharRef, value] = item;
1689
1681
  let num;
1690
- if (/^x[\dA-F]+/i.test(value)) {
1682
+ if (REG_NUM_HEX.test(value)) {
1691
1683
  num = parseInt(`0${value}`, HEX);
1692
- } else if (/^[\d]+/.test(value)) {
1684
+ } else if (REG_NUM_DECI.test(value)) {
1693
1685
  num = parseInt(value);
1694
1686
  }
1695
1687
  if (Number.isInteger(num)) {
@@ -1700,7 +1692,7 @@ var parseURLEncodedNumCharRef = (str, nest = 0) => {
1700
1692
  ];
1701
1693
  if (textCharCodes.has(num)) {
1702
1694
  res = `${preNum}${String.fromCharCode(num)}${postNum}`;
1703
- if (/#x?$/.test(preNum) || /^#(?:x(?:00)?[2-7]|\d)/.test(postNum)) {
1695
+ if (REG_NUM_HEAD.test(preNum) || REG_NUM_HEAD_ASCII.test(postNum)) {
1704
1696
  res = parseURLEncodedNumCharRef(res, ++nest);
1705
1697
  }
1706
1698
  } else if (num < HEX * HEX) {
@@ -1711,12 +1703,6 @@ var parseURLEncodedNumCharRef = (str, nest = 0) => {
1711
1703
  }
1712
1704
  return res;
1713
1705
  };
1714
- var purifyURLEncodedDOM = (dom) => {
1715
- if (!isString(dom)) {
1716
- throw new TypeError(`Expected String but got ${getType(dom)}.`);
1717
- }
1718
- return encodeURIComponent(import_dompurify.default.sanitize(decodeURIComponent(dom)));
1719
- };
1720
1706
  var URISchemes = class {
1721
1707
  /* private fields */
1722
1708
  #schemes;
@@ -1774,7 +1760,7 @@ var URISchemes = class {
1774
1760
  /**
1775
1761
  * verify URI
1776
1762
  *
1777
- * @param {string} uri - URI input
1763
+ * @param {string} uri - URI
1778
1764
  * @returns {boolean} - result
1779
1765
  */
1780
1766
  verify(uri) {
@@ -1782,7 +1768,7 @@ var URISchemes = class {
1782
1768
  if (isString(uri)) {
1783
1769
  try {
1784
1770
  const { protocol } = new URL(uri);
1785
- const scheme = protocol.replace(/:$/, "");
1771
+ const scheme = protocol.replace(REG_END_COLON, "");
1786
1772
  const schemeParts = scheme.split("+");
1787
1773
  res = !REG_SCRIPT.test(scheme) && REG_SCHEME_CUSTOM.test(scheme) || schemeParts.every((s) => this.#schemes.has(s));
1788
1774
  } catch (e) {
@@ -1804,17 +1790,72 @@ var URLSanitizer = class extends URISchemes {
1804
1790
  this.#nest = 0;
1805
1791
  this.#recurse = /* @__PURE__ */ new Set();
1806
1792
  }
1793
+ /**
1794
+ * replace matched data URLs
1795
+ *
1796
+ * @param {string} data - data URL
1797
+ * @returns {string} - replaced data URL
1798
+ */
1799
+ replace(data) {
1800
+ if (!isString(data)) {
1801
+ throw new TypeError(`Expected String but got ${getType(data)}.`);
1802
+ }
1803
+ let replacedData = data;
1804
+ if (REG_DATA_URL.test(replacedData)) {
1805
+ const matchedDataUrls = replacedData.matchAll(REG_DATA_URL_G);
1806
+ const items = [...matchedDataUrls].reverse();
1807
+ for (const item of items) {
1808
+ let [dataUrl] = item;
1809
+ if (REG_DATA_URL_BASE64.test(dataUrl)) {
1810
+ [dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);
1811
+ }
1812
+ this.#nest++;
1813
+ this.#recurse.add(dataUrl);
1814
+ const parsedDataUrl = this.sanitize(dataUrl, {
1815
+ allow: ["data"]
1816
+ });
1817
+ const { index } = item;
1818
+ const [preDataUrl, postDataUrl] = [
1819
+ replacedData.substring(0, index),
1820
+ replacedData.substring(index + dataUrl.length)
1821
+ ];
1822
+ if (parsedDataUrl) {
1823
+ replacedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;
1824
+ } else {
1825
+ replacedData = `${preDataUrl}${postDataUrl}`;
1826
+ }
1827
+ }
1828
+ }
1829
+ return replacedData;
1830
+ }
1831
+ /**
1832
+ * purify URL encoded DOM
1833
+ *
1834
+ * @param {string} dom - DOM string
1835
+ * @returns {string} - purified DOM string
1836
+ */
1837
+ purify(dom) {
1838
+ if (!isString(dom)) {
1839
+ throw new TypeError(`Expected String but got ${getType(dom)}.`);
1840
+ }
1841
+ let purifiedDom = import_dompurify.default.sanitize(decodeURIComponent(dom));
1842
+ if (purifiedDom && REG_DATA_URL.test(purifiedDom)) {
1843
+ purifiedDom = this.replace(purifiedDom);
1844
+ }
1845
+ purifiedDom = purifiedDom.replace(REG_END_NUM, "").replace(REG_END_QUEST, "");
1846
+ return encodeURI(purifiedDom);
1847
+ }
1807
1848
  /**
1808
1849
  * sanitize URL
1809
- * NOTE: `data` and/or `file` schemes must be explicitly allowed
1810
- * `javascript` and/or `vbscript` schemes can not be allowed
1850
+ * NOTE: `blob`, `data` and `file` schemes must be explicitly allowed
1851
+ * `javascript` and `vbscript` schemes can not be allowed
1811
1852
  *
1812
- * @param {string} url - URL input
1853
+ * @param {string} url - URL
1813
1854
  * @param {object} opt - options
1814
1855
  * @param {Array.<string>} opt.allow - array of allowed schemes
1815
1856
  * @param {Array.<string>} opt.deny - array of denied schemes
1816
1857
  * @param {Array.<string>} opt.only - array of specific schemes to allow
1817
- * @param {boolean} opt.truncate - truncate tag and/or quote and the rest
1858
+ * @param {boolean} opt.remove - remove tag and/or quote and the rest
1818
1859
  * @returns {?string} - sanitized URL
1819
1860
  */
1820
1861
  sanitize(url, opt = { allow: [], deny: [], only: [] }) {
@@ -1822,8 +1863,9 @@ var URLSanitizer = class extends URISchemes {
1822
1863
  this.#nest = 0;
1823
1864
  throw new Error("Data URLs nested too deeply.");
1824
1865
  }
1825
- const { allow, deny, only, truncate } = opt ?? {};
1866
+ const { allow, deny, only, remove } = opt ?? {};
1826
1867
  const schemeMap = /* @__PURE__ */ new Map([
1868
+ ["blob", false],
1827
1869
  ["data", false],
1828
1870
  ["file", false],
1829
1871
  ["javascrpt", false],
@@ -1894,7 +1936,7 @@ var URLSanitizer = class extends URISchemes {
1894
1936
  let sanitizedUrl;
1895
1937
  if (super.verify(url)) {
1896
1938
  const { hash, href, pathname, protocol, search } = new URL(url);
1897
- const scheme = protocol.replace(/:$/, "");
1939
+ const scheme = protocol.replace(REG_END_COLON, "");
1898
1940
  const schemeParts = scheme.split("+");
1899
1941
  let bool;
1900
1942
  if (restrictScheme) {
@@ -1908,79 +1950,66 @@ var URLSanitizer = class extends URISchemes {
1908
1950
  }
1909
1951
  }
1910
1952
  if (bool) {
1911
- let escapeHtml;
1953
+ const isDataUrl = schemeParts.includes("data");
1954
+ let finalize;
1912
1955
  let urlToSanitize = href;
1913
- if (schemeParts.includes("data")) {
1956
+ if (isDataUrl) {
1914
1957
  const [head, ...body] = pathname.split(",");
1915
1958
  const data = `${body.join(",")}${search}${hash}`;
1916
1959
  const mediaType = head.split(";");
1960
+ const isBase64 = mediaType[mediaType.length - 1] === "base64";
1917
1961
  let parsedData = data;
1918
- if (mediaType[mediaType.length - 1] === "base64") {
1919
- mediaType.pop();
1962
+ if (isBase64) {
1920
1963
  parsedData = parseBase64(data);
1921
- } else {
1922
- try {
1923
- const decodedData = parseURLEncodedNumCharRef(parsedData);
1924
- const { protocol: dataScheme } = new URL(decodedData.trim());
1925
- const dataSchemeParts = dataScheme.replace(/:$/, "").split("+");
1926
- if (dataSchemeParts.some((s) => REG_SCRIPT.test(s))) {
1927
- urlToSanitize = "";
1928
- }
1929
- } catch (e) {
1964
+ }
1965
+ try {
1966
+ const decodedData = parseURLEncodedNumCharRef(parsedData);
1967
+ const { protocol: dataScheme } = new URL(decodedData.trim());
1968
+ const dataSchemeParts = dataScheme.replace(REG_END_COLON, "").split("+");
1969
+ if (dataSchemeParts.some((s) => REG_SCRIPT.test(s))) {
1970
+ urlToSanitize = "";
1930
1971
  }
1972
+ } catch (e) {
1931
1973
  }
1932
- const containsDataUrl = /data:[^,]*,/.test(parsedData);
1974
+ const containsDataUrl = REG_DATA_URL.test(parsedData);
1933
1975
  if (parsedData !== data || containsDataUrl) {
1934
1976
  if (containsDataUrl) {
1935
- const matchedDataUrls = parsedData.matchAll(REG_DATA_URL);
1936
- const items = [...matchedDataUrls].reverse();
1937
- for (const item of items) {
1938
- let [dataUrl] = item;
1939
- if (REG_DATA_URL_BASE64.test(dataUrl)) {
1940
- [dataUrl] = REG_DATA_URL_BASE64.exec(dataUrl);
1941
- }
1942
- this.#nest++;
1943
- this.#recurse.add(dataUrl);
1944
- const parsedDataUrl = this.sanitize(dataUrl, {
1945
- allow: ["data"]
1946
- });
1947
- if (parsedDataUrl) {
1948
- const { index } = item;
1949
- const [preDataUrl, postDataUrl] = [
1950
- parsedData.substring(0, index),
1951
- parsedData.substring(index + dataUrl.length)
1952
- ];
1953
- parsedData = `${preDataUrl}${parsedDataUrl}${postDataUrl}`;
1954
- }
1955
- }
1956
- if (this.#recurse.has(url)) {
1957
- this.#recurse.delete(url);
1958
- } else {
1959
- escapeHtml = true;
1960
- }
1977
+ parsedData = this.replace(parsedData);
1961
1978
  } else if (this.#recurse.has(url)) {
1962
1979
  this.#recurse.delete(url);
1963
1980
  } else {
1964
- escapeHtml = true;
1981
+ finalize = true;
1965
1982
  }
1966
- urlToSanitize = `${scheme}:${mediaType.join(";")},${parsedData}`;
1967
1983
  } else if (this.#recurse.has(url)) {
1968
1984
  this.#recurse.delete(url);
1969
1985
  } else {
1970
- escapeHtml = true;
1986
+ finalize = true;
1987
+ }
1988
+ if (!head || REG_MIME_DOM.test(head)) {
1989
+ parsedData = this.purify(parsedData);
1990
+ }
1991
+ if (urlToSanitize && parsedData) {
1992
+ if (isBase64 && parsedData !== data) {
1993
+ mediaType.pop();
1994
+ }
1995
+ urlToSanitize = `${scheme}:${mediaType.join(";")},${parsedData}`;
1996
+ } else {
1997
+ urlToSanitize = "";
1971
1998
  }
1972
1999
  } else {
1973
- escapeHtml = true;
2000
+ finalize = true;
1974
2001
  }
1975
- if (!schemeParts.includes("data") && truncate && REG_HTML_SP_URL_ENC_SHORT.test(urlToSanitize)) {
1976
- const item = REG_HTML_SP_URL_ENC_SHORT.exec(urlToSanitize);
2002
+ if (!isDataUrl && remove && REG_HTML_URL_ENC_SHORT.test(urlToSanitize)) {
2003
+ const item = REG_HTML_URL_ENC_SHORT.exec(urlToSanitize);
1977
2004
  const { index } = item;
1978
2005
  urlToSanitize = urlToSanitize.substring(0, index);
1979
2006
  }
1980
2007
  if (urlToSanitize) {
1981
2008
  sanitizedUrl = urlToSanitize.replace(REG_HTML_SP, getURLEncodedString).replace(REG_URL_ENC_AMP, escapeURLEncodedHTMLChars);
1982
- if (escapeHtml) {
1983
- sanitizedUrl = sanitizedUrl.replace(REG_HTML_SP_URL_ENC, escapeURLEncodedHTMLChars);
2009
+ if (finalize) {
2010
+ if (!isDataUrl) {
2011
+ sanitizedUrl = sanitizedUrl.replace(REG_HTML_URL_ENC, escapeURLEncodedHTMLChars);
2012
+ }
1984
2013
  this.#nest = 0;
1985
2014
  }
1986
2015
  } else {
@@ -1999,7 +2028,7 @@ var URLSanitizer = class extends URISchemes {
1999
2028
  * @property {boolean} valid - is valid URI
2000
2029
  * @property {object} data - parsed result of data URL, `null`able
2001
2030
  * @property {string} data.mime - MIME type
2002
- * @property {boolean} data.base64 - `true` if base64 encoded
2031
+ * @property {boolean} data.base64 - is base64 encoded
2003
2032
  * @property {string} data.data - data part of the data URL
2004
2033
  * @property {string} href - sanitized URL input
2005
2034
  * @property {string} origin - scheme, domain and port of the sanitized URL
@@ -2011,13 +2040,12 @@ var URLSanitizer = class extends URISchemes {
2011
2040
  * @property {string} port - port number of the sanitized URL
2012
2041
  * @property {string} pathname - path of the sanitized URL
2013
2042
  * @property {string} search - query string of the sanitized URL
2014
- * @property {object} searchParams - URLSearchParams object
2015
2043
  * @property {string} hash - fragment identifier of the sanitized URL
2016
2044
  */
2017
2045
  /**
2018
2046
  * parse sanitized URL
2019
2047
  *
2020
- * @param {string} url - URL input
2048
+ * @param {string} url - URL
2021
2049
  * @param {object} opt - options
2022
2050
  * @returns {ParsedURL} - result with enhanced props based on URL API
2023
2051
  */
@@ -2026,7 +2054,7 @@ var URLSanitizer = class extends URISchemes {
2026
2054
  throw new TypeError(`Expected String but got ${getType(url)}.`);
2027
2055
  }
2028
2056
  const sanitizedUrl = this.sanitize(url, opt ?? {
2029
- allow: ["data", "file"]
2057
+ allow: ["blob", "data", "file"]
2030
2058
  });
2031
2059
  const parsedUrl = /* @__PURE__ */ new Map([
2032
2060
  ["input", url]
@@ -2034,9 +2062,10 @@ var URLSanitizer = class extends URISchemes {
2034
2062
  if (sanitizedUrl) {
2035
2063
  const urlObj = new URL(sanitizedUrl);
2036
2064
  const { pathname, protocol } = urlObj;
2037
- const schemeParts = protocol.replace(/:$/, "").split("+");
2065
+ const schemeParts = protocol.replace(REG_END_COLON, "").split("+");
2066
+ const isDataUrl = schemeParts.includes("data");
2038
2067
  parsedUrl.set("valid", true);
2039
- if (schemeParts.includes("data")) {
2068
+ if (isDataUrl) {
2040
2069
  const dataUrl = /* @__PURE__ */ new Map();
2041
2070
  const [head, ...body] = pathname.split(",");
2042
2071
  const data = `${body.join(",")}`;
@@ -2047,51 +2076,15 @@ var URLSanitizer = class extends URISchemes {
2047
2076
  }
2048
2077
  dataUrl.set("mime", mediaType.join(";"));
2049
2078
  dataUrl.set("base64", isBase64);
2050
- let purifiedDom;
2051
- if (!isBase64 && REG_MIME_DOM.test(head)) {
2052
- let parsedData = data;
2053
- const matchedHtmlChars = parsedData.matchAll(REG_URL_ENC_HTML_SP);
2054
- const items = [...matchedHtmlChars].reverse();
2055
- for (const item of items) {
2056
- const [htmlChar] = item;
2057
- const { index } = item;
2058
- const [preHtmlChar, postHtmlChar] = [
2059
- parsedData.substring(0, index),
2060
- parsedData.substring(index + htmlChar.length)
2061
- ];
2062
- const unescapedHtmlChar = unescapeURLEncodedHTMLChars(htmlChar);
2063
- parsedData = `${preHtmlChar}${unescapedHtmlChar}${postHtmlChar}`;
2064
- }
2065
- purifiedDom = purifyURLEncodedDOM(parsedData);
2066
- dataUrl.set("data", purifiedDom);
2067
- } else {
2068
- dataUrl.set("data", data);
2069
- }
2079
+ dataUrl.set("data", data);
2070
2080
  parsedUrl.set("data", Object.fromEntries(dataUrl));
2071
- for (const key in urlObj) {
2072
- let value = urlObj[key];
2073
- if (isString(value)) {
2074
- if (isString(purifiedDom)) {
2075
- switch (key) {
2076
- case "href":
2077
- value = `${protocol}${mediaType.join(";")},${purifiedDom}`;
2078
- break;
2079
- case "pathname":
2080
- value = `${mediaType.join(";")},${purifiedDom}`;
2081
- break;
2082
- default:
2083
- }
2084
- }
2085
- parsedUrl.set(key, value);
2086
- }
2087
- }
2088
2081
  } else {
2089
2082
  parsedUrl.set("data", null);
2090
- for (const key in urlObj) {
2091
- const value = urlObj[key];
2092
- if (isString(value)) {
2093
- parsedUrl.set(key, value);
2094
- }
2083
+ }
2084
+ for (const key in urlObj) {
2085
+ const value = urlObj[key];
2086
+ if (isString(value)) {
2087
+ parsedUrl.set(key, value);
2095
2088
  }
2096
2089
  }
2097
2090
  } else {
@@ -2111,19 +2104,11 @@ var parseURL = async (url) => {
2111
2104
  const res = await parseURLSync(url);
2112
2105
  return res;
2113
2106
  };
2114
- var sanitizeURLSync = (url, opt) => {
2115
- const parsedUrl = urlSanitizer.parse(url, opt ?? {
2116
- allow: [],
2117
- deny: [],
2118
- only: []
2119
- });
2120
- let res;
2121
- if (parsedUrl) {
2122
- const { href } = parsedUrl;
2123
- res = href;
2124
- }
2125
- return res ?? null;
2126
- };
2107
+ var sanitizeURLSync = (url, opt) => urlSanitizer.sanitize(url, opt ?? {
2108
+ allow: [],
2109
+ deny: [],
2110
+ only: []
2111
+ });
2127
2112
  var sanitizeURL = async (url, opt) => {
2128
2113
  const res = await sanitizeURLSync(url, opt);
2129
2114
  return res;