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
@@ -0,0 +1,30 @@
1
+ //#region src/tracking/housekeeping.ts
2
+ const housekeepingParams = [
3
+ "usqp",
4
+ "guccounter",
5
+ "guce_referrer",
6
+ "guce_referrer_sig",
7
+ "doing_wp_cron",
8
+ "preview",
9
+ "preview_id",
10
+ "preview_nonce",
11
+ "replytocom",
12
+ "_",
13
+ "timestamp",
14
+ "ts",
15
+ "cb",
16
+ "cachebuster",
17
+ "nocache",
18
+ "rand",
19
+ "random",
20
+ "sbdcrw",
21
+ "forceByPassCache",
22
+ "sucurianticache",
23
+ "cleancache",
24
+ "rebuildcache",
25
+ "kontrol_health_check_timestamp",
26
+ "at_preview_index",
27
+ "__readwiseLocation"
28
+ ];
29
+ //#endregion
30
+ export { housekeepingParams };
@@ -0,0 +1,4 @@
1
+ import { TrackingParam } from "../types.mjs";
2
+ //#region src/tracking/visitorId.d.ts
3
+ export declare const visitorIdParams: Array<TrackingParam>;
4
+ //#endregion
@@ -0,0 +1,40 @@
1
+ //#region src/tracking/visitorId.ts
2
+ const visitorIdParams = [
3
+ "utm_cid",
4
+ "fb_action_ids",
5
+ "mibextid",
6
+ "_ga",
7
+ "_gl",
8
+ "_bk",
9
+ "_ke",
10
+ "_kx",
11
+ "__s",
12
+ "mc_eid",
13
+ "mc_tc",
14
+ "mkt_tok",
15
+ "igshid",
16
+ "igsh",
17
+ "hsCtaTracking",
18
+ "_hsenc",
19
+ "_hsmi",
20
+ "__hstc",
21
+ "__hsfp",
22
+ "__hssc",
23
+ "wtrid",
24
+ "_bhlid",
25
+ "_branch_match_id",
26
+ "_branch_referrer",
27
+ "ck_subscriber_id",
28
+ "ml_subscriber",
29
+ "ml_subscriber_hash",
30
+ "oly_anon_id",
31
+ "oly_enc_id",
32
+ "vero_conv",
33
+ "vero_id",
34
+ "vgo_ee",
35
+ /^bsft_[a-z0-9_]+$/,
36
+ /^sfmc_[a-z0-9_]+$/,
37
+ /^oft_[a-z0-9_]+$/
38
+ ];
39
+ //#endregion
40
+ export { visitorIdParams };
@@ -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 { createParamExtractor, decodeBase64 } from "../utils.mjs";
3
3
  //#region src/unwraps/aceml.ts
4
4
  const encodedSchemeRegex = /^https?%3A/i;
@@ -11,9 +11,7 @@ const unwrapAceml = (url) => {
11
11
  const raw = baseExtractor(url);
12
12
  if (!raw) return;
13
13
  let decoded = decodeBase64(raw);
14
- if (decoded && encodedSchemeRegex.test(decoded)) try {
15
- decoded = decodeURIComponent(decoded);
16
- } catch {}
14
+ if (decoded && encodedSchemeRegex.test(decoded)) decoded = decodePercent(decoded);
17
15
  if (decoded && isHttpUrl(decoded)) return decoded;
18
16
  if (isHttpUrl(raw)) return raw;
19
17
  };
@@ -4,17 +4,17 @@ import { createParamExtractor, getParamTarget } from "../utils.mjs";
4
4
  const hosts = ["app.adjust.com", "app.adjust.net.in"];
5
5
  const pathRegex = /^\/[^/]+$/;
6
6
  const trackerParams = [
7
+ "redirect_windows",
7
8
  "redirect",
8
- "fallback",
9
- "redirect_macos"
9
+ "fallback"
10
10
  ];
11
11
  const unwrapUniversalLink = createParamExtractor({
12
12
  hosts: /^[a-z0-9]{4}(?:\.tr)?\.adj\.st$/,
13
13
  params: [
14
+ "adj_redirect_windows",
14
15
  "adj_redirect",
15
- "adj_fallback",
16
- "adj_redirect_macos",
17
- "adjust_fallback"
16
+ "adjust_fallback",
17
+ "adj_fallback"
18
18
  ]
19
19
  });
20
20
  const unwrapTracker = (url) => {
@@ -1,14 +1,12 @@
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/amazonSes.ts
3
3
  const awstrackPathRegex = /^\/L0\/(.+?)\/\d+\/[^/]+\/[^/]+$/;
4
4
  const customPathRegex = /^\/CL0\/(.+?)\/\d+\/[^/]+-000000\/[^/]+$/;
5
5
  const unwrapAmazonSes = (url) => {
6
6
  const match = (isHostOrSubdomainOf(url, "awstrack.me") ? awstrackPathRegex : customPathRegex).exec(url.pathname);
7
7
  if (!match?.[1]) return;
8
- try {
9
- const target = decodeURIComponent(match[1]);
10
- if (isHttpUrl(target)) return target;
11
- } catch {}
8
+ const target = decodePercent(match[1]);
9
+ if (isHttpUrl(target)) return target;
12
10
  };
13
11
  //#endregion
14
12
  export { unwrapAmazonSes };
@@ -1,5 +1,4 @@
1
- import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
- import { percentDecode } from "../utils.mjs";
1
+ import { decodePercent, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
3
2
  //#region src/unwraps/anchor.ts
4
3
  const playPrefixRegex = /^\/s\/[^/]+\/podcast\/play\/[^/]+\/(?:sponsor\/[^/]+\/)?/;
5
4
  const encodedSchemeRegex = /^https?%(?:25)?3A/i;
@@ -8,7 +7,7 @@ const unwrapAnchor = (url) => {
8
7
  const match = url.pathname.match(playPrefixRegex);
9
8
  if (!match) return;
10
9
  let target = url.pathname.slice(match[0].length);
11
- while (encodedSchemeRegex.test(target)) target = percentDecode(target);
10
+ while (encodedSchemeRegex.test(target)) target = decodePercent(target);
12
11
  return `${target}${url.hash}`;
13
12
  };
14
13
  //#endregion
@@ -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/apptrkr.ts
4
4
  const encodedSchemeRegex = /^https?%3A/i;
5
5
  const unwrapApptrkr = (url) => {
6
6
  if (url.hostname !== "apptrkr.com" || url.pathname !== "/get_redirect.php") return;
7
7
  let target = getParamValues(url, "targetURL").at(-1);
8
8
  if (!target) return;
9
- if (encodedSchemeRegex.test(target)) target = percentDecode(target);
9
+ if (encodedSchemeRegex.test(target)) target = decodePercent(target);
10
10
  if (isHttpUrl(target)) return target;
11
11
  };
12
12
  //#endregion
@@ -1,4 +1,4 @@
1
- import { decodeSegment, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
1
+ import { decodePercent, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
2
  //#region src/unwraps/archiveToday.ts
3
3
  const hostRegex = /^(?:www\.)?archive\.(?:is|ph|today|md|fo|vn|li)$/;
4
4
  const pathRegex = /^\/(?:\d{14}|\d{4}\.\d{2}\.\d{2}-\d{6}|o\/[^/]+|newest)\/(.+)$/;
@@ -11,7 +11,7 @@ const unwrapArchiveToday = (url) => {
11
11
  const match = url.pathname.match(pathRegex);
12
12
  if (!match) return;
13
13
  let target = match[1];
14
- if (encodedSchemeRegex.test(target)) target = decodeSegment(target);
14
+ if (encodedSchemeRegex.test(target)) target = decodePercent(target);
15
15
  if (!target) return;
16
16
  if (!schemeRegex.test(target)) target = `http://${target}`;
17
17
  target = target.replace(escapedQueryRegex, "?").replace("%23", "#");
@@ -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 { createParamExtractor, decodeBase64 } from "../utils.mjs";
3
3
  //#region src/unwraps/augure.ts
4
4
  const baseExtractor = createParamExtractor({
@@ -16,12 +16,7 @@ const unwrapAugure = (url) => {
16
16
  if (!raw) return;
17
17
  const decoded = decodeBase64(raw);
18
18
  if (!decoded) return;
19
- let target;
20
- try {
21
- target = decodeURIComponent(decoded);
22
- } catch {
23
- return;
24
- }
19
+ const target = decodePercent(decoded);
25
20
  if (isHttpUrl(target)) return target;
26
21
  };
27
22
  //#endregion
@@ -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, getParamTarget } from "../utils.mjs";
3
+ import { decodeBase64Url, getParamTarget, getParamValues } from "../utils.mjs";
4
4
  //#region src/unwraps/bing.ts
5
5
  const bingHosts = [
6
6
  "bing.com",
@@ -20,7 +20,7 @@ const unwrapBing = (url) => {
20
20
  return target;
21
21
  }
22
22
  if (url.pathname !== "/ck/a") return;
23
- const value = url.searchParams.get("u");
23
+ const value = getParamValues(url, "u").at(0);
24
24
  if (!value || !bingPrefixRegex.test(value)) return;
25
25
  const decoded = decodeBase64Url(value.slice(2));
26
26
  if (!decoded || !isHttpUrl(decoded)) return;
@@ -1,18 +1,16 @@
1
1
  import { isAnyOf } from "../node_modules/trousse/dist/matching.mjs";
2
- import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
3
- import { decodeBase64Url } from "../utils.mjs";
2
+ import { decodePercent, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
3
+ import { decodeBase64Url, getParamValues } from "../utils.mjs";
4
4
  import { bingHosts } from "./bing.mjs";
5
5
  //#region src/unwraps/bingAds.ts
6
6
  const adPaths = ["/aclk", "/aclick"];
7
7
  const unwrapBingAds = (url) => {
8
8
  if (!isAnyOf(url.hostname, bingHosts) || !adPaths.includes(url.pathname)) return;
9
- const value = url.searchParams.get("u");
9
+ const value = getParamValues(url, "u").at(0);
10
10
  if (!value) return;
11
11
  const decoded = decodeBase64Url(value) ?? "";
12
- try {
13
- const target = decodeURIComponent(decoded);
14
- if (isHttpUrl(target)) return target;
15
- } catch {}
12
+ const target = decodePercent(decoded);
13
+ if (isHttpUrl(target)) return target;
16
14
  };
17
15
  //#endregion
18
16
  export { unwrapBingAds };
@@ -1,9 +1,10 @@
1
- import { getParamValues, percentDecode } from "../utils.mjs";
1
+ import { decodePercent } from "../node_modules/trousse/dist/urls.mjs";
2
+ import { getParamValues } from "../utils.mjs";
2
3
  //#region src/unwraps/bitrix.ts
3
4
  const encodedSchemeRegex = /^https?%3A/i;
4
5
  const getBitrixTarget = (url) => {
5
6
  let target = getParamValues(url, "goto").at(0);
6
- if (target && encodedSchemeRegex.test(target)) target = percentDecode(target);
7
+ if (target && encodedSchemeRegex.test(target)) target = decodePercent(target);
7
8
  return target;
8
9
  };
9
10
  const unwrapBitrix = (url) => {
@@ -1,16 +1,13 @@
1
- import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { percentDecode } from "../utils.mjs";
1
+ import { decodePercent, isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
3
2
  //#region src/unwraps/ciscoSecureWeb.ts
4
3
  const pathRegex = /^\/[\w-]+\/(https?(?:%3A|%253A)(?:%2F|%252F){2}[^/]*)$/i;
5
4
  const unwrapCiscoSecureWeb = (url) => {
6
5
  if (!isHostOf(url, "secure-web.cisco.com")) return;
7
6
  const match = pathRegex.exec(url.pathname);
8
7
  if (!match?.[1]) return;
9
- try {
10
- let target = decodeURIComponent(match[1]);
11
- if (!isHttpUrl(target)) target = percentDecode(target);
12
- if (isHttpUrl(target)) return target;
13
- } catch {}
8
+ let target = decodePercent(match[1]);
9
+ if (!isHttpUrl(target)) target = decodePercent(target);
10
+ if (isHttpUrl(target)) return target;
14
11
  };
15
12
  //#endregion
16
13
  export { unwrapCiscoSecureWeb };
@@ -1,4 +1,5 @@
1
1
  import { isAnyOf } from "../node_modules/trousse/dist/matching.mjs";
2
+ import { decodePercent } from "../node_modules/trousse/dist/urls.mjs";
2
3
  import { createParamExtractor } from "../utils.mjs";
3
4
  //#region src/unwraps/cjNetwork.ts
4
5
  const hosts = [
@@ -20,13 +21,6 @@ const hosts = [
20
21
  ];
21
22
  const clickPathRegex = /^\/(?:t\/)?[^/]+$/;
22
23
  const deepLinkPathRegex = /^\/links\/\d+\/type\/(?:dlg|am)\/(?:sid\/[^/]*\/)?(?:fragment\/([^/]*)\/)?(https?):\/\/?(.+)$/;
23
- const decodeFragment = (value) => {
24
- try {
25
- return decodeURIComponent(value);
26
- } catch {
27
- return value;
28
- }
29
- };
30
24
  const extractUrlParam = createParamExtractor({
31
25
  hosts,
32
26
  params: ["url", "loc"]
@@ -39,7 +33,7 @@ const unwrapCjNetwork = (url) => {
39
33
  }
40
34
  if (!isAnyOf(url.hostname, hosts)) return;
41
35
  const [, fragment, scheme, target] = match;
42
- const hash = url.hash || (fragment ? `#${decodeFragment(fragment)}` : "");
36
+ const hash = url.hash || (fragment ? `#${decodePercent(fragment)}` : "");
43
37
  return `${scheme}://${target}${url.search}${hash}`;
44
38
  };
45
39
  //#endregion
@@ -1,5 +1,4 @@
1
- import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { percentDecode } from "../utils.mjs";
1
+ import { decodePercent, isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
3
2
  //#region src/unwraps/cse360.ts
4
3
  const encodedSchemeRegex = /^https?%3A/i;
5
4
  const clickPathRegex = /^\/Click\/AddCampaignEmailClick\/[0-9a-f-]{36}\/([^/]+)\/[0-9a-f-]{36}\/[^/]+\/(?:True|False)$/;
@@ -7,11 +6,9 @@ const unwrapCse360 = (url) => {
7
6
  if (!isHostOf(url, "click.cse360.com.br")) return;
8
7
  const match = clickPathRegex.exec(url.pathname);
9
8
  if (!match?.[1]) return;
10
- try {
11
- let target = decodeURIComponent(match[1]);
12
- if (encodedSchemeRegex.test(target)) target = percentDecode(target);
13
- if (isHttpUrl(target)) return target;
14
- } catch {}
9
+ let target = decodePercent(match[1]);
10
+ if (encodedSchemeRegex.test(target)) target = decodePercent(target);
11
+ if (isHttpUrl(target)) return target;
15
12
  };
16
13
  //#endregion
17
14
  export { unwrapCse360 };
@@ -1,11 +1,11 @@
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/datalifeEngine.ts
4
4
  const unwrapDatalifeEngine = (url) => {
5
5
  const isEngineGo = url.pathname === "/engine/go.php";
6
6
  const isIndexGo = url.pathname === "/index.php" && url.searchParams.get("do") === "go";
7
7
  if (!isEngineGo && !isIndexGo) return;
8
- const raw = url.searchParams.get("url");
8
+ const raw = getParamValues(url, "url").at(0);
9
9
  if (!raw) return;
10
10
  const decoded = decodeBase64(raw);
11
11
  if (decoded && isHttpUrl(decoded)) return decoded;
@@ -1,5 +1,5 @@
1
1
  import { isHostOf, 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/deployer.ts
4
4
  const hosts = [
5
5
  "daily.news.humanevents.com",
@@ -9,7 +9,7 @@ const hosts = [
9
9
  const paths = ["/link.php", "/wta/link.php"];
10
10
  const unwrapDeployer = (url) => {
11
11
  if (!isHostOf(url, hosts) || !paths.includes(url.pathname) || !url.searchParams.has("AGENCY")) return;
12
- const value = url.searchParams.get("drurl")?.replaceAll(" ", "+");
12
+ const value = getParamValues(url, "drurl").at(0)?.replaceAll(" ", "+");
13
13
  if (!value) return;
14
14
  const target = decodeBase64(value);
15
15
  if (target && isHttpUrl(target)) return target;
@@ -1,10 +1,10 @@
1
1
  import { isHostOf, 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/digikala.ts
4
4
  const pathRegex = /^\/api\/v1\/Click\/b\/[A-Za-z0-9]+$/;
5
5
  const unwrapDigikala = (url) => {
6
6
  if (!isHostOf(url, "dgkl.io") || !pathRegex.test(url.pathname)) return;
7
- const encoded = url.searchParams.get("b64");
7
+ const encoded = getParamValues(url, "b64").at(0);
8
8
  if (!encoded) return;
9
9
  const target = decodeBase64(encoded);
10
10
  if (target && isHttpUrl(target)) return target;
@@ -1,13 +1,16 @@
1
1
  import { createParamExtractor } from "../utils.mjs";
2
2
  //#region src/unwraps/disqus.ts
3
3
  const paths = ["/", "/url"];
4
+ const signatureRegex = /:[\w-]{27}$/;
4
5
  const extractTarget = createParamExtractor({
5
6
  hosts: "disq.us",
6
7
  params: ["url"]
7
8
  });
8
9
  const unwrapDisqus = (url) => {
9
10
  if (!paths.includes(url.pathname)) return;
10
- return extractTarget(url);
11
+ const target = extractTarget(url);
12
+ if (url.pathname !== "/url") return target;
13
+ return target?.replace(signatureRegex, "");
11
14
  };
12
15
  //#endregion
13
16
  export { unwrapDisqus };
@@ -1,5 +1,5 @@
1
1
  import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { decodeBase64Url, getParamTarget } from "../utils.mjs";
2
+ import { decodeBase64Url, getParamTarget, getParamValues } from "../utils.mjs";
3
3
  //#region src/unwraps/easyMarketing.ts
4
4
  const pathRegex = /^\/trck\/eclick\/[0-9a-f]{32}$/;
5
5
  const hosts = [
@@ -11,7 +11,7 @@ const unwrapEasyMarketing = (url) => {
11
11
  if (!isHostOf(url, hosts) || !pathRegex.test(url.pathname)) return;
12
12
  const target = getParamTarget(url, "url");
13
13
  if (target) return target;
14
- const encoded = url.searchParams.get("url64fb");
14
+ const encoded = getParamValues(url, "url64fb").at(0);
15
15
  if (!encoded) return;
16
16
  const decoded = decodeBase64Url(encoded);
17
17
  if (decoded && isHttpUrl(decoded)) return decoded;
@@ -1,5 +1,5 @@
1
- import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
- import { createParamExtractor, percentDecode } from "../utils.mjs";
1
+ import { decodePercent, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
+ import { createParamExtractor } from "../utils.mjs";
3
3
  //#region src/unwraps/facebook.ts
4
4
  const legacyTargetRegex = /^\/l\/[\w-]+[/;]\/*([^/].*)$/;
5
5
  const legacyEncodedSchemeRegex = /^https?%(?:25)?3A/i;
@@ -35,11 +35,9 @@ const unwrapLsr = createParamExtractor({
35
35
  params: ["u"]
36
36
  });
37
37
  const decodeLegacyTarget = (value) => {
38
- try {
39
- const decoded = decodeURIComponent(value);
40
- if (!encodedSchemeRegex.test(decoded)) return decoded;
41
- return percentDecode(decoded);
42
- } catch {}
38
+ const decoded = decodePercent(value);
39
+ if (!encodedSchemeRegex.test(decoded)) return decoded;
40
+ return decodePercent(decoded);
43
41
  };
44
42
  const unwrapLegacy = (url) => {
45
43
  if (!isHostOf(url, ["www.facebook.com", "l.facebook.com"])) 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/feedStatistics.ts
4
4
  const pathRegex = /^\/(?:[^/]+\/){0,2}$/;
5
5
  const unwrapFeedStatistics = (url) => {
6
6
  if (!pathRegex.test(url.pathname)) return;
7
- const target = decodeBase64(url.searchParams.get("feed-stats-url") ?? "");
7
+ const target = decodeBase64(getParamValues(url, "feed-stats-url").at(0) ?? "");
8
8
  if (!target || !isHttpUrl(target)) return;
9
9
  return target;
10
10
  };
@@ -1,7 +1,7 @@
1
1
  import { createParamExtractor } from "../utils.mjs";
2
2
  //#region src/unwraps/firebaseDynamicLinks.ts
3
3
  const appPathRegex = /^\/app\/[\w-]+$/;
4
- const params = ["link", "ofl"];
4
+ const params = ["ofl", "link"];
5
5
  const extractTarget = createParamExtractor({
6
6
  domains: ["app.goo.gl", "page.link"],
7
7
  path: "/",
@@ -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
  import { getParamTarget } from "../utils.mjs";
3
3
  import { getPathTarget } from "../pathTarget.mjs";
4
4
  //#region src/unwraps/firstory.ts
@@ -13,9 +13,7 @@ const unwrapFirstory = (url) => {
13
13
  if (!isHostOf(url, trackHosts)) return;
14
14
  const match = url.pathname.match(trackPrefixRegex);
15
15
  if (!match) return;
16
- try {
17
- return `${decodeURIComponent(url.pathname.slice(match[0].length))}${url.search}${url.hash}`;
18
- } catch {}
16
+ return `${decodePercent(url.pathname.slice(match[0].length))}${url.search}${url.hash}`;
19
17
  };
20
18
  //#endregion
21
19
  export { unwrapFirstory };
@@ -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/gfnLinkProxy.ts
4
4
  const pathRegex = /^(?:\/[^/]+)?\/redirect\/?$/;
5
5
  const unwrapGfnLinkProxy = (url) => {
6
6
  if (!pathRegex.test(url.pathname)) return;
7
- const raw = url.searchParams.get("to");
7
+ const raw = getParamValues(url, "to").at(0);
8
8
  if (!raw) return;
9
9
  const decoded = decodeBase64(raw);
10
10
  if (decoded && isHttpUrl(decoded)) return decoded;
@@ -1,5 +1,5 @@
1
- import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
- import { createParamExtractor, percentDecode } from "../utils.mjs";
1
+ import { decodePercent, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
+ import { createParamExtractor } from "../utils.mjs";
3
3
  //#region src/unwraps/godcaster.ts
4
4
  const episodePrefixRegex = /^\/act\/e\/\d+\/\d+\/\d+\//;
5
5
  const encodedSchemeRegex = /^https?%(?:25)?3A/i;
@@ -14,7 +14,7 @@ const unwrapGodcaster = (url) => {
14
14
  const match = url.pathname.match(episodePrefixRegex);
15
15
  if (!match) return;
16
16
  let target = url.pathname.slice(match[0].length);
17
- while (encodedSchemeRegex.test(target)) target = percentDecode(target);
17
+ while (encodedSchemeRegex.test(target)) target = decodePercent(target);
18
18
  return `${target}${url.hash}`;
19
19
  };
20
20
  //#endregion
@@ -0,0 +1,4 @@
1
+ import { UrlUnwrapper } from "../types.mjs";
2
+ //#region src/unwraps/govdelivery.d.ts
3
+ export declare const unwrapGovdelivery: UrlUnwrapper;
4
+ //#endregion
@@ -0,0 +1,12 @@
1
+ import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
+ //#region src/unwraps/govdelivery.ts
3
+ const clickQueryRegex = /^\?type=click&enid=[^&]+&&&\d+&&&(.+)$/;
4
+ const unwrapGovdelivery = (url) => {
5
+ if (!isHostOf(url, "links.govdelivery.com") || url.pathname !== "/track") return;
6
+ const match = clickQueryRegex.exec(url.search);
7
+ if (!match?.[1]) return;
8
+ const target = `${match[1]}${url.hash}`;
9
+ if (isHttpUrl(target)) return target;
10
+ };
11
+ //#endregion
12
+ export { unwrapGovdelivery };
@@ -1,5 +1,5 @@
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/impact.ts
4
4
  const pathRegex = /^\/c\/\d+\/\d+\/\d+$/;
5
5
  const sjvHostRegex = /\.sjv\.io$/;
@@ -12,7 +12,7 @@ const unwrapImpact = (url) => {
12
12
  const isPxfPath = pxfHostRegex.test(url.hostname) && pxfPathRegex.test(url.pathname);
13
13
  if (!pathRegex.test(url.pathname) && !isSjvPath && !isPxfPath) return;
14
14
  let target = getParamValues(url, "u").at(0);
15
- if (target && encodedSchemeRegex.test(target)) target = percentDecode(target);
15
+ if (target && encodedSchemeRegex.test(target)) target = decodePercent(target);
16
16
  if (target && isHttpUrl(target)) return target;
17
17
  };
18
18
  //#endregion
@@ -1,5 +1,5 @@
1
- import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
- import { createParamExtractor, percentDecode } from "../utils.mjs";
1
+ import { decodePercent, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
2
+ import { createParamExtractor } from "../utils.mjs";
3
3
  //#region src/unwraps/indexHu.ts
4
4
  const sectionParamRegex = /^index_[a-z]+_cikklink$/;
5
5
  const encodedSchemeRegex = /^https?%3A/i;
@@ -17,7 +17,7 @@ const unwrapSectionCounter = (url) => {
17
17
  for (const [key, value] of url.searchParams) {
18
18
  if (!sectionParamRegex.test(key) || !value) continue;
19
19
  if (!encodedSchemeRegex.test(value)) return value;
20
- return percentDecode(value);
20
+ return decodePercent(value);
21
21
  }
22
22
  };
23
23
  const unwrapIndexHu = (url) => {
@@ -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/invisionNoExternalLinks.ts
4
4
  const pathRegex = /^(?:\/[^/]+)?\/redirect\/$/;
5
5
  const encodedSchemeRegex = /^https?%3A/i;
6
6
  const unwrapInvisionNoExternalLinks = (url) => {
7
7
  if (!pathRegex.test(url.pathname)) return;
8
8
  let target = getParamValues(url, "to").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;
11
11
  return target;
12
12
  };
@@ -1,5 +1,5 @@
1
- import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
- import { getParamValues, percentDecode } from "../utils.mjs";
1
+ import { decodePercent, isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
2
+ import { getParamValues } from "../utils.mjs";
3
3
  //#region src/unwraps/linksynergy.ts
4
4
  const linksynergyHosts = [
5
5
  "click.linksynergy.com",
@@ -19,7 +19,7 @@ const unwrapLinksynergy = (url) => {
19
19
  const target = getParamValues(url, param).at(0);
20
20
  if (!target) return;
21
21
  if (isHttpUrl(target)) return target;
22
- const decoded = percentDecode(target);
22
+ const decoded = decodePercent(target);
23
23
  if (isHttpUrl(decoded)) return decoded;
24
24
  };
25
25
  //#endregion
@@ -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/logicboard.ts
4
4
  const pathRegex = /^(?:\/[^/]+){0,2}\/away\.php$/;
5
5
  const encodedSchemeRegex = /^https?%3A/i;
6
6
  const unwrapLogicboard = (url) => {
7
7
  if (!pathRegex.test(url.pathname)) return;
8
8
  let target = getParamValues(url, "s").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;
11
11
  return target;
12
12
  };
@@ -1,9 +1,9 @@
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/mailinblack.ts
4
4
  const unwrapMailinblack = (url) => {
5
5
  if (url.pathname !== "/securelink/") return;
6
- const key = url.searchParams.get("key");
6
+ const key = getParamValues(url, "key").at(0);
7
7
  if (!key) return;
8
8
  const json = decodeBase64Url(key);
9
9
  if (!json) return;