urlpurify 1.6.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +27 -8
  2. package/dist/clean.mjs +7 -17
  3. package/dist/defaults.d.mts +9 -3
  4. package/dist/defaults.mjs +38 -17
  5. package/dist/index.d.mts +8 -4
  6. package/dist/index.mjs +8 -4
  7. package/dist/node_modules/trousse/dist/urls.mjs +33 -4
  8. package/dist/tracking/affiliate.d.mts +4 -0
  9. package/dist/tracking/affiliate.mjs +18 -0
  10. package/dist/tracking/campaign.d.mts +4 -0
  11. package/dist/tracking/campaign.mjs +77 -0
  12. package/dist/tracking/clickAttribution.d.mts +4 -0
  13. package/dist/tracking/clickAttribution.mjs +53 -0
  14. package/dist/tracking/housekeeping.d.mts +4 -0
  15. package/dist/tracking/housekeeping.mjs +30 -0
  16. package/dist/tracking/visitorId.d.mts +4 -0
  17. package/dist/tracking/visitorId.mjs +40 -0
  18. package/dist/unwraps/aceml.mjs +2 -4
  19. package/dist/unwraps/adjust.mjs +5 -5
  20. package/dist/unwraps/amazonSes.mjs +3 -5
  21. package/dist/unwraps/anchor.mjs +2 -3
  22. package/dist/unwraps/apptrkr.mjs +3 -3
  23. package/dist/unwraps/archiveToday.mjs +2 -2
  24. package/dist/unwraps/augure.mjs +2 -7
  25. package/dist/unwraps/bing.mjs +2 -2
  26. package/dist/unwraps/bingAds.mjs +5 -7
  27. package/dist/unwraps/bitrix.mjs +3 -2
  28. package/dist/unwraps/ciscoSecureWeb.mjs +4 -7
  29. package/dist/unwraps/cjNetwork.mjs +2 -8
  30. package/dist/unwraps/cse360.mjs +4 -7
  31. package/dist/unwraps/datalifeEngine.mjs +2 -2
  32. package/dist/unwraps/deployer.mjs +2 -2
  33. package/dist/unwraps/digikala.mjs +2 -2
  34. package/dist/unwraps/disqus.mjs +4 -1
  35. package/dist/unwraps/easyMarketing.mjs +2 -2
  36. package/dist/unwraps/facebook.mjs +5 -7
  37. package/dist/unwraps/feedStatistics.mjs +2 -2
  38. package/dist/unwraps/firebaseDynamicLinks.mjs +1 -1
  39. package/dist/unwraps/firstory.mjs +2 -4
  40. package/dist/unwraps/gfnLinkProxy.mjs +2 -2
  41. package/dist/unwraps/godcaster.mjs +3 -3
  42. package/dist/unwraps/govdelivery.d.mts +4 -0
  43. package/dist/unwraps/govdelivery.mjs +12 -0
  44. package/dist/unwraps/impact.mjs +3 -3
  45. package/dist/unwraps/indexHu.mjs +3 -3
  46. package/dist/unwraps/invisionNoExternalLinks.mjs +3 -3
  47. package/dist/unwraps/linksynergy.mjs +3 -3
  48. package/dist/unwraps/logicboard.mjs +3 -3
  49. package/dist/unwraps/mailinblack.mjs +2 -2
  50. package/dist/unwraps/mandrill.mjs +2 -2
  51. package/dist/unwraps/mimecast.mjs +1 -4
  52. package/dist/unwraps/mohtwize.mjs +2 -6
  53. package/dist/unwraps/mozillaOutgoing.mjs +2 -2
  54. package/dist/unwraps/newswire.mjs +2 -2
  55. package/dist/unwraps/postAffiliatePro.mjs +3 -3
  56. package/dist/unwraps/postmark.mjs +2 -2
  57. package/dist/unwraps/prezly.mjs +2 -7
  58. package/dist/unwraps/proofpointV1.mjs +6 -15
  59. package/dist/unwraps/proofpointV2.mjs +12 -2
  60. package/dist/unwraps/qualityClick.mjs +3 -3
  61. package/dist/unwraps/researchgate.mjs +3 -5
  62. package/dist/unwraps/reviveAdserver.mjs +3 -5
  63. package/dist/unwraps/serendipity.mjs +2 -2
  64. package/dist/unwraps/streak.mjs +3 -5
  65. package/dist/unwraps/surly.mjs +2 -8
  66. package/dist/unwraps/webArchive.mjs +2 -2
  67. package/dist/unwraps/xengentr.mjs +2 -2
  68. package/dist/unwraps/yahooJapanAmpViewer.mjs +2 -7
  69. package/dist/unwraps/yahooSearch.mjs +3 -2
  70. package/dist/unwraps/yandexMail.mjs +2 -2
  71. package/dist/unwraps/yourMembership.mjs +3 -3
  72. package/dist/utils.mjs +17 -14
  73. package/package.json +2 -2
  74. package/dist/tracking/literals.d.mts +0 -3
  75. package/dist/tracking/literals.mjs +0 -184
  76. package/dist/tracking/patterns.d.mts +0 -3
  77. package/dist/tracking/patterns.mjs +0 -19
@@ -1,5 +1,5 @@
1
1
  import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { createParamExtractor, decodeBase64Url } from "../utils.mjs";
2
+ import { createParamExtractor, decodeBase64Url, getParamValues } from "../utils.mjs";
3
3
  //#region src/unwraps/mandrill.ts
4
4
  const hosts = ["go.mnsvc.com", "mandrillapp.com"];
5
5
  const clickPathRegex = /^\/track\/click\/\d+\/[^/]+$/;
@@ -18,7 +18,7 @@ const unwrapMandrill = (url) => {
18
18
  const target = extractClickPhp(url);
19
19
  if (target) return target;
20
20
  if (!isHostOf(url, hosts) || !clickPathRegex.test(url.pathname)) return;
21
- const payload = url.searchParams.get("p");
21
+ const payload = getParamValues(url, "p").at(0);
22
22
  if (!payload) return;
23
23
  return decodePayload(payload);
24
24
  };
@@ -5,10 +5,7 @@ const mimecastProtectHostRegex = /^url\.(?:au|ca|de|jer|uk|us|usb|za)\.m\.mimeca
5
5
  const mimecastPathRegex = /^\/s\/[^/]+$/;
6
6
  const unwrapMimecast = (url) => {
7
7
  if (!(mimecastHostRegex.test(url.hostname) || mimecastProtectHostRegex.test(url.hostname)) || !mimecastPathRegex.test(url.pathname)) return;
8
- const targetUrl = getParamTarget(url, "url");
9
- if (targetUrl) return targetUrl;
10
- const targetDomain = url.searchParams.get("domain");
11
- if (targetDomain) return `https://${targetDomain}`;
8
+ return getParamTarget(url, "url");
12
9
  };
13
10
  //#endregion
14
11
  export { unwrapMimecast };
@@ -1,4 +1,4 @@
1
- import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
2
  //#region src/unwraps/mohtwize.ts
3
3
  const carrierPrefix = "?fileURL=/";
4
4
  const schemeRegex = /^https?:/i;
@@ -7,11 +7,7 @@ const unwrapMohtwize = (url) => {
7
7
  if (!isHostOf(url, "stats.mohtwize.net") || url.pathname !== "/redirect.mp3") return;
8
8
  if (!url.search.startsWith(carrierPrefix)) return;
9
9
  let target = `${url.search.slice(10)}${url.hash}`;
10
- if (encodedSchemeRegex.test(target)) try {
11
- target = decodeURIComponent(target);
12
- } catch {
13
- return;
14
- }
10
+ if (encodedSchemeRegex.test(target)) target = decodePercent(target);
15
11
  if (!target) return;
16
12
  if (schemeRegex.test(target)) return target;
17
13
  return `https://${target}`;
@@ -1,4 +1,4 @@
1
- import { decodeSegment, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
2
  //#region src/unwraps/mozillaOutgoing.ts
3
3
  const pathRegex = /^\/v1\/[0-9a-f]{64}\/(.+)$/;
4
4
  const mozillaOutgoingHosts = [
@@ -10,7 +10,7 @@ const unwrapMozillaOutgoing = (url) => {
10
10
  if (!isHostOf(url, mozillaOutgoingHosts)) return;
11
11
  const match = url.pathname.match(pathRegex);
12
12
  if (!match) return;
13
- return decodeSegment(match[1]);
13
+ return decodePercent(match[1]);
14
14
  };
15
15
  //#endregion
16
16
  export { unwrapMozillaOutgoing };
@@ -1,6 +1,6 @@
1
1
  import { isAnyOf } from "../node_modules/trousse/dist/matching.mjs";
2
2
  import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
3
- import { decodeBase64Url } from "../utils.mjs";
3
+ import { decodeBase64Url, getParamValues } from "../utils.mjs";
4
4
  //#region src/unwraps/newswire.ts
5
5
  const hosts = [
6
6
  "stats.newswire.com",
@@ -9,7 +9,7 @@ const hosts = [
9
9
  ];
10
10
  const unwrapNewswire = (url) => {
11
11
  if (!isAnyOf(url.hostname, hosts) || url.pathname !== "/x/html") return;
12
- const value = url.searchParams.get("final");
12
+ const value = getParamValues(url, "final").at(0);
13
13
  if (!value) return;
14
14
  const decoded = decodeBase64Url(value);
15
15
  if (!decoded || !isHttpUrl(decoded)) return;
@@ -1,12 +1,12 @@
1
- import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { getParamValues, percentDecode } from "../utils.mjs";
1
+ import { decodePercent, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
+ import { getParamValues } from "../utils.mjs";
3
3
  //#region src/unwraps/postAffiliatePro.ts
4
4
  const pathRegex = /^\/(?:[^/]+\/)*scripts\/click\.php$/;
5
5
  const encodedSchemeRegex = /^https?%3A/i;
6
6
  const unwrapPostAffiliatePro = (url) => {
7
7
  if (!pathRegex.test(url.pathname)) return;
8
8
  let target = getParamValues(url, "desturl").at(0);
9
- if (target && encodedSchemeRegex.test(target)) target = percentDecode(target);
9
+ if (target && encodedSchemeRegex.test(target)) target = decodePercent(target);
10
10
  if (target && isHttpUrl(target)) return target;
11
11
  };
12
12
  //#endregion
@@ -1,11 +1,11 @@
1
- import { decodeSegment, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
2
  //#region src/unwraps/postmark.ts
3
3
  const postmarkPathRegex = /^\/[23][mt]?(s?)\/([^/]+)\//;
4
4
  const unwrapPostmark = (url) => {
5
5
  if (!isHostOf(url, ["click.pstmrk.it", "track.pstmrk.it"])) return;
6
6
  const match = url.pathname.match(postmarkPathRegex);
7
7
  if (!match) return;
8
- const target = decodeSegment(match[2]);
8
+ const target = decodePercent(match[2]);
9
9
  if (!target) return;
10
10
  return `${match[1] ? "https" : "http"}://${target}`;
11
11
  };
@@ -1,16 +1,11 @@
1
- import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
2
  //#region src/unwraps/prezly.ts
3
3
  const pathRegex = /^\/c\/[0-9a-f-]{36}\/[0-9a-f]{8}\/([^/]+)$/;
4
4
  const unwrapPrezly = (url) => {
5
5
  if (!isHostOf(url, "prezlymail.com")) return;
6
6
  const match = pathRegex.exec(url.pathname);
7
7
  if (!match?.[1]) return;
8
- let target;
9
- try {
10
- target = decodeURIComponent(match[1]);
11
- } catch {
12
- return;
13
- }
8
+ const target = decodePercent(match[1]);
14
9
  if (isHttpUrl(target)) return target;
15
10
  };
16
11
  //#endregion
@@ -1,18 +1,9 @@
1
- import { decodeSegment } from "../node_modules/trousse/dist/urls.mjs";
2
1
  import { createParamExtractor } from "../utils.mjs";
3
2
  //#region src/unwraps/proofpointV1.ts
4
- const createProofpointUnwrapper = (path) => {
5
- const baseExtractor = createParamExtractor({
6
- hosts: "urldefense.proofpoint.com",
7
- path,
8
- params: ["u"]
9
- });
10
- return (url) => {
11
- const raw = baseExtractor(url);
12
- if (!raw) return;
13
- return decodeSegment(raw.replace(/-/g, "%").replace(/_/g, "/"));
14
- };
15
- };
16
- const unwrapProofpointV1 = createProofpointUnwrapper("/v1/url");
3
+ const unwrapProofpointV1 = createParamExtractor({
4
+ hosts: "urldefense.proofpoint.com",
5
+ path: "/v1/url",
6
+ params: ["u"]
7
+ });
17
8
  //#endregion
18
- export { createProofpointUnwrapper, unwrapProofpointV1 };
9
+ export { unwrapProofpointV1 };
@@ -1,5 +1,15 @@
1
- import { createProofpointUnwrapper } from "./proofpointV1.mjs";
1
+ import { decodePercent } from "../node_modules/trousse/dist/urls.mjs";
2
+ import { createParamExtractor } from "../utils.mjs";
2
3
  //#region src/unwraps/proofpointV2.ts
3
- const unwrapProofpointV2 = createProofpointUnwrapper("/v2/url");
4
+ const extractTarget = createParamExtractor({
5
+ hosts: "urldefense.proofpoint.com",
6
+ path: "/v2/url",
7
+ params: ["u"]
8
+ });
9
+ const unwrapProofpointV2 = (url) => {
10
+ const raw = extractTarget(url);
11
+ if (!raw) return;
12
+ return decodePercent(raw.replace(/-/g, "%").replace(/_/g, "/"));
13
+ };
4
14
  //#endregion
5
15
  export { unwrapProofpointV2 };
@@ -1,12 +1,12 @@
1
- import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { getParamValues, percentDecode } from "../utils.mjs";
1
+ import { decodePercent, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
+ import { getParamValues } from "../utils.mjs";
3
3
  //#region src/unwraps/qualityClick.ts
4
4
  const encodedSchemeRegex = /^https?%3A/i;
5
5
  const unwrapQualityClick = (url) => {
6
6
  if (url.pathname !== "/go.cgi") return;
7
7
  if (!url.searchParams.has("pid") || !url.searchParams.has("wmid")) return;
8
8
  let target = getParamValues(url, "target").at(0);
9
- if (target && encodedSchemeRegex.test(target)) target = percentDecode(target);
9
+ if (target && encodedSchemeRegex.test(target)) target = decodePercent(target);
10
10
  if (target && isHttpUrl(target)) return target;
11
11
  };
12
12
  //#endregion
@@ -1,4 +1,4 @@
1
- import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
2
  import { createParamExtractor } from "../utils.mjs";
3
3
  //#region src/unwraps/researchgate.ts
4
4
  const derefPathRegex = /^\/deref\/(.+)$/;
@@ -14,10 +14,8 @@ const unwrapResearchgate = (url) => {
14
14
  const match = derefPathRegex.exec(url.pathname);
15
15
  if (!match?.[1]) return;
16
16
  if (isHttpUrl(match[1])) return `${match[1]}${url.search}${url.hash}`;
17
- try {
18
- const target = decodeURIComponent(match[1]);
19
- if (isHttpUrl(target)) return target;
20
- } catch {}
17
+ const target = decodePercent(match[1]);
18
+ if (isHttpUrl(target)) return target;
21
19
  };
22
20
  //#endregion
23
21
  export { unwrapResearchgate };
@@ -1,4 +1,4 @@
1
- import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
2
  import { getParamTarget } from "../utils.mjs";
3
3
  //#region src/unwraps/reviveAdserver.ts
4
4
  const clickPathRegex = /^(?:\/[^/]+)*\/c[kl]\.php$/;
@@ -14,10 +14,8 @@ const unwrapReviveAdserver = (url) => {
14
14
  index = url.search.indexOf(marker);
15
15
  }
16
16
  if (index === -1) return;
17
- try {
18
- const target = decodeURIComponent(url.search.slice(index + marker.length));
19
- if (isHttpUrl(target)) return target;
20
- } catch {}
17
+ const target = decodePercent(url.search.slice(index + marker.length));
18
+ if (isHttpUrl(target)) return target;
21
19
  return;
22
20
  }
23
21
  if (!legacyClickPathRegex.test(url.pathname) || !url.searchParams.has("bannerid")) return;
@@ -1,10 +1,10 @@
1
1
  import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { decodeBase64 } from "../utils.mjs";
2
+ import { decodeBase64, getParamValues } from "../utils.mjs";
3
3
  //#region src/unwraps/serendipity.ts
4
4
  const pathRegex = /^(?:\/[^/]+)?\/exit\.php$/;
5
5
  const unwrapSerendipity = (url) => {
6
6
  if (!pathRegex.test(url.pathname) || !url.searchParams.has("entry_id")) return;
7
- const raw = url.searchParams.get("url");
7
+ const raw = getParamValues(url, "url").at(0);
8
8
  if (!raw) return;
9
9
  const decoded = decodeBase64(raw);
10
10
  if (decoded && isHttpUrl(decoded)) return decoded;
@@ -1,4 +1,4 @@
1
- import { isHostOrSubdomainOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHostOrSubdomainOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
2
  //#region src/unwraps/streak.ts
3
3
  const domains = ["streaklinks.com", "streak-link.com"];
4
4
  const pathRegex = /^\/[\w-]{24}\/([^/]+)$/;
@@ -6,10 +6,8 @@ const unwrapStreak = (url) => {
6
6
  if (!isHostOrSubdomainOf(url, domains)) return;
7
7
  const match = pathRegex.exec(url.pathname);
8
8
  if (!match?.[1]) return;
9
- try {
10
- const target = decodeURIComponent(match[1]);
11
- if (isHttpUrl(target)) return target;
12
- } catch {}
9
+ const target = decodePercent(match[1]);
10
+ if (isHttpUrl(target)) return target;
13
11
  };
14
12
  //#endregion
15
13
  export { unwrapStreak };
@@ -1,4 +1,4 @@
1
- import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
2
  //#region src/unwraps/surly.ts
3
3
  const pathRegex = /^\/o\/([^/].*?)(?:\/AA\d{6})?$/;
4
4
  const schemeRegex = /^https?:\/\//i;
@@ -6,13 +6,7 @@ const unwrapSurly = (url) => {
6
6
  if (!isHostOf(url, ["sur.ly", "www.sur.ly"])) return;
7
7
  const match = pathRegex.exec(url.pathname);
8
8
  if (!match?.[1]) return;
9
- let path;
10
- try {
11
- path = decodeURIComponent(match[1]);
12
- } catch {
13
- return;
14
- }
15
- const target = `https://${path.replace(schemeRegex, "")}`;
9
+ const target = `https://${decodePercent(match[1]).replace(schemeRegex, "")}`;
16
10
  if (isHttpUrl(target)) return target;
17
11
  };
18
12
  //#endregion
@@ -1,4 +1,4 @@
1
- import { decodeSegment, isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
2
  //#region src/unwraps/webArchive.ts
3
3
  const hosts = [
4
4
  "web.archive.org",
@@ -30,7 +30,7 @@ const unwrapWebArchive = (url) => {
30
30
  if (isHostOf(url, "wayback.archive-it.org")) match = url.pathname.match(archiveItPathRegex);
31
31
  if (isHostOf(url, "scholar.archive.org")) match = url.pathname.match(scholarPathRegex);
32
32
  if (!match) return;
33
- let target = decodeSegment(match[1]);
33
+ let target = decodePercent(match[1]);
34
34
  if (target && !schemeRegex.test(target) && schemelessRegex.test(target)) target = `http://${target}`;
35
35
  if (!target || !isHttpUrl(target)) return;
36
36
  return `${target}${url.search}${url.hash}`;
@@ -1,9 +1,9 @@
1
1
  import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { decodeBase64 } from "../utils.mjs";
2
+ import { decodeBase64, getParamValues } from "../utils.mjs";
3
3
  //#region src/unwraps/xengentr.ts
4
4
  const unwrapXengentr = (url) => {
5
5
  if (url.pathname !== "/yonlendirme") return;
6
- const raw = url.searchParams.get("to");
6
+ const raw = getParamValues(url, "to").at(0);
7
7
  if (!raw) return;
8
8
  const decoded = decodeBase64(raw);
9
9
  if (decoded && isHttpUrl(decoded)) return decoded;
@@ -1,4 +1,4 @@
1
- import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
2
  //#region src/unwraps/yahooJapanAmpViewer.ts
3
3
  const httpsPathRegex = /^\/amp\/s\/(.+)$/;
4
4
  const httpPathRegex = /^\/amp\/(?!s\/)(.+)$/;
@@ -7,12 +7,7 @@ const unwrapYahooJapanAmpViewer = (url) => {
7
7
  const httpsMatch = httpsPathRegex.exec(url.pathname);
8
8
  const match = httpsMatch ?? httpPathRegex.exec(url.pathname);
9
9
  if (!match?.[1]) return;
10
- let path;
11
- try {
12
- path = decodeURIComponent(match[1]);
13
- } catch {
14
- return;
15
- }
10
+ const path = decodePercent(match[1]);
16
11
  const target = `${httpsMatch ? "https" : "http"}://${path}${url.search}`;
17
12
  if (isHttpUrl(target)) return target;
18
13
  };
@@ -1,4 +1,5 @@
1
- import { decodeSegment, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
+ import { decodeEncodedScheme } from "../utils.mjs";
2
3
  //#region src/unwraps/yahooSearch.ts
3
4
  const hosts = [
4
5
  "r.search.yahoo.com",
@@ -10,7 +11,7 @@ const unencodedTargetRegex = /^(?:\/[^/]+)*\/RU=(https?:\/\/.+?)\/RK=/;
10
11
  const unwrapYahooSearch = (url) => {
11
12
  if (!isHostOf(url, hosts)) return;
12
13
  const match = url.pathname.match(yahooPathRegex);
13
- if (match) return decodeSegment(match[1]);
14
+ if (match) return decodeEncodedScheme(decodePercent(match[1]));
14
15
  const unencodedMatch = url.pathname.match(unencodedTargetRegex);
15
16
  if (unencodedMatch) return unencodedMatch[1];
16
17
  };
@@ -1,10 +1,10 @@
1
1
  import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { decodeBase64Url } from "../utils.mjs";
2
+ import { decodeBase64Url, getParamValues } from "../utils.mjs";
3
3
  //#region src/unwraps/yandexMail.ts
4
4
  const hostRegex = /^mail\.yandex\.(?:com\.tr|[a-z]{2,3})$/;
5
5
  const unwrapYandexMail = (url) => {
6
6
  if (!hostRegex.test(url.hostname) || url.pathname !== "/re.jsx") return;
7
- const value = url.searchParams.get("l");
7
+ const value = getParamValues(url, "l").at(0);
8
8
  if (!value) return;
9
9
  const decoded = decodeBase64Url(value);
10
10
  if (!decoded || !isHttpUrl(decoded)) return;
@@ -1,12 +1,12 @@
1
- import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { getParamValues, percentDecode } from "../utils.mjs";
1
+ import { decodePercent, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
+ import { getParamValues } from "../utils.mjs";
3
3
  //#region src/unwraps/yourMembership.ts
4
4
  const ymlinkRegex = /^\d+$/;
5
5
  const encodedSchemeRegex = /^https?%3A/i;
6
6
  const unwrapYourMembership = (url) => {
7
7
  if (url.pathname !== "/link.asp" || !ymlinkRegex.test(url.searchParams.get("ymlink") ?? "")) return;
8
8
  let target = getParamValues(url, "finalurl").at(0);
9
- if (target && encodedSchemeRegex.test(target)) target = percentDecode(target);
9
+ if (target && encodedSchemeRegex.test(target)) target = decodePercent(target);
10
10
  if (target && isHttpUrl(target)) return target;
11
11
  };
12
12
  //#endregion
package/dist/utils.mjs CHANGED
@@ -1,14 +1,10 @@
1
1
  import { isAnyOf } from "./node_modules/trousse/dist/matching.mjs";
2
- import { isHostOf, isHostOrSubdomainOf } from "./node_modules/trousse/dist/urls.mjs";
2
+ import { decodePercent, isHostOf, isHostOrSubdomainOf } from "./node_modules/trousse/dist/urls.mjs";
3
3
  //#region src/utils.ts
4
- const percentDecode = (value) => {
5
- const escaped = value.replaceAll("+", "%2B").replaceAll("&", "%26");
6
- return new URLSearchParams(`value=${escaped}`).get("value") ?? "";
7
- };
8
4
  const encodedSchemeRegex = /^https?%3A/i;
9
5
  const decodeEncodedScheme = (value) => {
10
6
  if (!encodedSchemeRegex.test(value)) return value;
11
- return percentDecode(value);
7
+ return decodePercent(value);
12
8
  };
13
9
  const unencodedTargetRegex = /^https?:\/\//i;
14
10
  const getParamValues = (url, name) => {
@@ -16,12 +12,13 @@ const getParamValues = (url, name) => {
16
12
  for (const pair of url.search.slice(1).split("&")) {
17
13
  const entry = new URLSearchParams(`&${pair}`).entries().next().value;
18
14
  if (!entry || entry[0] !== name) continue;
19
- const raw = pair.slice(pair.indexOf("=") + 1);
15
+ const separator = pair.indexOf("=");
16
+ const raw = separator === -1 ? "" : pair.slice(separator + 1);
20
17
  if (!unencodedTargetRegex.test(raw)) {
21
- values.push(entry[1]);
18
+ values.push(decodePercent(raw.replaceAll("+", " ")));
22
19
  continue;
23
20
  }
24
- values.push(percentDecode(raw));
21
+ values.push(decodePercent(raw));
25
22
  }
26
23
  return values;
27
24
  };
@@ -50,13 +47,19 @@ const decodeBase64Binary = (value) => {
50
47
  return atob(value);
51
48
  } catch {}
52
49
  };
53
- const utf8Decoder = new TextDecoder();
54
50
  const decodeBase64 = (value) => {
55
51
  const binary = decodeBase64Binary(value);
56
52
  if (binary === void 0) return;
57
- const bytes = new Uint8Array(binary.length);
58
- for (let index = 0; index < binary.length; index++) bytes[index] = binary.charCodeAt(index);
59
- return utf8Decoder.decode(bytes);
53
+ let encoded = "";
54
+ for (let index = 0; index < binary.length; index++) {
55
+ const byte = binary.charCodeAt(index);
56
+ if (byte < 128 && binary[index] !== "%") {
57
+ encoded += binary[index];
58
+ continue;
59
+ }
60
+ encoded += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
61
+ }
62
+ return decodePercent(encoded);
60
63
  };
61
64
  const toBase64 = (base64Url) => {
62
65
  return base64Url.replace(/-/g, "+").replace(/_/g, "/");
@@ -72,4 +75,4 @@ const getUtf8ByteLength = (value) => {
72
75
  return utf8Encoder.encode(value).length;
73
76
  };
74
77
  //#endregion
75
- export { createParamExtractor, decodeBase64, decodeBase64Binary, decodeBase64Url, decodeBase64UrlBinary, getParamTarget, getParamValues, getUtf8ByteLength, percentDecode };
78
+ export { createParamExtractor, decodeBase64, decodeBase64Binary, decodeBase64Url, decodeBase64UrlBinary, decodeEncodedScheme, getParamTarget, getParamValues, getUtf8ByteLength };
package/package.json CHANGED
@@ -42,8 +42,8 @@
42
42
  "devDependencies": {
43
43
  "@types/bun": "^1.4.2",
44
44
  "kvalita": "^1.24.3",
45
- "trousse": "^2.10.1",
45
+ "trousse": "^2.15.0",
46
46
  "tsdown": "^0.23.0"
47
47
  },
48
- "version": "1.6.1"
48
+ "version": "2.1.0"
49
49
  }
@@ -1,3 +0,0 @@
1
- //#region src/tracking/literals.d.ts
2
- export declare const trackingParamsLiterals: string[];
3
- //#endregion
@@ -1,184 +0,0 @@
1
- //#region src/tracking/literals.ts
2
- const trackingParamsLiterals = [
3
- "utm_source",
4
- "utm_medium",
5
- "utm_campaign",
6
- "utm_term",
7
- "utm_content",
8
- "utm_reader",
9
- "utm_name",
10
- "utm_cid",
11
- "utm_viz_id",
12
- "gclid",
13
- "dclid",
14
- "gbraid",
15
- "wbraid",
16
- "gclsrc",
17
- "gad_source",
18
- "gad_campaignid",
19
- "srsltid",
20
- "usqp",
21
- "fbclid",
22
- "fb_action_ids",
23
- "fb_action_types",
24
- "fb_source",
25
- "fb_ref",
26
- "mibextid",
27
- "_ga",
28
- "_gl",
29
- "_bk",
30
- "_ke",
31
- "_kx",
32
- "__s",
33
- "mc_cid",
34
- "mc_eid",
35
- "mc_tc",
36
- "mkt_tok",
37
- "msclkid",
38
- "twclid",
39
- "__twitter_impression",
40
- "ttclid",
41
- "igshid",
42
- "igsh",
43
- "mtm_campaign",
44
- "mtm_cid",
45
- "mtm_content",
46
- "mtm_group",
47
- "mtm_keyword",
48
- "mtm_medium",
49
- "mtm_placement",
50
- "mtm_source",
51
- "pk_campaign",
52
- "pk_cid",
53
- "pk_content",
54
- "pk_keyword",
55
- "pk_medium",
56
- "pk_source",
57
- "ncid",
58
- "sr_share",
59
- "cmpid",
60
- "hsa_acc",
61
- "hsa_ad",
62
- "hsa_cam",
63
- "hsa_grp",
64
- "hsa_kw",
65
- "hsa_mt",
66
- "hsa_net",
67
- "hsa_src",
68
- "hsa_tgt",
69
- "hsa_ver",
70
- "hsCtaTracking",
71
- "_hsenc",
72
- "_hsmi",
73
- "__hstc",
74
- "__hsfp",
75
- "__hssc",
76
- "s_kwcid",
77
- "sc_cid",
78
- "ef_id",
79
- "s_cid",
80
- "wt_mc",
81
- "wt_zmc",
82
- "wtrid",
83
- "cx_click",
84
- "cx_recsOrder",
85
- "cx_recsWidget",
86
- "obOrigUrl",
87
- "dicbo",
88
- "yclid",
89
- "ysclid",
90
- "_openstat",
91
- "guccounter",
92
- "guce_referrer",
93
- "guce_referrer_sig",
94
- "awinaffid",
95
- "awinmid",
96
- "clickref",
97
- "afftrack",
98
- "sscid",
99
- "awc",
100
- "cjevent",
101
- "cjdata",
102
- "irclickid",
103
- "irgwc",
104
- "ir_adid",
105
- "ir_campaignid",
106
- "ir_partnerid",
107
- "itm_source",
108
- "itm_medium",
109
- "itm_campaign",
110
- "itm_content",
111
- "itm_channel",
112
- "itm_audience",
113
- "int_source",
114
- "int_medium",
115
- "int_campaign",
116
- "int_content",
117
- "int_placement",
118
- "int_campaign_type",
119
- "int_keycode",
120
- "g2i_source",
121
- "g2i_medium",
122
- "g2i_campaign",
123
- "g2i_or_o",
124
- "g2i_or_p",
125
- "doing_wp_cron",
126
- "preview",
127
- "preview_id",
128
- "preview_nonce",
129
- "replytocom",
130
- "_",
131
- "timestamp",
132
- "ts",
133
- "cb",
134
- "cachebuster",
135
- "nocache",
136
- "rand",
137
- "random",
138
- "sbdcrw",
139
- "forceByPassCache",
140
- "sucurianticache",
141
- "cleancache",
142
- "rebuildcache",
143
- "kontrol_health_check_timestamp",
144
- "action_object_map",
145
- "action_ref_map",
146
- "action_type_map",
147
- "algo_expid",
148
- "algo_pvid",
149
- "at_campaign",
150
- "at_custom1",
151
- "at_custom2",
152
- "at_custom3",
153
- "at_custom4",
154
- "at_medium",
155
- "at_preview_index",
156
- "_bhlid",
157
- "_branch_match_id",
158
- "_branch_referrer",
159
- "__readwiseLocation",
160
- "campaign_id",
161
- "click_sum",
162
- "fref",
163
- "gs_l",
164
- "hmb_campaign",
165
- "hmb_medium",
166
- "hmb_source",
167
- "ck_subscriber_id",
168
- "ml_subscriber",
169
- "ml_subscriber_hash",
170
- "oly_anon_id",
171
- "oly_enc_id",
172
- "rb_clickid",
173
- "referer",
174
- "referrer",
175
- "spm",
176
- "trk",
177
- "vero_conv",
178
- "vero_id",
179
- "vgo_ee",
180
- "wickedid",
181
- "xtor"
182
- ];
183
- //#endregion
184
- export { trackingParamsLiterals };
@@ -1,3 +0,0 @@
1
- //#region src/tracking/patterns.d.ts
2
- export declare const trackingParamsPatterns: Array<RegExp>;
3
- //#endregion