Skip to content

Commit d823252

Browse files
authored
Merge pull request #67 from ZhgChgLi/feature/harry/list-item-format
Feature/harry/list item format
2 parents 9e8132c + 50094b1 commit d823252

30 files changed

+421
-188
lines changed

Sources/ZMarkupParser/Core/Markup/Markups/ListMarkup.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ final class ListMarkup: Markup {
1111
weak var parentMarkup: Markup? = nil
1212
var childMarkups: [Markup] = []
1313

14-
let styleList: MarkupStyleList
15-
init(styleList: MarkupStyleList) {
16-
self.styleList = styleList
14+
let startingItemNumber: Int
15+
init(startingItemNumber: Int = 1) {
16+
self.startingItemNumber = startingItemNumber
1717
}
1818

1919
func accept<V>(_ visitor: V) -> V.Result where V : MarkupVisitor {

Sources/ZMarkupParser/Core/MarkupStyle/MarkupStyleFont.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ public struct MarkupStyleFont: MarkupStyleItem {
122122
italic,
123123
familyName] as [Any?]).contains(where: { $0 != nil})
124124
}
125+
126+
func sizeOf(string: String) -> CGSize? {
127+
guard let font = getFont() else {
128+
return nil
129+
}
130+
131+
return (string as NSString).size(withAttributes: [.font: font])
132+
}
125133
}
126134

127135
#if canImport(UIKit)

Sources/ZMarkupParser/Core/MarkupStyle/MarkupStyleList.swift

Lines changed: 143 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -12,98 +12,154 @@ import UIKit
1212
import AppKit
1313
#endif
1414

15-
public struct MarkupStyleList {
16-
let type: MarkupStyleType
17-
let headIndentMultiply: CGFloat
18-
let indentMultiply: CGFloat
19-
let startingItemNumber: Int
15+
public enum MarkupStyleType {
16+
case octal
17+
case lowercaseAlpha
18+
case decimal
19+
case lowercaseHexadecimal
20+
case lowercaseLatin
21+
case lowercaseRoman
22+
case uppercaseAlpha
23+
case uppercaseLatin
24+
case uppercaseRoman
25+
case uppercaseHexadecimal
26+
case hyphen
27+
case check
28+
case circle
29+
case disc
30+
case diamond
31+
case box
32+
case square
33+
case custom(String)
2034

21-
/// {headIndentMultiply} - {indentMultiply} List Item 1
22-
/// {headIndentMultiply} - {indentMultiply} List Item 2
23-
/// mutiply base size is current font size
24-
public init(type: MarkupStyleType = .disc, headIndentMultiply: CGFloat = 0.25, indentMultiply: CGFloat = 0.5, startingItemNumber: Int = 1) {
25-
self.type = type
26-
self.headIndentMultiply = headIndentMultiply
27-
self.startingItemNumber = startingItemNumber
28-
self.indentMultiply = indentMultiply
35+
public init?(format: NSTextList.MarkerFormat) {
36+
switch format {
37+
case .octal:
38+
self = .octal
39+
case .lowercaseAlpha:
40+
self = .lowercaseAlpha
41+
case .decimal:
42+
self = .decimal
43+
case .lowercaseHexadecimal:
44+
self = .lowercaseHexadecimal
45+
case .lowercaseLatin:
46+
self = .lowercaseLatin
47+
case .lowercaseRoman:
48+
self = .lowercaseRoman
49+
case .uppercaseAlpha:
50+
self = .uppercaseAlpha
51+
case .uppercaseLatin:
52+
self = .uppercaseLatin
53+
case .uppercaseRoman:
54+
self = .uppercaseRoman
55+
case .uppercaseHexadecimal:
56+
self = .uppercaseHexadecimal
57+
case .hyphen:
58+
self = .hyphen
59+
case .check:
60+
self = .check
61+
case .circle:
62+
self = .circle
63+
case .disc:
64+
self = .disc
65+
case .diamond:
66+
self = .diamond
67+
case .box:
68+
self = .box
69+
case .square:
70+
self = .square
71+
default:
72+
return nil
73+
}
2974
}
3075

31-
func marker(forItemNumber: Int) -> String {
32-
return type.marker(forItemNumber: forItemNumber, startingItemNumber: startingItemNumber)
76+
func isOrder() -> Bool {
77+
switch self {
78+
case .octal,.lowercaseAlpha,.decimal,.lowercaseHexadecimal,.lowercaseLatin,.lowercaseRoman,.uppercaseAlpha,.uppercaseLatin,.uppercaseRoman,.uppercaseHexadecimal:
79+
return true
80+
case .hyphen, .check, .circle, .disc, .diamond, .box, .square, .custom:
81+
return false
82+
}
3383
}
3484

35-
// due to tab width caculator, we can't provide custom(String)
36-
public enum MarkupStyleType {
37-
case octal
38-
case lowercaseAlpha
39-
case decimal
40-
case lowercaseHexadecimal
41-
case lowercaseLatin
42-
case lowercaseRoman
43-
case uppercaseAlpha
44-
case uppercaseLatin
45-
case uppercaseRoman
46-
case uppercaseHexadecimal
47-
case hyphen
48-
case check
49-
case circle
50-
case disc
51-
case diamond
52-
case box
53-
case square
54-
55-
func isOrder() -> Bool {
56-
switch self {
57-
case .octal,.lowercaseAlpha,.decimal,.lowercaseHexadecimal,.lowercaseLatin,.lowercaseRoman,.uppercaseAlpha,.uppercaseLatin,.uppercaseRoman,.uppercaseHexadecimal:
58-
return true
59-
case .hyphen, .check, .circle, .disc, .diamond, .box, .square:
60-
return false
61-
}
62-
}
63-
64-
func marker(forItemNumber: Int, startingItemNumber: Int) -> String {
65-
let textList: NSTextList
66-
switch self {
67-
case .octal:
68-
textList = NSTextList(markerFormat: .octal, options: 0)
69-
case .lowercaseAlpha:
70-
textList = NSTextList(markerFormat: .lowercaseAlpha, options: 0)
71-
case .decimal:
72-
textList = NSTextList(markerFormat: .decimal, options: 0)
73-
case .lowercaseHexadecimal:
74-
textList = NSTextList(markerFormat: .lowercaseHexadecimal, options: 0)
75-
case .lowercaseLatin:
76-
textList = NSTextList(markerFormat: .lowercaseLatin, options: 0)
77-
case .lowercaseRoman:
78-
textList = NSTextList(markerFormat: .lowercaseRoman, options: 0)
79-
case .uppercaseAlpha:
80-
textList = NSTextList(markerFormat: .uppercaseAlpha, options: 0)
81-
case .uppercaseLatin:
82-
textList = NSTextList(markerFormat: .uppercaseLatin, options: 0)
83-
case .uppercaseRoman:
84-
textList = NSTextList(markerFormat: .uppercaseRoman, options: 0)
85-
case .uppercaseHexadecimal:
86-
textList = NSTextList(markerFormat: .uppercaseHexadecimal, options: 0)
87-
case .hyphen:
88-
textList = NSTextList(markerFormat: .hyphen, options: 0)
89-
case .check:
90-
textList = NSTextList(markerFormat: .check, options: 0)
91-
case .circle:
92-
textList = NSTextList(markerFormat: .circle, options: 0)
93-
case .disc:
94-
textList = NSTextList(markerFormat: .disc, options: 0)
95-
case .diamond:
96-
textList = NSTextList(markerFormat: .diamond, options: 0)
97-
case .box:
98-
textList = NSTextList(markerFormat: .box, options: 0)
99-
case .square:
100-
textList = NSTextList(markerFormat: .square, options: 0)
101-
}
102-
103-
textList.startingItemNumber = startingItemNumber
104-
let format = (isOrder()) ? ("\t%@.\t") : ("\t%@\t")
105-
return String(format: format, textList.marker(forItemNumber: forItemNumber))
85+
func getItem(startingItemNumber: Int, forItemNumber: Int) -> String {
86+
// We only NSTextList to generate symbol, because NSTextList have abnormal extra spaces.
87+
// ref: https://stackoverflow.com/questions/66714650/nstextlist-formatting
88+
switch self {
89+
case .octal:
90+
let textList = NSTextList(markerFormat: .octal, options: 0)
91+
textList.startingItemNumber = startingItemNumber
92+
return textList.marker(forItemNumber: forItemNumber)
93+
case .lowercaseAlpha:
94+
let textList = NSTextList(markerFormat: .lowercaseAlpha, options: 0)
95+
textList.startingItemNumber = startingItemNumber
96+
return textList.marker(forItemNumber: forItemNumber)
97+
case .decimal:
98+
let textList = NSTextList(markerFormat: .decimal, options: 0)
99+
textList.startingItemNumber = startingItemNumber
100+
return textList.marker(forItemNumber: forItemNumber)
101+
case .lowercaseHexadecimal:
102+
let textList = NSTextList(markerFormat: .lowercaseHexadecimal, options: 0)
103+
textList.startingItemNumber = startingItemNumber
104+
return textList.marker(forItemNumber: forItemNumber)
105+
case .lowercaseLatin:
106+
let textList = NSTextList(markerFormat: .lowercaseLatin, options: 0)
107+
textList.startingItemNumber = startingItemNumber
108+
return textList.marker(forItemNumber: forItemNumber)
109+
case .lowercaseRoman:
110+
let textList = NSTextList(markerFormat: .lowercaseRoman, options: 0)
111+
textList.startingItemNumber = startingItemNumber
112+
return textList.marker(forItemNumber: forItemNumber)
113+
case .uppercaseAlpha:
114+
let textList = NSTextList(markerFormat: .uppercaseAlpha, options: 0)
115+
textList.startingItemNumber = startingItemNumber
116+
return textList.marker(forItemNumber: forItemNumber)
117+
case .uppercaseLatin:
118+
let textList = NSTextList(markerFormat: .uppercaseLatin, options: 0)
119+
textList.startingItemNumber = startingItemNumber
120+
return textList.marker(forItemNumber: forItemNumber)
121+
case .uppercaseRoman:
122+
let textList = NSTextList(markerFormat: .uppercaseRoman, options: 0)
123+
textList.startingItemNumber = startingItemNumber
124+
return textList.marker(forItemNumber: forItemNumber)
125+
case .uppercaseHexadecimal:
126+
let textList = NSTextList(markerFormat: .uppercaseHexadecimal, options: 0)
127+
textList.startingItemNumber = startingItemNumber
128+
return textList.marker(forItemNumber: forItemNumber)
129+
case .hyphen:
130+
let textList = NSTextList(markerFormat: .hyphen, options: 0)
131+
textList.startingItemNumber = startingItemNumber
132+
return textList.marker(forItemNumber: forItemNumber)
133+
case .check:
134+
let textList = NSTextList(markerFormat: .check, options: 0)
135+
textList.startingItemNumber = startingItemNumber
136+
return textList.marker(forItemNumber: forItemNumber)
137+
case .circle:
138+
let textList = NSTextList(markerFormat: .circle, options: 0)
139+
textList.startingItemNumber = startingItemNumber
140+
return textList.marker(forItemNumber: forItemNumber)
141+
case .disc:
142+
let textList = NSTextList(markerFormat: .disc, options: 0)
143+
textList.startingItemNumber = startingItemNumber
144+
return textList.marker(forItemNumber: forItemNumber)
145+
case .diamond:
146+
let textList = NSTextList(markerFormat: .diamond, options: 0)
147+
textList.startingItemNumber = startingItemNumber
148+
return textList.marker(forItemNumber: forItemNumber)
149+
case .box:
150+
let textList = NSTextList(markerFormat: .box, options: 0)
151+
textList.startingItemNumber = startingItemNumber
152+
return textList.marker(forItemNumber: forItemNumber)
153+
case .square:
154+
let textList = NSTextList(markerFormat: .square, options: 0)
155+
textList.startingItemNumber = startingItemNumber
156+
return textList.marker(forItemNumber: forItemNumber)
157+
case .custom(let custom):
158+
return custom
106159
}
107160
}
108-
161+
162+
func getFormat() -> String {
163+
return (isOrder()) ? ("\t%@.\t") : ("\t%@\t")
164+
}
109165
}

Sources/ZMarkupParser/Core/MarkupStyle/MarkupStyleParagraphStyle.swift

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ public struct MarkupStyleParagraphStyle: MarkupStyleItem {
3333
public var allowsDefaultTighteningForTruncation:Bool? = nil
3434
public var lineBreakStrategy: NSParagraphStyle.LineBreakStrategy? = nil
3535

36-
public init(lineSpacing: CGFloat? = nil, paragraphSpacing: CGFloat? = nil, alignment: NSTextAlignment? = nil, headIndent: CGFloat? = nil, tailIndent: CGFloat? = nil, firstLineHeadIndent: CGFloat? = nil, minimumLineHeight: CGFloat? = nil, maximumLineHeight: CGFloat? = nil, lineBreakMode: NSLineBreakMode? = nil, baseWritingDirection: NSWritingDirection? = nil, lineHeightMultiple: CGFloat? = nil, paragraphSpacingBefore: CGFloat? = nil, hyphenationFactor: Float? = nil, usesDefaultHyphenation: Bool? = nil, tabStops: [NSTextTab]? = nil, defaultTabInterval: CGFloat? = nil, textLists: [NSTextList]? = nil, allowsDefaultTighteningForTruncation: Bool? = nil, lineBreakStrategy: NSParagraphStyle.LineBreakStrategy? = nil) {
36+
public var textListStyleType: MarkupStyleType? = nil
37+
public var textListHeadIndent: CGFloat? = nil
38+
public var textListIndent: CGFloat? = nil
39+
40+
41+
public init(lineSpacing: CGFloat? = nil, paragraphSpacing: CGFloat? = nil, alignment: NSTextAlignment? = nil, headIndent: CGFloat? = nil, tailIndent: CGFloat? = nil, firstLineHeadIndent: CGFloat? = nil, minimumLineHeight: CGFloat? = nil, maximumLineHeight: CGFloat? = nil, lineBreakMode: NSLineBreakMode? = nil, baseWritingDirection: NSWritingDirection? = nil, lineHeightMultiple: CGFloat? = nil, paragraphSpacingBefore: CGFloat? = nil, hyphenationFactor: Float? = nil, usesDefaultHyphenation: Bool? = nil, tabStops: [NSTextTab]? = nil, defaultTabInterval: CGFloat? = nil, textLists: [NSTextList]? = nil, allowsDefaultTighteningForTruncation: Bool? = nil, lineBreakStrategy: NSParagraphStyle.LineBreakStrategy? = nil, textListStyleType: MarkupStyleType? = nil, textListHeadIndent: CGFloat? = nil, textListIndent: CGFloat? = nil) {
3742
self.lineSpacing = lineSpacing
3843
self.paragraphSpacing = paragraphSpacing
3944
self.alignment = alignment
@@ -53,6 +58,10 @@ public struct MarkupStyleParagraphStyle: MarkupStyleItem {
5358
self.textLists = textLists
5459
self.allowsDefaultTighteningForTruncation = allowsDefaultTighteningForTruncation
5560
self.lineBreakStrategy = lineBreakStrategy
61+
62+
self.textListStyleType = textListStyleType
63+
self.textListHeadIndent = textListHeadIndent
64+
self.textListIndent = textListIndent
5665
}
5766

5867
public init(_ paragraphStyle: NSParagraphStyle) {
@@ -87,6 +96,12 @@ public struct MarkupStyleParagraphStyle: MarkupStyleItem {
8796
self.textLists = paragraphStyle.textLists
8897
self.allowsDefaultTighteningForTruncation = paragraphStyle.allowsDefaultTighteningForTruncation
8998
self.lineBreakStrategy = paragraphStyle.lineBreakStrategy
99+
100+
if let firstTextListMarkerFromat = paragraphStyle.textLists.first?.markerFormat {
101+
self.textListStyleType = .init(format: firstTextListMarkerFromat)
102+
} else {
103+
self.textListStyleType = nil
104+
}
90105
}
91106

92107
mutating func fillIfNil(from: MarkupStyleParagraphStyle?) {
@@ -120,6 +135,9 @@ public struct MarkupStyleParagraphStyle: MarkupStyleItem {
120135

121136
self.allowsDefaultTighteningForTruncation = self.allowsDefaultTighteningForTruncation ?? from?.allowsDefaultTighteningForTruncation
122137
self.lineBreakStrategy = self.lineBreakStrategy ?? from?.lineBreakStrategy
138+
self.textListStyleType = self.textListStyleType ?? from?.textListStyleType
139+
self.textListIndent = self.textListIndent ?? from?.textListIndent
140+
self.textListHeadIndent = self.textListHeadIndent ?? from?.textListHeadIndent
123141
}
124142

125143
func isNil() -> Bool {
@@ -141,7 +159,10 @@ public struct MarkupStyleParagraphStyle: MarkupStyleItem {
141159
defaultTabInterval,
142160
textLists,
143161
allowsDefaultTighteningForTruncation,
144-
lineBreakStrategy] as [Any?]).contains(where: { $0 != nil})
162+
lineBreakStrategy,
163+
textListStyleType,
164+
textListIndent,
165+
textListHeadIndent] as [Any?]).contains(where: { $0 != nil})
145166
}
146167
}
147168

0 commit comments

Comments
 (0)