urlpurify 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,6 +51,8 @@ Applies the unwrappers in order (one pass) and returns the first extracted targe
51
51
 
52
52
  Removes matching query parameters and returns the cleaned URL. The input is returned unchanged when nothing matches or it cannot be parsed.
53
53
 
54
+ Both `cleanUrl` and `stripTrackingParams` also drop a `ref` parameter when its value is the URL's own host (Ghost's self-referral `?ref=example.com` on `example.com`), regardless of the tracking list passed. With any other value `ref` is left alone, since it is often a real referral target.
55
+
54
56
  ### `createParamExtractor(config)`
55
57
 
56
58
  Builds an unwrapper for the common case where the target URL sits in a query parameter:
@@ -70,7 +72,13 @@ For wrappers that encode the target (base64 path segments, custom escaping), wri
70
72
 
71
73
  ### Defaults
72
74
 
73
- `defaultTrackingParams` is the combined default list for `cleanUrl` and `stripTrackingParams`: literal names plus family regexes like `/^utm_[a-z0-9_-]+$/` that cover vendor namespaces where new variants keep appearing. Its parts are exported separately as `trackingParamsLiterals` (strings only, for consumers that need a plain string list) and `trackingParamsPatterns`. `defaultUnwrappers` is exported alongside. `defaultUnwrappers` enables a conservative subset of the catalog (search-engine redirects and social-platform shims); everything else is exported individually for explicit opt-in.
75
+ `defaultTrackingParams` is the combined default list for `cleanUrl` and `stripTrackingParams`: literal names plus family regexes like `/^utm_[a-z0-9_-]+$/` that cover vendor namespaces where new variants keep appearing. Its parts are exported separately as `trackingParamsLiterals` (strings only, for consumers that need a plain string list) and `trackingParamsPatterns`. `defaultUnwrappers` is exported alongside. `defaultUnwrappers` enables a conservative subset of the catalog; everything else is exported individually for explicit opt-in.
76
+
77
+ **On by default:** redirects that only track the click — search-engine redirects and platform shims. Unwrapping them costs the destination nothing.
78
+
79
+ **Off by default:** affiliate and referral wrappers (`unwrapSkimlinks`, `unwrapAwin`, `unwrapShareasale`, `unwrapAmazonAffiliate`, `unwrapViglink`, and the rest). The reader lands on the same page either way — unwrapping only removes the writer's commission, which for a small blog is the money paying for the work. Opt in explicitly if you want them.
80
+
81
+ Prevalence is not the test: affiliate wrappers are more common than tracking shims.
74
82
 
75
83
  ## Unwrappers
76
84
 
@@ -79,16 +87,34 @@ Enabled by default:
79
87
  | Unwrapper | Description |
80
88
  | --- | --- |
81
89
  | `unwrapBing` | Bing search-result redirect (www.bing.com/ck/a?u=a1\<base64url\>) |
82
- | `unwrapFacebookShim` | Facebook link shim (l.facebook.com/l.php?u=\<target\>) |
90
+ | `unwrapBlueskyRedirect` | Bluesky outbound link redirect (go.bsky.app/redirect?u=\<target\>) |
91
+ | `unwrapDisqus` | Disqus outbound link redirect (disq.us/?url=\<target\>) |
92
+ | `unwrapDouban` | Douban external link redirect (www.douban.com/link2/?url=\<target\>) |
93
+ | `unwrapFacebookShim` | Meta link shim (l.facebook.com / l.messenger.com /l.php?u=\<target\>) |
94
+ | `unwrapFlipboard` | Flipboard outbound redirect (flipboard.com/redirect?url=\<target\>) |
95
+ | `unwrapGitee` | Gitee external link redirect (gitee.com/link?target=\<target\>) |
83
96
  | `unwrapGoogle` | Google redirect (google.\<TLD\>/url?url=\<target\> or ?q=\<target\>) |
84
97
  | `unwrapGoogleAmpViewer` | Google AMP viewer (www.google.\<TLD\>/amp/s/\<host\>/\<path\>) |
85
98
  | `unwrapGoogleNews` | Google News legacy redirect (news.google.\<TLD\>/news/url?url=\<target\>) |
86
99
  | `unwrapGoogleNewsModern` | Google News modern article URLs (news.google.com/articles/\<base64\>) |
87
100
  | `unwrapGoogleScholar` | Google Scholar search-result redirect (scholar.google.\<TLD\>/scholar_url?url=\<target\>) |
101
+ | `unwrapHashnode` | Hashnode outbound redirect (hashnode.com/util/redirect?url=\<target\>) |
102
+ | `unwrapHrefLi` | href.li referrer stripper (href.li/?\<target\>), used by Tumblr |
88
103
  | `unwrapInstagramShim` | Instagram outbound link shim (l.instagram.com with ?u=\<target\>) |
104
+ | `unwrapJianshuGo` | Jianshu external link redirect (links.jianshu.com/go?to=\<target\>) |
105
+ | `unwrapJuejin` | Juejin external link redirect (link.juejin.cn/?target=\<target\>) |
106
+ | `unwrapMedium` | Medium outbound link redirect (medium.com/r/?url=\<target\>) |
107
+ | `unwrapMozillaOutgoing` | Mozilla outgoing-link redirector (outgoing.prod.mozaws.net/v1/\<hash\>/\<target\>) |
108
+ | `unwrapPocket` | Pocket redirect (getpocket.com/redirect?url=\<target\>) |
89
109
  | `unwrapRedditOut` | Reddit outbound click tracker (out.reddit.com/?url=\<target\>) |
110
+ | `unwrapSegmentfault` | Segmentfault external link redirect (link.segmentfault.com/?enc=\<base64\>) |
111
+ | `unwrapSspai` | Sspai external link redirect (sspai.com/link?target=\<target\>) |
112
+ | `unwrapSteamLinkfilter` | Steam outbound link filter (steamcommunity.com/linkfilter/?url=\<target\>) |
113
+ | `unwrapThreadsShim` | Threads outbound link shim (l.threads.com / l.threads.net with ?u=\<target\>) |
114
+ | `unwrapTumblr` | Tumblr outbound redirect (t.umblr.com/redirect?z=\<target\>) |
90
115
  | `unwrapVkAway` | VK away redirect (vk.com/away.php?to=\<target\>) |
91
116
  | `unwrapYahooSearch` | Yahoo Search redirect (r.search.yahoo.com/.../RU=\<target\>/RK=...) |
92
117
  | `unwrapYouTube` | YouTube external redirect (www.youtube.com/redirect?q=\<target\>) |
118
+ | `unwrapZhihu` | Zhihu external redirect (link.zhihu.com/?target=\<target\>) |
93
119
 
94
120
  Many more are available for explicit opt-in: email security gateways (Outlook SafeLinks, Proofpoint, Mimecast), affiliate networks (Awin, Skimlinks, Commission Junction), CJK platforms, AMP caches, and others. See [src/unwraps](src/unwraps) for the full catalog, each documented in its source file.
package/dist/clean.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { parseUrl } from "./node_modules/trousse/dist/urls.js";
1
2
  import { defaultTrackingParams, defaultUnwrappers } from "./defaults.js";
2
3
  //#region src/clean.ts
3
4
  const trackingMatcherCache = /* @__PURE__ */ new WeakMap();
@@ -16,11 +17,6 @@ const getTrackingMatcher = (params) => {
16
17
  }
17
18
  return cached;
18
19
  };
19
- const parseUrl = (url) => {
20
- try {
21
- return new URL(url);
22
- } catch {}
23
- };
24
20
  const deleteTrackingParams = (url, trackingParams) => {
25
21
  if (!url.search) return false;
26
22
  const matcher = getTrackingMatcher(trackingParams);
@@ -32,6 +28,16 @@ const deleteTrackingParams = (url, trackingParams) => {
32
28
  for (const key of keysToDelete) url.searchParams.delete(key);
33
29
  return keysToDelete.length > 0;
34
30
  };
31
+ const wwwPrefixRegex = /^www\./;
32
+ const stripHostPrefix = (host) => {
33
+ return host.replace(wwwPrefixRegex, "").toLowerCase();
34
+ };
35
+ const deleteSelfReferentialParams = (url) => {
36
+ const value = url.searchParams.get("ref");
37
+ if (!value || stripHostPrefix(value) !== stripHostPrefix(url.hostname)) return false;
38
+ url.searchParams.delete("ref");
39
+ return true;
40
+ };
35
41
  const applyUnwrappers = (url, unwrappers) => {
36
42
  for (const unwrap of unwrappers) {
37
43
  const target = unwrap(url);
@@ -46,7 +52,9 @@ const unwrapUrl = (url, unwrappers = defaultUnwrappers) => {
46
52
  const stripTrackingParams = (url, trackingParams = defaultTrackingParams) => {
47
53
  const parsed = parseUrl(url);
48
54
  if (!parsed) return url;
49
- if (deleteTrackingParams(parsed, trackingParams)) return parsed.toString();
55
+ const trackingRemoved = deleteTrackingParams(parsed, trackingParams);
56
+ const selfReferentialRemoved = deleteSelfReferentialParams(parsed);
57
+ if (trackingRemoved || selfReferentialRemoved) return parsed.toString();
50
58
  return url;
51
59
  };
52
60
  const cleanUrl = (url, options) => {
@@ -65,7 +73,9 @@ const cleanUrl = (url, options) => {
65
73
  currentUrl = target;
66
74
  currentParsed = targetParsed;
67
75
  }
68
- if (deleteTrackingParams(currentParsed, trackingParams)) return currentParsed.toString();
76
+ const trackingRemoved = deleteTrackingParams(currentParsed, trackingParams);
77
+ const selfReferentialRemoved = deleteSelfReferentialParams(currentParsed);
78
+ if (trackingRemoved || selfReferentialRemoved) return currentParsed.toString();
69
79
  return currentUrl;
70
80
  };
71
81
  //#endregion
package/dist/defaults.js CHANGED
@@ -1,17 +1,35 @@
1
+ import { trackingParamsLiterals } from "./tracking/literals.js";
2
+ import { trackingParamsPatterns } from "./tracking/patterns.js";
1
3
  import { unwrapBing } from "./unwraps/bing.js";
4
+ import { unwrapBlueskyRedirect } from "./unwraps/bsky.js";
5
+ import { unwrapDisqus } from "./unwraps/disqus.js";
6
+ import { unwrapDouban } from "./unwraps/douban.js";
2
7
  import { unwrapFacebookShim } from "./unwraps/facebook.js";
8
+ import { unwrapFlipboard } from "./unwraps/flipboard.js";
9
+ import { unwrapGitee } from "./unwraps/gitee.js";
3
10
  import { unwrapGoogle } from "./unwraps/google.js";
4
11
  import { unwrapGoogleAmpViewer } from "./unwraps/googleAmpViewer.js";
5
12
  import { unwrapGoogleNews } from "./unwraps/googleNews.js";
6
13
  import { unwrapGoogleNewsModern } from "./unwraps/googleNewsModern.js";
7
14
  import { unwrapGoogleScholar } from "./unwraps/googleScholar.js";
15
+ import { unwrapHashnode } from "./unwraps/hashnode.js";
16
+ import { unwrapHrefLi } from "./unwraps/hrefLi.js";
8
17
  import { unwrapInstagramShim } from "./unwraps/instagram.js";
18
+ import { unwrapJianshuGo } from "./unwraps/jianshuGo.js";
19
+ import { unwrapJuejin } from "./unwraps/juejin.js";
20
+ import { unwrapMedium } from "./unwraps/medium.js";
21
+ import { unwrapMozillaOutgoing } from "./unwraps/mozillaOutgoing.js";
22
+ import { unwrapPocket } from "./unwraps/pocket.js";
9
23
  import { unwrapRedditOut } from "./unwraps/redditOut.js";
24
+ import { unwrapSegmentfault } from "./unwraps/segmentfault.js";
25
+ import { unwrapSspai } from "./unwraps/sspai.js";
26
+ import { unwrapSteamLinkfilter } from "./unwraps/steamLinkfilter.js";
27
+ import { unwrapThreadsShim } from "./unwraps/threads.js";
28
+ import { unwrapTumblr } from "./unwraps/tumblr.js";
10
29
  import { unwrapVkAway } from "./unwraps/vkAway.js";
11
30
  import { unwrapYahooSearch } from "./unwraps/yahooSearch.js";
12
31
  import { unwrapYouTube } from "./unwraps/youtube.js";
13
- import { trackingParamsLiterals } from "./tracking/literals.js";
14
- import { trackingParamsPatterns } from "./tracking/patterns.js";
32
+ import { unwrapZhihu } from "./unwraps/zhihu.js";
15
33
  //#region src/defaults.ts
16
34
  const defaultTrackingParams = [...trackingParamsLiterals, ...trackingParamsPatterns];
17
35
  const defaultUnwrappers = [
@@ -25,8 +43,26 @@ const defaultUnwrappers = [
25
43
  unwrapYouTube,
26
44
  unwrapFacebookShim,
27
45
  unwrapInstagramShim,
46
+ unwrapThreadsShim,
47
+ unwrapPocket,
48
+ unwrapTumblr,
49
+ unwrapHrefLi,
28
50
  unwrapVkAway,
29
- unwrapRedditOut
51
+ unwrapRedditOut,
52
+ unwrapBlueskyRedirect,
53
+ unwrapDisqus,
54
+ unwrapSteamLinkfilter,
55
+ unwrapDouban,
56
+ unwrapMedium,
57
+ unwrapFlipboard,
58
+ unwrapZhihu,
59
+ unwrapJuejin,
60
+ unwrapSspai,
61
+ unwrapJianshuGo,
62
+ unwrapSegmentfault,
63
+ unwrapGitee,
64
+ unwrapHashnode,
65
+ unwrapMozillaOutgoing
30
66
  ];
31
67
  //#endregion
32
68
  export { defaultTrackingParams, defaultUnwrappers };
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ import { unwrapAmazonAffiliate } from "./unwraps/amazonAffiliate.js";
9
9
  import { unwrapAmpCache } from "./unwraps/ampCache.js";
10
10
  import { unwrapAwin } from "./unwraps/awin.js";
11
11
  import { unwrapBing } from "./unwraps/bing.js";
12
+ import { unwrapBlueskyRedirect } from "./unwraps/bsky.js";
12
13
  import { unwrapCjNetwork } from "./unwraps/cjNetwork.js";
13
14
  import { unwrapDigidip } from "./unwraps/digidip.js";
14
15
  import { unwrapDisqus } from "./unwraps/disqus.js";
@@ -31,6 +32,7 @@ import { unwrapGoogleNewsModern } from "./unwraps/googleNewsModern.js";
31
32
  import { unwrapGoogleScholar } from "./unwraps/googleScholar.js";
32
33
  import { unwrapGoogleTranslate } from "./unwraps/googleTranslate.js";
33
34
  import { unwrapHashnode } from "./unwraps/hashnode.js";
35
+ import { unwrapHrefLi } from "./unwraps/hrefLi.js";
34
36
  import { unwrapIcptrack } from "./unwraps/icptrack.js";
35
37
  import { unwrapIdealoPartner } from "./unwraps/idealoPartner.js";
36
38
  import { unwrapInstagramShim } from "./unwraps/instagram.js";
@@ -67,6 +69,7 @@ import { unwrapSmartredirect } from "./unwraps/smartredirect.js";
67
69
  import { unwrapSspai } from "./unwraps/sspai.js";
68
70
  import { unwrapSteamLinkfilter } from "./unwraps/steamLinkfilter.js";
69
71
  import { unwrapTelegramIv } from "./unwraps/telegramIv.js";
72
+ import { unwrapThreadsShim } from "./unwraps/threads.js";
70
73
  import { unwrapTradedoubler } from "./unwraps/tradedoubler.js";
71
74
  import { unwrapTumblr } from "./unwraps/tumblr.js";
72
75
  import { unwrapValuecommerce } from "./unwraps/valuecommerce.js";
@@ -78,4 +81,4 @@ import { unwrapYandexTurbo } from "./unwraps/yandexTurbo.js";
78
81
  import { unwrapYouTube } from "./unwraps/youtube.js";
79
82
  import { unwrapZhihu } from "./unwraps/zhihu.js";
80
83
  import { ParamExtractorConfig, createParamExtractor } from "./utils.js";
81
- export { type CleanUrlOptions, type ParamExtractorConfig, type TrackingParam, type UrlUnwrapper, cleanUrl, createParamExtractor, defaultTrackingParams, defaultUnwrappers, stripTrackingParams, trackingParamsLiterals, trackingParamsPatterns, unwrapAceml, unwrapAdjust, unwrapAmazonAffiliate, unwrapAmpCache, unwrapAwin, unwrapBing, unwrapCjNetwork, unwrapDigidip, unwrapDisqus, unwrapDouban, unwrapDuckduckgo, unwrapEbayRover, unwrapEffiliation, unwrapEmbedly, unwrapFacebookShim, unwrapFeedsportal, unwrapFirebaseDynamicLinks, unwrapFlipboard, unwrapGateSc, unwrapGeoriot, unwrapGitee, unwrapGoogle, unwrapGoogleAmpViewer, unwrapGoogleNews, unwrapGoogleNewsModern, unwrapGoogleScholar, unwrapGoogleTranslate, unwrapHashnode, unwrapIcptrack, unwrapIdealoPartner, unwrapInstagramShim, unwrapJianshuGo, unwrapJuejin, unwrapLeverAnalytics, unwrapLinksynergy, unwrapMailchimp, unwrapMailpanion, unwrapMailpgn, unwrapMailtrack, unwrapMedium, unwrapMimecast, unwrapMozillaOutgoing, unwrapNarrativ, unwrapNicoMs, unwrapOutlookSafelinks, unwrapPartnerAds, unwrapPocket, unwrapPostmark, unwrapProofpointV1, unwrapProofpointV2, unwrapProofpointV3, unwrapPxf, unwrapRecruitics, unwrapRedditOut, unwrapRedirectingat, unwrapSegmentfault, unwrapShareasale, unwrapSjv, unwrapSkimlinks, unwrapSlack, unwrapSmartredirect, unwrapSspai, unwrapSteamLinkfilter, unwrapTelegramIv, unwrapTradedoubler, unwrapTumblr, unwrapUrl, unwrapValuecommerce, unwrapViglink, unwrapVkAway, unwrapWebArchive, unwrapYahooSearch, unwrapYandexTurbo, unwrapYouTube, unwrapZhihu };
84
+ export { type CleanUrlOptions, type ParamExtractorConfig, type TrackingParam, type UrlUnwrapper, cleanUrl, createParamExtractor, defaultTrackingParams, defaultUnwrappers, stripTrackingParams, trackingParamsLiterals, trackingParamsPatterns, unwrapAceml, unwrapAdjust, unwrapAmazonAffiliate, unwrapAmpCache, unwrapAwin, unwrapBing, unwrapBlueskyRedirect, unwrapCjNetwork, unwrapDigidip, unwrapDisqus, unwrapDouban, unwrapDuckduckgo, unwrapEbayRover, unwrapEffiliation, unwrapEmbedly, unwrapFacebookShim, unwrapFeedsportal, unwrapFirebaseDynamicLinks, unwrapFlipboard, unwrapGateSc, unwrapGeoriot, unwrapGitee, unwrapGoogle, unwrapGoogleAmpViewer, unwrapGoogleNews, unwrapGoogleNewsModern, unwrapGoogleScholar, unwrapGoogleTranslate, unwrapHashnode, unwrapHrefLi, unwrapIcptrack, unwrapIdealoPartner, unwrapInstagramShim, unwrapJianshuGo, unwrapJuejin, unwrapLeverAnalytics, unwrapLinksynergy, unwrapMailchimp, unwrapMailpanion, unwrapMailpgn, unwrapMailtrack, unwrapMedium, unwrapMimecast, unwrapMozillaOutgoing, unwrapNarrativ, unwrapNicoMs, unwrapOutlookSafelinks, unwrapPartnerAds, unwrapPocket, unwrapPostmark, unwrapProofpointV1, unwrapProofpointV2, unwrapProofpointV3, unwrapPxf, unwrapRecruitics, unwrapRedditOut, unwrapRedirectingat, unwrapSegmentfault, unwrapShareasale, unwrapSjv, unwrapSkimlinks, unwrapSlack, unwrapSmartredirect, unwrapSspai, unwrapSteamLinkfilter, unwrapTelegramIv, unwrapThreadsShim, unwrapTradedoubler, unwrapTumblr, unwrapUrl, unwrapValuecommerce, unwrapViglink, unwrapVkAway, unwrapWebArchive, unwrapYahooSearch, unwrapYandexTurbo, unwrapYouTube, unwrapZhihu };
package/dist/index.js CHANGED
@@ -1,18 +1,36 @@
1
+ import { trackingParamsLiterals } from "./tracking/literals.js";
2
+ import { trackingParamsPatterns } from "./tracking/patterns.js";
1
3
  import { createParamExtractor } from "./utils.js";
2
4
  import { unwrapBing } from "./unwraps/bing.js";
5
+ import { unwrapBlueskyRedirect } from "./unwraps/bsky.js";
6
+ import { unwrapDisqus } from "./unwraps/disqus.js";
7
+ import { unwrapDouban } from "./unwraps/douban.js";
3
8
  import { unwrapFacebookShim } from "./unwraps/facebook.js";
9
+ import { unwrapFlipboard } from "./unwraps/flipboard.js";
10
+ import { unwrapGitee } from "./unwraps/gitee.js";
4
11
  import { unwrapGoogle } from "./unwraps/google.js";
5
12
  import { unwrapGoogleAmpViewer } from "./unwraps/googleAmpViewer.js";
6
13
  import { unwrapGoogleNews } from "./unwraps/googleNews.js";
7
14
  import { unwrapGoogleNewsModern } from "./unwraps/googleNewsModern.js";
8
15
  import { unwrapGoogleScholar } from "./unwraps/googleScholar.js";
16
+ import { unwrapHashnode } from "./unwraps/hashnode.js";
17
+ import { unwrapHrefLi } from "./unwraps/hrefLi.js";
9
18
  import { unwrapInstagramShim } from "./unwraps/instagram.js";
19
+ import { unwrapJianshuGo } from "./unwraps/jianshuGo.js";
20
+ import { unwrapJuejin } from "./unwraps/juejin.js";
21
+ import { unwrapMedium } from "./unwraps/medium.js";
22
+ import { unwrapMozillaOutgoing } from "./unwraps/mozillaOutgoing.js";
23
+ import { unwrapPocket } from "./unwraps/pocket.js";
10
24
  import { unwrapRedditOut } from "./unwraps/redditOut.js";
25
+ import { unwrapSegmentfault } from "./unwraps/segmentfault.js";
26
+ import { unwrapSspai } from "./unwraps/sspai.js";
27
+ import { unwrapSteamLinkfilter } from "./unwraps/steamLinkfilter.js";
28
+ import { unwrapThreadsShim } from "./unwraps/threads.js";
29
+ import { unwrapTumblr } from "./unwraps/tumblr.js";
11
30
  import { unwrapVkAway } from "./unwraps/vkAway.js";
12
31
  import { unwrapYahooSearch } from "./unwraps/yahooSearch.js";
13
32
  import { unwrapYouTube } from "./unwraps/youtube.js";
14
- import { trackingParamsLiterals } from "./tracking/literals.js";
15
- import { trackingParamsPatterns } from "./tracking/patterns.js";
33
+ import { unwrapZhihu } from "./unwraps/zhihu.js";
16
34
  import { defaultTrackingParams, defaultUnwrappers } from "./defaults.js";
17
35
  import { cleanUrl, stripTrackingParams, unwrapUrl } from "./clean.js";
18
36
  import { unwrapAceml } from "./unwraps/aceml.js";
@@ -22,38 +40,28 @@ import { unwrapAmpCache } from "./unwraps/ampCache.js";
22
40
  import { unwrapAwin } from "./unwraps/awin.js";
23
41
  import { unwrapCjNetwork } from "./unwraps/cjNetwork.js";
24
42
  import { unwrapDigidip } from "./unwraps/digidip.js";
25
- import { unwrapDisqus } from "./unwraps/disqus.js";
26
- import { unwrapDouban } from "./unwraps/douban.js";
27
43
  import { unwrapDuckduckgo } from "./unwraps/duckduckgo.js";
28
44
  import { unwrapEbayRover } from "./unwraps/ebayRover.js";
29
45
  import { unwrapEffiliation } from "./unwraps/effiliation.js";
30
46
  import { unwrapEmbedly } from "./unwraps/embedly.js";
31
47
  import { unwrapFeedsportal } from "./unwraps/feedsportal.js";
32
48
  import { unwrapFirebaseDynamicLinks } from "./unwraps/firebaseDynamicLinks.js";
33
- import { unwrapFlipboard } from "./unwraps/flipboard.js";
34
49
  import { unwrapGateSc } from "./unwraps/gateSc.js";
35
50
  import { unwrapGeoriot } from "./unwraps/georiot.js";
36
- import { unwrapGitee } from "./unwraps/gitee.js";
37
51
  import { unwrapGoogleTranslate } from "./unwraps/googleTranslate.js";
38
- import { unwrapHashnode } from "./unwraps/hashnode.js";
39
52
  import { unwrapIcptrack } from "./unwraps/icptrack.js";
40
53
  import { unwrapIdealoPartner } from "./unwraps/idealoPartner.js";
41
- import { unwrapJianshuGo } from "./unwraps/jianshuGo.js";
42
- import { unwrapJuejin } from "./unwraps/juejin.js";
43
54
  import { unwrapLeverAnalytics } from "./unwraps/leverAnalytics.js";
44
55
  import { unwrapLinksynergy } from "./unwraps/linksynergy.js";
45
56
  import { unwrapMailchimp } from "./unwraps/mailchimp.js";
46
57
  import { unwrapMailpanion } from "./unwraps/mailpanion.js";
47
58
  import { unwrapMailpgn } from "./unwraps/mailpgn.js";
48
59
  import { unwrapMailtrack } from "./unwraps/mailtrack.js";
49
- import { unwrapMedium } from "./unwraps/medium.js";
50
60
  import { unwrapMimecast } from "./unwraps/mimecast.js";
51
- import { unwrapMozillaOutgoing } from "./unwraps/mozillaOutgoing.js";
52
61
  import { unwrapNarrativ } from "./unwraps/narrativ.js";
53
62
  import { unwrapNicoMs } from "./unwraps/nicoMs.js";
54
63
  import { unwrapOutlookSafelinks } from "./unwraps/outlookSafelinks.js";
55
64
  import { unwrapPartnerAds } from "./unwraps/partnerAds.js";
56
- import { unwrapPocket } from "./unwraps/pocket.js";
57
65
  import { unwrapPostmark } from "./unwraps/postmark.js";
58
66
  import { unwrapProofpointV1 } from "./unwraps/proofpointV1.js";
59
67
  import { unwrapProofpointV2 } from "./unwraps/proofpointV2.js";
@@ -61,20 +69,15 @@ import { unwrapProofpointV3 } from "./unwraps/proofpointV3.js";
61
69
  import { unwrapPxf } from "./unwraps/pxf.js";
62
70
  import { unwrapRecruitics } from "./unwraps/recruitics.js";
63
71
  import { unwrapRedirectingat } from "./unwraps/redirectingat.js";
64
- import { unwrapSegmentfault } from "./unwraps/segmentfault.js";
65
72
  import { unwrapShareasale } from "./unwraps/shareasale.js";
66
73
  import { unwrapSjv } from "./unwraps/sjv.js";
67
74
  import { unwrapSkimlinks } from "./unwraps/skimlinks.js";
68
75
  import { unwrapSlack } from "./unwraps/slack.js";
69
76
  import { unwrapSmartredirect } from "./unwraps/smartredirect.js";
70
- import { unwrapSspai } from "./unwraps/sspai.js";
71
- import { unwrapSteamLinkfilter } from "./unwraps/steamLinkfilter.js";
72
77
  import { unwrapTelegramIv } from "./unwraps/telegramIv.js";
73
78
  import { unwrapTradedoubler } from "./unwraps/tradedoubler.js";
74
- import { unwrapTumblr } from "./unwraps/tumblr.js";
75
79
  import { unwrapValuecommerce } from "./unwraps/valuecommerce.js";
76
80
  import { unwrapViglink } from "./unwraps/viglink.js";
77
81
  import { unwrapWebArchive } from "./unwraps/webArchive.js";
78
82
  import { unwrapYandexTurbo } from "./unwraps/yandexTurbo.js";
79
- import { unwrapZhihu } from "./unwraps/zhihu.js";
80
- export { cleanUrl, createParamExtractor, defaultTrackingParams, defaultUnwrappers, stripTrackingParams, trackingParamsLiterals, trackingParamsPatterns, unwrapAceml, unwrapAdjust, unwrapAmazonAffiliate, unwrapAmpCache, unwrapAwin, unwrapBing, unwrapCjNetwork, unwrapDigidip, unwrapDisqus, unwrapDouban, unwrapDuckduckgo, unwrapEbayRover, unwrapEffiliation, unwrapEmbedly, unwrapFacebookShim, unwrapFeedsportal, unwrapFirebaseDynamicLinks, unwrapFlipboard, unwrapGateSc, unwrapGeoriot, unwrapGitee, unwrapGoogle, unwrapGoogleAmpViewer, unwrapGoogleNews, unwrapGoogleNewsModern, unwrapGoogleScholar, unwrapGoogleTranslate, unwrapHashnode, unwrapIcptrack, unwrapIdealoPartner, unwrapInstagramShim, unwrapJianshuGo, unwrapJuejin, unwrapLeverAnalytics, unwrapLinksynergy, unwrapMailchimp, unwrapMailpanion, unwrapMailpgn, unwrapMailtrack, unwrapMedium, unwrapMimecast, unwrapMozillaOutgoing, unwrapNarrativ, unwrapNicoMs, unwrapOutlookSafelinks, unwrapPartnerAds, unwrapPocket, unwrapPostmark, unwrapProofpointV1, unwrapProofpointV2, unwrapProofpointV3, unwrapPxf, unwrapRecruitics, unwrapRedditOut, unwrapRedirectingat, unwrapSegmentfault, unwrapShareasale, unwrapSjv, unwrapSkimlinks, unwrapSlack, unwrapSmartredirect, unwrapSspai, unwrapSteamLinkfilter, unwrapTelegramIv, unwrapTradedoubler, unwrapTumblr, unwrapUrl, unwrapValuecommerce, unwrapViglink, unwrapVkAway, unwrapWebArchive, unwrapYahooSearch, unwrapYandexTurbo, unwrapYouTube, unwrapZhihu };
83
+ export { cleanUrl, createParamExtractor, defaultTrackingParams, defaultUnwrappers, stripTrackingParams, trackingParamsLiterals, trackingParamsPatterns, unwrapAceml, unwrapAdjust, unwrapAmazonAffiliate, unwrapAmpCache, unwrapAwin, unwrapBing, unwrapBlueskyRedirect, unwrapCjNetwork, unwrapDigidip, unwrapDisqus, unwrapDouban, unwrapDuckduckgo, unwrapEbayRover, unwrapEffiliation, unwrapEmbedly, unwrapFacebookShim, unwrapFeedsportal, unwrapFirebaseDynamicLinks, unwrapFlipboard, unwrapGateSc, unwrapGeoriot, unwrapGitee, unwrapGoogle, unwrapGoogleAmpViewer, unwrapGoogleNews, unwrapGoogleNewsModern, unwrapGoogleScholar, unwrapGoogleTranslate, unwrapHashnode, unwrapHrefLi, unwrapIcptrack, unwrapIdealoPartner, unwrapInstagramShim, unwrapJianshuGo, unwrapJuejin, unwrapLeverAnalytics, unwrapLinksynergy, unwrapMailchimp, unwrapMailpanion, unwrapMailpgn, unwrapMailtrack, unwrapMedium, unwrapMimecast, unwrapMozillaOutgoing, unwrapNarrativ, unwrapNicoMs, unwrapOutlookSafelinks, unwrapPartnerAds, unwrapPocket, unwrapPostmark, unwrapProofpointV1, unwrapProofpointV2, unwrapProofpointV3, unwrapPxf, unwrapRecruitics, unwrapRedditOut, unwrapRedirectingat, unwrapSegmentfault, unwrapShareasale, unwrapSjv, unwrapSkimlinks, unwrapSlack, unwrapSmartredirect, unwrapSspai, unwrapSteamLinkfilter, unwrapTelegramIv, unwrapThreadsShim, unwrapTradedoubler, unwrapTumblr, unwrapUrl, unwrapValuecommerce, unwrapViglink, unwrapVkAway, unwrapWebArchive, unwrapYahooSearch, unwrapYandexTurbo, unwrapYouTube, unwrapZhihu };
@@ -0,0 +1,17 @@
1
+ //#region node_modules/trousse/dist/matching.js
2
+ const isAnyOf = (value, patterns, parser) => {
3
+ const parsedValue = parser ? parser(value) : value?.toLowerCase()?.trim();
4
+ return patterns.some((pattern) => {
5
+ if (pattern instanceof RegExp) return pattern.test(parsedValue);
6
+ return parsedValue === pattern.toLowerCase().trim();
7
+ });
8
+ };
9
+ const endsWithAnyOf = (value, patterns) => {
10
+ const lowerValue = value.toLowerCase();
11
+ return patterns.some((pattern) => {
12
+ if (pattern instanceof RegExp) return pattern.test(lowerValue);
13
+ return pattern && lowerValue.endsWith(pattern.toLowerCase());
14
+ });
15
+ };
16
+ //#endregion
17
+ export { endsWithAnyOf, isAnyOf };
@@ -0,0 +1,20 @@
1
+ import { endsWithAnyOf, isAnyOf } from "./matching.js";
2
+ //#region node_modules/trousse/dist/urls.js
3
+ const parseUrl = (value, base) => {
4
+ if (value instanceof URL && base === void 0) return value;
5
+ try {
6
+ return new URL(value, base);
7
+ } catch {}
8
+ };
9
+ const isHostOf = (url, hosts) => {
10
+ const hostname = parseUrl(url)?.hostname;
11
+ if (!hostname) return false;
12
+ return isAnyOf(hostname, Array.isArray(hosts) ? hosts : [hosts]);
13
+ };
14
+ const isSubdomainOf = (url, domains) => {
15
+ const hostname = parseUrl(url)?.hostname;
16
+ if (!hostname) return false;
17
+ return endsWithAnyOf(hostname, (Array.isArray(domains) ? domains : [domains]).map((domain) => `.${domain}`));
18
+ };
19
+ //#endregion
20
+ export { isHostOf, isSubdomainOf, parseUrl };
@@ -17,23 +17,29 @@ const trackingParamsLiterals = [
17
17
  "gad_source",
18
18
  "gad_campaignid",
19
19
  "srsltid",
20
+ "usqp",
20
21
  "fbclid",
21
22
  "fb_action_ids",
22
23
  "fb_action_types",
23
24
  "fb_source",
24
25
  "fb_ref",
26
+ "mibextid",
25
27
  "_ga",
26
28
  "_gl",
27
29
  "_bk",
28
30
  "_ke",
31
+ "_kx",
32
+ "__s",
29
33
  "mc_cid",
30
34
  "mc_eid",
31
35
  "mc_tc",
32
36
  "mkt_tok",
33
37
  "msclkid",
34
38
  "twclid",
39
+ "__twitter_impression",
35
40
  "ttclid",
36
41
  "igshid",
42
+ "igsh",
37
43
  "mtm_campaign",
38
44
  "mtm_cid",
39
45
  "mtm_content",
@@ -50,6 +56,7 @@ const trackingParamsLiterals = [
50
56
  "pk_source",
51
57
  "ncid",
52
58
  "sr_share",
59
+ "cmpid",
53
60
  "hsa_acc",
54
61
  "hsa_ad",
55
62
  "hsa_cam",
@@ -70,15 +77,34 @@ const trackingParamsLiterals = [
70
77
  "s_kwcid",
71
78
  "sc_cid",
72
79
  "ef_id",
80
+ "s_cid",
81
+ "wt_mc",
82
+ "wt_zmc",
83
+ "wtrid",
84
+ "cx_click",
85
+ "cx_recsOrder",
86
+ "cx_recsWidget",
73
87
  "obOrigUrl",
74
88
  "dicbo",
75
89
  "yclid",
76
90
  "ysclid",
77
91
  "_openstat",
92
+ "guccounter",
93
+ "guce_referrer",
94
+ "guce_referrer_sig",
78
95
  "awinaffid",
79
96
  "awinmid",
80
97
  "clickref",
81
98
  "afftrack",
99
+ "sscid",
100
+ "awc",
101
+ "cjevent",
102
+ "cjdata",
103
+ "irclickid",
104
+ "irgwc",
105
+ "ir_adid",
106
+ "ir_campaignid",
107
+ "ir_partnerid",
82
108
  "itm_source",
83
109
  "itm_medium",
84
110
  "itm_campaign",
@@ -150,6 +176,7 @@ const trackingParamsLiterals = [
150
176
  "trk",
151
177
  "vero_conv",
152
178
  "vero_id",
179
+ "vgo_ee",
153
180
  "wickedid",
154
181
  "xtor"
155
182
  ];
@@ -1,4 +1,4 @@
1
- import { isHostOf, isSubdomainOf } from "../utils.js";
1
+ import { isHostOf, isSubdomainOf } from "../node_modules/trousse/dist/urls.js";
2
2
  //#region src/unwraps/ampCache.ts
3
3
  const httpsPathRegex = /^\/c\/s\/(.+)$/;
4
4
  const httpPathRegex = /^\/c\/(?!s\/)(.+)$/;
@@ -0,0 +1,6 @@
1
+ import { UrlUnwrapper } from "../types.js";
2
+
3
+ //#region src/unwraps/bsky.d.ts
4
+ declare const unwrapBlueskyRedirect: UrlUnwrapper;
5
+ //#endregion
6
+ export { unwrapBlueskyRedirect };
@@ -0,0 +1,9 @@
1
+ import { createParamExtractor } from "../utils.js";
2
+ //#region src/unwraps/bsky.ts
3
+ const unwrapBlueskyRedirect = createParamExtractor({
4
+ hosts: "go.bsky.app",
5
+ path: "/redirect",
6
+ params: ["u"]
7
+ });
8
+ //#endregion
9
+ export { unwrapBlueskyRedirect };
@@ -1,7 +1,11 @@
1
1
  import { createParamExtractor } from "../utils.js";
2
2
  //#region src/unwraps/facebook.ts
3
3
  const unwrapFacebookShim = createParamExtractor({
4
- hosts: ["l.facebook.com", "lm.facebook.com"],
4
+ hosts: [
5
+ "l.facebook.com",
6
+ "lm.facebook.com",
7
+ "l.messenger.com"
8
+ ],
5
9
  path: "/l.php",
6
10
  params: ["u"]
7
11
  });
@@ -1,4 +1,5 @@
1
- import { decodeBase64Binary, isHostOf } from "../utils.js";
1
+ import { isHostOf } from "../node_modules/trousse/dist/urls.js";
2
+ import { decodeBase64Binary } from "../utils.js";
2
3
  //#region src/unwraps/googleNewsModern.ts
3
4
  const articleIdRegex = /^\/(?:rss\/)?articles\/([\w-]+)/;
4
5
  const base64UrlMinusRegex = /-/g;
@@ -0,0 +1,6 @@
1
+ import { UrlUnwrapper } from "../types.js";
2
+
3
+ //#region src/unwraps/hrefLi.d.ts
4
+ declare const unwrapHrefLi: UrlUnwrapper;
5
+ //#endregion
6
+ export { unwrapHrefLi };
@@ -0,0 +1,7 @@
1
+ //#region src/unwraps/hrefLi.ts
2
+ const unwrapHrefLi = (url) => {
3
+ if (url.hostname !== "href.li" && url.hostname !== "www.href.li") return;
4
+ return url.search.slice(1) || void 0;
5
+ };
6
+ //#endregion
7
+ export { unwrapHrefLi };
@@ -0,0 +1,6 @@
1
+ import { UrlUnwrapper } from "../types.js";
2
+
3
+ //#region src/unwraps/threads.d.ts
4
+ declare const unwrapThreadsShim: UrlUnwrapper;
5
+ //#endregion
6
+ export { unwrapThreadsShim };
@@ -0,0 +1,8 @@
1
+ import { createParamExtractor } from "../utils.js";
2
+ //#region src/unwraps/threads.ts
3
+ const unwrapThreadsShim = createParamExtractor({
4
+ hosts: ["l.threads.com", "l.threads.net"],
5
+ params: ["u"]
6
+ });
7
+ //#endregion
8
+ export { unwrapThreadsShim };
package/dist/utils.js CHANGED
@@ -15,30 +15,18 @@ const createParamExtractor = (config) => {
15
15
  }
16
16
  };
17
17
  };
18
- const isHostOf = (url, hosts) => {
19
- try {
20
- const hostname = (url instanceof URL ? url : new URL(url)).hostname.toLowerCase();
21
- return (Array.isArray(hosts) ? hosts : [hosts]).some((host) => hostname === host.toLowerCase().trim());
22
- } catch {}
23
- return false;
24
- };
25
- const isSubdomainOf = (url, domains) => {
26
- try {
27
- const hostname = (url instanceof URL ? url : new URL(url)).hostname.toLowerCase();
28
- return (Array.isArray(domains) ? domains : [domains]).some((domain) => hostname.endsWith(`.${domain}`));
29
- } catch {}
30
- return false;
31
- };
32
18
  const decodeBase64Binary = (value) => {
33
19
  try {
34
20
  return atob(value);
35
21
  } catch {}
36
22
  };
23
+ const utf8Decoder = new TextDecoder();
37
24
  const decodeBase64 = (value) => {
38
25
  const binary = decodeBase64Binary(value);
39
26
  if (binary === void 0) return;
40
- const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
41
- return new TextDecoder().decode(bytes);
27
+ const bytes = new Uint8Array(binary.length);
28
+ for (let index = 0; index < binary.length; index++) bytes[index] = binary.charCodeAt(index);
29
+ return utf8Decoder.decode(bytes);
42
30
  };
43
31
  const decodeBase64Url = (value) => {
44
32
  return decodeBase64(value.replace(/-/g, "+").replace(/_/g, "/"));
@@ -47,4 +35,4 @@ const getUtf8ByteLength = (value) => {
47
35
  return new TextEncoder().encode(value).length;
48
36
  };
49
37
  //#endregion
50
- export { createParamExtractor, decodeBase64, decodeBase64Binary, decodeBase64Url, getUtf8ByteLength, isHostOf, isSubdomainOf };
38
+ export { createParamExtractor, decodeBase64, decodeBase64Binary, decodeBase64Url, getUtf8ByteLength };
package/package.json CHANGED
@@ -38,8 +38,9 @@
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/bun": "^1.3.14",
41
- "kvalita": "^1.14.0",
41
+ "kvalita": "^1.15.0",
42
+ "trousse": "^1.0.0",
42
43
  "tsdown": "^0.22.2"
43
44
  },
44
- "version": "1.1.0"
45
+ "version": "1.3.0"
45
46
  }