MCPcopy Create free account
hub / github.com/scriptscat/scriptcat / prettyUrl

Function prettyUrl

src/pkg/utils/url-utils.ts:7–71  ·  view source on GitHub ↗
(s: string | undefined | null, baseUrl?: string)

Source from the content-addressed store, hash-verified

5 * 把编码URL变成使用者可以阅读的格式
6 */
7export const prettyUrl = (s: string | undefined | null, baseUrl?: string): string => {
8 if (!s) return "";
9
10 const EXTRA = {
11 DECODE_URI: 0,
12 DECODE_COMP: 1,
13 PRESERVE_Q: 2,
14 PRESERVE_H: 4,
15 PRESERVE_A: 8,
16 } as const;
17 const safeDecode = (val: string, extra: number) => {
18 try {
19 const decodeFn = extra & EXTRA.DECODE_COMP ? decodeURIComponent : decodeURI;
20 let decoded = decodeFn(val);
21 // Re-encode delimiters to prevent breaking the URL structure
22 if (extra & EXTRA.PRESERVE_Q) decoded = decoded.replace(/[=&\s]/g, encodeURIComponent);
23 if (extra & EXTRA.PRESERVE_H) decoded = decoded.replace(/\s/g, encodeURIComponent);
24 if (extra & EXTRA.PRESERVE_A) decoded = decoded.replace(/[=&:@/\\\s]/g, encodeURIComponent);
25 return decoded;
26 } catch {
27 return val;
28 }
29 };
30
31 try {
32 const u = new URL(s, baseUrl);
33
34 // 1. Core components: Protocol, Punycode Host, and Port
35 const protocol = u.protocol ? `${u.protocol}//` : "";
36 const host = u.hostname
37 .split(".")
38 .map((p) => {
39 try {
40 return p.startsWith("xn--") ? decodePunycode(p) : p;
41 } catch {
42 // punycode 解码失败时回退到原始 label,避免整个 prettyUrl 失败
43 return p;
44 }
45 })
46 .join(".");
47 const port = u.port ? `:${u.port}` : "";
48
49 // 2. Decode Path and Hash safely
50 const path = safeDecode(u.pathname, EXTRA.DECODE_URI);
51 let hash = safeDecode(u.hash, EXTRA.DECODE_URI | EXTRA.PRESERVE_H);
52 if (!hash && s.endsWith("#")) hash = "#";
53
54 // 3. Search Params: Decode key/value pairs while escaping delimiters
55 const params = Array.from(new URLSearchParams(u.search));
56 const m = params.map(
57 ([k, v]) =>
58 `${safeDecode(k, EXTRA.DECODE_COMP | EXTRA.PRESERVE_Q)}=${safeDecode(v, EXTRA.DECODE_COMP | EXTRA.PRESERVE_Q)}`
59 );
60 const search = params.length ? `?${m.join("&")}` : "";
61
62 // 4. Auth: User and Password
63 const user = safeDecode(u.username, EXTRA.DECODE_COMP | EXTRA.PRESERVE_A);
64 const pass = safeDecode(u.password, EXTRA.DECODE_COMP | EXTRA.PRESERVE_A);

Callers 2

ScriptInstallViewFunction · 0.90
url-utils.test.tsFile · 0.90

Calls 2

decodePunycodeFunction · 0.90
safeDecodeFunction · 0.85

Tested by

no test coverage detected