Skip to content

Commit

Permalink
result builder (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanPodymov committed Mar 16, 2023
1 parent 295b17e commit 3951ee4
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.1
// swift-tools-version:5.4

import PackageDescription

Expand Down
2 changes: 1 addition & 1 deletion SwiftyAttributes.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ Pod::Spec.new do |s|
s.tvos.deployment_target = '9.0'
s.watchos.deployment_target = '2.0'

s.swift_versions = ['5.0', '5.1']
s.swift_versions = ['5.0', '5.1', '5.4']
end
4 changes: 4 additions & 0 deletions SwiftyAttributes.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
9E04C4D126EA09A5009BA429 /* SwiftyAttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E04C4D026EA09A5009BA429 /* SwiftyAttributedStringBuilder.swift */; };
9E0DA889229B2F8600E29BFD /* UIKit+SwiftyAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E0DA888229B2F8600E29BFD /* UIKit+SwiftyAttributes.swift */; };
9E0DA88E229B34D800E29BFD /* UIKit+SwiftyAttributes_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E0DA88D229B34D800E29BFD /* UIKit+SwiftyAttributes_Tests.swift */; };
9E28077022A424320097CE8A /* NSString+macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E28076F22A424320097CE8A /* NSString+macOS.swift */; };
Expand Down Expand Up @@ -74,6 +75,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
9E04C4D026EA09A5009BA429 /* SwiftyAttributedStringBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftyAttributedStringBuilder.swift; path = common/SwiftyAttributedStringBuilder.swift; sourceTree = "<group>"; };
9E0DA888229B2F8600E29BFD /* UIKit+SwiftyAttributes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIKit+SwiftyAttributes.swift"; sourceTree = "<group>"; };
9E0DA88D229B34D800E29BFD /* UIKit+SwiftyAttributes_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIKit+SwiftyAttributes_Tests.swift"; sourceTree = "<group>"; };
9E28076F22A424320097CE8A /* NSString+macOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSString+macOS.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -249,6 +251,7 @@
9EB6D1A222A1CAC200D00CFC /* NSString+SwiftyAttributes.swift */,
C05082241DFA72F700D39B3B /* Operators.swift */,
C05082251DFA72F700D39B3B /* String+SwiftyAttributes.swift */,
9E04C4D026EA09A5009BA429 /* SwiftyAttributedStringBuilder.swift */,
C05082261DFA72F700D39B3B /* TextEffect.swift */,
C05082271DFA72F700D39B3B /* VerticalGlyphForm.swift */,
C05082281DFA72F700D39B3B /* WritingDirection.swift */,
Expand Down Expand Up @@ -479,6 +482,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9E04C4D126EA09A5009BA429 /* SwiftyAttributedStringBuilder.swift in Sources */,
C050822A1DFA72F700D39B3B /* Attribute.swift in Sources */,
C050822F1DFA72F700D39B3B /* Operators.swift in Sources */,
C050822E1DFA72F700D39B3B /* NSMutableAttributedString+SwiftyAttributes.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ extension NSAttributedString {
self.init(string: str, attributes: dictionary(from: attrs))
}

#if swift(>=5.4)
/**
Creates a new `NSAttributedString` with the specified attributes.
- parameter str: The string for the new attributed string.
- parameter swiftyAttributes: The attributes for the new attributed string.
*/
public convenience init(string str: String, @SwiftyAttributedStringBuilder swiftyAttributes attrs: () -> [NSAttributedString.Key: Any]) {
self.init(string: str, attributes: attrs())
}
#endif

/**
Returns an attributed string with the specified attributes added.
Expand All @@ -40,6 +52,20 @@ extension NSAttributedString {
return mutable
}

#if swift(>=5.4)
/**
Returns an attributed string with the specified attributes added.
- parameter attributes: The attributes to add to the new attributed string.
- returns: An `NSMutableAttributedString` with the new attributes applied.
*/
public func withAttributes(@SwiftyAttributedStringBuilder _ attributes: () -> [NSAttributedString.Key: Any]) -> NSMutableAttributedString {
let mutable = mutableCopy() as! NSMutableAttributedString
mutable.addAttributes(attributes(), range: NSRange(location: 0, length: length))
return mutable
}
#endif

/**
Returns an attributed string with the specified attribute added.
Expand Down
12 changes: 12 additions & 0 deletions SwiftyAttributes/Sources/common/String+SwiftyAttributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ extension String {
return attributedString.withAttributes(attributes)
}

#if swift(>=5.4)
/**
Returns an attributed string with the specified attributes added.
- parameter attributes: The attributes to add to the new attributed string.
- returns: An `NSMutableAttributedString` with the new attributes applied.
*/
public func withAttributes(@SwiftyAttributedStringBuilder _ attributes: () -> [NSAttributedString.Key: Any]) -> NSMutableAttributedString {
return attributedString.withAttributes(attributes)
}
#endif

/**
Returns an attributed string with the specified attribute added.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// SwiftyAttributedStringBuilder.swift
// SwiftyAttributes
//
// Created by Roman Podymov on 09/09/21.
// Copyright © 2021 Roman Podymov. All rights reserved.
//

#if swift(>=5.4)
import Foundation

public protocol AttributesProvider {
var attributes: [Attribute] { get }
}

extension Attribute: AttributesProvider {
public var attributes: [Attribute] { [self] }
}

extension Array: AttributesProvider where Element == Attribute {
public var attributes: [Attribute] { self }
}

@resultBuilder
public struct SwiftyAttributedStringBuilder {
public static func buildBlock(_ components: AttributesProvider...) -> [Attribute] {
components.flatMap { $0.attributes }
}

public static func buildEither(first components: [AttributesProvider]) -> [Attribute] {
components.flatMap { $0.attributes }
}

public static func buildEither(second components: [AttributesProvider]) -> [Attribute] {
components.flatMap { $0.attributes }
}

public static func buildOptional(_ components: [Attribute]?) -> [Attribute] {
components?.flatMap { $0.attributes } ?? []
}

public static func buildFinalResult(_ components: [Attribute]) -> [NSAttributedString.Key: Any] {
dictionary(from: components)
}
}
#endif
36 changes: 36 additions & 0 deletions SwiftyAttributesTests/NSAttributedString_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,42 @@ class NSAttributedString_Tests: XCTestCase {
XCTAssertEqual(subject, expected)
}

#if swift(>=5.4)
func testInit_withSwiftyAttributedStringBuilder() {
let shouldAddStrokeWidth = true
let subject = NSAttributedString(string: "Hello World") {
Attribute.strokeColor(.green)
if let link = URL(string: "").map { Attribute.link($0) } {
link
}
if shouldAddStrokeWidth {
Attribute.strokeWidth(3)
} else {
Attribute.strokeColor(.yellow)
}
}
let expected = NSAttributedString(string: "Hello World", attributes: [.strokeColor: Color.green, .strokeWidth: 3])
XCTAssertEqual(subject, expected)
}

func testWithAttributes_SwiftyAttributedStringBuilder() {
let shouldAddStrokeWidth = true
let subject = NSAttributedString(string: "Hello World").withAttributes {
Attribute.strokeColor(.green)
if let link = URL(string: "").map { Attribute.link($0) } {
link
}
if shouldAddStrokeWidth {
Attribute.strokeWidth(3)
} else {
Attribute.strokeColor(.yellow)
}
}
let expected = NSAttributedString(string: "Hello World", attributes: [.strokeColor: Color.green, .strokeWidth: 3])
XCTAssertEqual(subject, expected)
}
#endif

func testSubstringFromRange() {
let str = "Hello".withStrikethroughColor(.blue).withUnderlineStyle(.patternDash)
str.addAttributes([.backgroundColor(.brown)], range: 0 ..< 3)
Expand Down
19 changes: 19 additions & 0 deletions SwiftyAttributesTests/SwiftyAttributes_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,25 @@ import SwiftyAttributes

class SwiftyAttributesTests: XCTestCase {

#if swift(>=5.4)
func testString_withAttributes_SwiftyAttributedStringBuilder() {
let shouldAddStrokeWidth = true
let subject = "Hello".withAttributes {
Attribute.strokeColor(.green)
if let link = URL(string: "").map { Attribute.link($0) } {
link
}
if shouldAddStrokeWidth {
Attribute.strokeWidth(3)
} else {
Attribute.strokeColor(.yellow)
}
}
let expected = NSAttributedString(string: "Hello", attributes: [.strokeColor: Color.green, .strokeWidth: 3])
XCTAssertEqual(subject, expected)
}
#endif

func testString_withAttribute() {
let subject = "Hello".withAttribute(.strokeWidth(4))
let expected = NSAttributedString(string: "Hello", attributes: [.strokeWidth: NSNumber(value: 4)])
Expand Down

0 comments on commit 3951ee4

Please sign in to comment.