diff --git a/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift b/Aztec/Classes/NSAttributedString/Conversions/HTMLConverter.swift index 20ed30e13..77c6b8621 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 characterToReplaceLastEmptyLine: 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 = characterToReplaceLastEmptyLine { + 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.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)) + result = mutableString + } + return result + } + /// Check if the given html string is supported to be parsed into Attributed Strings. /// 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 } diff --git a/AztecTests/TextKit/TextStorageTests.swift b/AztecTests/TextKit/TextStorageTests.swift index fcd5a536d..633204a3f 100644 --- a/AztecTests/TextKit/TextStorageTests.swift +++ b/AztecTests/TextKit/TextStorageTests.swift @@ -494,4 +494,48 @@ class TextStorageTests: XCTestCase { XCTAssertEqual(expectedResult, result) } + + func testEmptyListOutput() { + let initialHTML = "