diff --git a/Package.swift b/Package.swift index 80a3f45bb..6c13e55d8 100644 --- a/Package.swift +++ b/Package.swift @@ -19,7 +19,10 @@ let package = Package( ) ], dependencies: [ - .package(url: "https://github.com/danielsaidi/MockingKit.git", .upToNextMajor(from: "1.5.0")) + .package( + url: "https://github.com/danielsaidi/MockingKit.git", + .upToNextMajor(from: "1.5.0") + ) ], targets: [ .target( diff --git a/Sources/RichTextKit/Actions/RichTextAction+Button.swift b/Sources/RichTextKit/Actions/RichTextAction+Button.swift index 1e3732140..5ebf73959 100644 --- a/Sources/RichTextKit/Actions/RichTextAction+Button.swift +++ b/Sources/RichTextKit/Actions/RichTextAction+Button.swift @@ -10,21 +10,18 @@ import SwiftUI public extension RichTextAction { - /** - This button can be used to trigger a ``RichTextAction``. - - This renders a plain `Button`, which means that you can - use and configure it as a normal button. - */ + /// This view can be used to trigger a ``RichTextAction``. + /// + /// It renders a plain `Button`, which means you can use + /// and configure it as a normal button. struct Button: View { - /** - Create a rich text action button. - - Parameters: - - action: The action to trigger. - - context: The context to affect. - - fillVertically: WhetherP or not fill up vertical space, by default `false`. - */ + /// Create a rich text action button. + /// + /// - Parameters: + /// - action: The action to trigger. + /// - context: The context to affect. + /// - fillVertically: Whether to fill up vertical space, by default `false`. public init( action: RichTextAction, context: RichTextContext, diff --git a/Sources/RichTextKit/Actions/RichTextAction+ButtonGroup.swift b/Sources/RichTextKit/Actions/RichTextAction+ButtonGroup.swift index 066bec5ae..aa22636e1 100644 --- a/Sources/RichTextKit/Actions/RichTextAction+ButtonGroup.swift +++ b/Sources/RichTextKit/Actions/RichTextAction+ButtonGroup.swift @@ -11,22 +11,18 @@ import SwiftUI public extension RichTextAction { - /** - This view lists ``RichTextAction`` buttons in a group. - - Since this view uses multiple values, it binds directly - to a ``RichTextContext`` instead of individual values. - */ + /// This view adds ``RichTextAction`` buttons to a group. + /// + /// Since the view will bind to multiple values, it uses + /// a ``RichTextContext`` instead of individual values. struct ButtonGroup: View { - /** - Create a rich text action button stack. - - - Parameters: - - context: The context to affect. - - actions: The actions to list, by default all non-size actions. - - greedy: Whether or not the group is horizontally greedy, by default `true`. - */ + /// Create a rich text action button stack. + /// + /// - Parameters: + /// - context: The context to affect. + /// - actions: The actions to list, by default all non-size actions. + /// - greedy: Whether or not the group is horizontally greedy, by default `true`. public init( context: RichTextContext, actions: [RichTextAction], diff --git a/Sources/RichTextKit/Actions/RichTextAction+ButtonStack.swift b/Sources/RichTextKit/Actions/RichTextAction+ButtonStack.swift index b9bb9a575..222340615 100644 --- a/Sources/RichTextKit/Actions/RichTextAction+ButtonStack.swift +++ b/Sources/RichTextKit/Actions/RichTextAction+ButtonStack.swift @@ -10,22 +10,18 @@ import SwiftUI public extension RichTextAction { - /** - This view lists ``RichTextAction`` buttons in a stack. - - Since this view uses multiple values, it binds directly - to a ``RichTextContext`` instead of individual values. - */ + /// This view adds ``RichTextAction`` buttons to a stack. + /// + /// Since the view will bind to multiple values, it uses + /// a ``RichTextContext`` instead of individual values. struct ButtonStack: View { - /** - Create a rich text action button stack. - - - Parameters: - - context: The context to affect. - - actions: The actions to list, by default all non-size actions. - - spacing: The spacing to apply to stack items, by default `5`. - */ + /// Create a rich text action button stack. + /// + /// - Parameters: + /// - context: The context to affect. + /// - actions: The actions to list, by default all non-size actions. + /// - spacing: The spacing to apply to stack items, by default `5`. public init( context: RichTextContext, actions: [RichTextAction], diff --git a/Sources/RichTextKit/Actions/RichTextAction+KeyboardShortcutModifier.swift b/Sources/RichTextKit/Actions/RichTextAction+KeyboardShortcutModifier.swift index a2cfde709..7e8728559 100644 --- a/Sources/RichTextKit/Actions/RichTextAction+KeyboardShortcutModifier.swift +++ b/Sources/RichTextKit/Actions/RichTextAction+KeyboardShortcutModifier.swift @@ -10,13 +10,10 @@ import SwiftUI public extension RichTextAction { - /** - This view modifier can apply keyboard shortcuts for any - ``RichTextAction`` to any view. - - You can also apply it with the `.keyboardShortcut(for:)` - view modifier. - */ + /// Apply keyboard shortcuts for a ``RichTextAction`` to + /// the view. + /// + /// You can also use ``SwiftUICore/View/keyboardShortcut(for:)-9i7js``. struct KeyboardShortcutModifier: ViewModifier { public init(_ action: RichTextAction) { @@ -33,21 +30,22 @@ public extension RichTextAction { public extension View { - /// Apply a ``RichTextAction/KeyboardShortcutModifier``. + /// Apply keyboard shortcuts for a ``RichTextAction`` to + /// the view. @ViewBuilder func keyboardShortcut(for action: RichTextAction) -> some View { #if iOS || macOS || os(visionOS) switch action { - case .copy: keyboardShortcut("c", modifiers: .command) + case .copy: self.keyboardShortcut("c", modifiers: .command) case .dismissKeyboard: self - case .print: keyboardShortcut("p", modifiers: .command) - case .redoLatestChange: keyboardShortcut("z", modifiers: [.command, .shift]) - case .setAlignment(let align): keyboardShortcut(for: align) - case .stepFontSize(let points): keyboardShortcut(points < 0 ? "-" : "+", modifiers: .command) - case .stepIndent(let steps): keyboardShortcut(steps < 0 ? "Ö" : "Ä", modifiers: .command) + case .print: self.keyboardShortcut("p", modifiers: .command) + case .redoLatestChange: self.keyboardShortcut("z", modifiers: [.command, .shift]) + case .setAlignment(let align): self.keyboardShortcut(for: align) + case .stepFontSize(let points): self.keyboardShortcut(points < 0 ? "-" : "+", modifiers: .command) + case .stepIndent(let steps): self.keyboardShortcut(steps < 0 ? "Ö" : "Ä", modifiers: .command) case .stepSuperscript: self - case .toggleStyle(let style): keyboardShortcut(for: style) - case .undoLatestChange: keyboardShortcut("z", modifiers: .command) + case .toggleStyle(let style): self.keyboardShortcut(for: style) + case .undoLatestChange: self.keyboardShortcut("z", modifiers: .command) default: self // TODO: Probably not defined, object to discuss. } #else diff --git a/Sources/RichTextKit/Actions/RichTextAction.swift b/Sources/RichTextKit/Actions/RichTextAction.swift index c0a0bb1d2..985936ef6 100644 --- a/Sources/RichTextKit/Actions/RichTextAction.swift +++ b/Sources/RichTextKit/Actions/RichTextAction.swift @@ -9,13 +9,11 @@ import SwiftUI import Combine -/** - This enum defines rich text actions that can be executed on - a rich text editor. - - This type also serves as a type namespace for other related - types and views, like ``RichTextAction/Button``. - */ +/// This enum defines rich text actions that can be executed +/// on a rich text editor. +/// +/// It's also a namespace for action-related types and views, +/// like ``RichTextAction/Button``. public enum RichTextAction: Identifiable, Equatable, RichTextLabelValue { /// Copy the currently selected text, if any. diff --git a/Sources/RichTextKit/Alignment/RichTextAlignment+KeyboardShortcutModifier.swift b/Sources/RichTextKit/Alignment/RichTextAlignment+KeyboardShortcutModifier.swift index 836f26f5f..b426b4d7e 100644 --- a/Sources/RichTextKit/Alignment/RichTextAlignment+KeyboardShortcutModifier.swift +++ b/Sources/RichTextKit/Alignment/RichTextAlignment+KeyboardShortcutModifier.swift @@ -10,13 +10,10 @@ import SwiftUI public extension RichTextAlignment { - /** - This view modifier can apply keyboard shortcuts for any - ``RichTextAlignment`` to any view. - - You can also apply it with the `.keyboardShortcut(for:)` - view modifier. - */ + /// Apply keyboard shortcuts for a ``RichTextAlignment`` + /// to the view. + /// + /// You can also use ``SwiftUICore/View/keyboardShortcut(for:)-22ksm``. struct KeyboardShortcutModifier: ViewModifier { public init(_ alignment: RichTextAlignment) { @@ -33,19 +30,15 @@ public extension RichTextAlignment { public extension View { - /** - Add a keyboard shortcut that toggles a certain style. - - This modifier only has effect on platforms that support - keyboard shortcuts. - */ + /// Apply keyboard shortcuts for a ``RichTextAlignment`` + /// to the view. @ViewBuilder func keyboardShortcut(for alignment: RichTextAlignment) -> some View { #if iOS || macOS || os(visionOS) switch alignment { - case .left: keyboardShortcut("Ö", modifiers: [.command, .shift]) - case .center: keyboardShortcut("*", modifiers: [.command]) - case .right: keyboardShortcut("Ä", modifiers: [.command, .shift]) + case .left: self.keyboardShortcut("Ö", modifiers: [.command, .shift]) + case .center: self.keyboardShortcut("*", modifiers: [.command]) + case .right: self.keyboardShortcut("Ä", modifiers: [.command, .shift]) case .justified: self } #else diff --git a/Sources/RichTextKit/Alignment/RichTextAlignment+Picker.swift b/Sources/RichTextKit/Alignment/RichTextAlignment+Picker.swift index 3cb6a4d52..2ea13b148 100644 --- a/Sources/RichTextKit/Alignment/RichTextAlignment+Picker.swift +++ b/Sources/RichTextKit/Alignment/RichTextAlignment+Picker.swift @@ -10,21 +10,17 @@ import SwiftUI public extension RichTextAlignment { - /** - This picker can be used to pick a rich text alignment. - - The view returns a plain SwiftUI `Picker` view that can - be styled and configured with plain SwiftUI. - */ + /// This picker can be used to pick a text alignment. + /// + /// This view returns a plain SwiftUI `Picker` view that + /// can be styled and configured with a `PickerStyle`. struct Picker: View { - /** - Create a rich text alignment picker. - - - Parameters: - - selection: The binding to update with the picker. - - values: The pickable alignments, by default `.allCases`. - */ + /// Create a rich text alignment picker. + /// + /// - Parameters: + /// - selection: The binding to update with the picker. + /// - values: The pickable alignments, by default `.allCases`. public init( selection: Binding, values: [RichTextAlignment] = RichTextAlignment.allCases diff --git a/Sources/RichTextKit/Alignment/RichTextAlignment.swift b/Sources/RichTextKit/Alignment/RichTextAlignment.swift index 0602be4ae..cfb54a63d 100644 --- a/Sources/RichTextKit/Alignment/RichTextAlignment.swift +++ b/Sources/RichTextKit/Alignment/RichTextAlignment.swift @@ -14,12 +14,10 @@ import SwiftUI */ public enum RichTextAlignment: String, CaseIterable, Codable, Equatable, Identifiable, RichTextLabelValue { - /** - Initialize a rich text alignment with a native alignment. - - - Parameters: - - alignment: The native alignment to use. - */ + /// Create a rich text alignment with a native alignment. + /// + /// - Parameters: + /// - alignment: The native alignment to use. public init(_ alignment: NSTextAlignment) { switch alignment { case .left: self = .left diff --git a/Sources/RichTextKit/_Foundation/RichTextCoordinator.swift b/Sources/RichTextKit/_Foundation/RichTextCoordinator.swift index 434d522b9..70d43c2ad 100644 --- a/Sources/RichTextKit/_Foundation/RichTextCoordinator.swift +++ b/Sources/RichTextKit/_Foundation/RichTextCoordinator.swift @@ -10,30 +10,24 @@ import Combine import SwiftUI -/** - This coordinator is used to keep a ``RichTextView`` in sync - with a ``RichTextContext``. - - This is used by ``RichTextEditor`` to coordinate changes in - its context and the underlying text view. - - The coordinator sets itself as the text view's delegate. It - updates the context when things change in the text view and - syncs to context changes to the text view. - */ +/// This class is used to keep ``RichTextView`` in sync with +/// a ``RichTextContext``. +/// +/// This is used by ``RichTextEditor`` to coordinate changes +/// in its context and the underlying text view. It will set +/// itself as the text view delegate, and update the context +/// when things change in the text view, and vice versa. @preconcurrency @MainActor open class RichTextCoordinator: NSObject { // MARK: - Initialization - /** - Create a rich text coordinator. - - - Parameters: - - text: The rich text to edit. - - textView: The rich text view to keep in sync. - - richTextContext: The context to keep in sync. - */ + /// Create a rich text coordinator. + /// + /// - Parameters: + /// - text: The rich text to edit. + /// - textView: The rich text view to keep in sync. + /// - richTextContext: The context to keep in sync. public init( text: Binding, textView: RichTextView, @@ -67,16 +61,13 @@ open class RichTextCoordinator: NSObject { // MARK: - Internal Properties - /** - The background color that was used before the currently - highlighted range was set. - */ + /// The background color that was set before any current + /// highlighted range was set. var highlightedRangeOriginalBackgroundColor: ColorRepresentable? - /** - The foreground color that was used before the currently - highlighted range was set. - */ + + /// The foreground color that was set before any current + /// highlighted range was set. var highlightedRangeOriginalForegroundColor: ColorRepresentable? #if canImport(UIKit) @@ -213,20 +204,17 @@ extension RichTextCoordinator { } } - /** - On macOS, we have to update the font and colors when we - move the text input cursor and there's no selected text. - - The code looks very strange, but setting current values - to the current values will reset the text view in a way - that is otherwise not done correctly. - - To try out the incorrect behavior, comment out the code - below, then change font size, colors etc. for a part of - the text then move the input cursor around. When you do, - the presented information will be correct, but when you - type, the last selected font, colors etc. will be used. - */ + /// On macOS, we have to update the font and colors when + /// we move the text input cursor with no selected text. + /// + /// The code may look strange, but setting values resets + /// the text view in a way that is otherwise not correct. + /// + /// To try out the incorrect behavior, disable this code, + /// then change font size, colors etc. for a part of the + /// text, then move the input cursor around. When you do, + /// the information will show correctly, but as you type, + /// the last selected font, colors etc. will be used. func updateTextViewAttributesIfNeeded() { #if macOS if textView.hasSelectedRange { return } diff --git a/Sources/RichTextKit/_Foundation/RichTextPresenter.swift b/Sources/RichTextKit/_Foundation/RichTextPresenter.swift index 77fc34b86..1a967c0f0 100644 --- a/Sources/RichTextKit/_Foundation/RichTextPresenter.swift +++ b/Sources/RichTextKit/_Foundation/RichTextPresenter.swift @@ -8,14 +8,8 @@ import Foundation -/** - This protocol can be implemented any types that can present - a rich text and provide a ``selectedRange``. - - This protocol is implemented by ``RichTextEditor`` since it - can both present and select text. It is also implemented by - the platform-specific ``RichTextView`` components. - */ +/// This protocol can be implemented by any type that can be +/// used to present rich text and provide a ``selectedRange``. public protocol RichTextPresenter: RichTextReader { /// Get the currently selected range. diff --git a/Sources/RichTextKit/_Foundation/RichTextReader.swift b/Sources/RichTextKit/_Foundation/RichTextReader.swift index 663f8b583..570f6007b 100644 --- a/Sources/RichTextKit/_Foundation/RichTextReader.swift +++ b/Sources/RichTextKit/_Foundation/RichTextReader.swift @@ -8,17 +8,12 @@ import Foundation -/** - This protocol can be implemented any types that can provide - a rich text string. - - The protocol is implemented by `NSAttributedString` as well - as other types in the library. - */ +/// This protocol can be implemented by any type that can be +/// used to access an ``attributedString``. @preconcurrency @MainActor public protocol RichTextReader { - /// The attributed string to use as rich text. + /// The attributed string. var attributedString: NSAttributedString { get } } @@ -30,54 +25,44 @@ extension NSAttributedString: RichTextReader { public extension RichTextReader { - /** - The rich text to use. - - This is a convenience name alias for ``attributedString`` - to provide this type with a property that uses the rich - text naming convention. - */ + /// The rich text. + /// + /// This is a name alias for ``attributedString``. var richText: NSAttributedString { attributedString } - /** - Get the full range of the entire ``richText``. - - This uses `safeRange(for:)` to return a range that will - always be valid for the current rich text. - */ + /// The full range of the entire ``richText``. + /// + /// This will use ``safeRange(for:isAttributeOperation:)`` + /// to return a range that is always valid for this text. var richTextRange: NSRange { let range = NSRange(location: 0, length: richText.length) let safeRange = safeRange(for: range) return safeRange } - /** - Get the rich text at a certain range. - - Since this function uses `safeRange(for:)` to not crash - for invalid ranges, always use this function instead of - the unsafe `attributedSubstring`. - - - Parameters: - - range: The range for which to get the rich text. - */ + /// The rich text at a certain range. + /// + /// This will use ``safeRange(for:isAttributeOperation:)`` + /// to return a range that is always valid for the range, + /// so use it instead of the unsafe `attributedSubstring`. + /// + /// - Parameters: + /// - range: The range for which to get the rich text. func richText(at range: NSRange) -> NSAttributedString { let range = safeRange(for: range) return attributedString.attributedSubstring(from: range) } - /** - Get a safe range for the provided range. - - A safe range is limited to the bounds of the attributed - string and helps protecting against range overflow. - - - Parameters: - - range: The range for which to get a safe range. - - isAttributeOperation: Set this to `true` to avoid last position. - */ + /// Get a safe range for the provided range. + /// + /// This range is capped to the bounds of the attributed + /// string and helps protecting against range overflow. + /// + /// - Parameters: + /// - range: The range for which to get a safe range. + /// - isAttributeOperation: Set this to `true` to avoid last position. func safeRange( for range: NSRange, isAttributeOperation: Bool = false diff --git a/Sources/RichTextKit/_Foundation/RichTextWriter.swift b/Sources/RichTextKit/_Foundation/RichTextWriter.swift index 9a0051c41..40c53887a 100644 --- a/Sources/RichTextKit/_Foundation/RichTextWriter.swift +++ b/Sources/RichTextKit/_Foundation/RichTextWriter.swift @@ -8,16 +8,13 @@ import Foundation -/** - This protocol extends ``RichTextReader`` and is implemented - by types that can provide a writable rich text string. - - This protocol is implemented by `NSMutableAttributedString` - as well as other types in the library. - */ +/// This protocol can be implemented by any type that can be +/// used to access an ``mutableAttributedString``. +/// +/// public protocol RichTextWriter: RichTextReader { - /// Get the writable attributed string for the type. + /// The mutable attributed string. var mutableAttributedString: NSMutableAttributedString? { get } } @@ -31,35 +28,40 @@ extension NSMutableAttributedString: RichTextWriter { public extension RichTextWriter { - /** - Get the writable rich text from the implementing type. - - This is an alias for ``mutableAttributedString`` and is - used to get a property that uses the rich text naming. - */ + /// The mutable rich text. + /// + /// This is a name alias for ``mutableAttributedString``. var mutableRichText: NSMutableAttributedString? { mutableAttributedString } - /** - Replace the text in a certain range with a new string. - - - Parameters: - - range: The range to replace text in. - - string: The string to replace the current text with. - */ - func replaceText(in range: NSRange, with string: String) { - mutableRichText?.replaceCharacters(in: range, with: string) + /// Replace the text in a certain range. + /// + /// - Parameters: + /// - range: The range to replace text in. + /// - string: The string to replace the current text with. + func replaceText( + in range: NSRange, + with string: String + ) { + mutableRichText?.replaceCharacters( + in: range, + with: string + ) } - /** - Replace the text in a certain range with a new string. - - - Parameters: - - range: The range to replace text in. - - string: The string to replace the current text with. - */ - func replaceText(in range: NSRange, with string: NSAttributedString) { - mutableRichText?.replaceCharacters(in: range, with: string) + /// Replace the text in a certain range. + /// + /// - Parameters: + /// - range: The range to replace text in. + /// - string: The string to replace the current text with. + func replaceText( + in range: NSRange, + with string: NSAttributedString + ) { + mutableRichText?.replaceCharacters( + in: range, + with: string + ) } }