Fall back to Foundation URL if WebURL parsing fails

WebURL doesn't support Unicode domains/IDNA
This commit is contained in:
Shadowfacts 2022-05-17 11:57:59 -04:00
parent 2617d22819
commit f106cc78bb
5 changed files with 46 additions and 6 deletions

View File

@ -35,8 +35,7 @@ public class Hashtag: Codable {
throw DecodingError.dataCorruptedError(forKey: .url, in: container, debugDescription: "unable to convert WebURL \(s?.debugDescription ?? "nil") to URL") throw DecodingError.dataCorruptedError(forKey: .url, in: container, debugDescription: "unable to convert WebURL \(s?.debugDescription ?? "nil") to URL")
} }
} catch { } catch {
let s = try? container.decode(String.self, forKey: .url) self.url = try container.decode(URL.self, forKey: .url)
throw DecodingError.dataCorruptedError(forKey: .url, in: container, debugDescription: "unable to decode WebURL from \(s?.debugDescription ?? "nil")")
} }
self.history = try container.decodeIfPresent([History].self, forKey: .history) self.history = try container.decodeIfPresent([History].self, forKey: .history)
} }

View File

@ -8,14 +8,33 @@
import Foundation import Foundation
import WebURL import WebURL
import WebURLFoundationExtras
public class Mention: Codable { public class Mention: Codable {
public let url: WebURL public let url: URL
public let username: String public let username: String
public let acct: String public let acct: String
/// The instance-local ID of the user being mentioned. /// The instance-local ID of the user being mentioned.
public let id: String public let id: String
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.username = try container.decode(String.self, forKey: .username)
self.acct = try container.decode(String.self, forKey: .acct)
self.id = try container.decode(String.self, forKey: .id)
do {
let webURL = try container.decode(WebURL.self, forKey: .url)
if let url = URL(webURL) {
self.url = url
} else {
let s = try? container.decode(String.self, forKey: .url)
throw DecodingError.dataCorruptedError(forKey: .url, in: container, debugDescription: "unable to convert WebURL \(s?.debugDescription ?? "nil") to URL")
}
} catch {
self.url = try container.decode(URL.self, forKey: .url)
}
}
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case url case url
case username case username

View File

@ -0,0 +1,20 @@
//
// URLTests.swift
//
//
// Created by Shadowfacts on 5/17/22.
//
import XCTest
import WebURL
import WebURLFoundationExtras
class URLTests: XCTestCase {
func testDecodeURL() {
print(WebURL(URL(string: "https://xn--baw-joa.social/@unituebingen")!))
let url = WebURL("https://xn--baw-joa.social/@unituebingen")
print(url)
}
}

View File

@ -108,10 +108,12 @@ class ContentTextView: LinkTextView, BaseEmojiLabel {
// screws up its determination of the line height making multiple lines of emojis squash together // screws up its determination of the line height making multiple lines of emojis squash together
attributed.append(NSAttributedString(string: "\n", attributes: [.font: defaultFont])) attributed.append(NSAttributedString(string: "\n", attributes: [.font: defaultFont]))
case "a": case "a":
if let link = try? node.attr("href"), let href = try! node.attr("href")
let webURL = WebURL(link), if let webURL = WebURL(href),
let url = URL(webURL) { let url = URL(webURL) {
attributed.addAttribute(.link, value: url, range: attributed.fullRange) attributed.addAttribute(.link, value: url, range: attributed.fullRange)
} else if let url = URL(string: href) {
attributed.addAttribute(.link, value: url, range: attributed.fullRange)
} }
case "p": case "p":
attributed.append(NSAttributedString(string: "\n\n", attributes: [.font: defaultFont])) attributed.append(NSAttributedString(string: "\n\n", attributes: [.font: defaultFont]))

View File

@ -27,7 +27,7 @@ class StatusContentTextView: ContentTextView {
let status = mastodonController.persistentContainer.status(for: statusID) { let status = mastodonController.persistentContainer.status(for: statusID) {
mention = status.mentions.first { (mention) in mention = status.mentions.first { (mention) in
// Mastodon and Pleroma include the @ in the <a> text, GNU Social does not // Mastodon and Pleroma include the @ in the <a> text, GNU Social does not
(text.dropFirst() == mention.username || text == mention.username) && url.host == mention.url.host!.serialized (text.dropFirst() == mention.username || text == mention.username) && url.host == mention.url.host!
} }
} else { } else {
mention = nil mention = nil