Skip to content

Feat/add-element #31

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

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
Open
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
24 changes: 12 additions & 12 deletions Sources/Tsumiji/Attribute+NSAttributedString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,12 @@
// Created by rrbox on 2022/12/22.
//

#if os(macOS)
import AppKit
#elseif os(iOS)
import UIKit
#endif
import SwiftUI

extension AttributeContext {
func attribute(_ attrString: inout AttributedString) {
attrString.foregroundColor = self.foregroundColor
attrString.font = Font(name: self.fontName, size: CGFloat(truncating: self.fontSize))
attrString.backgroundColor = self.backgroundColor

attrString.mergeAttributes(self.container)
attrString.font = Scope.FontAttribute.Value(name: self.fontName, size: CGFloat(truncating: self.fontSize))
}
}

Expand All @@ -28,9 +22,15 @@ extension AttributeElement {
case let .fontSize(value):
context.fontSize = value
case let .foregroundColor(value):
context.foregroundColor = value
context.container.foregroundColor = value
case let .backgroundColor(value):
context.backgroundColor = value
context.container.backgroundColor = value
case let .kern(value):
context.container.kern = value
case let .tracking(value):
context.container.tracking = value
case let .baselineOffset(value):
context.container.baselineOffset = value
}
}
}
Expand All @@ -47,7 +47,7 @@ extension AttributeLink {
}

func createContext() -> AttributeContext {
var result = AttributeContext()
var result = AttributeContext(container: AttributeContainer())
self.modify(&result)
return result
}
Expand Down
90 changes: 90 additions & 0 deletions Sources/Tsumiji/Attribute.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//
// Tsumiji.swift
//
//
// Created by rrbox on 2022/02/09.
//

import SwiftUI

#if os(iOS)
public typealias Scope = AttributeScopes.UIKitAttributes
#elseif os(macOS)
public typealias Scope = AttributeScopes.AppKitAttributes
#endif

struct AttributeContext {
var fontName: String = "HelveticaNeue-UltraLight"
var fontSize: NSNumber = NSNumber(value: 32)
var container: AttributeContainer = AttributeContainer()
}

enum AttributeElement {
case fontName(String)
case fontSize(NSNumber)
case foregroundColor(Scope.ForegroundColorAttribute.Value)
case backgroundColor(Scope.BackgroundColorAttribute.Value)
case kern(Scope.KernAttribute.Value)
case tracking(Scope.TrackingAttribute.Value)
case baselineOffset(Scope.BaselineOffsetAttribute.Value)
}

indirect enum AttributeLink {
case single(AttributeElement)
case link(Self, AttributeElement)
}

public struct Attribute {
let body: AttributeLink
init(body: AttributeLink) {
self.body = body
}
}

public extension Attribute {
static func fontName(_ value: String) -> Attribute {
.init(body: .single(.fontName(value)))
}
static func fontSize(_ value: NSNumber) -> Attribute {
.init(body: .single(.fontSize(value)))
}
static func foregroundColor(_ value: Scope.ForegroundColorAttribute.Value) -> Attribute {
.init(body: .single(.foregroundColor(value)))
}
static func backgroundColor(_ value: Scope.BackgroundColorAttribute.Value) -> Attribute {
.init(body: .single(.backgroundColor(value)))
}
static func kern(_ value: Scope.KernAttribute.Value) -> Attribute {
.init(body: .single(.kern(value)))
}
static func tracking(_ value: Scope.TrackingAttribute.Value) -> Attribute {
.init(body: .single(.tracking(value)))
}
static func baselineOffset(_ value: Scope.BaselineOffsetAttribute.Value) -> Attribute {
.init(body: .single(.baselineOffset(value)))
}
}

public extension Attribute {
func fontName(_ value: String) -> Attribute {
.init(body: .link(self.body, .fontName(value)))
}
func fontSize(_ value: NSNumber) -> Attribute {
.init(body: .link(self.body, .fontSize(value)))
}
func foregroundColor(_ value: Scope.ForegroundColorAttribute.Value) -> Attribute {
.init(body: .link(self.body, .foregroundColor(value)))
}
func backgroundColor(_ value: Scope.BackgroundColorAttribute.Value) -> Attribute {
.init(body: .link(self.body, .backgroundColor(value)))
}
func kern(_ value: Scope.KernAttribute.Value) -> Attribute {
.init(body: .link(self.body, .kern(value)))
}
func tracking(_ value: Scope.TrackingAttribute.Value) -> Attribute {
.init(body: .link(self.body, .tracking(value)))
}
func baselineOffset(_ value: Scope.BaselineOffsetAttribute.Value) -> Attribute {
.init(body: .link(self.body, .baselineOffset(value)))
}
}
76 changes: 0 additions & 76 deletions Sources/Tsumiji/AttributeLink.swift

This file was deleted.

10 changes: 3 additions & 7 deletions Sources/Tsumiji/Editor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,21 @@ public struct Editor {

public init() {}

public init(_ nsAttributedString: NSAttributedString) {
self.product = AttributedString(nsAttributedString)
}

@discardableResult public func text(_ value: String) -> Self {
public func text(_ value: String) -> Self {
var result = self
var attributedText = AttributedString(value)
self.stack.getFirst().attribute(&attributedText)
result.product += attributedText
return result
}

@discardableResult public func font(_ value: Attribute) -> Self {
public func font(_ value: Attribute) -> Self {
var result = self
result.stack.add(attr: value)
return result
}

@discardableResult public func fontEnd() -> Self {
public func fontEnd() -> Self {
var result = self
result.stack.remove()
return result
Expand Down
96 changes: 58 additions & 38 deletions Tests/TsumijiTests/TsumijiTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,48 +32,62 @@ extension Attribute {
static let big: Self = .fontSize(50)
static let impact: Self = .fontName("times")
static let blueBack: Self = .backgroundColor(.blue)
static let wideKern: Self = .kern(10)
static let wideTracking: Self = .tracking(1)

static let bigRed: Self = .fontSize(50).foregroundColor(.red)
}

final class TsumijiTests: XCTestCase {

let singleElementAttrCase = NSMutableAttributedString()
let complexElemetAttrCase = NSMutableAttributedString()
var singleElement = AttributedString()
var complexElement = AttributedString()

override func setUp() {


}

override func setUp() async throws {

singleElementAttrCase.append(NSAttributedString(string: "color", attributes: [
.font: Font.default!,
.foregroundColor: Color.red,
.backgroundColor: Color.defaultBackground
]))
singleElementAttrCase.append(NSAttributedString(string: "fontSize", attributes: [
.font: Font(name: .defaultFontName, size: 50)!,
.foregroundColor: Color.default,
.backgroundColor: Color.defaultBackground
]))
singleElementAttrCase.append(NSAttributedString(string: "fontName", attributes: [
.font: Font(name: "times", size: .defaultFontSize)!,
.foregroundColor: Color.default,
.backgroundColor: Color.defaultBackground
]))
singleElementAttrCase.append(NSAttributedString(string: "backgroundColor", attributes: [
.font: Font.default!,
.foregroundColor: Color.default,
.backgroundColor: Color.blue
]))

complexElemetAttrCase.append(NSAttributedString(string: "color + backgroundColor", attributes: [
.font: Font.default!,
.foregroundColor: Color.red,
.backgroundColor: Color.blue
]))
complexElemetAttrCase.append(NSAttributedString(string: "fontSize + color", attributes: [
.font: Font(name: .defaultFontName, size: 50)!,
.foregroundColor: Color.red,
.backgroundColor: Color.defaultBackground
]))
var color = AttributedString("color")
color.font = Font.default!
color.foregroundColor = Color.red
singleElement += color

var fontSize = AttributedString("fontSize")
fontSize.font = Font(name: .defaultFontName, size: 50)!
singleElement += fontSize

var fontName = AttributedString("fontName")
fontName.font = Font(name: "times", size: .defaultFontSize)!
singleElement += fontName

var backgroundColor = AttributedString("backgroundColor")
backgroundColor.font = .default
backgroundColor.backgroundColor = Color.blue
singleElement += backgroundColor

var kern = AttributedString("wideKern")
kern.font = .default
kern.kern = 10
singleElement += kern

var tracking = AttributedString("tracking")
tracking.font = .default
tracking.tracking = 1
singleElement += tracking

var colorBackground = AttributedString("color + backgroundColor")
colorBackground.font = .default
colorBackground.foregroundColor = Color.red
colorBackground.backgroundColor = Color.blue
complexElement += colorBackground

var fontSizeColor = AttributedString("fontSize + color")
fontSizeColor.font = Font(name: .defaultFontName, size: 50)!
fontSizeColor.foregroundColor = Color.red
complexElement += fontSizeColor

}

Expand All @@ -93,17 +107,23 @@ final class TsumijiTests: XCTestCase {
.font(.blueBack)
.text("backgroundColor")
.fontEnd()
.font(.wideKern)
.text("wideKern")
.fontEnd()
.font(.wideTracking)
.text("tracking")
.fontEnd()

XCTAssertEqual(editor.product, AttributedString(singleElementAttrCase))
XCTAssertEqual(editor.product, singleElement)

}

func testLiteral() throws {

// test : editor literal
let editedLiteral: EditorLiteral = "\(.red)color\(.fontEnd)\(.big)fontSize\(.fontEnd)\(.impact)fontName\(.fontEnd)\(.blueBack)backgroundColor\(.fontEnd)"
let editedLiteral: EditorLiteral = "\(.red)color\(.fontEnd)\(.big)fontSize\(.fontEnd)\(.impact)fontName\(.fontEnd)\(.blueBack)backgroundColor\(.fontEnd)\(.wideKern)wideKern\(.fontEnd)\(.wideTracking)tracking\(.fontEnd)"

XCTAssertEqual(editedLiteral.product, AttributedString(singleElementAttrCase))
XCTAssertEqual(editedLiteral.product, singleElement)

}

Expand All @@ -118,14 +138,14 @@ final class TsumijiTests: XCTestCase {
.text("fontSize + color")
.fontEnd()

XCTAssertEqual(editor.product, AttributedString(complexElemetAttrCase))
XCTAssertEqual(editor.product, complexElement)
}

func testComplexElementLiteral() throws {

let editedLiteral: EditorLiteral = "\(.red)\(.blueBack)color + backgroundColor\(.fontEnd)\(.fontEnd)\(.bigRed)fontSize + color\(.fontEnd)"

XCTAssertEqual(editedLiteral.product, AttributedString(complexElemetAttrCase))
XCTAssertEqual(editedLiteral.product, complexElement)

}

Expand Down
Loading