import Foundation /// The pulls and issues a Markdown text names by their `at://` URIs, as the /// server links them: read from the HTML it made of the text, where each one /// of the repository's is a link to its page, a bare one showing its title. /// One the server didn't link, as another repository's, stays as written. struct MarkdownReferences: Hashable, Sendable { /// The title of each the server linked, by its URI. var titles: [String: String] = [:] /// Each the server linked, a bare one or a link's target. var known: Set = [] /// What a link to a pull or issue the app opens itself points at. static let scheme = "knotless-thread" init() {} init(html: String, source: String) { for found in html.matches(of: #/(.*?)/#.dotMatchesNewlines()) { let uri = "at://\(found.output.2)/dev.knotless.\(found.output.1)/\(found.output.3)" known.insert(uri) let title = MarkdownFences.unescaped(String(found.output.4).replacing(#/<[^>]*>/#, with: "")) // Where the text links the URI itself, those are its own words, not the title. if titles[uri] == nil, !source.contains("[\(title)](\(uri)") { titles[uri] = title } } } /// `text` with each `at://` URI the server linked made a link the app opens: /// a bare one showing its title, as the pages show it. Not in code. func linked(_ text: String) -> String { guard !known.isEmpty, text.contains("at://") else { return text } var out = "" var done = text.startIndex var from = text.startIndex while let found = text[from...].range(of: "at://") { from = found.upperBound let at = found.lowerBound let before = text[..()[]\"'`".contains($0) } ?? rest.endIndex while end > at, ".,;:!?".contains(text[text.index(before: end)]) { end = text.index(before: end) } let uri = String(text[at.. String? { if url.scheme == scheme { return url.absoluteString.dropFirst(scheme.count + 1).removingPercentEncoding } guard url.scheme == "https", url.host() == URL(string: MarkdownPlace.site)?.host() else { return nil } let p = url.path(percentEncoded: false).split(separator: "/").map(String.init) guard p.count == 5, [repo.handle, repo.did].contains(p[0]), p[1] == repo.name, ["issue", "pull"].contains(p[2]), p[3].hasPrefix("did:") else { return nil } return "at://\(p[3])/dev.knotless.\(p[2])/\(p[4])" } private static func target(_ uri: String) -> String { "\(scheme):" + (uri.addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? uri) } private static func escaped(_ title: String) -> String { var out = "" for c in title { if "\\`*_[]<>!~".contains(c) { out.append("\\") } out.append(c) } return out } }