diff --git a/Aztec.xcodeproj/project.pbxproj b/Aztec.xcodeproj/project.pbxproj index 9b480a079..b4e837494 100644 --- a/Aztec.xcodeproj/project.pbxproj +++ b/Aztec.xcodeproj/project.pbxproj @@ -223,6 +223,8 @@ F99D5CF321B989FF0089314A /* StringRangeMultibyteConversionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F99D5CF221B989FF0089314A /* StringRangeMultibyteConversionTests.swift */; }; FF0714021EFD78AF00E50713 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FF0714001EFD78AF00E50713 /* Media.xcassets */; }; FF17B2D2227A589F0022AECE /* LIElementConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF17B2D1227A589F0022AECE /* LIElementConverter.swift */; }; + FF1F56A123955EF600E93A30 /* ColorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1F56A023955EF600E93A30 /* ColorProvider.swift */; }; + FF1F56A3239562B900E93A30 /* html_colors.json in Resources */ = {isa = PBXBuildFile; fileRef = FF1F56A2239562B900E93A30 /* html_colors.json */; }; FF20D6401EDC389A00294B78 /* ShortcodeAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF20D63D1EDC389A00294B78 /* ShortcodeAttribute.swift */; }; FF20D6411EDC389A00294B78 /* HTMLProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF20D63E1EDC389A00294B78 /* HTMLProcessor.swift */; }; FF20D6421EDC389A00294B78 /* Processor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF20D63F1EDC389A00294B78 /* Processor.swift */; }; @@ -499,6 +501,8 @@ F99D5CF221B989FF0089314A /* StringRangeMultibyteConversionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringRangeMultibyteConversionTests.swift; sourceTree = ""; }; FF0714001EFD78AF00E50713 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; FF17B2D1227A589F0022AECE /* LIElementConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LIElementConverter.swift; sourceTree = ""; }; + FF1F56A023955EF600E93A30 /* ColorProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorProvider.swift; sourceTree = ""; }; + FF1F56A2239562B900E93A30 /* html_colors.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = html_colors.json; sourceTree = ""; }; FF20D63D1EDC389A00294B78 /* ShortcodeAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcodeAttribute.swift; sourceTree = ""; }; FF20D63E1EDC389A00294B78 /* HTMLProcessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLProcessor.swift; sourceTree = ""; }; FF20D63F1EDC389A00294B78 /* Processor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Processor.swift; sourceTree = ""; }; @@ -810,6 +814,7 @@ B5A99D831EBA073D00DED081 /* HTMLStorage.swift */, F9982CF521877663001E606B /* TextViewPasteboardDelegate.swift */, FF7EAEC3234D253B007A26E0 /* FontProvider.swift */, + FF1F56A023955EF600E93A30 /* ColorProvider.swift */, ); path = TextKit; sourceTree = ""; @@ -1337,6 +1342,7 @@ isa = PBXGroup; children = ( FF0714001EFD78AF00E50713 /* Media.xcassets */, + FF1F56A2239562B900E93A30 /* html_colors.json */, ); path = Assets; sourceTree = ""; @@ -1486,6 +1492,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + FF1F56A3239562B900E93A30 /* html_colors.json in Resources */, FF0714021EFD78AF00E50713 /* Media.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1540,6 +1547,7 @@ FFD3C1732344DCA900AE8DA0 /* ForegroundColorElementAttributeConverter.swift in Sources */, F1656FDE2152A6A6009C7E3A /* CiteStringAttributeConverter.swift in Sources */, 599F254B1D8BC9A1002871D6 /* String+RangeConversion.swift in Sources */, + FF1F56A123955EF600E93A30 /* ColorProvider.swift in Sources */, 599F25481D8BC9A1002871D6 /* Metrics.swift in Sources */, 914CD9E72200B2D200DDD5C9 /* BoldFormatter.swift in Sources */, F1BDDDE72060403B000714E1 /* FigureFormatter.swift in Sources */, diff --git a/Aztec/Assets/html_colors.json b/Aztec/Assets/html_colors.json new file mode 100644 index 000000000..7a1480dce --- /dev/null +++ b/Aztec/Assets/html_colors.json @@ -0,0 +1,150 @@ +{ + "aliceblue": "#f0f8ff", + "antiquewhite": "#faebd7", + "aqua": "#00ffff", + "aquamarine": "#7fffd4", + "azure": "#f0ffff", + "beige": "#f5f5dc", + "bisque": "#ffe4c4", + "black": "#000000", + "blanchedalmond": "#ffebcd", + "blue": "#0000ff", + "blueviolet": "#8a2be2", + "brown": "#a52a2a", + "burlywood": "#deb887", + "cadetblue": "#5f9ea0", + "chartreuse": "#7fff00", + "chocolate": "#d2691e", + "coral": "#ff7f50", + "cornflowerblue": "#6495ed", + "cornsilk": "#fff8dc", + "crimson": "#dc143c", + "cyan": "#00ffff", + "darkblue": "#00008b", + "darkcyan": "#008b8b", + "darkgoldenrod": "#b8860b", + "darkgray": "#a9a9a9", + "darkgreen": "#006400", + "darkgrey": "#a9a9a9", + "darkkhaki": "#bdb76b", + "darkmagenta": "#8b008b", + "darkolivegreen": "#556b2f", + "darkorange": "#ff8c00", + "darkorchid": "#9932cc", + "darkred": "#8b0000", + "darksalmon": "#e9967a", + "darkseagreen": "#8fbc8f", + "darkslateblue": "#483d8b", + "darkslategray": "#2f4f4f", + "darkslategrey": "#2f4f4f", + "darkturquoise": "#00ced1", + "darkviolet": "#9400d3", + "deeppink": "#ff1493", + "deepskyblue": "#00bfff", + "dimgray": "#696969", + "dimgrey": "#696969", + "dodgerblue": "#1e90ff", + "firebrick": "#b22222", + "floralwhite": "#fffaf0", + "forestgreen": "#228b22", + "fuchsia": "#ff00ff", + "gainsboro": "#dcdcdc", + "ghostwhite": "#f8f8ff", + "goldenrod": "#daa520", + "gold": "#ffd700", + "gray": "#808080", + "green": "#008000", + "greenyellow": "#adff2f", + "grey": "#808080", + "honeydew": "#f0fff0", + "hotpink": "#ff69b4", + "indianred": "#cd5c5c", + "indigo": "#4b0082", + "ivory": "#fffff0", + "khaki": "#f0e68c", + "lavenderblush": "#fff0f5", + "lavender": "#e6e6fa", + "lawngreen": "#7cfc00", + "lemonchiffon": "#fffacd", + "lightblue": "#add8e6", + "lightcoral": "#f08080", + "lightcyan": "#e0ffff", + "lightgoldenrodyellow": "#fafad2", + "lightgray": "#d3d3d3", + "lightgreen": "#90ee90", + "lightgrey": "#d3d3d3", + "lightpink": "#ffb6c1", + "lightsalmon": "#ffa07a", + "lightseagreen": "#20b2aa", + "lightskyblue": "#87cefa", + "lightslategray": "#778899", + "lightslategrey": "#778899", + "lightsteelblue": "#b0c4de", + "lightyellow": "#ffffe0", + "lime": "#00ff00", + "limegreen": "#32cd32", + "linen": "#faf0e6", + "magenta": "#ff00ff", + "maroon": "#800000", + "mediumaquamarine": "#66cdaa", + "mediumblue": "#0000cd", + "mediumorchid": "#ba55d3", + "mediumpurple": "#9370db", + "mediumseagreen": "#3cb371", + "mediumslateblue": "#7b68ee", + "mediumspringgreen": "#00fa9a", + "mediumturquoise": "#48d1cc", + "mediumvioletred": "#c71585", + "midnightblue": "#191970", + "mintcream": "#f5fffa", + "mistyrose": "#ffe4e1", + "moccasin": "#ffe4b5", + "navajowhite": "#ffdead", + "navy": "#000080", + "oldlace": "#fdf5e6", + "olive": "#808000", + "olivedrab": "#6b8e23", + "orange": "#ffa500", + "orangered": "#ff4500", + "orchid": "#da70d6", + "palegoldenrod": "#eee8aa", + "palegreen": "#98fb98", + "paleturquoise": "#afeeee", + "palevioletred": "#db7093", + "papayawhip": "#ffefd5", + "peachpuff": "#ffdab9", + "peru": "#cd853f", + "pink": "#ffc0cb", + "plum": "#dda0dd", + "powderblue": "#b0e0e6", + "purple": "#800080", + "rebeccapurple": "#663399", + "red": "#ff0000", + "rosybrown": "#bc8f8f", + "royalblue": "#4169e1", + "saddlebrown": "#8b4513", + "salmon": "#fa8072", + "sandybrown": "#f4a460", + "seagreen": "#2e8b57", + "seashell": "#fff5ee", + "sienna": "#a0522d", + "silver": "#c0c0c0", + "skyblue": "#87ceeb", + "slateblue": "#6a5acd", + "slategray": "#708090", + "slategrey": "#708090", + "snow": "#fffafa", + "springgreen": "#00ff7f", + "steelblue": "#4682b4", + "tan": "#d2b48c", + "teal": "#008080", + "thistle": "#d8bfd8", + "tomato": "#ff6347", + "turquoise": "#40e0d0", + "violet": "#ee82ee", + "wheat": "#f5deb3", + "white": "#ffffff", + "whitesmoke": "#f5f5f5", + "yellow": "#ffff00", + "yellowgreen": "#9acd32" +} diff --git a/Aztec/Classes/Converters/AttributesToStringAttributes/Implementations/ForegroundColorElementAttributeConverter.swift b/Aztec/Classes/Converters/AttributesToStringAttributes/Implementations/ForegroundColorElementAttributeConverter.swift index ba661389e..1b3a9f3ac 100644 --- a/Aztec/Classes/Converters/AttributesToStringAttributes/Implementations/ForegroundColorElementAttributeConverter.swift +++ b/Aztec/Classes/Converters/AttributesToStringAttributes/Implementations/ForegroundColorElementAttributeConverter.swift @@ -11,7 +11,7 @@ class ForegroundColorElementAttributesConverter: ElementAttributeConverter { guard let cssColor = attribute.firstCSSAttribute(ofType: .foregroundColor), let colorValue = cssColor.value, - let color = UIColor(hexString: colorValue) else { + let color = ColorProvider.shared.color(named: colorValue) ?? UIColor(hexString: colorValue) else { return attributes } diff --git a/Aztec/Classes/Extensions/NSAttributedString+Lists.swift b/Aztec/Classes/Extensions/NSAttributedString+Lists.swift index cd63dc92a..1c8238d41 100644 --- a/Aztec/Classes/Extensions/NSAttributedString+Lists.swift +++ b/Aztec/Classes/Extensions/NSAttributedString+Lists.swift @@ -68,13 +68,41 @@ extension NSAttributedString { return resultRange } + /// Returns the number of items of a list at the given location. + /// + /// - Parameters: + /// - list: The list. + /// - location: The location of the item. + /// + /// - Returns: Returns the total number of items within the list or NSNotFound if no list is available at location. + /// + func numberOfItems(in list: TextList, at location: Int) -> Int { + guard + let paragraphStyle = attribute(.paragraphStyle, at: location, effectiveRange: nil) as? ParagraphStyle + else { + return NSNotFound + } + let listDepth = paragraphStyle.lists.count + guard let rangeOfList = range(of:list, at: location) else { + return NSNotFound + } + var numberInList = 0 + let paragraphRanges = self.paragraphRanges(intersecting: rangeOfList) + for (_, enclosingRange) in paragraphRanges { + if let paragraphStyle = attribute(.paragraphStyle, at: enclosingRange.location, effectiveRange: nil) as? ParagraphStyle, + listDepth == paragraphStyle.lists.count { + numberInList += 1 + } + } + return numberInList + } /// Returns the index of the item at the given location within the list. /// /// - Parameters: /// - list: The list. /// - location: The location of the item. /// - /// - Returns: Returns the index within the list. + /// - Returns: Returns the index within the list or NSNotFound is no list is available at location. /// func itemNumber(in list: TextList, at location: Int) -> Int { guard @@ -86,7 +114,7 @@ extension NSAttributedString { guard let rangeOfList = range(of:list, at: location) else { return NSNotFound } - var numberInList = 1 + var numberInList = 0 let paragraphRanges = self.paragraphRanges(intersecting: rangeOfList) for (_, enclosingRange) in paragraphRanges { diff --git a/Aztec/Classes/Formatters/Implementations/CodeFormatter.swift b/Aztec/Classes/Formatters/Implementations/CodeFormatter.swift index 04918e19d..b5bdded4b 100644 --- a/Aztec/Classes/Formatters/Implementations/CodeFormatter.swift +++ b/Aztec/Classes/Formatters/Implementations/CodeFormatter.swift @@ -12,7 +12,7 @@ class CodeFormatter: AttributeFormatter { // MARK: - Init - init(monospaceFont: UIFont = FontProvider.shared.monospaceFont, backgroundColor: UIColor = UIColor.lightGray) { + init(monospaceFont: UIFont = FontProvider.shared.monospaceFont, backgroundColor: UIColor = ColorProvider.shared.codeBackgroungColor) { self.monospaceFont = monospaceFont self.backgroundColor = backgroundColor self.htmlRepresentationKey = .codeHtmlRepresentation diff --git a/Aztec/Classes/Libxml2/DOM/Data/AttributeType.swift b/Aztec/Classes/Libxml2/DOM/Data/AttributeType.swift index 04413c324..5cbae7de6 100644 --- a/Aztec/Classes/Libxml2/DOM/Data/AttributeType.swift +++ b/Aztec/Classes/Libxml2/DOM/Data/AttributeType.swift @@ -36,4 +36,6 @@ extension AttributeType { public static let src = AttributeType("src") public static let style = AttributeType("style") public static let target = AttributeType("target") + public static let reversed = AttributeType("reversed") + public static let start = AttributeType("start") } diff --git a/Aztec/Classes/NSAttributedString/Conversions/AttributedStringParser.swift b/Aztec/Classes/NSAttributedString/Conversions/AttributedStringParser.swift index 94d4fcd3d..84f763f4a 100644 --- a/Aztec/Classes/NSAttributedString/Conversions/AttributedStringParser.swift +++ b/Aztec/Classes/NSAttributedString/Conversions/AttributedStringParser.swift @@ -765,6 +765,15 @@ private extension AttributedStringParser { listElement = element.toElementNode() } else { listElement = ElementNode(type: listType) + if list.style == .ordered { + if list.reversed { + listElement.updateAttribute(named: "reversed", value: .none) + } + + if let start = list.start { + listElement.updateAttribute(named: "start", value: .string("\(start)")) + } + } } return listElement diff --git a/Aztec/Classes/TextKit/ColorProvider.swift b/Aztec/Classes/TextKit/ColorProvider.swift new file mode 100644 index 000000000..f6351e094 --- /dev/null +++ b/Aztec/Classes/TextKit/ColorProvider.swift @@ -0,0 +1,55 @@ +import Foundation +import UIKit + +/// A class that provides colors to the formatter in TextKit. +/// By default only the standard html colors are provided, but new color can be added by using the `add(namedColors:)` method. +public class ColorProvider { + + + private init() { + + } + + public static var shared = ColorProvider() + + private lazy var htmlColors: [String: UIColor] = { + guard let colorDataURL = Bundle.aztecBundle.url(forResource: "html_colors", withExtension: "json"), + let data = try? Data(contentsOf: colorDataURL), + let object = try? JSONSerialization.jsonObject(with: data, options: .allowFragments), + let colorDict = object as? [String: String] else { + return [String:UIColor]() + } + + return colorDict.compactMapValues { UIColor(hexString: $0) } + }() + + private var extraColors = [String:UIColor]() + + /// Adds extra named colors to be used by the `color(named:)` method. + /// If there is a name collision, the value in the added dictionary will overwrite the current color. + /// - Parameter namedColors: a dictionary of colors keyed by name + public func add(namedColors: [String: UIColor]) { + extraColors.merge(namedColors) { (base, other) -> UIColor in + return other + } + } + + /// Returns a color designated by name or nil if the name is not available + /// By default the the color available are the ones defined in the HTML specification: https://www.w3schools.com/colors/colors_names.asp + /// - Parameter name: the name of the color + public func color(named name: String) -> UIColor? { + if let color = htmlColors[name.lowercased()] { + return color + } + + return extraColors[name] + } + + public lazy var codeBackgroungColor: UIColor = { + if #available(iOS 13.0, *) { + return .secondarySystemBackground + } else { + return .lightGray + } + }() +} diff --git a/Aztec/Classes/TextKit/LayoutManager.swift b/Aztec/Classes/TextKit/LayoutManager.swift index 525ac19d0..2f7a8ca9b 100644 --- a/Aztec/Classes/TextKit/LayoutManager.swift +++ b/Aztec/Classes/TextKit/LayoutManager.swift @@ -210,8 +210,16 @@ private extension LayoutManager { let glyphRange = self.glyphRange(forCharacterRange: enclosingRange, actualCharacterRange: nil) let markerRect = rectForItem(range: glyphRange, origin: origin, paragraphStyle: paragraphStyle) - let markerNumber = textStorage.itemNumber(in: list, at: enclosingRange.location) - + var markerNumber = textStorage.itemNumber(in: list, at: enclosingRange.location) + var start = list.start ?? 1 + if list.reversed { + markerNumber = -markerNumber + if list.start == nil { + start = textStorage.numberOfItems(in: list, at: enclosingRange.location) + } + } + markerNumber += start + drawItem(number: markerNumber, in: markerRect, from: list, using: paragraphStyle, at: enclosingRange.location) } } diff --git a/Aztec/Classes/TextKit/ParagraphProperty/TextList.swift b/Aztec/Classes/TextKit/ParagraphProperty/TextList.swift index 0c18e4b77..8c4d0bc44 100644 --- a/Aztec/Classes/TextKit/ParagraphProperty/TextList.swift +++ b/Aztec/Classes/TextKit/ParagraphProperty/TextList.swift @@ -22,14 +22,34 @@ open class TextList: ParagraphProperty { } } + public let reversed: Bool + + public let start: Int? + // MARK: - Properties /// Kind of List: Ordered / Unordered /// let style: Style - init(style: Style, with representation: HTMLRepresentation? = nil) { + init(style: Style, start: Int? = nil, reversed: Bool = false, with representation: HTMLRepresentation? = nil) { self.style = style + + if let representation = representation, case let .element( html ) = representation.kind { + self.reversed = html.attribute(ofType: .reversed) != nil + + if let startAttribute = html.attribute(ofType: .start), + case let .string( value ) = startAttribute.value, + let start = Int(value) + { + self.start = start + } else { + self.start = nil + } + } else { + self.start = start + self.reversed = reversed + } super.init(with: representation) } @@ -40,15 +60,31 @@ open class TextList: ParagraphProperty { } else { style = .ordered } + if aDecoder.containsValue(forKey: AttributeType.start.rawValue) { + let decodedStart = aDecoder.decodeInteger(forKey: AttributeType.start.rawValue) + start = decodedStart + } else { + start = nil + } + + if aDecoder.containsValue(forKey: AttributeType.reversed.rawValue) { + let decodedReversed = aDecoder.decodeBool(forKey: AttributeType.reversed.rawValue) + reversed = decodedReversed + } else { + reversed = false + } + super.init(coder: aDecoder) } public override func encode(with aCoder: NSCoder) { super.encode(with: aCoder) aCoder.encode(style.rawValue, forKey: String(describing: Style.self)) + aCoder.encode(start, forKey: AttributeType.start.rawValue) + aCoder.encode(reversed, forKey: AttributeType.reversed.rawValue) } public static func ==(lhs: TextList, rhs: TextList) -> Bool { - return lhs.style == rhs.style + return lhs.style == rhs.style && lhs.start == rhs.start && lhs.reversed == rhs.reversed } } diff --git a/AztecTests/Formatters/TextListFormatterTests.swift b/AztecTests/Formatters/TextListFormatterTests.swift index 52c2522fd..c3a9406d4 100644 --- a/AztecTests/Formatters/TextListFormatterTests.swift +++ b/AztecTests/Formatters/TextListFormatterTests.swift @@ -33,8 +33,8 @@ class TextListFormatterTests: XCTestCase { XCTAssert(lists[2].style == .unordered) XCTAssert(lists[3].style == .ordered) - XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 1) - XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 1) + XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 0) + XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 0) } // Helpers #2: @@ -64,7 +64,7 @@ class TextListFormatterTests: XCTestCase { } for (index, textList) in lists.enumerated() { - XCTAssert(list.itemNumber(in: textList, at: ranges[index].location) == index + 1) + XCTAssert(list.itemNumber(in: textList, at: ranges[index].location) == index) } } @@ -92,7 +92,7 @@ class TextListFormatterTests: XCTestCase { XCTAssert(lists.count == 1) XCTAssert(lists[0].style == .ordered) - XCTAssert(string.itemNumber(in: lists[0], at: ranges[0].location) == 1) + XCTAssert(string.itemNumber(in: lists[0], at: ranges[0].location) == 0) } @@ -152,7 +152,7 @@ class TextListFormatterTests: XCTestCase { } for (index, textList) in lists.enumerated() { - XCTAssertEqual(list.itemNumber(in: textList, at: ranges[index+1].location), index + 1) + XCTAssertEqual(list.itemNumber(in: textList, at: ranges[index+1].location), index) } } @@ -185,7 +185,7 @@ class TextListFormatterTests: XCTestCase { XCTAssert(lists[2].style == .ordered) XCTAssert(lists[3].style == .unordered) - XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 1) + XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 0) XCTAssertEqual(list.itemNumber(in: lists[2], at: ranges[2].location), NSNotFound) } @@ -246,9 +246,9 @@ class TextListFormatterTests: XCTestCase { XCTAssert(lists[2].style == .unordered) XCTAssert(lists[3].style == .ordered) - XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 1) - XCTAssert(list.itemNumber(in: lists[1], at: ranges[1].location) == 2) - XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 1) + XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 0) + XCTAssert(list.itemNumber(in: lists[1], at: ranges[1].location) == 1) + XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 0) } @@ -280,9 +280,9 @@ class TextListFormatterTests: XCTestCase { XCTAssert(lists[3].style == .ordered) XCTAssert(lists[4].style == .ordered) - XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 1) - XCTAssert(list.itemNumber(in: lists[1], at: ranges[1].location) == 2) - XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 4) + XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 0) + XCTAssert(list.itemNumber(in: lists[1], at: ranges[1].location) == 1) + XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 3) } @@ -318,7 +318,7 @@ class TextListFormatterTests: XCTestCase { XCTAssert(list!.style == .ordered) - XCTAssert(string.itemNumber(in: list!, at: range.location) == index + 1) + XCTAssert(string.itemNumber(in: list!, at: range.location) == index) } } @@ -356,7 +356,7 @@ class TextListFormatterTests: XCTestCase { } XCTAssert(list.style == .ordered) - XCTAssert(string.itemNumber(in: list, at: range.location) == index+1) + XCTAssert(string.itemNumber(in: list, at: range.location) == index) } } @@ -424,11 +424,10 @@ class TextListFormatterTests: XCTestCase { XCTAssert(items.count == 5) - XCTAssert(list.itemNumber(in: items[0], at: 0) == 1) - XCTAssert(list.itemNumber(in: items[0], at: 13) == 2) + XCTAssert(list.itemNumber(in: items[0], at: 0) == 0) + XCTAssert(list.itemNumber(in: items[0], at: 13) == 1) } - // Verifies that the `present(in: at:)` helper effectively returns true, as needed. // func testPresentInStorageAtIndexReturnsTrueWhenTextListIsEffectivelyThere() { diff --git a/CHANGELOG.md b/CHANGELOG.md index 3963a2b79..1551740aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +1.14.0 +----- +* Support standard HTML colors by name. +* Add support for reverse and start attributes for ordered lists. + 1.13.0 ----- * Fix a bug when copying and pasting from other apps when running dark mode. diff --git a/Example/Example/SampleContent/content.html b/Example/Example/SampleContent/content.html index 8b514b77f..a6a54eb1e 100644 --- a/Example/Example/SampleContent/content.html +++ b/Example/Example/SampleContent/content.html @@ -12,7 +12,7 @@

Character Styles

Italic: Italic text
Underline: Underlined text
Strikethrough: Strikethrough
-Colors: Colors
+Colors: Royal Blue by name Red by hex

Undeline with CSS: Alternative underline text
Links: I'm a link!
Open in new window link!
Code: print("Hello world") @@ -37,6 +37,27 @@

Ordered List:

  • Three
  • +

    Start in 10 List:

    +
      +
    1. Ten
    2. +
    3. Eleven
    4. +
    5. Twelve
    6. +
    + +

    Reversed List:

    +
      +
    1. Three
    2. +
    3. Two
    4. +
    5. One
    6. +
    + +

    Reversed Start in 10 List:

    +
      +
    1. Ten
    2. +
    3. Nine
    4. +
    5. Eight
    6. +
    +

    Nested lists:

      diff --git a/WordPress-Aztec-iOS.podspec b/WordPress-Aztec-iOS.podspec index f47992a34..58b356250 100644 --- a/WordPress-Aztec-iOS.podspec +++ b/WordPress-Aztec-iOS.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'WordPress-Aztec-iOS' - s.version = '1.13.0' + s.version = '1.14.0' s.summary = 'The native HTML Editor.' # This description is used to generate tags and improve search results. diff --git a/WordPress-Editor-iOS.podspec b/WordPress-Editor-iOS.podspec index 41f0eae62..a3157c5b5 100644 --- a/WordPress-Editor-iOS.podspec +++ b/WordPress-Editor-iOS.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'WordPress-Editor-iOS' - s.version = '1.13.0' + s.version = '1.14.0' s.summary = 'The WordPress HTML Editor.' # This description is used to generate tags and improve search results.