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
|
import Foundation
enum SRHTWebURL {
static func repository(_ repository: RepositorySummary) -> URL? {
userScopedURL(
host: "\(repository.service.rawValue).sr.ht",
ownerCanonicalName: repository.owner.canonicalName,
pathComponents: [repository.name]
)
}
static func build(jobId: Int, ownerCanonicalName: String) -> URL? {
userScopedURL(
host: "builds.sr.ht",
ownerCanonicalName: ownerCanonicalName,
pathComponents: ["job", String(jobId)]
)
}
static func tracker(ownerUsername: String, trackerName: String) -> URL? {
userScopedURL(
host: "todo.sr.ht",
ownerUsername: ownerUsername,
pathComponents: [trackerName]
)
}
static func ticket(ownerUsername: String, trackerName: String, ticketId: Int) -> URL? {
userScopedURL(
host: "todo.sr.ht",
ownerUsername: ownerUsername,
pathComponents: [trackerName, String(ticketId)]
)
}
static func profile(canonicalName: String) -> URL? {
userScopedURL(
host: "meta.sr.ht",
ownerCanonicalName: canonicalName,
pathComponents: []
)
}
private static func userScopedURL(
host: String,
ownerCanonicalName: String,
pathComponents: [String]
) -> URL? {
userScopedURL(
host: host,
ownerUsername: username(from: ownerCanonicalName),
pathComponents: pathComponents
)
}
private static func userScopedURL(
host: String,
ownerUsername: String,
pathComponents: [String]
) -> URL? {
var components = URLComponents()
components.scheme = "https"
components.host = host
let encodedComponents = (["~\(ownerUsername)"] + pathComponents).map { pathComponent in
pathComponent.addingPercentEncoding(withAllowedCharacters: pathComponentCharacterSet) ?? pathComponent
}
components.percentEncodedPath = "/" + encodedComponents.joined(separator: "/")
return components.url
}
private static func username(from canonicalName: String) -> String {
if canonicalName.hasPrefix("~") {
return String(canonicalName.dropFirst())
}
return canonicalName
}
private static let pathComponentCharacterSet: CharacterSet = {
var characterSet = CharacterSet.urlPathAllowed
characterSet.remove(charactersIn: "/")
return characterSet
}()
}
|