diff --git a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilderV2.swift b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilderV2.swift index a7d1c791e..0904e4f19 100644 --- a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilderV2.swift +++ b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilderV2.swift @@ -76,6 +76,7 @@ struct AttributedStringBuilderV2: AttributedStringBuilderProtocol { detectPhishingAttempts(mutableAttributedString) addLinksAndMentions(mutableAttributedString) addMatrixEntityPermalinkAttributesTo(mutableAttributedString) + removeParsingArtefacts(mutableAttributedString) let result = try? AttributedString(mutableAttributedString, including: \.elementX) Self.cacheValue(result, forKey: originalHTMLString, cacheKey: cacheKey) @@ -410,6 +411,18 @@ struct AttributedStringBuilderV2: AttributedStringBuilderProtocol { attributedString.addAttribute(.link, value: finalURL, range: range) } + + private func removeParsingArtefacts(_ attributedString: NSMutableAttributedString) { + guard attributedString.length > 0 else { + return + } + + // Ruma's markdown parsing sometimes inserts extra trailing new lines + // https://github.com/ruma/ruma/blob/c3dc6de3e03b2ca131eab889a9d310ef160b95ac/crates/ruma-events/src/room/message.rs#L962 + while (attributedString.string as NSString).hasSuffixCharacter(from: .whitespacesAndNewlines) { + attributedString.deleteCharacters(in: .init(location: attributedString.length - 1, length: 1)) + } + } } private struct TextParsingMatch { diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPad-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPad-en-GB.png index bf0c3ff37..8ab6484b5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPad-en-GB.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPad-en-GB.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34fb889080b10018db0941940782f5c46ccf0611bb6bbf8cd2cefa8c0492f2a0 -size 1110617 +oid sha256:bbe5650088750690bb31a4aaedbbee8e087222f86bf563fd3cb57e1a82f31e5e +size 1106686 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPad-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPad-pseudo.png index bf0c3ff37..8ab6484b5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPad-pseudo.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPad-pseudo.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34fb889080b10018db0941940782f5c46ccf0611bb6bbf8cd2cefa8c0492f2a0 -size 1110617 +oid sha256:bbe5650088750690bb31a4aaedbbee8e087222f86bf563fd3cb57e1a82f31e5e +size 1106686 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPhone-16-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPhone-16-en-GB.png index c91f788ac..6aedf2d0a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPhone-16-en-GB.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPhone-16-en-GB.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60a1a287bd3c02dad38031e4ccfeafac7fc734384034147fa9b421090321eb05 -size 1282490 +oid sha256:52ad9c6b5db4c5e876ef28aa019a3a75395c00d606daf56b961a43f10c6ae378 +size 1281081 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPhone-16-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPhone-16-pseudo.png index c91f788ac..6aedf2d0a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPhone-16-pseudo.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.v2-iPhone-16-pseudo.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60a1a287bd3c02dad38031e4ccfeafac7fc734384034147fa9b421090321eb05 -size 1282490 +oid sha256:52ad9c6b5db4c5e876ef28aa019a3a75395c00d606daf56b961a43f10c6ae378 +size 1281081 diff --git a/UnitTests/Sources/AttributedStringBuilderTests.swift b/UnitTests/Sources/AttributedStringBuilderTests.swift index cba7af986..763f8a0ff 100644 --- a/UnitTests/Sources/AttributedStringBuilderTests.swift +++ b/UnitTests/Sources/AttributedStringBuilderTests.swift @@ -35,7 +35,7 @@ class AttributedStringBuilderV1Tests: XCTestCase { } if AttributedStringBuilder.useNextGenHTMLParser { - XCTAssertEqual(String(attributedString.characters), "H1 Header\n\nH2 Header\n\nH3 Header\n\nH4 Header\n\nH5 Header\n\nH6 Header\n") + XCTAssertEqual(String(attributedString.characters), "H1 Header\n\nH2 Header\n\nH3 Header\n\nH4 Header\n\nH5 Header\n\nH6 Header") XCTAssertEqual(attributedString.runs.count, 11) // newlines hold no attributes @@ -172,32 +172,21 @@ class AttributedStringBuilderV1Tests: XCTestCase { return } + XCTAssertEqual(String(h1AttributedString.characters), "Matrix.org") + XCTAssertEqual(String(h2AttributedString.characters), "Matrix.org") + XCTAssertEqual(String(h3AttributedString.characters), "Matrix.org") + + XCTAssertEqual(h1AttributedString.runs.count, 1) + XCTAssertEqual(h2AttributedString.runs.count, 1) + XCTAssertEqual(h3AttributedString.runs.count, 1) + + XCTAssertEqual(h1Font, h2Font) + XCTAssertEqual(h2Font, h3Font) + if AttributedStringBuilder.useNextGenHTMLParser { - XCTAssertEqual(String(h1AttributedString.characters), "Matrix.org\n") - XCTAssertEqual(String(h2AttributedString.characters), "Matrix.org\n") - XCTAssertEqual(String(h3AttributedString.characters), "Matrix.org\n") - - XCTAssertEqual(h1AttributedString.runs.count, 2) - XCTAssertEqual(h2AttributedString.runs.count, 2) - XCTAssertEqual(h3AttributedString.runs.count, 2) - - XCTAssertEqual(h1Font, h2Font) - XCTAssertEqual(h2Font, h3Font) - XCTAssert(h1Font.pointSize > UIFont.preferredFont(forTextStyle: .body).pointSize) XCTAssert(h1Font.pointSize <= 23) } else { - XCTAssertEqual(String(h1AttributedString.characters), "Matrix.org") - XCTAssertEqual(String(h2AttributedString.characters), "Matrix.org") - XCTAssertEqual(String(h3AttributedString.characters), "Matrix.org") - - XCTAssertEqual(h1AttributedString.runs.count, 1) - XCTAssertEqual(h2AttributedString.runs.count, 1) - XCTAssertEqual(h3AttributedString.runs.count, 1) - - XCTAssertEqual(h1Font, h2Font) - XCTAssertEqual(h2Font, h3Font) - XCTAssert(h1Font.pointSize > UIFont.preferredFont(forTextStyle: .body).pointSize) XCTAssert(h1Font.pointSize <= maxHeaderPointSize) } @@ -267,11 +256,9 @@ class AttributedStringBuilderV1Tests: XCTestCase { return } - if AttributedStringBuilder.useNextGenHTMLParser { - XCTAssertEqual(attributedString.runs.count, 4) - } else { - XCTAssertEqual(attributedString.runs.count, 3) - + XCTAssertEqual(attributedString.runs.count, 3) + + if !AttributedStringBuilder.useNextGenHTMLParser { for run in attributedString.runs { XCTAssertEqual(run.uiKit.font?.familyName, UIFont.preferredFont(forTextStyle: .body).familyName) }