Skip to content

Commit ebe9a95

Browse files
committed
Implement start and reversed in lists.
1 parent cd80f36 commit ebe9a95

7 files changed

Lines changed: 76 additions & 22 deletions

File tree

Aztec/Classes/Extensions/NSAttributedString+Lists.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ extension NSAttributedString {
8686
guard let rangeOfList = range(of:list, at: location) else {
8787
return NSNotFound
8888
}
89-
var numberInList = 1
89+
var numberInList = 0
9090
let paragraphRanges = self.paragraphRanges(intersecting: rangeOfList)
9191

9292
for (_, enclosingRange) in paragraphRanges {

Aztec/Classes/Libxml2/DOM/Data/AttributeType.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,6 @@ extension AttributeType {
3636
public static let src = AttributeType("src")
3737
public static let style = AttributeType("style")
3838
public static let target = AttributeType("target")
39+
public static let reversed = AttributeType("reversed")
40+
public static let start = AttributeType("start")
3941
}

Aztec/Classes/NSAttributedString/Conversions/AttributedStringParser.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,15 @@ private extension AttributedStringParser {
765765
listElement = element.toElementNode()
766766
} else {
767767
listElement = ElementNode(type: listType)
768+
if list.style == .ordered {
769+
if list.reversed {
770+
listElement.updateAttribute(named: "reversed", value: .none)
771+
}
772+
773+
if list.start != 1 {
774+
listElement.updateAttribute(named: "start", value: .string("\(list.start)"))
775+
}
776+
}
768777
}
769778

770779
return listElement

Aztec/Classes/TextKit/LayoutManager.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,12 @@ private extension LayoutManager {
210210

211211
let glyphRange = self.glyphRange(forCharacterRange: enclosingRange, actualCharacterRange: nil)
212212
let markerRect = rectForItem(range: glyphRange, origin: origin, paragraphStyle: paragraphStyle)
213-
let markerNumber = textStorage.itemNumber(in: list, at: enclosingRange.location)
214-
213+
var markerNumber = textStorage.itemNumber(in: list, at: enclosingRange.location)
214+
if list.reversed {
215+
markerNumber = -markerNumber
216+
}
217+
markerNumber += list.start
218+
215219
drawItem(number: markerNumber, in: markerRect, from: list, using: paragraphStyle, at: enclosingRange.location)
216220
}
217221
}

Aztec/Classes/TextKit/ParagraphProperty/TextList.swift

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,31 @@ open class TextList: ParagraphProperty {
2222
}
2323
}
2424

25+
public let reversed: Bool
26+
27+
public let start: Int
28+
2529
// MARK: - Properties
2630

2731
/// Kind of List: Ordered / Unordered
2832
///
2933
let style: Style
3034

31-
init(style: Style, with representation: HTMLRepresentation? = nil) {
35+
init(style: Style, start: Int = 1, reversed: Bool = false, with representation: HTMLRepresentation? = nil) {
3236
self.style = style
37+
38+
if let representation = representation, case let .element( html ) = representation.kind {
39+
self.reversed = html.attribute(ofType: .reversed) != nil
40+
41+
if let startAttribute = html.attribute(ofType: .start), case let .string( value ) = startAttribute.value, let start = Int(value) {
42+
self.start = start
43+
} else {
44+
self.start = 1
45+
}
46+
} else {
47+
self.start = start
48+
self.reversed = reversed
49+
}
3350
super.init(with: representation)
3451
}
3552

@@ -40,15 +57,31 @@ open class TextList: ParagraphProperty {
4057
} else {
4158
style = .ordered
4259
}
60+
if aDecoder.containsValue(forKey: AttributeType.start.rawValue) {
61+
let decodedStart = aDecoder.decodeInteger(forKey: AttributeType.start.rawValue)
62+
start = decodedStart
63+
} else {
64+
start = 1
65+
}
66+
67+
if aDecoder.containsValue(forKey: AttributeType.reversed.rawValue) {
68+
let decodedReversed = aDecoder.decodeBool(forKey: AttributeType.reversed.rawValue)
69+
reversed = decodedReversed
70+
} else {
71+
reversed = false
72+
}
73+
4374
super.init(coder: aDecoder)
4475
}
4576

4677
public override func encode(with aCoder: NSCoder) {
4778
super.encode(with: aCoder)
4879
aCoder.encode(style.rawValue, forKey: String(describing: Style.self))
80+
aCoder.encode(start, forKey: AttributeType.start.rawValue)
81+
aCoder.encode(reversed, forKey: AttributeType.reversed.rawValue)
4982
}
5083

5184
public static func ==(lhs: TextList, rhs: TextList) -> Bool {
52-
return lhs.style == rhs.style
85+
return lhs.style == rhs.style && lhs.start == rhs.start && lhs.reversed == rhs.reversed
5386
}
5487
}

AztecTests/Formatters/TextListFormatterTests.swift

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ class TextListFormatterTests: XCTestCase {
3333
XCTAssert(lists[2].style == .unordered)
3434
XCTAssert(lists[3].style == .ordered)
3535

36-
XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 1)
37-
XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 1)
36+
XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 0)
37+
XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 0)
3838
}
3939

4040
// Helpers #2:
@@ -64,7 +64,7 @@ class TextListFormatterTests: XCTestCase {
6464
}
6565

6666
for (index, textList) in lists.enumerated() {
67-
XCTAssert(list.itemNumber(in: textList, at: ranges[index].location) == index + 1)
67+
XCTAssert(list.itemNumber(in: textList, at: ranges[index].location) == index)
6868
}
6969
}
7070

@@ -92,7 +92,7 @@ class TextListFormatterTests: XCTestCase {
9292
XCTAssert(lists.count == 1)
9393

9494
XCTAssert(lists[0].style == .ordered)
95-
XCTAssert(string.itemNumber(in: lists[0], at: ranges[0].location) == 1)
95+
XCTAssert(string.itemNumber(in: lists[0], at: ranges[0].location) == 0)
9696
}
9797

9898

@@ -152,7 +152,7 @@ class TextListFormatterTests: XCTestCase {
152152
}
153153

154154
for (index, textList) in lists.enumerated() {
155-
XCTAssertEqual(list.itemNumber(in: textList, at: ranges[index+1].location), index + 1)
155+
XCTAssertEqual(list.itemNumber(in: textList, at: ranges[index+1].location), index)
156156
}
157157
}
158158

@@ -185,7 +185,7 @@ class TextListFormatterTests: XCTestCase {
185185
XCTAssert(lists[2].style == .ordered)
186186
XCTAssert(lists[3].style == .unordered)
187187

188-
XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 1)
188+
XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 0)
189189
XCTAssertEqual(list.itemNumber(in: lists[2], at: ranges[2].location), NSNotFound)
190190
}
191191

@@ -246,9 +246,9 @@ class TextListFormatterTests: XCTestCase {
246246
XCTAssert(lists[2].style == .unordered)
247247
XCTAssert(lists[3].style == .ordered)
248248

249-
XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 1)
250-
XCTAssert(list.itemNumber(in: lists[1], at: ranges[1].location) == 2)
251-
XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 1)
249+
XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 0)
250+
XCTAssert(list.itemNumber(in: lists[1], at: ranges[1].location) == 1)
251+
XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 0)
252252
}
253253

254254

@@ -280,9 +280,9 @@ class TextListFormatterTests: XCTestCase {
280280
XCTAssert(lists[3].style == .ordered)
281281
XCTAssert(lists[4].style == .ordered)
282282

283-
XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 1)
284-
XCTAssert(list.itemNumber(in: lists[1], at: ranges[1].location) == 2)
285-
XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 4)
283+
XCTAssert(list.itemNumber(in: lists[0], at: ranges[0].location) == 0)
284+
XCTAssert(list.itemNumber(in: lists[1], at: ranges[1].location) == 1)
285+
XCTAssert(list.itemNumber(in: lists[3], at: ranges[3].location) == 3)
286286

287287
}
288288

@@ -318,7 +318,7 @@ class TextListFormatterTests: XCTestCase {
318318
XCTAssert(list!.style == .ordered)
319319

320320

321-
XCTAssert(string.itemNumber(in: list!, at: range.location) == index + 1)
321+
XCTAssert(string.itemNumber(in: list!, at: range.location) == index)
322322
}
323323
}
324324

@@ -356,7 +356,7 @@ class TextListFormatterTests: XCTestCase {
356356
}
357357

358358
XCTAssert(list.style == .ordered)
359-
XCTAssert(string.itemNumber(in: list, at: range.location) == index+1)
359+
XCTAssert(string.itemNumber(in: list, at: range.location) == index)
360360
}
361361
}
362362

@@ -424,11 +424,10 @@ class TextListFormatterTests: XCTestCase {
424424

425425
XCTAssert(items.count == 5)
426426

427-
XCTAssert(list.itemNumber(in: items[0], at: 0) == 1)
428-
XCTAssert(list.itemNumber(in: items[0], at: 13) == 2)
427+
XCTAssert(list.itemNumber(in: items[0], at: 0) == 0)
428+
XCTAssert(list.itemNumber(in: items[0], at: 13) == 1)
429429
}
430430

431-
432431
// Verifies that the `present(in: at:)` helper effectively returns true, as needed.
433432
//
434433
func testPresentInStorageAtIndexReturnsTrueWhenTextListIsEffectivelyThere() {

Example/Example/SampleContent/content.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ <h4>Ordered List:</h4>
3737
<li>Three</li>
3838
</ol>
3939

40+
<h4>Reversed List:</h4>
41+
<ol reversed start="10">
42+
<li>One</li>
43+
<li>Two</li>
44+
<li>Three</li>
45+
</ol>
46+
4047
<h4>Nested lists:</h4>
4148

4249
<ol>

0 commit comments

Comments
 (0)