diff --git a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift
index cc1f56f8a..6b50b7a85 100644
--- a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift
+++ b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift
@@ -122,9 +122,9 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
for node in element.getChildNodes() {
if let textNode = node as? TextNode {
- // If this node is plain text just append its preformatted contents
+ // If this node is plain text append the whitespace normalised version
if node.parent() == documentBody {
- result.append(NSAttributedString(string: textNode.getWholeText()))
+ result.append(NSAttributedString(string: textNode.text()))
continue
}
@@ -237,7 +237,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
content = attributedString(element: childElement, documentBody: documentBody, preserveFormatting: preserveFormatting, listTag: tag, listIndex: &listIndex, indentLevel: indentLevel + 1)
- if indentLevel > 0 {
+ if indentLevel > 0 || !element.ownText().isEmpty {
content.insert(NSAttributedString("\n"), at: 0)
}
diff --git a/ElementX/Sources/Other/HTMLParsing/HTMLFixtures.swift b/ElementX/Sources/Other/HTMLParsing/HTMLFixtures.swift
index 10332fd3f..4fefc959e 100644
--- a/ElementX/Sources/Other/HTMLParsing/HTMLFixtures.swift
+++ b/ElementX/Sources/Other/HTMLParsing/HTMLFixtures.swift
@@ -29,11 +29,11 @@ enum HTMLFixtures: String, CaseIterable {
"""
case .headers:
"""
-
H1 Header
- H2 Header
- H3 Header
- H4 Header
- H5 Header
+ H1 Header
\
+ H2 Header
\
+ H3 Header
\
+ H4 Header
\
+ H5 Header
\
H6 Header
"""
case .paragraphs:
diff --git a/ElementX/Sources/Other/Pills/MessageText.swift b/ElementX/Sources/Other/Pills/MessageText.swift
index e4efb533e..6de78d490 100644
--- a/ElementX/Sources/Other/Pills/MessageText.swift
+++ b/ElementX/Sources/Other/Pills/MessageText.swift
@@ -199,11 +199,10 @@ struct MessageText_Previews: PreviewProvider, TestablePreview {
private static let htmlStringWithQuote =
"""
- A blockquote that is long and goes onto multiple lines as the first item in the message
- Then another line of text here to reply to the blockquote, which is also a multiline component.
+ A blockquote that is long and goes onto multiple lines as the first item in the message
Then another line of text here to reply to the blockquote, which is also a multiline component.
"""
- private static let htmlStringWithList = "This is a list
\n\n- One
\n- Two
\n- And number 3
\n
\n"
+ private static let htmlStringWithList = "This is a list
\n\n"
private static let attributedStringBuilder = AttributedStringBuilder(mentionBuilder: MentionBuilder())
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPad-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPad-en-GB-0.png
index 6533042f8..3cd3030c1 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPad-en-GB-0.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPad-en-GB-0.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:518aca90ecd814093b3ffbfcb361716bc55f0840fb1914d1d2dc9e6def6aee13
-size 1112322
+oid sha256:bce958a2c9eedbc8b4e63c7dc135dff80b249f64c812f47405400e1e2d314e22
+size 1069392
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPad-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPad-pseudo-0.png
index 6533042f8..3cd3030c1 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPad-pseudo-0.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPad-pseudo-0.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:518aca90ecd814093b3ffbfcb361716bc55f0840fb1914d1d2dc9e6def6aee13
-size 1112322
+oid sha256:bce958a2c9eedbc8b4e63c7dc135dff80b249f64c812f47405400e1e2d314e22
+size 1069392
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPhone-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPhone-en-GB-0.png
index 11b7513c1..9bbe78ed9 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPhone-en-GB-0.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPhone-en-GB-0.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d9858f3bc9676f311a526d2b08a86bc9e46d19a707a052db571f19abe7c9af86
-size 1267614
+oid sha256:c5e5b587c34f19aebcefabf0d9893dfde863390348132483ac8763387b692dc4
+size 1252781
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPhone-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPhone-pseudo-0.png
index 11b7513c1..9bbe78ed9 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPhone-pseudo-0.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/formattedBodyText.iPhone-pseudo-0.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d9858f3bc9676f311a526d2b08a86bc9e46d19a707a052db571f19abe7c9af86
-size 1267614
+oid sha256:c5e5b587c34f19aebcefabf0d9893dfde863390348132483ac8763387b692dc4
+size 1252781
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPad-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPad-en-GB.png
index dc3a5b16b..ed9fd6418 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPad-en-GB.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPad-en-GB.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f9991bd3bd6a88efc9f39fa075c0defc2a98f2a5f0f237df478b9926cbc6aadc
-size 86111
+oid sha256:5c60f428f0b84c2b499c2a3a5491ed302af3945d2dc93af2ac8702ba37f21568
+size 82432
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPad-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPad-pseudo.png
index dc3a5b16b..ed9fd6418 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPad-pseudo.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPad-pseudo.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f9991bd3bd6a88efc9f39fa075c0defc2a98f2a5f0f237df478b9926cbc6aadc
-size 86111
+oid sha256:5c60f428f0b84c2b499c2a3a5491ed302af3945d2dc93af2ac8702ba37f21568
+size 82432
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPhone-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPhone-en-GB.png
index ef8e37920..d1b1e9055 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPhone-en-GB.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPhone-en-GB.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ffac5d2e62703aefb5abec3a48eb22f84f4533fe26fc054b3250929138601718
-size 49165
+oid sha256:e36b3662d56586f0f759c03ac878eeebb325f29556e8192904b7146614802a98
+size 48271
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPhone-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPhone-pseudo.png
index ef8e37920..d1b1e9055 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPhone-pseudo.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-block-quote-iPhone-pseudo.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ffac5d2e62703aefb5abec3a48eb22f84f4533fe26fc054b3250929138601718
-size 49165
+oid sha256:e36b3662d56586f0f759c03ac878eeebb325f29556e8192904b7146614802a98
+size 48271
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPad-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPad-en-GB.png
index 8350f32be..5efead302 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPad-en-GB.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPad-en-GB.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8deba950d704d7e6b73183aa43c62f52c031fbb93bfa546d847282d12bca0b1c
-size 75467
+oid sha256:ff732f47d1ee83104eb640216c6849734a4d9b3ad8efa44f4b9bc7bb3284ccc1
+size 74485
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPad-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPad-pseudo.png
index 8350f32be..5efead302 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPad-pseudo.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPad-pseudo.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8deba950d704d7e6b73183aa43c62f52c031fbb93bfa546d847282d12bca0b1c
-size 75467
+oid sha256:ff732f47d1ee83104eb640216c6849734a4d9b3ad8efa44f4b9bc7bb3284ccc1
+size 74485
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPhone-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPhone-en-GB.png
index d5440a041..7150bd143 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPhone-en-GB.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPhone-en-GB.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:eabf0c072db6ae1062e14770b4267c1ccaf8d2478f20bde05f9a665594392b8e
-size 35067
+oid sha256:8699be861d421ee9615831cb23c28a6be20a223bcc775f7d86394709f1a4f87b
+size 34936
diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPhone-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPhone-pseudo.png
index d5440a041..7150bd143 100644
--- a/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPhone-pseudo.png
+++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/messageText.With-list-iPhone-pseudo.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:eabf0c072db6ae1062e14770b4267c1ccaf8d2478f20bde05f9a665594392b8e
-size 35067
+oid sha256:8699be861d421ee9615831cb23c28a6be20a223bcc775f7d86394709f1a4f87b
+size 34936
diff --git a/UnitTests/Sources/AttributedStringBuilderTests.swift b/UnitTests/Sources/AttributedStringBuilderTests.swift
index 6d2b55ecd..3b61d9088 100644
--- a/UnitTests/Sources/AttributedStringBuilderTests.swift
+++ b/UnitTests/Sources/AttributedStringBuilderTests.swift
@@ -23,12 +23,12 @@ class AttributedStringBuilderTests: XCTestCase {
return
}
- XCTAssertEqual(String(attributedString.characters), "H1 Header\n\nH2 Header\n\nH3 Header\n\nH4 Header\n\nH5 Header\n\nH6 Header")
+ XCTAssertEqual(String(attributedString.characters), "H1 Header\nH2 Header\nH3 Header\nH4 Header\nH5 Header\nH6 Header")
- XCTAssertEqual(attributedString.runs.count, 11) // newlines hold no attributes
+ XCTAssertEqual(attributedString.runs.count, 4) // newlines hold no attributes
let pointSizes = attributedString.runs.compactMap(\.uiKit.font?.pointSize)
- XCTAssertEqual(pointSizes, [23, 23, 23, 21, 19, 17])
+ XCTAssertEqual(pointSizes, [23, 21, 19, 17])
}
func testRenderHTMLStringWithPreCode() {
@@ -46,7 +46,7 @@ class AttributedStringBuilderTests: XCTestCase {
return
}
- XCTAssertEqual(regex.numberOfMatches(in: string, options: [], range: .init(location: 0, length: string.count)), 18)
+ XCTAssertEqual(regex.numberOfMatches(in: string, options: [], range: .init(location: 0, length: string.count)), 13)
}
func testRenderHTMLStringWithLink() {
@@ -270,22 +270,24 @@ class AttributedStringBuilderTests: XCTestCase {
}
func testSingleBlockquote() {
- let htmlString = "Blockquote
"
+ let htmlString = "Blockquote
Another paragraph
"
guard let attributedString = attributedStringBuilder.fromHTML(htmlString) else {
XCTFail("Could not build the attributed string")
return
}
- XCTAssertEqual(attributedString.runs.count, 1)
+ XCTAssertEqual(attributedString.runs.count, 2)
- XCTAssertEqual(attributedString.formattedComponents.count, 1)
+ XCTAssertEqual(attributedString.formattedComponents.count, 2)
for run in attributedString.runs where run.elementX.blockquote ?? false {
return
}
XCTFail("Couldn't find blockquote")
+
+ XCTAssertEqual(String(attributedString.characters), "Blockquote\nAnother paragraph")
}
// swiftlint:disable line_length
@@ -699,7 +701,7 @@ class AttributedStringBuilderTests: XCTestCase {
return
}
- XCTAssertEqual(String(attributedString.characters), "like\n\n • this\ntest")
+ XCTAssertEqual(String(attributedString.characters), "like\n • this\ntest")
}
func testUnorderedList() {
@@ -768,6 +770,30 @@ class AttributedStringBuilderTests: XCTestCase {
XCTAssertEqual(String(attributedString.characters), " 1. A\n • A1\n • A2\n • A3\n 2. B\n 3. C")
}
+ // https://github.com/element-hq/element-x-ios/issues/4856
+ func testNormalisedWhitespaces() {
+ let html = """
+ Stefan pushed
+ 2 commits
+ to
+ main:
+ """
+ guard let attributedString = attributedStringBuilder.fromHTML(html) else {
+ XCTFail("Could not build the attributed string")
+ return
+ }
+
+ XCTAssertEqual(String(attributedString.characters), "Stefan pushed 2 commits to main:\n • Some update \n • Some other update")
+ }
+
// MARK: - Phishing prevention
func testPhishingLink() {