diff --git a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift index e6e0285f2..b42e9e463 100644 --- a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift +++ b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift @@ -84,9 +84,9 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol { removeDefaultForegroundColor(mutableAttributedString) addLinks(mutableAttributedString) removeLinkColors(mutableAttributedString) - removeDTCoreTextArtifacts(mutableAttributedString) replaceMarkedBlockquotes(mutableAttributedString) replaceMarkedCodeBlocks(mutableAttributedString) + removeDTCoreTextArtifacts(mutableAttributedString) return try? AttributedString(mutableAttributedString, including: \.elementX) } @@ -95,10 +95,17 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol { guard let attributedString = attributedString else { return nil } - + return attributedString.runs[\.blockquote].map { (value, range) in - AttributedStringBuilderComponent(attributedString: AttributedString(attributedString[range]), - isBlockquote: value != nil) + var attributedString = AttributedString(attributedString[range]) + + // Remove trailing new lines if any + if let lastCharacter = attributedString.characters.last, + lastCharacter.isNewline { + attributedString = AttributedString(attributedString.characters.dropLast()) + } + + return AttributedStringBuilderComponent(attributedString: attributedString, isBlockquote: value != nil) } } diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift index c57f17030..11bba6ae1 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift @@ -13,7 +13,7 @@ struct FormattedBodyText: View { let attributedComponents: [AttributedStringBuilderComponent] var body: some View { - VStack(alignment: .leading, spacing: 0.0) { + VStack(alignment: .leading, spacing: 8.0) { ForEach(attributedComponents, id: \.self) { component in if component.isBlockquote { HStack(spacing: 4.0) { diff --git a/ElementXTests/AttributedStringBuilderTests.swift b/ElementXTests/AttributedStringBuilderTests.swift index d3b12a966..501aeb6d8 100644 --- a/ElementXTests/AttributedStringBuilderTests.swift +++ b/ElementXTests/AttributedStringBuilderTests.swift @@ -223,10 +223,31 @@ class AttributedStringBuilderTests: XCTestCase { XCTAssertTrue(foundLink) } - func testBlockquotes() { + func testSingleBlockquote() { + let htmlString = "
Blockquote
" + + guard let attributedString = attributedStringBuilder.fromHTML(htmlString) else { + XCTFail("Could not build the attributed string") + return + } + + XCTAssertEqual(attributedString.runs.count, 1) + + XCTAssertEqual(attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString)?.count, 1) + + for run in attributedString.runs { + if run.elementX.blockquote != nil { + return + } + } + + XCTFail("Couldn't find blockquote") + } + + func testBlockquoteWithinText() { let htmlString = """ The text before the blockquote -
For 50 years, WWF has been protecting the future of nature. The world's leading conservation organization, WWF works in 100 countries and is supported by 1.2 million members in the United States and close to 5 million globally.
+
For 50 years, WWF has been protecting the future of nature. The world's leading conservation organization, WWF works in 100 countries and is supported by 1.2 million members in the United States and close to 5 million globally.
The text after the blockquote """ @@ -237,6 +258,8 @@ The text after the blockquote XCTAssertEqual(attributedString.runs.count, 3) + XCTAssertEqual(attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString)?.count, 3) + for run in attributedString.runs { if run.elementX.blockquote != nil { return @@ -244,8 +267,6 @@ The text after the blockquote } XCTFail("Couldn't find blockquote") - - XCTAssertEqual(attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString)?.count, 3) } // MARK: - Private