• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hexojs / hexo-util / 16651986209

31 Jul 2025 02:35PM UTC coverage: 73.036% (-23.8%) from 96.875%
16651986209

Pull #426

github

web-flow
Merge e24598988 into d497bc760
Pull Request #426: build: restructure for dual ESM/CJS output, update tooling, and enhance utilities

811 of 1128 branches covered (71.9%)

1594 of 2028 new or added lines in 40 files covered. (78.6%)

6 existing lines in 1 file now uncovered.

5290 of 7243 relevant lines covered (73.04%)

69.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.47
/lib/decode_url.ts
1
import { punycode } from './_punycode.js';
2✔
2

2✔
3
function safeDecodeURIComponent(str: string) {
26✔
4
  try {
26✔
5
    return decodeURIComponent(str);
26✔
6
  } catch {
26!
NEW
7
    return str;
×
NEW
8
  }
×
9
}
26✔
10

2✔
11
export const decodeURL = (str: string) => {
2✔
12
  // Handle data URLs
17✔
13
  if (/^data:/i.test(str)) return str;
17✔
14

16✔
15
  // Try absolute URL
16✔
16
  try {
16✔
17
    const url = new URL(str);
16✔
18
    // Convert punycode host to Unicode if needed
16✔
19
    const unicodeHost = punycode.toUnicode(url.hostname);
16✔
20
    // Decode pathname only if not already decoded
16✔
21
    const pathname = safeDecodeURIComponent(url.pathname);
16✔
22
    // Decode search params
16✔
23
    let search = '';
16✔
24
    if (url.search) {
17✔
25
      const params = new URLSearchParams(url.search);
3✔
26
      const decodedParams = [];
3✔
27
      for (const [key, value] of params.entries()) {
3✔
28
        decodedParams.push(`${safeDecodeURIComponent(key)}=${safeDecodeURIComponent(value)}`);
4✔
29
      }
4✔
30
      search = decodedParams.length ? '?' + decodedParams.join('&') : '';
3!
31
    }
3✔
32
    // Decode hash
11✔
33
    const hash = url.hash ? '#' + safeDecodeURIComponent(url.hash.slice(1)) : '';
17✔
34
    // Rebuild URL string manually to preserve Unicode hostname
17✔
35
    let result = url.protocol + '//';
17✔
36
    if (url.username || url.password) {
17✔
37
      result += url.username;
1✔
38
      if (url.password) result += ':' + url.password;
1✔
39
      result += '@';
1✔
40
    }
1✔
41
    result += unicodeHost;
11✔
42
    if (url.port) result += ':' + url.port;
17✔
43
    result += pathname + search + hash;
11✔
44
    // Remove trailing slash for file URLs if not present in input
11✔
45
    if (/^file:/i.test(str) && !/\/$/.test(str)) {
17!
NEW
46
      result = result.replace(/\/$/, '');
×
NEW
47
    }
×
48
    return result;
11✔
49
  } catch {
17✔
50
    // Not an absolute URL, try relative path or fragment
5✔
51
    // Handle hash only
5✔
52
    if (str.startsWith('#')) {
5✔
53
      return '#' + safeDecodeURIComponent(str.slice(1));
1✔
54
    }
1✔
55
    // Handle relative path with query/hash
4✔
56
    const [path, search = ''] = str.split('?');
4✔
57
    const [pathname, hash = ''] = search.split('#');
4✔
58
    let decoded = safeDecodeURIComponent(path);
4✔
59
    if (pathname) {
5!
NEW
60
      decoded += '?' + safeDecodeURIComponent(pathname);
×
NEW
61
    }
×
62
    if (hash) {
5!
NEW
63
      decoded += '#' + safeDecodeURIComponent(hash);
×
NEW
64
    }
×
65
    return decoded;
4✔
66
  }
4✔
67
};
17✔
68

2✔
69
// For ESM compatibility
2✔
70
export default decodeURL;
2✔
71
// For CommonJS compatibility
2✔
72
if (typeof module !== 'undefined' && typeof module.exports === 'object' && module.exports !== null) {
2!
73
  module.exports = decodeURL;
1✔
74
  // For ESM compatibility
1✔
75
  module.exports.default = decodeURL;
1✔
76
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc