Skip to content
Merged
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
69 changes: 31 additions & 38 deletions Utils/Utils/String/String+Attributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import UIKit

/// Attributes for string.
public enum StringAttribute {
/// Text line spacing
/// Text line spacing (paragraphStyle.lineSpacing)
case lineSpacing(CGFloat)
/// Letter spacing
case kern(CGFloat)
Expand All @@ -27,12 +27,11 @@ public enum StringAttribute {
case lineBreakMode(NSLineBreakMode)
/// Text base line offset (vertical)
case baselineOffset(CGFloat)

/// Figma friendly case means that lineSpacing = lineHeight - font.lineHeight
/// This case provide possibility to set both `font` and `lineSpacing`
/// First parameter is Font and second parameter is lineHeight property from Figma
/// For more details see [#14](https://github.com/surfstudio/iOS-Utils/issues/14)
case lineHeight(CGFloat, font: UIFont)
/// Text line height, in points.
///
/// If you also specify `.font` value, then will be used `paragraph.lineHeightMultiple`,
/// otherwise - `paragraph.minimumLineHeight` and `paragraph.maximumLineHeight`
case lineHeight(CGFloat)
}

// MARK: - Nested types
Expand Down Expand Up @@ -97,8 +96,8 @@ extension StringAttribute {
return value
case .aligment(let value):
return value
case .lineHeight(let lineHeight, let font):
return lineHeight - font.lineHeight
case .lineHeight(let value):
return value
case .crossOut(let style):
return style.coreValue.rawValue
case .lineBreakMode(let value):
Expand Down Expand Up @@ -142,12 +141,8 @@ public extension StringAttribute {
let mutableParagraphStyle = value as? NSMutableParagraphStyle {
stringAttributedArray.append(.aligment(mutableParagraphStyle.alignment))
stringAttributedArray.append(.lineBreakMode(mutableParagraphStyle.lineBreakMode))

if let font = dictionary[.font] as? UIFont {
stringAttributedArray.append(.lineHeight(mutableParagraphStyle.lineSpacing, font: font))
} else {
stringAttributedArray.append(.lineSpacing(mutableParagraphStyle.lineSpacing))
}
stringAttributedArray.append(.lineHeight(mutableParagraphStyle.minimumLineHeight))
stringAttributedArray.append(.lineSpacing(mutableParagraphStyle.lineSpacing))
}

return stringAttributedArray
Expand All @@ -163,35 +158,21 @@ public extension String {
}
}

// MARK: - Private array extension

private extension Array where Element == StringAttribute {
func normalizedAttributes() -> [StringAttribute] {
var result = [StringAttribute](self)

self.forEach { item in
switch item {
case .lineHeight(_, let font):
result.append(.font(font))
default:
break
}
}

return result
}
}

// MARK: - Public array extension
// MARK: - Array extension

public extension Array where Element == StringAttribute {
func toDictionary() -> [NSAttributedString.Key: Any] {
var resultAttributes = [NSAttributedString.Key: Any]()
let paragraph = NSMutableParagraphStyle()
for attribute in self.normalizedAttributes() {
for attribute in self {
switch attribute {
case .lineHeight(let lineHeight, let font):
paragraph.lineSpacing = lineHeight - font.lineHeight
case .lineHeight(let lineHeight):
if let font = self.findFont() {
paragraph.lineHeightMultiple = lineHeight / font.lineHeight
} else {
paragraph.minimumLineHeight = lineHeight
paragraph.maximumLineHeight = lineHeight
}
resultAttributes[attribute.attributeKey] = paragraph
case .lineSpacing(let value):
paragraph.lineSpacing = value
Expand All @@ -208,4 +189,16 @@ public extension Array where Element == StringAttribute {
}
return resultAttributes
}

// MARK: - Private Methods

/// Returns font from array of StringAttributes, if it exists, and nil otherwise
private func findFont() -> UIFont? {
for value in self {
if case .font(let font) = value {
return font
}
}
return nil
}
}