forked from quoid/userscripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUrlPolyfill.swift
More file actions
105 lines (101 loc) · 3.8 KB
/
Copy pathUrlPolyfill.swift
File metadata and controls
105 lines (101 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import Foundation
extension CharacterSet {
// https://developer.apple.com/documentation/foundation/characterset#2902136
public static let urlAllowed_ = CharacterSet(charactersIn: "#")
.union(.urlFragmentAllowed)
.union(.urlHostAllowed)
.union(.urlPasswordAllowed)
.union(.urlPathAllowed)
.union(.urlQueryAllowed)
.union(.urlUserAllowed)
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI
func encodeURI(_ uri: String) -> String {
// https://developer.apple.com/documentation/foundation/characterset#2902136
// var urlAllowed = CharacterSet(charactersIn: "#")
// urlAllowed.formUnion(.urlFragmentAllowed)
// urlAllowed.formUnion(.urlHostAllowed)
// urlAllowed.formUnion(.urlPasswordAllowed)
// urlAllowed.formUnion(.urlPathAllowed)
// urlAllowed.formUnion(.urlQueryAllowed)
// urlAllowed.formUnion(.urlUserAllowed)
return uri.addingPercentEncoding(withAllowedCharacters: .urlAllowed_) ?? uri
}
func fixedURL(string urlString: String) -> URL? {
let rawUrlString = urlString.removingPercentEncoding ?? urlString
var url: URL?
if #available(macOS 14.0, iOS 17.0, *) {
url = URL(string: rawUrlString, encodingInvalidCharacters: true)
} else {
url = URL(string: encodeURI(rawUrlString))
}
return url
}
// https://developer.mozilla.org/en-US/docs/Web/API/URL
func jsLikeURL(_ urlString: String, baseString: String? = nil) -> [String: String]? {
var _url: URL?
if let baseString = baseString {
guard let baseUrl = fixedURL(string: baseString) else {
return nil
}
_url = URL(string: urlString, relativeTo: baseUrl)
} else {
_url = fixedURL(string: urlString)
}
guard let url = _url else {
return nil
}
guard let scheme = url.scheme else {
return nil
}
var port = ""
if let portInt = url.port { port = String(portInt) }
if (scheme == "http" && port == "80") { port = "" }
if (scheme == "https" && port == "443") { port = "" }
/*
The issue still exists as of macOS 14.4, iOS 17.0
https://stackoverflow.com/questions/74445926/url-host-deprecated-but-replacement-crashes
https://forums.swift.org/t/does-url-query-percentencoded-calls-url-host-percentencoded-under-the-hood/70452
https://forums.developer.apple.com/forums/thread/722451
*/
if #available(macOS 15.0, iOS 18.0, *) {
guard let hostname = url.host(percentEncoded: true) else { return nil }
let host = (port == "") ? hostname : "\(hostname):\(port)"
let query = url.query(percentEncoded: true) ?? ""
let fragment = url.fragment(percentEncoded: true) ?? ""
return [
"hash": fragment == "" ? "" : "#\(fragment)",
"host": host,
"hostname": hostname,
// "href": url.absoluteString,
"origin": "\(scheme)://\(host)",
"password": url.password(percentEncoded: true) ?? "",
"pathname": url.path(percentEncoded: true),
"port": port,
"protocol": "\(scheme):",
"search": query == "" ? "" : "?\(query)",
"username": url.user(percentEncoded: true) ?? ""
]
} else {
guard let hostname = url.host else { return nil }
let host = (port == "") ? hostname : "\(hostname):\(port)"
let query = url.query ?? ""
let fragment = url.fragment ?? ""
/// If the path has a trailing slash, it is stripped. https://developer.apple.com/documentation/foundation/nsurl/1408809-path
let strippedPath = url.path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? url.path
let pathname = (strippedPath != "/" && url.hasDirectoryPath) ? "\(strippedPath)/" : strippedPath
return [
"hash": fragment == "" ? "" : "#\(fragment)",
"host": host,
"hostname": hostname,
// "href": url.absoluteString,
"origin": "\(scheme)://\(host)",
"password": url.password ?? "",
"pathname": pathname,
"port": port,
"protocol": "\(scheme):",
"search": query == "" ? "" : "?\(query)",
"username": url.user?.addingPercentEncoding(withAllowedCharacters: .urlUserAllowed) ?? ""
]
}
}