From f5b43e7dccf6128dc4ac34757a0c6d931e5f2342 Mon Sep 17 00:00:00 2001 From: Theo Date: Fri, 3 Nov 2023 12:36:22 +0100 Subject: [PATCH] Extend styling --- ...NSMutableAttributedString+Extensions.swift | 29 ++++++++++++++++--- Sources/Quilt/QuiltString+Extensions.swift | 13 +++++---- Tests/QuiltTests/QuiltStringTests.swift | 26 +++++++---------- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/Sources/Quilt/NSMutableAttributedString+Extensions.swift b/Sources/Quilt/NSMutableAttributedString+Extensions.swift index a373c9b..a68f783 100644 --- a/Sources/Quilt/NSMutableAttributedString+Extensions.swift +++ b/Sources/Quilt/NSMutableAttributedString+Extensions.swift @@ -1,14 +1,35 @@ +import AppKit import Foundation public extension NSMutableAttributedString { func setTextAttribute(_ key: Key, to newValue: Any, at range: NSRange) { - let range = safeRange(for: range) + let safeRange = safeRange(for: range) guard length > 0, range.location >= 0 else { return } beginEditing() - enumerateAttribute(key, in: range, options: .init()) { _, range, _ in - addAttribute(key, value: newValue, range: range) - fixAttributes(in: range) + removeAttribute(key, range: safeRange) + addAttribute(key, value: newValue, range: safeRange) + endEditing() + } + + func setAttributes(_ attrs: [NSAttributedString.Key: Any], range: NSRange) { + let safeRange = self.safeRange(for: range) + guard length > 0, safeRange.location >= 0 else { return } + beginEditing() + attrs.forEach { key, value in + removeAttribute(key, range: safeRange) + addAttribute(key, value: value, range: safeRange) } endEditing() } + + func makeBold(range: NSRange) { + let boldFont = NSFont.boldSystemFont(ofSize: NSFont.systemFontSize) + setTextAttribute(.font, to: boldFont, at: range) + } + + func makeItalic(range: NSRange) { + let italicFont = NSFont.systemFont(ofSize: NSFont.systemFontSize) + italicFont.fontDescriptor.withSymbolicTraits([.italic]) + setTextAttribute(.font, to: italicFont, at: range) + } } diff --git a/Sources/Quilt/QuiltString+Extensions.swift b/Sources/Quilt/QuiltString+Extensions.swift index 9dca96f..e928e55 100644 --- a/Sources/Quilt/QuiltString+Extensions.swift +++ b/Sources/Quilt/QuiltString+Extensions.swift @@ -14,18 +14,19 @@ extension QuiltString { private func applyFormatting(string: NSMutableAttributedString) -> NSMutableAttributedString { for operation in quilt.operations { if case let .addMark(type, start, end) = operation.type { + let range = NSRange( + location: getSpanMarkerIndex(marker: start), + length: getSpanMarkerIndex(marker: end) + 1 + ) switch type { case .underline: string.setTextAttribute( - .underlineStyle, to: true, at: NSRange( - location: getSpanMarkerIndex(marker: start), - length: getSpanMarkerIndex(marker: end) + 1 - ) + .underlineStyle, to: true, at: range ) case .bold: - print("TODO bold") + string.makeBold(range: range) case .italic: - print("TODO italic") + string.makeItalic(range: range) } } } diff --git a/Tests/QuiltTests/QuiltStringTests.swift b/Tests/QuiltTests/QuiltStringTests.swift index 3b4f382..e567ebf 100644 --- a/Tests/QuiltTests/QuiltStringTests.swift +++ b/Tests/QuiltTests/QuiltStringTests.swift @@ -58,15 +58,15 @@ final class QuiltStringTests: XCTestCase { clientA.set(newText: "Hello World") clientA.addMark(mark: .underline, fromIndex: 0, toIndex: 10) - let exptected = NSMutableAttributedString("Hello World") - exptected.setTextAttribute( + let expected = NSMutableAttributedString("Hello World") + expected.setTextAttribute( .underlineStyle, to: true, at: NSRange(location: 0, length: 11) ) let fontBase = NSFont.systemFont(ofSize: 16) - exptected.setTextAttribute( + expected.setTextAttribute( .font, to: fontBase, at: NSRange(location: 0, length: 11) ) - XCTAssertTrue(clientA.attString.isEqual(to: exptected)) + XCTAssertTrue(clientA.attString.isEqual(to: expected)) } func testRemoveUnderlineAttributedString() throws { @@ -89,11 +89,9 @@ final class QuiltStringTests: XCTestCase { clientA.addMark(mark: .bold, fromIndex: 0, toIndex: 10) let exptected = NSMutableAttributedString("Hello World") -// exptected.setTextAttribute( -// .underlineStyle, to: true, at: NSRange(location: 0, length: 11) -// ) -// print(clientA.attString) -// XCTAssertTrue(clientA.attString.isEqual(to: exptected)) + exptected.makeBold(range: NSRange(location: 0, length: 11)) + + XCTAssertTrue(clientA.attString.isEqual(to: exptected)) } func testItalicAttributedString() throws { @@ -102,12 +100,10 @@ final class QuiltStringTests: XCTestCase { clientA.set(newText: "Hello World") clientA.addMark(mark: .italic, fromIndex: 0, toIndex: 10) - let exptected = NSMutableAttributedString("Hello World") -// exptected.setTextAttribute( -// .underlineStyle, to: true, at: NSRange(location: 0, length: 11) -// ) + let expected = NSMutableAttributedString("Hello World") + expected.makeItalic(range: NSRange(location: 0, length: 11)) -// print(clientA.attString) -// XCTAssertTrue(clientA.attString.isEqual(to: exptected)) + print(clientA.attString) + XCTAssertTrue(clientA.attString.isEqual(to: expected)) } }