urlpurify 1.4.1 → 1.5.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 +2 -0
- package/dist/clean.mjs +15 -23
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +2 -1
- package/dist/node_modules/trousse/dist/is.mjs +6 -0
- package/dist/node_modules/trousse/dist/matching.mjs +11 -5
- package/dist/node_modules/trousse/dist/urls.mjs +42 -5
- package/dist/tracking/literals.mjs +0 -1
- package/dist/unwraps/aceml.mjs +2 -1
- package/dist/unwraps/adjust.mjs +3 -2
- package/dist/unwraps/amazonAffiliate.mjs +3 -1
- package/dist/unwraps/ampCache.mjs +4 -4
- package/dist/unwraps/anonymTo.mjs +5 -2
- package/dist/unwraps/bing.mjs +2 -1
- package/dist/unwraps/deviantartOutgoing.mjs +5 -2
- package/dist/unwraps/feedsportal.mjs +2 -1
- package/dist/unwraps/googleAmpViewer.mjs +2 -2
- package/dist/unwraps/googleNewsModern.mjs +2 -5
- package/dist/unwraps/hrefLi.mjs +5 -2
- package/dist/unwraps/mozillaOutgoing.mjs +4 -5
- package/dist/unwraps/nicoMs.mjs +2 -1
- package/dist/unwraps/postmark.mjs +3 -4
- package/dist/unwraps/proofpointV1.mjs +14 -12
- package/dist/unwraps/proofpointV2.mjs +2 -13
- package/dist/unwraps/proofpointV3.mjs +9 -13
- package/dist/unwraps/segmentfault.mjs +2 -1
- package/dist/unwraps/webArchive.mjs +5 -4
- package/dist/unwraps/yahooSearch.mjs +3 -4
- package/dist/unwraps/yandexTranslate.d.mts +4 -0
- package/dist/unwraps/yandexTranslate.mjs +11 -0
- package/dist/utils.mjs +12 -10
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -53,6 +53,8 @@ Removes matching query parameters and returns the cleaned URL. The input is retu
|
|
|
53
53
|
|
|
54
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
55
|
|
|
56
|
+
A tracking list is compiled the first time it's used, and later calls with the same array reuse that result. To change the list, pass a new array. Entries pushed onto an array that's already been used are ignored.
|
|
57
|
+
|
|
56
58
|
### `createParamExtractor(config)`
|
|
57
59
|
|
|
58
60
|
Builds an unwrapper for the common case where the target URL sits in a query parameter:
|
package/dist/clean.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseUrl } from "./node_modules/trousse/dist/urls.mjs";
|
|
1
|
+
import { isHttpUrl, parseUrl, stripWww } from "./node_modules/trousse/dist/urls.mjs";
|
|
2
2
|
import { defaultTrackingParams, defaultUnwrappers } from "./defaults.mjs";
|
|
3
3
|
//#region src/clean.ts
|
|
4
4
|
const trackingMatcherCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -20,28 +20,24 @@ const getTrackingMatcher = (params) => {
|
|
|
20
20
|
const deleteTrackingParams = (url, trackingParams) => {
|
|
21
21
|
if (!url.search) return false;
|
|
22
22
|
const matcher = getTrackingMatcher(trackingParams);
|
|
23
|
-
const
|
|
24
|
-
|
|
23
|
+
const host = stripWww(url.hostname);
|
|
24
|
+
const pairs = url.search.slice(1).split("&");
|
|
25
|
+
const keptPairs = pairs.filter((pair) => {
|
|
26
|
+
const entry = new URLSearchParams(pair).entries().next().value;
|
|
27
|
+
if (!entry) return true;
|
|
28
|
+
const [key, value] = entry;
|
|
25
29
|
const name = key.toLowerCase();
|
|
26
|
-
if (matcher.literals.has(name) || matcher.patterns.some((pattern) =>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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");
|
|
30
|
+
if (matcher.literals.has(name) || matcher.patterns.some((pattern) => name.search(pattern) !== -1)) return false;
|
|
31
|
+
return key !== "ref" || stripWww(value.toLowerCase()) !== host;
|
|
32
|
+
});
|
|
33
|
+
if (keptPairs.length === pairs.length) return false;
|
|
34
|
+
url.search = keptPairs.join("&");
|
|
39
35
|
return true;
|
|
40
36
|
};
|
|
41
37
|
const applyUnwrappers = (url, unwrappers) => {
|
|
42
38
|
for (const unwrap of unwrappers) {
|
|
43
39
|
const target = unwrap(url);
|
|
44
|
-
if (target) return target;
|
|
40
|
+
if (target && isHttpUrl(target)) return target;
|
|
45
41
|
}
|
|
46
42
|
};
|
|
47
43
|
const unwrapUrl = (url, unwrappers = defaultUnwrappers) => {
|
|
@@ -52,9 +48,7 @@ const unwrapUrl = (url, unwrappers = defaultUnwrappers) => {
|
|
|
52
48
|
const stripTrackingParams = (url, trackingParams = defaultTrackingParams) => {
|
|
53
49
|
const parsed = parseUrl(url);
|
|
54
50
|
if (!parsed) return url;
|
|
55
|
-
|
|
56
|
-
const selfReferentialRemoved = deleteSelfReferentialParams(parsed);
|
|
57
|
-
if (trackingRemoved || selfReferentialRemoved) return parsed.toString();
|
|
51
|
+
if (deleteTrackingParams(parsed, trackingParams)) return parsed.toString();
|
|
58
52
|
return url;
|
|
59
53
|
};
|
|
60
54
|
const cleanUrl = (url, options) => {
|
|
@@ -73,9 +67,7 @@ const cleanUrl = (url, options) => {
|
|
|
73
67
|
currentUrl = target;
|
|
74
68
|
currentParsed = targetParsed;
|
|
75
69
|
}
|
|
76
|
-
|
|
77
|
-
const selfReferentialRemoved = deleteSelfReferentialParams(currentParsed);
|
|
78
|
-
if (trackingRemoved || selfReferentialRemoved) return currentParsed.toString();
|
|
70
|
+
if (deleteTrackingParams(currentParsed, trackingParams)) return currentParsed.toString();
|
|
79
71
|
return currentUrl;
|
|
80
72
|
};
|
|
81
73
|
//#endregion
|
package/dist/index.d.mts
CHANGED
|
@@ -81,8 +81,9 @@ import { unwrapViglink } from "./unwraps/viglink.mjs";
|
|
|
81
81
|
import { unwrapVkAway } from "./unwraps/vkAway.mjs";
|
|
82
82
|
import { unwrapWebArchive } from "./unwraps/webArchive.mjs";
|
|
83
83
|
import { unwrapYahooSearch } from "./unwraps/yahooSearch.mjs";
|
|
84
|
+
import { unwrapYandexTranslate } from "./unwraps/yandexTranslate.mjs";
|
|
84
85
|
import { unwrapYandexTurbo } from "./unwraps/yandexTurbo.mjs";
|
|
85
86
|
import { unwrapYouTube } from "./unwraps/youtube.mjs";
|
|
86
87
|
import { unwrapZhihu } from "./unwraps/zhihu.mjs";
|
|
87
88
|
import { ParamExtractorConfig, createParamExtractor } from "./utils.mjs";
|
|
88
|
-
export { type CleanUrlOptions, type ParamExtractorConfig, type TrackingParam, type UrlUnwrapper, cleanUrl, createParamExtractor, defaultTrackingParams, defaultUnwrappers, stripTrackingParams, trackingParamsLiterals, trackingParamsPatterns, unwrapAceml, unwrapAdjust, unwrapAmazonAffiliate, unwrapAmpCache, unwrapAnonymTo, unwrapAwin, unwrapBing, unwrapBlueskyRedirect, unwrapCjNetwork, unwrapCsdn, unwrapDeviantartOutgoing, 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, unwrapNaverOutgoing, 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 };
|
|
89
|
+
export { type CleanUrlOptions, type ParamExtractorConfig, type TrackingParam, type UrlUnwrapper, cleanUrl, createParamExtractor, defaultTrackingParams, defaultUnwrappers, stripTrackingParams, trackingParamsLiterals, trackingParamsPatterns, unwrapAceml, unwrapAdjust, unwrapAmazonAffiliate, unwrapAmpCache, unwrapAnonymTo, unwrapAwin, unwrapBing, unwrapBlueskyRedirect, unwrapCjNetwork, unwrapCsdn, unwrapDeviantartOutgoing, 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, unwrapNaverOutgoing, 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, unwrapYandexTranslate, unwrapYandexTurbo, unwrapYouTube, unwrapZhihu };
|
package/dist/index.mjs
CHANGED
|
@@ -83,5 +83,6 @@ import { unwrapTradedoubler } from "./unwraps/tradedoubler.mjs";
|
|
|
83
83
|
import { unwrapValuecommerce } from "./unwraps/valuecommerce.mjs";
|
|
84
84
|
import { unwrapViglink } from "./unwraps/viglink.mjs";
|
|
85
85
|
import { unwrapWebArchive } from "./unwraps/webArchive.mjs";
|
|
86
|
+
import { unwrapYandexTranslate } from "./unwraps/yandexTranslate.mjs";
|
|
86
87
|
import { unwrapYandexTurbo } from "./unwraps/yandexTurbo.mjs";
|
|
87
|
-
export { cleanUrl, createParamExtractor, defaultTrackingParams, defaultUnwrappers, stripTrackingParams, trackingParamsLiterals, trackingParamsPatterns, unwrapAceml, unwrapAdjust, unwrapAmazonAffiliate, unwrapAmpCache, unwrapAnonymTo, unwrapAwin, unwrapBing, unwrapBlueskyRedirect, unwrapCjNetwork, unwrapCsdn, unwrapDeviantartOutgoing, 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, unwrapNaverOutgoing, 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 };
|
|
88
|
+
export { cleanUrl, createParamExtractor, defaultTrackingParams, defaultUnwrappers, stripTrackingParams, trackingParamsLiterals, trackingParamsPatterns, unwrapAceml, unwrapAdjust, unwrapAmazonAffiliate, unwrapAmpCache, unwrapAnonymTo, unwrapAwin, unwrapBing, unwrapBlueskyRedirect, unwrapCjNetwork, unwrapCsdn, unwrapDeviantartOutgoing, 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, unwrapNaverOutgoing, 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, unwrapYandexTranslate, unwrapYandexTurbo, unwrapYouTube, unwrapZhihu };
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
import { isNullish } from "./is.mjs";
|
|
1
2
|
//#region node_modules/trousse/dist/matching.js
|
|
3
|
+
const testRegex = (regex, value) => {
|
|
4
|
+
regex.lastIndex = 0;
|
|
5
|
+
return regex.test(value);
|
|
6
|
+
};
|
|
2
7
|
const isAnyOf = (value, patterns, parser) => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
if (isNullish(value)) return false;
|
|
9
|
+
const parsedValue = parser ? parser(value) : value.toLowerCase().trim();
|
|
10
|
+
return (typeof patterns === "string" || patterns instanceof RegExp ? [patterns] : patterns).some((pattern) => {
|
|
11
|
+
if (pattern instanceof RegExp) return testRegex(pattern, parsedValue);
|
|
12
|
+
return parsedValue === (parser ? pattern : pattern.toLowerCase().trim());
|
|
7
13
|
});
|
|
8
14
|
};
|
|
9
15
|
const endsWithAnyOf = (value, patterns) => {
|
|
10
16
|
const lowerValue = value.toLowerCase();
|
|
11
17
|
return patterns.some((pattern) => {
|
|
12
|
-
if (pattern instanceof RegExp) return pattern
|
|
18
|
+
if (pattern instanceof RegExp) return testRegex(pattern, lowerValue);
|
|
13
19
|
return pattern && lowerValue.endsWith(pattern.toLowerCase());
|
|
14
20
|
});
|
|
15
21
|
};
|
|
@@ -1,20 +1,57 @@
|
|
|
1
1
|
import { endsWithAnyOf, isAnyOf } from "./matching.mjs";
|
|
2
2
|
//#region node_modules/trousse/dist/urls.js
|
|
3
|
+
const httpProtocols = ["http:", "https:"];
|
|
3
4
|
const parseUrl = (value, base) => {
|
|
4
5
|
if (value instanceof URL && base === void 0) return value;
|
|
6
|
+
if (URL.parse) return URL.parse(value, base) ?? void 0;
|
|
5
7
|
try {
|
|
6
8
|
return new URL(value, base);
|
|
7
9
|
} catch {}
|
|
8
10
|
};
|
|
9
|
-
const
|
|
11
|
+
const getHostname = (url) => {
|
|
10
12
|
const hostname = parseUrl(url)?.hostname;
|
|
13
|
+
if (!hostname) return;
|
|
14
|
+
return hostname.endsWith(".") ? hostname.slice(0, -1) : hostname;
|
|
15
|
+
};
|
|
16
|
+
const nonAsciiRegex = /[\u0080-\uffff]/;
|
|
17
|
+
const normalizeDomain = (domain) => {
|
|
18
|
+
const trimmed = domain.trim();
|
|
19
|
+
const bare = trimmed.endsWith(".") ? trimmed.slice(0, -1) : trimmed;
|
|
20
|
+
if (!nonAsciiRegex.test(bare)) return bare;
|
|
21
|
+
return parseUrl(`http://${bare}`)?.hostname ?? bare;
|
|
22
|
+
};
|
|
23
|
+
const isHostOf = (url, hosts) => {
|
|
24
|
+
const hostname = getHostname(url);
|
|
11
25
|
if (!hostname) return false;
|
|
12
|
-
return isAnyOf(hostname, typeof hosts === "string" ? [hosts] : hosts);
|
|
26
|
+
return isAnyOf(hostname, (typeof hosts === "string" ? [hosts] : hosts).map(normalizeDomain));
|
|
13
27
|
};
|
|
14
28
|
const isSubdomainOf = (url, domains) => {
|
|
15
|
-
const hostname =
|
|
29
|
+
const hostname = getHostname(url);
|
|
16
30
|
if (!hostname) return false;
|
|
17
|
-
return endsWithAnyOf(hostname, (typeof domains === "string" ? [domains] : domains).map((domain) => `.${domain}`));
|
|
31
|
+
return endsWithAnyOf(hostname, (typeof domains === "string" ? [domains] : domains).map((domain) => `.${normalizeDomain(domain)}`));
|
|
32
|
+
};
|
|
33
|
+
const isHttpUrl = (url) => {
|
|
34
|
+
const protocol = parseUrl(url)?.protocol;
|
|
35
|
+
if (!protocol) return false;
|
|
36
|
+
return httpProtocols.includes(protocol);
|
|
37
|
+
};
|
|
38
|
+
const isHostOrSubdomainOf = (url, domains) => {
|
|
39
|
+
return isHostOf(url, domains) || isSubdomainOf(url, domains);
|
|
40
|
+
};
|
|
41
|
+
const decodeSegment = (segment) => {
|
|
42
|
+
if (segment === void 0) return;
|
|
43
|
+
try {
|
|
44
|
+
return decodeURIComponent(segment);
|
|
45
|
+
} catch {}
|
|
46
|
+
};
|
|
47
|
+
const wwwPrefixRegex = /^www\./;
|
|
48
|
+
const schemeSeparator = String.raw`\.*[:\s=\\/][:\s=.\\/]*`;
|
|
49
|
+
const leadingSchemeSeparator = String.raw`\.*(?::[:\s=.\\/]*|[\s=\\/][:\s=.\\/]+)`;
|
|
50
|
+
String.raw`^\/?[htps]{2,7}${leadingSchemeSeparator}([htps]{2,7})(?!:\d)${schemeSeparator}[.,:/]*(www[./]+)?`;
|
|
51
|
+
String.raw`^\/?(?:h[htps():]{1,10}|t{1,2}ps?)${leadingSchemeSeparator}[.,:/]*(www[./]+)?`;
|
|
52
|
+
const stripWww = (hostname) => {
|
|
53
|
+
const stripped = hostname.replace(wwwPrefixRegex, "");
|
|
54
|
+
return stripped.includes(".") ? stripped : hostname;
|
|
18
55
|
};
|
|
19
56
|
//#endregion
|
|
20
|
-
export { isHostOf, isSubdomainOf, parseUrl };
|
|
57
|
+
export { decodeSegment, isHostOf, isHostOrSubdomainOf, isHttpUrl, isSubdomainOf, parseUrl, stripWww };
|
package/dist/unwraps/aceml.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
import { createParamExtractor, decodeBase64 } from "../utils.mjs";
|
|
2
3
|
//#region src/unwraps/aceml.ts
|
|
3
4
|
const baseExtractor = createParamExtractor({
|
|
@@ -9,7 +10,7 @@ const unwrapAceml = (url) => {
|
|
|
9
10
|
const raw = baseExtractor(url);
|
|
10
11
|
if (!raw) return;
|
|
11
12
|
const decoded = decodeBase64(raw);
|
|
12
|
-
if (decoded && (decoded
|
|
13
|
+
if (decoded && isHttpUrl(decoded)) return decoded;
|
|
13
14
|
};
|
|
14
15
|
//#endregion
|
|
15
16
|
export { unwrapAceml };
|
package/dist/unwraps/adjust.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { isHostOf, isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
//#region src/unwraps/adjust.ts
|
|
2
3
|
const unwrapAdjust = (url) => {
|
|
3
|
-
if (url
|
|
4
|
+
if (!isHostOf(url, "app.adjust.com")) return;
|
|
4
5
|
const target = url.searchParams.get("redirect");
|
|
5
|
-
if (target
|
|
6
|
+
if (!target || !isHttpUrl(target)) return;
|
|
6
7
|
return target;
|
|
7
8
|
};
|
|
8
9
|
//#endregion
|
|
@@ -3,7 +3,9 @@ const amazonHostRegex = /\.amazon-adsystem\.com$/;
|
|
|
3
3
|
const amazonPathRegex = /^\/x\/c\/[^/]+\/(https?:\/\/.+)$/;
|
|
4
4
|
const unwrapAmazonAffiliate = (url) => {
|
|
5
5
|
if (!amazonHostRegex.test(url.hostname)) return;
|
|
6
|
-
|
|
6
|
+
const match = url.pathname.match(amazonPathRegex);
|
|
7
|
+
if (!match) return;
|
|
8
|
+
return `${match[1]}${url.search}${url.hash}`;
|
|
7
9
|
};
|
|
8
10
|
//#endregion
|
|
9
11
|
export { unwrapAmazonAffiliate };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isHostOrSubdomainOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
2
2
|
//#region src/unwraps/ampCache.ts
|
|
3
3
|
const httpsPathRegex = /^\/c\/s\/(.+)$/;
|
|
4
4
|
const httpPathRegex = /^\/c\/(?!s\/)(.+)$/;
|
|
5
5
|
const unwrapAmpCache = (url) => {
|
|
6
|
-
if (!
|
|
6
|
+
if (!isHostOrSubdomainOf(url, "cdn.ampproject.org")) return;
|
|
7
7
|
const httpsMatch = url.pathname.match(httpsPathRegex);
|
|
8
|
-
if (httpsMatch) return `https://${httpsMatch[1]}`;
|
|
8
|
+
if (httpsMatch) return `https://${httpsMatch[1]}${url.search}${url.hash}`;
|
|
9
9
|
const httpMatch = url.pathname.match(httpPathRegex);
|
|
10
|
-
if (httpMatch) return `http://${httpMatch[1]}`;
|
|
10
|
+
if (httpMatch) return `http://${httpMatch[1]}${url.search}${url.hash}`;
|
|
11
11
|
};
|
|
12
12
|
//#endregion
|
|
13
13
|
export { unwrapAmpCache };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
//#region src/unwraps/anonymTo.ts
|
|
2
3
|
const unwrapAnonymTo = (url) => {
|
|
3
|
-
if (url
|
|
4
|
-
|
|
4
|
+
if (!isHostOf(url, ["anonym.to", "www.anonym.to"])) return;
|
|
5
|
+
const target = url.search.slice(1);
|
|
6
|
+
if (!target) return;
|
|
7
|
+
return `${target}${url.hash}`;
|
|
5
8
|
};
|
|
6
9
|
//#endregion
|
|
7
10
|
export { unwrapAnonymTo };
|
package/dist/unwraps/bing.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
import { decodeBase64Url } from "../utils.mjs";
|
|
2
3
|
//#region src/unwraps/bing.ts
|
|
3
4
|
const bingHostRegex = /^(?:www\.|cn\.)?bing\.com$/;
|
|
@@ -7,7 +8,7 @@ const unwrapBing = (url) => {
|
|
|
7
8
|
const value = url.searchParams.get("u");
|
|
8
9
|
if (!value || !bingPrefixRegex.test(value)) return;
|
|
9
10
|
const decoded = decodeBase64Url(value.slice(2));
|
|
10
|
-
if (!decoded || !
|
|
11
|
+
if (!decoded || !isHttpUrl(decoded)) return;
|
|
11
12
|
return decoded;
|
|
12
13
|
};
|
|
13
14
|
//#endregion
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { isHostOrSubdomainOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
//#region src/unwraps/deviantartOutgoing.ts
|
|
2
3
|
const unwrapDeviantartOutgoing = (url) => {
|
|
3
|
-
if (!url
|
|
4
|
-
|
|
4
|
+
if (!isHostOrSubdomainOf(url, "deviantart.com") || !url.pathname.endsWith("/outgoing")) return;
|
|
5
|
+
const target = url.search.slice(1);
|
|
6
|
+
if (!target) return;
|
|
7
|
+
return `${target}${url.hash}`;
|
|
5
8
|
};
|
|
6
9
|
//#endregion
|
|
7
10
|
export { unwrapDeviantartOutgoing };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
//#region src/unwraps/feedsportal.ts
|
|
2
3
|
const feedsportalPathRegex = /\/([0-9A-Za-z]{20,})\/story01\.htm$/;
|
|
3
4
|
const feedsportalAlphabet = {
|
|
@@ -37,7 +38,7 @@ const unwrapFeedsportal = (url) => {
|
|
|
37
38
|
const substitution = head ? feedsportalAlphabet[head] : void 0;
|
|
38
39
|
return substitution === void 0 ? `0${chunk}` : substitution + chunk.slice(1);
|
|
39
40
|
}).join("");
|
|
40
|
-
if (!
|
|
41
|
+
if (!isHttpUrl(decoded)) return;
|
|
41
42
|
return decoded;
|
|
42
43
|
};
|
|
43
44
|
//#endregion
|
|
@@ -5,9 +5,9 @@ const httpPathRegex = /^\/amp\/(?!s\/)(.+)$/;
|
|
|
5
5
|
const unwrapGoogleAmpViewer = (url) => {
|
|
6
6
|
if (!googleAmpHostRegex.test(url.hostname)) return;
|
|
7
7
|
const httpsMatch = url.pathname.match(httpsPathRegex);
|
|
8
|
-
if (httpsMatch) return `https://${httpsMatch[1]}`;
|
|
8
|
+
if (httpsMatch) return `https://${httpsMatch[1]}${url.search}`;
|
|
9
9
|
const httpMatch = url.pathname.match(httpPathRegex);
|
|
10
|
-
if (httpMatch) return `http://${httpMatch[1]}`;
|
|
10
|
+
if (httpMatch) return `http://${httpMatch[1]}${url.search}`;
|
|
11
11
|
};
|
|
12
12
|
//#endregion
|
|
13
13
|
export { unwrapGoogleAmpViewer };
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { decodeBase64UrlBinary } from "../utils.mjs";
|
|
3
3
|
//#region src/unwraps/googleNewsModern.ts
|
|
4
4
|
const articleIdRegex = /^\/(?:rss\/)?articles\/([\w-]+)/;
|
|
5
|
-
const base64UrlMinusRegex = /-/g;
|
|
6
|
-
const base64UrlUnderscoreRegex = /_/g;
|
|
7
5
|
const protobufFramingRegex = /\x08\x13".+?(https?:\/\/[^\xd2]+)\xd2\x01/;
|
|
8
6
|
const unwrapGoogleNewsModern = (url) => {
|
|
9
7
|
if (!isHostOf(url, "news.google.com")) return;
|
|
10
8
|
const match = url.pathname.match(articleIdRegex);
|
|
11
9
|
if (!match) return;
|
|
12
|
-
|
|
13
|
-
return (decodeBase64Binary(padded)?.match(protobufFramingRegex))?.[1];
|
|
10
|
+
return (decodeBase64UrlBinary(match[1])?.match(protobufFramingRegex))?.[1];
|
|
14
11
|
};
|
|
15
12
|
//#endregion
|
|
16
13
|
export { unwrapGoogleNewsModern };
|
package/dist/unwraps/hrefLi.mjs
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
//#region src/unwraps/hrefLi.ts
|
|
2
3
|
const unwrapHrefLi = (url) => {
|
|
3
|
-
if (url
|
|
4
|
-
|
|
4
|
+
if (!isHostOf(url, ["href.li", "www.href.li"])) return;
|
|
5
|
+
const target = url.search.slice(1);
|
|
6
|
+
if (!target) return;
|
|
7
|
+
return `${target}${url.hash}`;
|
|
5
8
|
};
|
|
6
9
|
//#endregion
|
|
7
10
|
export { unwrapHrefLi };
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
+
import { decodeSegment, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
//#region src/unwraps/mozillaOutgoing.ts
|
|
2
3
|
const pathRegex = /^\/v1\/[0-9a-f]{64}\/(.+)$/;
|
|
3
|
-
const mozillaOutgoingHosts =
|
|
4
|
+
const mozillaOutgoingHosts = ["outgoing.prod.mozaws.net", "prod.outgoing.prod.webservices.mozgcp.net"];
|
|
4
5
|
const unwrapMozillaOutgoing = (url) => {
|
|
5
|
-
if (!
|
|
6
|
+
if (!isHostOf(url, mozillaOutgoingHosts)) return;
|
|
6
7
|
const match = url.pathname.match(pathRegex);
|
|
7
8
|
if (!match) return;
|
|
8
|
-
|
|
9
|
-
return decodeURIComponent(match[1]);
|
|
10
|
-
} catch {}
|
|
9
|
+
return decodeSegment(match[1]);
|
|
11
10
|
};
|
|
12
11
|
//#endregion
|
|
13
12
|
export { unwrapMozillaOutgoing };
|
package/dist/unwraps/nicoMs.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
//#region src/unwraps/nicoMs.ts
|
|
2
3
|
const nicoMsRegex = /^\/((?:sm|nm|so|im)\w+)$/;
|
|
3
4
|
const unwrapNicoMs = (url) => {
|
|
4
|
-
if (url
|
|
5
|
+
if (!isHostOf(url, "nico.ms")) return;
|
|
5
6
|
const match = url.pathname.match(nicoMsRegex);
|
|
6
7
|
if (!match) return;
|
|
7
8
|
const id = match[1];
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
import { decodeSegment, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
//#region src/unwraps/postmark.ts
|
|
2
3
|
const postmarkPathRegex = /^\/[23][st]\/([^/]+)\//;
|
|
3
4
|
const unwrapPostmark = (url) => {
|
|
4
|
-
if (url
|
|
5
|
+
if (!isHostOf(url, "click.pstmrk.it")) return;
|
|
5
6
|
const match = url.pathname.match(postmarkPathRegex);
|
|
6
7
|
if (!match) return;
|
|
7
|
-
|
|
8
|
-
return decodeURIComponent(match[1]);
|
|
9
|
-
} catch {}
|
|
8
|
+
return decodeSegment(match[1]);
|
|
10
9
|
};
|
|
11
10
|
//#endregion
|
|
12
11
|
export { unwrapPostmark };
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { decodeSegment } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
import { createParamExtractor } from "../utils.mjs";
|
|
2
3
|
//#region src/unwraps/proofpointV1.ts
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return
|
|
13
|
-
}
|
|
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
|
+
};
|
|
14
15
|
};
|
|
16
|
+
const unwrapProofpointV1 = createProofpointUnwrapper("/v1/url");
|
|
15
17
|
//#endregion
|
|
16
|
-
export { unwrapProofpointV1 };
|
|
18
|
+
export { createProofpointUnwrapper, unwrapProofpointV1 };
|
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createProofpointUnwrapper } from "./proofpointV1.mjs";
|
|
2
2
|
//#region src/unwraps/proofpointV2.ts
|
|
3
|
-
const
|
|
4
|
-
hosts: "urldefense.proofpoint.com",
|
|
5
|
-
path: "/v2/url",
|
|
6
|
-
params: ["u"]
|
|
7
|
-
});
|
|
8
|
-
const unwrapProofpointV2 = (url) => {
|
|
9
|
-
const raw = baseExtractor(url);
|
|
10
|
-
if (!raw) return;
|
|
11
|
-
try {
|
|
12
|
-
return decodeURIComponent(raw.replace(/-/g, "%").replace(/_/g, "/"));
|
|
13
|
-
} catch {}
|
|
14
|
-
};
|
|
3
|
+
const unwrapProofpointV2 = createProofpointUnwrapper("/v2/url");
|
|
15
4
|
//#endregion
|
|
16
5
|
export { unwrapProofpointV2 };
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
+
import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
import { decodeBase64Url, getUtf8ByteLength } from "../utils.mjs";
|
|
2
3
|
//#region src/unwraps/proofpointV3.ts
|
|
3
4
|
const v3PathRegex = /^\/v3\/__(.+)__;([^!]*)!/;
|
|
4
|
-
const
|
|
5
|
+
const v3Hosts = [
|
|
5
6
|
"urldefense.com",
|
|
6
7
|
"urldefense.proofpoint.com",
|
|
7
8
|
"urldefense.us"
|
|
8
|
-
]
|
|
9
|
-
const
|
|
10
|
-
const map = {};
|
|
11
|
-
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
12
|
-
for (let index = 0; index < 64; index += 1) map[alphabet[index]] = index + 2;
|
|
13
|
-
return map;
|
|
14
|
-
})();
|
|
9
|
+
];
|
|
10
|
+
const runLengthAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
15
11
|
const decodeReplacements = (mangled, replacementBase64) => {
|
|
16
12
|
if (replacementBase64.length === 0) return mangled;
|
|
17
13
|
const replacement = decodeBase64Url(replacementBase64);
|
|
@@ -19,11 +15,11 @@ const decodeReplacements = (mangled, replacementBase64) => {
|
|
|
19
15
|
const replacementChars = Array.from(replacement);
|
|
20
16
|
const urlChars = Array.from(mangled);
|
|
21
17
|
const result = [];
|
|
22
|
-
const
|
|
18
|
+
const markerRegex = /(?<!\*)\*(?!\*)|\*{2}[A-Za-z0-9\-_]/g;
|
|
23
19
|
let lastIndex = 0;
|
|
24
20
|
let savedBytes = 0;
|
|
25
21
|
let match;
|
|
26
|
-
match =
|
|
22
|
+
match = markerRegex.exec(mangled);
|
|
27
23
|
while (match !== null) {
|
|
28
24
|
const startChar = positionInChars(mangled, match.index);
|
|
29
25
|
const endChar = positionInChars(mangled, match.index + match[0].length);
|
|
@@ -33,7 +29,7 @@ const decodeReplacements = (mangled, replacementBase64) => {
|
|
|
33
29
|
if (next === void 0) return;
|
|
34
30
|
result.push(next);
|
|
35
31
|
} else {
|
|
36
|
-
let bytesToReplace =
|
|
32
|
+
let bytesToReplace = runLengthAlphabet.indexOf(match[0][2]) + 2;
|
|
37
33
|
if (savedBytes !== 0) {
|
|
38
34
|
bytesToReplace += savedBytes;
|
|
39
35
|
savedBytes = 0;
|
|
@@ -53,7 +49,7 @@ const decodeReplacements = (mangled, replacementBase64) => {
|
|
|
53
49
|
}
|
|
54
50
|
}
|
|
55
51
|
lastIndex = endChar;
|
|
56
|
-
match =
|
|
52
|
+
match = markerRegex.exec(mangled);
|
|
57
53
|
}
|
|
58
54
|
for (let charIndex = lastIndex; charIndex < urlChars.length; charIndex += 1) result.push(urlChars[charIndex]);
|
|
59
55
|
return result.join("");
|
|
@@ -69,7 +65,7 @@ const positionInChars = (source, codeUnitIndex) => {
|
|
|
69
65
|
return charIndex;
|
|
70
66
|
};
|
|
71
67
|
const unwrapProofpointV3 = (url) => {
|
|
72
|
-
if (!
|
|
68
|
+
if (!isHostOf(url, v3Hosts)) return;
|
|
73
69
|
const match = `${url.pathname}${url.search}`.match(v3PathRegex);
|
|
74
70
|
if (!match) return;
|
|
75
71
|
return decodeReplacements(match[1], match[2]);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isHttpUrl } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
import { createParamExtractor, decodeBase64 } from "../utils.mjs";
|
|
2
3
|
//#region src/unwraps/segmentfault.ts
|
|
3
4
|
const baseExtractor = createParamExtractor({
|
|
@@ -8,7 +9,7 @@ const unwrapSegmentfault = (url) => {
|
|
|
8
9
|
const raw = baseExtractor(url);
|
|
9
10
|
if (!raw) return;
|
|
10
11
|
const decoded = decodeBase64(raw);
|
|
11
|
-
if (decoded && (decoded
|
|
12
|
+
if (decoded && isHttpUrl(decoded)) return decoded;
|
|
12
13
|
};
|
|
13
14
|
//#endregion
|
|
14
15
|
export { unwrapSegmentfault };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import { decodeSegment, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
//#region src/unwraps/webArchive.ts
|
|
2
3
|
const pathRegex = /^\/web\/\d{14}\*?\/(.+)$/;
|
|
3
4
|
const unwrapWebArchive = (url) => {
|
|
4
|
-
if (url
|
|
5
|
+
if (!isHostOf(url, "web.archive.org")) return;
|
|
5
6
|
const match = url.pathname.match(pathRegex);
|
|
6
7
|
if (!match) return;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const target = decodeSegment(match[1]);
|
|
9
|
+
if (!target) return;
|
|
10
|
+
return `${target}${url.search}${url.hash}`;
|
|
10
11
|
};
|
|
11
12
|
//#endregion
|
|
12
13
|
export { unwrapWebArchive };
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
import { decodeSegment, isHostOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
1
2
|
//#region src/unwraps/yahooSearch.ts
|
|
2
3
|
const yahooPathRegex = /\/RU=([^/]+)\/RK=/;
|
|
3
4
|
const unwrapYahooSearch = (url) => {
|
|
4
|
-
if (url
|
|
5
|
+
if (!isHostOf(url, "r.search.yahoo.com")) return;
|
|
5
6
|
const match = url.pathname.match(yahooPathRegex);
|
|
6
7
|
if (!match) return;
|
|
7
|
-
|
|
8
|
-
return decodeURIComponent(match[1]);
|
|
9
|
-
} catch {}
|
|
8
|
+
return decodeSegment(match[1]);
|
|
10
9
|
};
|
|
11
10
|
//#endregion
|
|
12
11
|
export { unwrapYahooSearch };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { isHostOf } from "../node_modules/trousse/dist/urls.mjs";
|
|
2
|
+
//#region src/unwraps/yandexTranslate.ts
|
|
3
|
+
const proxyPathRegex = /^\/proxy_u\/[^/]+\/(?:(https?)\/)?(.+)$/;
|
|
4
|
+
const unwrapYandexTranslate = (url) => {
|
|
5
|
+
if (!isHostOf(url, "translated.turbopages.org")) return;
|
|
6
|
+
const match = url.pathname.match(proxyPathRegex);
|
|
7
|
+
if (!match) return;
|
|
8
|
+
return `${match[1] ?? "http"}://${match[2]}${url.search}${url.hash}`;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { unwrapYandexTranslate };
|
package/dist/utils.mjs
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
+
import { isAnyOf } from "./node_modules/trousse/dist/matching.mjs";
|
|
1
2
|
//#region src/utils.ts
|
|
2
|
-
const createHostMatcher = (hosts) => {
|
|
3
|
-
if (hosts instanceof RegExp) return (host) => hosts.test(host);
|
|
4
|
-
const hostSet = new Set(Array.isArray(hosts) ? hosts : [hosts]);
|
|
5
|
-
return (host) => hostSet.has(host);
|
|
6
|
-
};
|
|
7
3
|
const createParamExtractor = (config) => {
|
|
8
|
-
const matchesHost = createHostMatcher(config.hosts);
|
|
9
4
|
return (url) => {
|
|
10
|
-
if (!
|
|
5
|
+
if (!isAnyOf(url.hostname, config.hosts)) return;
|
|
11
6
|
if (config.path && url.pathname !== config.path) return;
|
|
12
7
|
for (const param of config.params) {
|
|
13
8
|
const value = url.searchParams.get(param);
|
|
@@ -28,11 +23,18 @@ const decodeBase64 = (value) => {
|
|
|
28
23
|
for (let index = 0; index < binary.length; index++) bytes[index] = binary.charCodeAt(index);
|
|
29
24
|
return utf8Decoder.decode(bytes);
|
|
30
25
|
};
|
|
26
|
+
const toBase64 = (base64Url) => {
|
|
27
|
+
return base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
28
|
+
};
|
|
31
29
|
const decodeBase64Url = (value) => {
|
|
32
|
-
return decodeBase64(value
|
|
30
|
+
return decodeBase64(toBase64(value));
|
|
31
|
+
};
|
|
32
|
+
const decodeBase64UrlBinary = (value) => {
|
|
33
|
+
return decodeBase64Binary(toBase64(value));
|
|
33
34
|
};
|
|
35
|
+
const utf8Encoder = new TextEncoder();
|
|
34
36
|
const getUtf8ByteLength = (value) => {
|
|
35
|
-
return
|
|
37
|
+
return utf8Encoder.encode(value).length;
|
|
36
38
|
};
|
|
37
39
|
//#endregion
|
|
38
|
-
export { createParamExtractor, decodeBase64, decodeBase64Binary, decodeBase64Url, getUtf8ByteLength };
|
|
40
|
+
export { createParamExtractor, decodeBase64, decodeBase64Binary, decodeBase64Url, decodeBase64UrlBinary, getUtf8ByteLength };
|
package/package.json
CHANGED