Skip to content

Commit

Permalink
Fixes #687 - Incorrect link detection and handling
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanceriu committed Apr 28, 2023
1 parent 18766d5 commit 3fb0829
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
var matches = MatrixEntityRegex.userIdentifierRegex.matches(in: string, options: [])
matches.append(contentsOf: MatrixEntityRegex.roomIdentifierRegex.matches(in: string, options: []))
// As of right now we do not handle event id links in any way so there is no need to add them as links
// matches.append(contentsOf: MatrixEntityRegex.eventIdentifierRegex.matches(in: string, options: []))
// matches.append(contentsOf: MatrixEntityRegex.eventIdentifierRegex.matches(in: string, options: []))
matches.append(contentsOf: MatrixEntityRegex.roomAliasRegex.matches(in: string, options: []))
matches.append(contentsOf: MatrixEntityRegex.linkRegex.matches(in: string, options: []))

guard matches.count > 0 else {
return
}

matches.forEach { match in
// Sort the links by length so the longest one always takes priority
matches.sorted { $0.range.length > $1.range.length }.forEach { match in
guard let matchRange = Range(match.range, in: string) else {
return
}
Expand All @@ -161,8 +161,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
return
}

let link = string[matchRange].addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
attributedString.addAttribute(.link, value: link as Any, range: match.range)
attributedString.addAttribute(.link, value: string[matchRange] as Any, range: match.range)
}
}

Expand Down
30 changes: 21 additions & 9 deletions UnitTests/Sources/AttributedStringBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,25 +159,37 @@ class AttributedStringBuilderTests: XCTestCase {
XCTAssertNil(attributedString.uiKit.attachment, "iFrame attachments should be removed as they're not included in the allowedHTMLTags array.")
}

func testLinkWithFragment() {
let string = "https://example.com/#/"
checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: string, expectedRuns: 1)
checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: string, expectedRuns: 1)
}

func testPermalink() {
let string = "https://matrix.to/#/!hello:matrix.org/$world?via=matrix.org"
checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: string, expectedRuns: 1)
checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: string, expectedRuns: 1)
}

func testUserIdLink() {
let userId = "@user:matrix.org"
let string = "The user is \(userId)."
checkMatrixEntityLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expected: userId)
checkMatrixEntityLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expected: userId)
checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: userId, expectedRuns: 3)
checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: userId, expectedRuns: 3)
}

func testRoomAliasLink() {
let roomAlias = "#matrix:matrix.org"
let string = "The room alias is \(roomAlias)."
checkMatrixEntityLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expected: roomAlias)
checkMatrixEntityLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expected: roomAlias)
checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: roomAlias, expectedRuns: 3)
checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: roomAlias, expectedRuns: 3)
}

func testRoomIdLink() {
let roomId = "!roomidentifier:matrix.org"
let string = "The room is \(roomId)."
checkMatrixEntityLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expected: roomId)
checkMatrixEntityLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expected: roomId)
checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: roomId, expectedRuns: 3)
checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: roomId, expectedRuns: 3)
}

// As of right now we do not handle event id links in any way so there is no need to add them as links
Expand Down Expand Up @@ -390,16 +402,16 @@ class AttributedStringBuilderTests: XCTestCase {

// MARK: - Private

private func checkMatrixEntityLinkIn(attributedString: AttributedString?, expected: String) {
private func checkLinkIn(attributedString: AttributedString?, expectedLink: String, expectedRuns: Int) {
guard let attributedString else {
XCTFail("Could not build the attributed string")
return
}

XCTAssertEqual(attributedString.runs.count, 3)
XCTAssertEqual(attributedString.runs.count, expectedRuns)

for run in attributedString.runs where run.link != nil {
XCTAssertEqual(run.link?.path, expected)
XCTAssertEqual(run.link?.absoluteString, expectedLink)
return
}

Expand Down
1 change: 1 addition & 0 deletions changelog.d/687.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed incorrect link detection and handling in the timeline

1 comment on commit 3fb0829

@habi
Copy link
Contributor

@habi habi commented on 3fb0829 Apr 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for that fix!

Please sign in to comment.