From 9cdaa782158a968a5aa9796daf430063f83f5fd8 Mon Sep 17 00:00:00 2001 From: Sergio Estevao Date: Thu, 13 Jun 2019 11:17:05 +0100 Subject: [PATCH 1/5] Add option to replace last empty lines by another special character. --- .../Conversions/HTMLConverter.swift | 24 +++++++++++++++++-- AztecTests/TextKit/TextStorageTests.swift | 22 +++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift b/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift index 20ed30e13..1dd5f3135 100644 --- a/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift +++ b/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift @@ -20,7 +20,11 @@ public class HTMLConverter { } // MARK: - Converters: HTML -> AttributedString - + + /// If a value is set the character set will be used to replace any last empty line created by the converter. + /// + open var characterToReplaceLastEmtpyLine: Character? + let htmlToTree = HTMLParser() private(set) lazy var treeToAttributedString: AttributedStringSerializer = { @@ -54,11 +58,27 @@ public class HTMLConverter { pluginManager.process(htmlTree: rootNode) let defaultAttributes = defaultAttributes ?? [:] - let attributedString = treeToAttributedString.serialize(rootNode, defaultAttributes: defaultAttributes) + var attributedString = treeToAttributedString.serialize(rootNode, defaultAttributes: defaultAttributes) + + if let characterToUse = characterToReplaceLastEmtpyLine { + attributedString = replaceLastEmptyLine(in: attributedString, with: characterToUse) + } return attributedString } + func replaceLastEmptyLine(in attributedString: NSAttributedString, with replacement: Character) -> NSAttributedString { + var result = attributedString + let string = attributedString.string + if string.isEmptyLineAtEndOfFile(at: string.count), !string.isEmpty, let location = string.location(before: attributedString.length) { + let mutableString = NSMutableAttributedString(attributedString: attributedString) + let attributes = mutableString.attributes(at: location, effectiveRange: nil) + mutableString.replaceCharacters(in: NSRange(location: location, length: attributedString.length-location), with: NSAttributedString(string: String(replacement), attributes: attributes)) + result = mutableString + } + return result + } + /// Check if the given html string is supported to be parsed into Attributed Strings. /// diff --git a/AztecTests/TextKit/TextStorageTests.swift b/AztecTests/TextKit/TextStorageTests.swift index fcd5a536d..69920fd24 100644 --- a/AztecTests/TextKit/TextStorageTests.swift +++ b/AztecTests/TextKit/TextStorageTests.swift @@ -494,4 +494,26 @@ class TextStorageTests: XCTestCase { XCTAssertEqual(expectedResult, result) } + + func testEmptyListOutput() { + let initialHTML = "" + + // Setup + let defaultAttributes: [NSAttributedString.Key: Any] = [.font: UIFont.systemFont(ofSize: 14), + .paragraphStyle: ParagraphStyle.default] + + storage.setHTML(initialHTML, defaultAttributes: defaultAttributes) + var expectedResult = String(.paragraphSeparator) + var result = String(storage.string) + + XCTAssertEqual(expectedResult, result) + + storage.htmlConverter.characterToReplaceLastEmtpyLine = Character(.zeroWidthSpace) + + storage.setHTML(initialHTML, defaultAttributes: defaultAttributes) + expectedResult = String(.zeroWidthSpace) + result = String(storage.string) + + XCTAssertEqual(expectedResult, result) + } } From e0ce66538ded26ee2d2812e31d3cc80320b008f6 Mon Sep 17 00:00:00 2001 From: Sergio Estevao Date: Thu, 13 Jun 2019 11:37:51 +0100 Subject: [PATCH 2/5] Make storage and html converter public. --- Aztec/Classes/TextKit/TextStorage.swift | 2 +- Aztec/Classes/TextKit/TextView.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Aztec/Classes/TextKit/TextStorage.swift b/Aztec/Classes/TextKit/TextStorage.swift index 3627df47d..5e9f63127 100644 --- a/Aztec/Classes/TextKit/TextStorage.swift +++ b/Aztec/Classes/TextKit/TextStorage.swift @@ -81,7 +81,7 @@ open class TextStorage: NSTextStorage { // MARK: - HTML Conversion - let htmlConverter = HTMLConverter() + public let htmlConverter = HTMLConverter() // MARK: - PluginManager diff --git a/Aztec/Classes/TextKit/TextView.swift b/Aztec/Classes/TextKit/TextView.swift index 7af801a46..53a175b51 100644 --- a/Aztec/Classes/TextKit/TextView.swift +++ b/Aztec/Classes/TextKit/TextView.swift @@ -267,7 +267,7 @@ open class TextView: UITextView { // MARK: - TextKit Aztec Subclasses - var storage: TextStorage { + public var storage: TextStorage { return textStorage as! TextStorage } From e2bf4374be6c06682c85d7e01561427d2b968fb8 Mon Sep 17 00:00:00 2001 From: Sergio Estevao Date: Fri, 14 Jun 2019 16:58:12 +0100 Subject: [PATCH 3/5] =?UTF-8?q?Check=20if=20it=E2=80=99s=20a=20paragraph?= =?UTF-8?q?=20separator.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Classes/NSAttributedString/Conversions/HTMLConverter.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift b/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift index 1dd5f3135..20ff39c50 100644 --- a/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift +++ b/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift @@ -70,7 +70,7 @@ public class HTMLConverter { func replaceLastEmptyLine(in attributedString: NSAttributedString, with replacement: Character) -> NSAttributedString { var result = attributedString let string = attributedString.string - if string.isEmptyLineAtEndOfFile(at: string.count), !string.isEmpty, let location = string.location(before: attributedString.length) { + if !string.isEmpty, string.isEmptyLineAtEndOfFile(at: string.count), string.hasSuffix(String(.paragraphSeparator)), let location = string.location(before: attributedString.length) { let mutableString = NSMutableAttributedString(attributedString: attributedString) let attributes = mutableString.attributes(at: location, effectiveRange: nil) mutableString.replaceCharacters(in: NSRange(location: location, length: attributedString.length-location), with: NSAttributedString(string: String(replacement), attributes: attributes)) From cb29d332e2a1bbc5bfee1cb9d5200b8e4e189fe2 Mon Sep 17 00:00:00 2001 From: Sergio Estevao Date: Fri, 14 Jun 2019 22:29:46 +0100 Subject: [PATCH 4/5] Fix typo on variable name. --- .../NSAttributedString/Conversions/HTMLConverter.swift | 4 ++-- AztecTests/TextKit/TextStorageTests.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift b/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift index 20ff39c50..77c6b8621 100644 --- a/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift +++ b/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift @@ -23,7 +23,7 @@ public class HTMLConverter { /// If a value is set the character set will be used to replace any last empty line created by the converter. /// - open var characterToReplaceLastEmtpyLine: Character? + open var characterToReplaceLastEmptyLine: Character? let htmlToTree = HTMLParser() @@ -60,7 +60,7 @@ public class HTMLConverter { let defaultAttributes = defaultAttributes ?? [:] var attributedString = treeToAttributedString.serialize(rootNode, defaultAttributes: defaultAttributes) - if let characterToUse = characterToReplaceLastEmtpyLine { + if let characterToUse = characterToReplaceLastEmptyLine { attributedString = replaceLastEmptyLine(in: attributedString, with: characterToUse) } diff --git a/AztecTests/TextKit/TextStorageTests.swift b/AztecTests/TextKit/TextStorageTests.swift index 69920fd24..1a203a98c 100644 --- a/AztecTests/TextKit/TextStorageTests.swift +++ b/AztecTests/TextKit/TextStorageTests.swift @@ -508,7 +508,7 @@ class TextStorageTests: XCTestCase { XCTAssertEqual(expectedResult, result) - storage.htmlConverter.characterToReplaceLastEmtpyLine = Character(.zeroWidthSpace) + storage.htmlConverter.characterToReplaceLastEmptyLine = Character(.zeroWidthSpace) storage.setHTML(initialHTML, defaultAttributes: defaultAttributes) expectedResult = String(.zeroWidthSpace) From 4d5551e044e49ad2bd82c910c2d50ef1765e61a3 Mon Sep 17 00:00:00 2001 From: Sergio Estevao Date: Fri, 14 Jun 2019 22:30:54 +0100 Subject: [PATCH 5/5] Add extra unit test to check if only paragraph separator is replaced. --- AztecTests/TextKit/TextStorageTests.swift | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/AztecTests/TextKit/TextStorageTests.swift b/AztecTests/TextKit/TextStorageTests.swift index 1a203a98c..633204a3f 100644 --- a/AztecTests/TextKit/TextStorageTests.swift +++ b/AztecTests/TextKit/TextStorageTests.swift @@ -516,4 +516,26 @@ class TextStorageTests: XCTestCase { XCTAssertEqual(expectedResult, result) } + + func testCiteOutput() { + let initialHTML = "Hello
" + + // Setup + let defaultAttributes: [NSAttributedString.Key: Any] = [.font: UIFont.systemFont(ofSize: 14), + .paragraphStyle: ParagraphStyle.default] + + storage.setHTML(initialHTML, defaultAttributes: defaultAttributes) + var expectedResult = String("Hello")+String(.lineSeparator) + var result = String(storage.string) + + XCTAssertEqual(expectedResult, result) + + storage.htmlConverter.characterToReplaceLastEmptyLine = Character(.zeroWidthSpace) + + storage.setHTML(initialHTML, defaultAttributes: defaultAttributes) + expectedResult = String("Hello")+String(.lineSeparator) + result = String(storage.string) + + XCTAssertEqual(expectedResult, result) + } }