diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 74a4f4854..74e5e5a56 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -10,11 +10,11 @@ Until then, minor updates may remove deprecated features and introduce breaking This release adds a lot of new `RichTextAction` cases and adjusts the context and coordinator subscription. -This release also deprecates `RichTextAttributeReader` and `RichTextAttributeWriter` functionality that are not used by the library, in favor of `RichTextViewComponent`. This is done to reduce the complexity of the library. +This release also deprecates `RichTextAttributeReader` and `RichTextAttributeWriter` functionality that are not used by the library, in favor of `RichTextViewComponent`, to reduce the complexity of the library. -Until now, the functions mostly did the same things, but sometimes the `RichTextViewComponent` have to use its text storage or layout manager, or update the typing attributes. Since these are not present in the reader and writer protocols, the code diverged and mostly identical copies had to co-exist. And since the reader and writer versions are not used by the library, they may not work as well as intended. +Until now, these functions mostly did the same thing, but sometimes the `RichTextViewComponent` have to use its text storage or layout manager, or update the typing attributes. This caused the code to diverge and mostly identical copies had co-exist, where the reader and writer versions were not even used by the library. -This change will hopefully make it possible to simplify the library in the 1.0 release, and focus more on unifying the different TextView platform implementations (`UITextView` in iOS and `NSTextView` in macOS), rather than providing a low level string handling interface. +By deprecating these functions, we can simplify the library in 1.0, and focus more on unifying the different `RichTextViewComponent` implementations (`UITextView` in iOS and `NSTextView` in macOS), rather than providing a low level string handling interface. ### ✨ Features @@ -39,10 +39,10 @@ This change will hopefully make it possible to simplify the library in the 1.0 r * `RichTextAlignment` now behaves better. * `RichTextCoordinator` now handles indentation changes. - ### 🗑️ Deprecations -* `RichTextAttributeWriter` deprecates many functions in favor of `RichTextViewComponent`. +* `RichTextAttributeReader` has deprecated a lot of functions. +* `RichTextAttributeWriter` has deprecated a lot of functions. * `RichTextCoordinator` functions that simply triggered `handle(_:)` have been deprecated. diff --git a/Sources/RichTextKit/Alignment/RichTextAlignment+Picker.swift b/Sources/RichTextKit/Alignment/RichTextAlignment+Picker.swift index 231c3278c..7531e0f78 100644 --- a/Sources/RichTextKit/Alignment/RichTextAlignment+Picker.swift +++ b/Sources/RichTextKit/Alignment/RichTextAlignment+Picker.swift @@ -17,6 +17,7 @@ public extension RichTextAlignment { be styled and configured with plain SwiftUI. */ struct Picker: View { + /** Create a rich text alignment picker. diff --git a/Sources/RichTextKit/Attributes/RichTextAttribute.swift b/Sources/RichTextKit/Attributes/RichTextAttribute.swift index eaa2796de..14fc42960 100644 --- a/Sources/RichTextKit/Attributes/RichTextAttribute.swift +++ b/Sources/RichTextKit/Attributes/RichTextAttribute.swift @@ -3,7 +3,7 @@ // RichTextKit // // Created by Daniel Saidi on 2022-05-28. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. +// Copyright © 2022-2024 Daniel Saidi. All rights reserved. // import Foundation diff --git a/Sources/RichTextKit/Attributes/RichTextAttributeReader.swift b/Sources/RichTextKit/Attributes/RichTextAttributeReader.swift index a796111c5..e4a1d630d 100644 --- a/Sources/RichTextKit/Attributes/RichTextAttributeReader.swift +++ b/Sources/RichTextKit/Attributes/RichTextAttributeReader.swift @@ -3,7 +3,7 @@ // RichTextKit // // Created by Daniel Saidi on 2022-05-27. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. +// Copyright © 2022-2024 Daniel Saidi. All rights reserved. // import Foundation @@ -14,6 +14,12 @@ import Foundation The protocol is implemented by `NSAttributedString` as well as other types in the library. + + Note that this protocol used to have a lot of functionality + for getting various attributes, styles, etc. However, since + ``RichTextViewComponent`` needs more capabilities, we ended + up with duplicated code where the reader had functions that + weren't even used within the library. */ public protocol RichTextAttributeReader: RichTextReader {} diff --git a/Sources/RichTextKit/Attributes/RichTextAttributeWriter.swift b/Sources/RichTextKit/Attributes/RichTextAttributeWriter.swift index 3b9d030e7..7ff4155c9 100644 --- a/Sources/RichTextKit/Attributes/RichTextAttributeWriter.swift +++ b/Sources/RichTextKit/Attributes/RichTextAttributeWriter.swift @@ -3,7 +3,7 @@ // RichTextKit // // Created by Daniel Saidi on 2022-05-27. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. +// Copyright © 2022-2024 Daniel Saidi. All rights reserved. // import Foundation @@ -17,12 +17,9 @@ import Foundation Note that this protocol used to have a lot of functionality for setting various attributes, styles, etc. However, since - ``RichTextViewComponent`` needs to perform changes in other - ways, we ended up with duplicated code where the writer had - functions that may have worked, but weren't used within the - library. As such, the ``RichTextViewComponent`` will be the - primary component for modifying rich text, while the writer - functionality is removed. This will help to avoid confusion. + ``RichTextViewComponent`` needs more capabilities, we ended + up with duplicated code where the writer had functions that + weren't even used within the library. */ public protocol RichTextAttributeWriter: RichTextWriter, RichTextAttributeReader {} diff --git a/Sources/RichTextKit/Component/RichTextViewComponent+Colors.swift b/Sources/RichTextKit/Component/RichTextViewComponent+Colors.swift index 7b160c596..f983782a8 100644 --- a/Sources/RichTextKit/Component/RichTextViewComponent+Colors.swift +++ b/Sources/RichTextKit/Component/RichTextViewComponent+Colors.swift @@ -17,6 +17,15 @@ public extension RichTextViewComponent { guard let attribute = color.attribute else { return nil } return richTextAttribute(attribute) } + + /// Get a certain rich text color at a certain range. + func richTextColor( + _ color: RichTextColor, + at range: NSRange + ) -> ColorRepresentable? { + guard let attribute = color.attribute else { return nil } + return richTextAttribute(attribute, at: range) + } /// Set a certain rich text color at current range. func setRichTextColor( diff --git a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Alignment.swift b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Alignment.swift similarity index 88% rename from Sources/RichTextKit/Attributes/RichTextAttributeReader+Alignment.swift rename to Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Alignment.swift index 4bd19c28a..908002a8c 100644 --- a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Alignment.swift +++ b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Alignment.swift @@ -8,6 +8,7 @@ import Foundation +@available(*, deprecated, message: "Use RichTextViewComponent instead.") public extension RichTextAttributeReader { /// Get the rich text alignment at a certain range. diff --git a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Colors.swift b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Colors.swift similarity index 83% rename from Sources/RichTextKit/Attributes/RichTextAttributeReader+Colors.swift rename to Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Colors.swift index a646fb65f..e89921814 100644 --- a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Colors.swift +++ b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Colors.swift @@ -8,10 +8,11 @@ import Foundation +@available(*, deprecated, message: "Use RichTextViewComponent instead") public extension RichTextAttributeReader { /// Get a certain rich text color at a certain range. - func richTextColor( + func richTextColorOld( _ color: RichTextColor, at range: NSRange ) -> ColorRepresentable? { diff --git a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Font.swift b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Font.swift similarity index 85% rename from Sources/RichTextKit/Attributes/RichTextAttributeReader+Font.swift rename to Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Font.swift index b1273ab75..94dfd51a7 100644 --- a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Font.swift +++ b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Font.swift @@ -8,6 +8,7 @@ import Foundation +@available(*, deprecated, message: "Use RichTextViewComponent instead.") public extension RichTextAttributeReader { /// Get the rich text font at a certain range. diff --git a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Indent.swift b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Indent.swift similarity index 87% rename from Sources/RichTextKit/Attributes/RichTextAttributeReader+Indent.swift rename to Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Indent.swift index 37cd60b3c..246ef9295 100644 --- a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Indent.swift +++ b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Indent.swift @@ -8,6 +8,7 @@ import Foundation +@available(*, deprecated, message: "Use RichTextViewComponent instead") public extension RichTextAttributeReader { /// Get the rich text indent at a certain range. diff --git a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Paragraph.swift b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Paragraph.swift similarity index 88% rename from Sources/RichTextKit/Attributes/RichTextAttributeReader+Paragraph.swift rename to Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Paragraph.swift index c2181c847..9229ec494 100644 --- a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Paragraph.swift +++ b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Paragraph.swift @@ -16,6 +16,7 @@ import UIKit import AppKit #endif +@available(*, deprecated, message: "Use RichTextViewComponent instead.") public extension RichTextAttributeReader { /// Get the rich text paragraph style at a certain range. diff --git a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Style.swift b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Style.swift similarity index 90% rename from Sources/RichTextKit/Attributes/RichTextAttributeReader+Style.swift rename to Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Style.swift index 02d66c31d..24c91d6d9 100644 --- a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Style.swift +++ b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Style.swift @@ -8,6 +8,7 @@ import Foundation +@available(*, deprecated, message: "Use RichTextViewComponent instead") public extension RichTextAttributeReader { /// Get all rich text styles at a certain range. diff --git a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Superscript.swift b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Superscript.swift similarity index 85% rename from Sources/RichTextKit/Attributes/RichTextAttributeReader+Superscript.swift rename to Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Superscript.swift index 314dbc601..73f3e8600 100644 --- a/Sources/RichTextKit/Attributes/RichTextAttributeReader+Superscript.swift +++ b/Sources/RichTextKit/_Deprecated/RichTextAttributeReader+Superscript.swift @@ -9,6 +9,7 @@ #if macOS import Foundation +@available(*, deprecated, message: "Use RichTextViewComponent instead.") public extension RichTextAttributeReader { /// Get the superscript level at a certain range. diff --git a/Sources/RichTextKit/_Deprecated/RichTextAttributeWriter+Colors.swift b/Sources/RichTextKit/_Deprecated/RichTextAttributeWriter+Colors.swift index e8541fbc3..4ba065e57 100644 --- a/Sources/RichTextKit/_Deprecated/RichTextAttributeWriter+Colors.swift +++ b/Sources/RichTextKit/_Deprecated/RichTextAttributeWriter+Colors.swift @@ -12,13 +12,13 @@ import Foundation public extension RichTextAttributeWriter { /// Set a certain rich text color at a certain range. - func setRichTextColor( + func setRichTextColorOld( _ color: RichTextColor, to val: ColorRepresentable, at range: NSRange ) { guard let attribute = color.attribute else { return } - if richTextColor(color, at: range) == val { return } + if richTextColorOld(color, at: range) == val { return } setRichTextAttribute(attribute, to: val, at: range) } } diff --git a/Tests/RichTextKitTests/Attributes/RichTextAttributeReader+AlignmentTests.swift b/Tests/RichTextKitTests/Attributes/RichTextAttributeReader+AlignmentTests.swift deleted file mode 100644 index d23aec3d8..000000000 --- a/Tests/RichTextKitTests/Attributes/RichTextAttributeReader+AlignmentTests.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// RichTextAttributeReader+AlignmentTests.swift -// RichTextKit -// -// Created by Daniel Saidi on 2022-05-30. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. -// - -#if iOS || macOS || os(tvOS) -import RichTextKit -import SwiftUI -import XCTest - -final class RichTextAttributeReader_AlignmentTests: XCTestCase { - - func testCanReadTextAlignment() { - let textView = RichTextView() - textView.attributedString = NSAttributedString(string: "foo bar") - let range = NSRange(location: 2, length: 3) - textView.selectedRange = range - textView.setRichTextAlignment(.justified) - let result = textView.attributedString.richTextAlignment(at: range) - XCTAssertEqual(result, .justified) - } -} - -#endif diff --git a/Tests/RichTextKitTests/RichTextCoordinatorIntegrationTests+UIKit.swift b/Tests/RichTextKitTests/RichTextCoordinatorIntegrationTests+UIKit.swift index bfafe1d28..a68dcc08c 100644 --- a/Tests/RichTextKitTests/RichTextCoordinatorIntegrationTests+UIKit.swift +++ b/Tests/RichTextKitTests/RichTextCoordinatorIntegrationTests+UIKit.swift @@ -72,7 +72,7 @@ final class RichTextCoordinatorIntegrationTests: XCTestCase { XCTAssertEqual(textView.richTextAttributes[.font] as? FontRepresentable, FontRepresentable.systemFont(ofSize: 16)) XCTAssertEqual(textView.richTextAttributes[.foregroundColor] as? ColorRepresentable, ColorRepresentable.red) - textView.setRichTextStyle(.strikethrough, to: true, at: textView.selectedRange) + textView.setRichTextStyle(.strikethrough, to: true) XCTAssertEqual(textView.richTextAttributes[.strikethroughStyle] as? Int, 1) } } diff --git a/Tests/RichTextKitTests/RichTextViewRepresentable+AttributesTests.swift b/Tests/RichTextKitTests/RichTextViewRepresentable+AttributesTests.swift index 5b3a58ed5..ae4a9f77e 100644 --- a/Tests/RichTextKitTests/RichTextViewRepresentable+AttributesTests.swift +++ b/Tests/RichTextKitTests/RichTextViewRepresentable+AttributesTests.swift @@ -47,7 +47,9 @@ final class RichTextViewComponent_AttributesTests: XCTestCase { textView.setRichTextAttribute(.font, to: font) assertEqualAttributes(textView.richTextAttributes) assertEqualAttributes(textView.richTextAttributes(at: selectedRange)) + #if iOS assertEqualAttributes(textView.typingAttributes) + #endif } func testTextAttributesIsValidForNoSelectedRange() { @@ -65,7 +67,9 @@ final class RichTextViewComponent_AttributesTests: XCTestCase { textView.setRichTextAttribute(.font, to: font) assertEqualAttribute(textView.richTextAttribute(.font)) assertEqualAttribute(textView.richTextAttribute(.font, at: selectedRange)) + #if iOS assertEqualAttribute(textView.typingAttributes[.font]) + #endif } func testTextAttributeValueForKeyIsValidForNoSelectedRange() { diff --git a/Tests/RichTextKitTests/RichTextViewRepresentable+ColorTests.swift b/Tests/RichTextKitTests/RichTextViewRepresentable+ColorTests.swift index d3873ace6..e76532455 100644 --- a/Tests/RichTextKitTests/RichTextViewRepresentable+ColorTests.swift +++ b/Tests/RichTextKitTests/RichTextViewRepresentable+ColorTests.swift @@ -56,7 +56,9 @@ final class RichTextViewComponent_ColorTests: XCTestCase { XCTAssertEqual(textView.richTextColor(.background), color) assertEqualColor(textView.richTextAttributes[.backgroundColor]) assertEqualColor(textView.richTextAttributes(at: selectedRange)[.backgroundColor]) + #if iOS || os(tvOS) assertEqualColor(textView.typingAttributes[.backgroundColor]) + #endif } func testRichTextBackgroundColorWorksForNoSelectedRange() { @@ -76,7 +78,9 @@ final class RichTextViewComponent_ColorTests: XCTestCase { XCTAssertEqual(textView.richTextColor(.foreground), color) assertEqualColor(textView.richTextAttributes[.foregroundColor]) assertEqualColor(textView.richTextAttributes(at: selectedRange)[.foregroundColor]) + #if iOS || os(tvOS) assertEqualColor(textView.typingAttributes[.foregroundColor]) + #endif } func testRichTextForegroundColorWorksForNoSelectedRange() { diff --git a/Tests/RichTextKitTests/RichTextViewRepresentable+FontSizeTests.swift b/Tests/RichTextKitTests/RichTextViewRepresentable+FontSizeTests.swift index ae33f66a6..eb9fbedae 100644 --- a/Tests/RichTextKitTests/RichTextViewRepresentable+FontSizeTests.swift +++ b/Tests/RichTextKitTests/RichTextViewRepresentable+FontSizeTests.swift @@ -51,7 +51,9 @@ final class RichTextViewComponent_FontSizeTests: XCTestCase { XCTAssertEqual(textView.richTextFont?.fontName, font.fontName) assertEqualFont(textView.richTextAttribute(.font)) assertEqualFont(textView.richTextAttributes(at: selectedRange)[.font]) + #if iOS || os(tvOS) assertEqualFont(textView.typingAttributes[.font]) + #endif } func testRichTextFontWorksForNoSelectedRange() { diff --git a/Tests/RichTextKitTests/RichTextViewRepresentableTests.swift b/Tests/RichTextKitTests/RichTextViewRepresentableTests.swift index 1a61d16d8..390c2c9d4 100644 --- a/Tests/RichTextKitTests/RichTextViewRepresentableTests.swift +++ b/Tests/RichTextKitTests/RichTextViewRepresentableTests.swift @@ -73,11 +73,14 @@ final class RichTextViewComponentTests: XCTestCase { #endif XCTAssertEqual(view.backgroundColor, .clear) XCTAssertEqual(view.contentCompressionResistancePriority(for: .horizontal), .defaultLow) - #if iOS || os(tvOS) + #if iOS + XCTAssertEqual(view.spellCheckingType, .no) + XCTAssertNil(view.textColor) + #elseif os(tvOS) XCTAssertEqual(view.spellCheckingType, .no) - XCTAssertEqual(view.textColor, nil) + XCTAssertNotNil(view.textColor) #elseif macOS - XCTAssertEqual(view.textColor, nil) + XCTAssertNotNil(view.textColor) #endif } }