Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/harry/list item format #67

Merged
merged 5 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Sources/ZMarkupParser/Core/Markup/Markups/ListMarkup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ final class ListMarkup: Markup {
weak var parentMarkup: Markup? = nil
var childMarkups: [Markup] = []

let styleList: MarkupStyleList
init(styleList: MarkupStyleList) {
self.styleList = styleList
let startingItemNumber: Int
init(startingItemNumber: Int = 1) {
self.startingItemNumber = startingItemNumber
}

func accept<V>(_ visitor: V) -> V.Result where V : MarkupVisitor {
Expand Down
8 changes: 8 additions & 0 deletions Sources/ZMarkupParser/Core/MarkupStyle/MarkupStyleFont.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ public struct MarkupStyleFont: MarkupStyleItem {
italic,
familyName] as [Any?]).contains(where: { $0 != nil})
}

func sizeOf(string: String) -> CGSize? {
guard let font = getFont() else {
return nil
}

return (string as NSString).size(withAttributes: [.font: font])
}
}

#if canImport(UIKit)
Expand Down
230 changes: 143 additions & 87 deletions Sources/ZMarkupParser/Core/MarkupStyle/MarkupStyleList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,98 +12,154 @@ import UIKit
import AppKit
#endif

public struct MarkupStyleList {
let type: MarkupStyleType
let headIndentMultiply: CGFloat
let indentMultiply: CGFloat
let startingItemNumber: Int
public enum MarkupStyleType {
case octal
case lowercaseAlpha
case decimal
case lowercaseHexadecimal
case lowercaseLatin
case lowercaseRoman
case uppercaseAlpha
case uppercaseLatin
case uppercaseRoman
case uppercaseHexadecimal
case hyphen
case check
case circle
case disc
case diamond
case box
case square
case custom(String)

/// {headIndentMultiply} - {indentMultiply} List Item 1
/// {headIndentMultiply} - {indentMultiply} List Item 2
/// mutiply base size is current font size
public init(type: MarkupStyleType = .disc, headIndentMultiply: CGFloat = 0.25, indentMultiply: CGFloat = 0.5, startingItemNumber: Int = 1) {
self.type = type
self.headIndentMultiply = headIndentMultiply
self.startingItemNumber = startingItemNumber
self.indentMultiply = indentMultiply
public init?(format: NSTextList.MarkerFormat) {
switch format {
case .octal:
self = .octal
case .lowercaseAlpha:
self = .lowercaseAlpha
case .decimal:
self = .decimal
case .lowercaseHexadecimal:
self = .lowercaseHexadecimal
case .lowercaseLatin:
self = .lowercaseLatin
case .lowercaseRoman:
self = .lowercaseRoman
case .uppercaseAlpha:
self = .uppercaseAlpha
case .uppercaseLatin:
self = .uppercaseLatin
case .uppercaseRoman:
self = .uppercaseRoman
case .uppercaseHexadecimal:
self = .uppercaseHexadecimal
case .hyphen:
self = .hyphen
case .check:
self = .check
case .circle:
self = .circle
case .disc:
self = .disc
case .diamond:
self = .diamond
case .box:
self = .box
case .square:
self = .square
default:
return nil
}
}

func marker(forItemNumber: Int) -> String {
return type.marker(forItemNumber: forItemNumber, startingItemNumber: startingItemNumber)
func isOrder() -> Bool {
switch self {
case .octal,.lowercaseAlpha,.decimal,.lowercaseHexadecimal,.lowercaseLatin,.lowercaseRoman,.uppercaseAlpha,.uppercaseLatin,.uppercaseRoman,.uppercaseHexadecimal:
return true
case .hyphen, .check, .circle, .disc, .diamond, .box, .square, .custom:
return false
}
}

// due to tab width caculator, we can't provide custom(String)
public enum MarkupStyleType {
case octal
case lowercaseAlpha
case decimal
case lowercaseHexadecimal
case lowercaseLatin
case lowercaseRoman
case uppercaseAlpha
case uppercaseLatin
case uppercaseRoman
case uppercaseHexadecimal
case hyphen
case check
case circle
case disc
case diamond
case box
case square

func isOrder() -> Bool {
switch self {
case .octal,.lowercaseAlpha,.decimal,.lowercaseHexadecimal,.lowercaseLatin,.lowercaseRoman,.uppercaseAlpha,.uppercaseLatin,.uppercaseRoman,.uppercaseHexadecimal:
return true
case .hyphen, .check, .circle, .disc, .diamond, .box, .square:
return false
}
}

func marker(forItemNumber: Int, startingItemNumber: Int) -> String {
let textList: NSTextList
switch self {
case .octal:
textList = NSTextList(markerFormat: .octal, options: 0)
case .lowercaseAlpha:
textList = NSTextList(markerFormat: .lowercaseAlpha, options: 0)
case .decimal:
textList = NSTextList(markerFormat: .decimal, options: 0)
case .lowercaseHexadecimal:
textList = NSTextList(markerFormat: .lowercaseHexadecimal, options: 0)
case .lowercaseLatin:
textList = NSTextList(markerFormat: .lowercaseLatin, options: 0)
case .lowercaseRoman:
textList = NSTextList(markerFormat: .lowercaseRoman, options: 0)
case .uppercaseAlpha:
textList = NSTextList(markerFormat: .uppercaseAlpha, options: 0)
case .uppercaseLatin:
textList = NSTextList(markerFormat: .uppercaseLatin, options: 0)
case .uppercaseRoman:
textList = NSTextList(markerFormat: .uppercaseRoman, options: 0)
case .uppercaseHexadecimal:
textList = NSTextList(markerFormat: .uppercaseHexadecimal, options: 0)
case .hyphen:
textList = NSTextList(markerFormat: .hyphen, options: 0)
case .check:
textList = NSTextList(markerFormat: .check, options: 0)
case .circle:
textList = NSTextList(markerFormat: .circle, options: 0)
case .disc:
textList = NSTextList(markerFormat: .disc, options: 0)
case .diamond:
textList = NSTextList(markerFormat: .diamond, options: 0)
case .box:
textList = NSTextList(markerFormat: .box, options: 0)
case .square:
textList = NSTextList(markerFormat: .square, options: 0)
}

textList.startingItemNumber = startingItemNumber
let format = (isOrder()) ? ("\t%@.\t") : ("\t%@\t")
return String(format: format, textList.marker(forItemNumber: forItemNumber))
func getItem(startingItemNumber: Int, forItemNumber: Int) -> String {
// We only NSTextList to generate symbol, because NSTextList have abnormal extra spaces.
// ref: https://stackoverflow.com/questions/66714650/nstextlist-formatting
switch self {
case .octal:
let textList = NSTextList(markerFormat: .octal, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .lowercaseAlpha:
let textList = NSTextList(markerFormat: .lowercaseAlpha, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .decimal:
let textList = NSTextList(markerFormat: .decimal, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .lowercaseHexadecimal:
let textList = NSTextList(markerFormat: .lowercaseHexadecimal, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .lowercaseLatin:
let textList = NSTextList(markerFormat: .lowercaseLatin, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .lowercaseRoman:
let textList = NSTextList(markerFormat: .lowercaseRoman, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .uppercaseAlpha:
let textList = NSTextList(markerFormat: .uppercaseAlpha, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .uppercaseLatin:
let textList = NSTextList(markerFormat: .uppercaseLatin, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .uppercaseRoman:
let textList = NSTextList(markerFormat: .uppercaseRoman, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .uppercaseHexadecimal:
let textList = NSTextList(markerFormat: .uppercaseHexadecimal, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .hyphen:
let textList = NSTextList(markerFormat: .hyphen, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .check:
let textList = NSTextList(markerFormat: .check, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .circle:
let textList = NSTextList(markerFormat: .circle, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .disc:
let textList = NSTextList(markerFormat: .disc, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .diamond:
let textList = NSTextList(markerFormat: .diamond, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .box:
let textList = NSTextList(markerFormat: .box, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .square:
let textList = NSTextList(markerFormat: .square, options: 0)
textList.startingItemNumber = startingItemNumber
return textList.marker(forItemNumber: forItemNumber)
case .custom(let custom):
return custom
}
}


func getFormat() -> String {
return (isOrder()) ? ("\t%@.\t") : ("\t%@\t")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ public struct MarkupStyleParagraphStyle: MarkupStyleItem {
public var allowsDefaultTighteningForTruncation:Bool? = nil
public var lineBreakStrategy: NSParagraphStyle.LineBreakStrategy? = nil

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) {
public var textListStyleType: MarkupStyleType? = nil
public var textListHeadIndent: CGFloat? = nil
public var textListIndent: CGFloat? = nil


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) {
self.lineSpacing = lineSpacing
self.paragraphSpacing = paragraphSpacing
self.alignment = alignment
Expand All @@ -53,6 +58,10 @@ public struct MarkupStyleParagraphStyle: MarkupStyleItem {
self.textLists = textLists
self.allowsDefaultTighteningForTruncation = allowsDefaultTighteningForTruncation
self.lineBreakStrategy = lineBreakStrategy

self.textListStyleType = textListStyleType
self.textListHeadIndent = textListHeadIndent
self.textListIndent = textListIndent
}

public init(_ paragraphStyle: NSParagraphStyle) {
Expand Down Expand Up @@ -87,6 +96,12 @@ public struct MarkupStyleParagraphStyle: MarkupStyleItem {
self.textLists = paragraphStyle.textLists
self.allowsDefaultTighteningForTruncation = paragraphStyle.allowsDefaultTighteningForTruncation
self.lineBreakStrategy = paragraphStyle.lineBreakStrategy

if let firstTextListMarkerFromat = paragraphStyle.textLists.first?.markerFormat {
self.textListStyleType = .init(format: firstTextListMarkerFromat)
} else {
self.textListStyleType = nil
}
}

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

self.allowsDefaultTighteningForTruncation = self.allowsDefaultTighteningForTruncation ?? from?.allowsDefaultTighteningForTruncation
self.lineBreakStrategy = self.lineBreakStrategy ?? from?.lineBreakStrategy
self.textListStyleType = self.textListStyleType ?? from?.textListStyleType
self.textListIndent = self.textListIndent ?? from?.textListIndent
self.textListHeadIndent = self.textListHeadIndent ?? from?.textListHeadIndent
}

func isNil() -> Bool {
Expand All @@ -141,7 +159,10 @@ public struct MarkupStyleParagraphStyle: MarkupStyleItem {
defaultTabInterval,
textLists,
allowsDefaultTighteningForTruncation,
lineBreakStrategy] as [Any?]).contains(where: { $0 != nil})
lineBreakStrategy,
textListStyleType,
textListIndent,
textListHeadIndent] as [Any?]).contains(where: { $0 != nil})
}
}

Expand Down
Loading
Loading