diff --git a/ElementX/Sources/Other/Extensions/String.swift b/ElementX/Sources/Other/Extensions/String.swift index d319ab666..10aa796d9 100644 --- a/ElementX/Sources/Other/Extensions/String.swift +++ b/ElementX/Sources/Other/Extensions/String.swift @@ -87,3 +87,27 @@ extension String { return "\(prefix(length))…" } } + +extension String { + func replacingHtmlBreaksOccurrences() -> String { + var result = self + let pattern = #"
(\n+)"#
+
+ guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
+ return result
+ }
+ let matches = regex.matches(in: self, options: [], range: NSRange(location: 0, length: utf16.count))
+
+ for match in matches.reversed() {
+ guard let range = Range(match.range, in: self),
+ let innerMatchRange = Range(match.range(at: 1), in: self) else {
+ continue
+ }
+ let numberOfBreaks = (self[innerMatchRange].components(separatedBy: "\n").count - 1)
+ let replacement = "
" + String(repeating: "
", count: numberOfBreaks)
+ result.replaceSubrange(range, with: replacement)
+ }
+
+ return result
+ }
+}
diff --git a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift
index 07192873b..943e1b364 100644
--- a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift
+++ b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift
@@ -73,14 +73,16 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
// that could happen with the default HTML renderer of NSAttributedString which is a
// webview.
func fromHTML(_ htmlString: String?) -> AttributedString? {
- guard let htmlString else {
+ guard var originalHTMLString = htmlString else {
return nil
}
- if let cached = Self.caches[cacheKey]?.value(forKey: htmlString) {
+ if let cached = Self.caches[cacheKey]?.value(forKey: originalHTMLString) {
return cached
}
+ let htmlString = originalHTMLString.replacingHtmlBreaksOccurrences()
+
guard let data = htmlString.data(using: .utf8) else {
return nil
}
diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift
index a1a48c99e..3464362cd 100644
--- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift
+++ b/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift
@@ -204,7 +204,8 @@ struct FormattedBodyText_Previews: PreviewProvider, TestablePreview {
Hello world
""",
"
This is a list
\ntest
\ntest
" ] let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder()) diff --git a/UnitTests/Sources/StringTests.swift b/UnitTests/Sources/StringTests.swift index 809f21b1b..b6920fa51 100644 --- a/UnitTests/Sources/StringTests.swift +++ b/UnitTests/Sources/StringTests.swift @@ -88,4 +88,27 @@ class StringTests: XCTestCase { func testEllipsizeNotNeeded() { XCTAssertEqual("ellipsize".ellipsize(length: 15), "ellipsize") } + + func testReplaceBreakOccurrences() { + let input0 = "" + let input1 = "
\n" + let input2 = "
\n\n" + let input3 = "
\n\n\n\n" + let input4 = "
a
\nb
" + let input5 = "empty" + + let expectedOutput0 = input0 + let expectedOutput1 = "a
b