Prevent links from showing up in color within code blocks, simplify foreground color stripping

This commit is contained in:
Stefan Ceriu 2024-05-10 10:36:20 +03:00 committed by Stefan Ceriu
parent a401976b2b
commit 099b69d2f2
2 changed files with 14 additions and 23 deletions

View File

@ -49,9 +49,9 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
} }
let mutableAttributedString = NSMutableAttributedString(string: string) let mutableAttributedString = NSMutableAttributedString(string: string)
removeDefaultForegroundColors(mutableAttributedString)
addLinksAndMentions(mutableAttributedString) addLinksAndMentions(mutableAttributedString)
detectPermalinks(mutableAttributedString) detectPermalinks(mutableAttributedString)
removeLinkColors(mutableAttributedString)
let result = try? AttributedString(mutableAttributedString, including: \.elementX) let result = try? AttributedString(mutableAttributedString, including: \.elementX)
Self.cacheValue(result, forKey: string, cacheKey: cacheKey) Self.cacheValue(result, forKey: string, cacheKey: cacheKey)
@ -105,12 +105,11 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
} }
let mutableAttributedString = NSMutableAttributedString(attributedString: attributedString) let mutableAttributedString = NSMutableAttributedString(attributedString: attributedString)
removeDefaultForegroundColor(mutableAttributedString) removeDefaultForegroundColors(mutableAttributedString)
addLinksAndMentions(mutableAttributedString) addLinksAndMentions(mutableAttributedString)
replaceMarkedBlockquotes(mutableAttributedString) replaceMarkedBlockquotes(mutableAttributedString)
replaceMarkedCodeBlocks(mutableAttributedString) replaceMarkedCodeBlocks(mutableAttributedString)
detectPermalinks(mutableAttributedString) detectPermalinks(mutableAttributedString)
removeLinkColors(mutableAttributedString)
removeDTCoreTextArtifacts(mutableAttributedString) removeDTCoreTextArtifacts(mutableAttributedString)
let result = try? AttributedString(mutableAttributedString, including: \.elementX) let result = try? AttributedString(mutableAttributedString, including: \.elementX)
@ -140,12 +139,8 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
return result return result
} }
private func removeDefaultForegroundColor(_ attributedString: NSMutableAttributedString) { private func removeDefaultForegroundColors(_ attributedString: NSMutableAttributedString) {
attributedString.enumerateAttribute(.foregroundColor, in: .init(location: 0, length: attributedString.length), options: []) { value, range, _ in attributedString.removeAttribute(.foregroundColor, range: .init(location: 0, length: attributedString.length))
if value as? UIColor == UIColor.black {
attributedString.removeAttribute(.foregroundColor, range: range)
}
}
} }
private func addLinksAndMentions(_ attributedString: NSMutableAttributedString) { private func addLinksAndMentions(_ attributedString: NSMutableAttributedString) {
@ -293,14 +288,6 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
} }
} }
private func removeLinkColors(_ attributedString: NSMutableAttributedString) {
attributedString.enumerateAttribute(.link, in: .init(location: 0, length: attributedString.length), options: []) { value, range, _ in
if value != nil {
attributedString.removeAttribute(.foregroundColor, range: range)
}
}
}
private func removeDTCoreTextArtifacts(_ attributedString: NSMutableAttributedString) { private func removeDTCoreTextArtifacts(_ attributedString: NSMutableAttributedString) {
guard attributedString.length > 0 else { guard attributedString.length > 0 else {
return return

View File

@ -206,16 +206,18 @@ class AttributedStringBuilderTests: XCTestCase {
checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: expectedLink.absoluteString, expectedRuns: 3) checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: expectedLink.absoluteString, expectedRuns: 3)
checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: expectedLink.absoluteString, expectedRuns: 3) checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: expectedLink.absoluteString, expectedRuns: 3)
} }
// `Plain link in codeblock: https://www.matrix.org`, Link tag in codeblock: <a href=\"https://www.matrix.org/\">link</a>, plain link: https://www.matrix.org, link tag: <a href=\"https://www.matrix.org/\">link</a>
func testDefaultFont() { func testDefaultFont() {
let htmlString = "<b>Test</b> <i>string</i>." let htmlString = "<b>Test</b> <i>string</i> "
guard let attributedString = attributedStringBuilder.fromHTML(htmlString) else { guard let attributedString = attributedStringBuilder.fromHTML(htmlString) else {
XCTFail("Could not build the attributed string") XCTFail("Could not build the attributed string")
return return
} }
XCTAssertEqual(attributedString.runs.count, 4) XCTAssertEqual(attributedString.runs.count, 3)
for run in attributedString.runs { for run in attributedString.runs {
XCTAssertEqual(run.uiKit.font?.familyName, UIFont.preferredFont(forTextStyle: .body).familyName) XCTAssertEqual(run.uiKit.font?.familyName, UIFont.preferredFont(forTextStyle: .body).familyName)
@ -223,14 +225,14 @@ class AttributedStringBuilderTests: XCTestCase {
} }
func testDefaultForegroundColor() { func testDefaultForegroundColor() {
let htmlString = "<b>Test</b> <i>string</i>." let htmlString = "<b>Test</b> <i>string</i> <a href=\"https://www.matrix.org/\">link</a> <code><a href=\"https://www.matrix.org/\">link</a></code>"
guard let attributedString = attributedStringBuilder.fromHTML(htmlString) else { guard let attributedString = attributedStringBuilder.fromHTML(htmlString) else {
XCTFail("Could not build the attributed string") XCTFail("Could not build the attributed string")
return return
} }
XCTAssertEqual(attributedString.runs.count, 4) XCTAssertEqual(attributedString.runs.count, 7)
for run in attributedString.runs { for run in attributedString.runs {
XCTAssertNil(run.uiKit.foregroundColor) XCTAssertNil(run.uiKit.foregroundColor)
@ -246,16 +248,18 @@ class AttributedStringBuilderTests: XCTestCase {
return return
} }
XCTAssertEqual(attributedString.runs.count, 8) XCTAssertEqual(attributedString.runs.count, 3)
var foundLink = false var foundLink = false
// Foreground colors should be completely stripped from the attributed string
// letting UI components chose the defaults (e.g. tintColor)
for run in attributedString.runs { for run in attributedString.runs {
if run.link != nil { if run.link != nil {
XCTAssertEqual(run.link?.host, "www.matrix.org") XCTAssertEqual(run.link?.host, "www.matrix.org")
XCTAssertNil(run.uiKit.foregroundColor) XCTAssertNil(run.uiKit.foregroundColor)
foundLink = true foundLink = true
} else { } else {
XCTAssertNotNil(run.uiKit.foregroundColor) XCTAssertNil(run.uiKit.foregroundColor)
} }
} }