diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f19608dfd..e0d69b926 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -19,6 +19,7 @@ By deprecating these functions, we can simplify the library in 1.0, and focus mo ### ✨ Features * `FontRepresentable` has new extensions. +* `RichTextAction` has a new `label` property. * `RichTextCommand.ActionButtonGroup` has many new initializers. * `RichTextCommand.FormatMenu` is more configurable than before. * `RichTextKeyboardToolbar` has a new config to always be shown. diff --git a/Sources/RichTextKit/Actions/RichTextAction.swift b/Sources/RichTextKit/Actions/RichTextAction.swift index 575612fbc..7f311553b 100644 --- a/Sources/RichTextKit/Actions/RichTextAction.swift +++ b/Sources/RichTextKit/Actions/RichTextAction.swift @@ -107,7 +107,12 @@ public extension RichTextAction { case .undoLatestChange: .richTextActionUndo } } - + + /// The localized label to use for the action. + var label: some View { + icon.label(title) + } + /// The localized title to use in the main menu. var menuTitle: String { menuTitleKey.text @@ -204,3 +209,15 @@ public extension RichTextAction { /// A name alias for `.undoLatestChange`. static var undo: RichTextAction { .undoLatestChange } } + +public extension CGFloat { + + /// The default rich text indent step size. + static var defaultRichTextIntentStepSize: CGFloat = 30.0 +} + +public extension UInt { + + /// The default rich text indent step size. + static var defaultRichTextIntentStepSize: UInt = 30 +} diff --git a/Sources/RichTextKit/Commands/RichTextCommand+ShareMenu.swift b/Sources/RichTextKit/Commands/RichTextCommand+ShareMenu.swift index f52997a4c..d29c01519 100644 --- a/Sources/RichTextKit/Commands/RichTextCommand+ShareMenu.swift +++ b/Sources/RichTextKit/Commands/RichTextCommand+ShareMenu.swift @@ -121,7 +121,7 @@ private extension RichTextCommand.ShareMenu { var printButton: some View { if let action = printAction { Button(action: action) { - Label(RTKL10n.menuPrint.text, .richTextActionPrint) + RichTextAction.print.label } .keyboardShortcut(for: .print) } diff --git a/Sources/RichTextKit/Data/RichTextDataFormat+Menu.swift b/Sources/RichTextKit/Data/RichTextDataFormat+Menu.swift index c507f8dc4..984fb7c5b 100644 --- a/Sources/RichTextKit/Data/RichTextDataFormat+Menu.swift +++ b/Sources/RichTextKit/Data/RichTextDataFormat+Menu.swift @@ -50,16 +50,16 @@ public extension RichTextDataFormat { Button { formatAction(format) } label: { - Label(format.fileFormatText, icon) + icon.label(format.fileFormatText) } } if let action = pdfAction { Button(action: action) { - Label(RTKL10n.fileFormatPdf.text, icon) + icon.label(RTKL10n.fileFormatPdf.text) } } } label: { - Label(title, icon) + icon.label(title) } } } diff --git a/Sources/RichTextKit/Extensions/CGFloat+Indent.swift b/Sources/RichTextKit/Extensions/CGFloat+Indent.swift deleted file mode 100644 index 1bb1b2008..000000000 --- a/Sources/RichTextKit/Extensions/CGFloat+Indent.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// CGFloat+Indent.swift -// RichTextKit -// -// Created by Daniel Saidi on 2023-10-12. -// Copyright © 2023 Daniel Saidi. All rights reserved. -// - -import Foundation - -public extension CGFloat { - - static var defaultRichTextIntentStepSize: CGFloat = 30.0 -} - -public extension UInt { - - static var defaultRichTextIntentStepSize: UInt = 30 -} diff --git a/Sources/RichTextKit/Extensions/Character+Newline.swift b/Sources/RichTextKit/Extensions/Character+Newline.swift deleted file mode 100644 index 7dad6869c..000000000 --- a/Sources/RichTextKit/Extensions/Character+Newline.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// Character+Newline.swift -// RichTextKit -// -// Created by Daniel Saidi on 2022-05-29. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. -// - -import Foundation - -extension Character { - - /// Check if a character is a new line separator. - var isNewLineSeparator: Bool { - self == .newLine || self == .carriageReturn - } -} diff --git a/Sources/RichTextKit/Extensions/Image+Label.swift b/Sources/RichTextKit/Extensions/Image+Label.swift new file mode 100644 index 000000000..3f83144e5 --- /dev/null +++ b/Sources/RichTextKit/Extensions/Image+Label.swift @@ -0,0 +1,21 @@ +// +// Image+Label.swift +// RichTextKit +// +// Created by Daniel Saidi on 2022-12-20. +// Copyright © 2022-2024 Daniel Saidi. All rights reserved. +// + +import SwiftUI + +extension Image { + + /// Create a label from the icon. + func label(_ title: String) -> some View { + Label { + Text(title) + } icon: { + self + } + } +} diff --git a/Sources/RichTextKit/Extensions/Label+Init.swift b/Sources/RichTextKit/Extensions/Label+Init.swift deleted file mode 100644 index 800673562..000000000 --- a/Sources/RichTextKit/Extensions/Label+Init.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// Label+Init.swift -// RichTextKit -// -// Created by Daniel Saidi on 2022-12-20. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. -// - -import SwiftUI - -extension Label where Icon == Image, Title == Text { - - init(_ title: String, _ image: Image) { - self.init { - Text(title) - } icon: { - image - } - } -} diff --git a/Sources/RichTextKit/Extensions/NSAttributedString+Empty.swift b/Sources/RichTextKit/Extensions/NSAttributedString+Empty.swift index 804d15fd2..88c99dfc1 100644 --- a/Sources/RichTextKit/Extensions/NSAttributedString+Empty.swift +++ b/Sources/RichTextKit/Extensions/NSAttributedString+Empty.swift @@ -3,7 +3,7 @@ // RichTextKit // // Created by Daniel Saidi on 2022-06-01. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. +// Copyright © 2022-2024 Daniel Saidi. All rights reserved. // import Foundation @@ -12,6 +12,6 @@ public extension NSAttributedString { /// Create an empty attributed string. static var empty: NSAttributedString { - NSAttributedString(string: "") + .init(string: "") } } diff --git a/Sources/RichTextKit/Extensions/NSImage+CGImage.swift b/Sources/RichTextKit/Extensions/NSImage+CGImage.swift deleted file mode 100644 index 31a6e8bca..000000000 --- a/Sources/RichTextKit/Extensions/NSImage+CGImage.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// NSImage+JpegData.swift -// RichTextKit -// -// Created by Daniel Saidi on 2022-06-05. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. -// - -#if canImport(AppKit) && !targetEnvironment(macCatalyst) -import AppKit - -public extension NSImage { - - /// Try to get a CoreGraphic image from the AppKit image. - var cgImage: CGImage? { - cgImage(forProposedRect: nil, context: nil, hints: nil) - } -} -#endif diff --git a/Sources/RichTextKit/Extensions/NSImage+JpegData.swift b/Sources/RichTextKit/Extensions/NSImage+JpegData.swift deleted file mode 100644 index d82e1d34b..000000000 --- a/Sources/RichTextKit/Extensions/NSImage+JpegData.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// NSImage+JpegData.swift -// RichTextKit -// -// Created by Daniel Saidi on 2022-06-05. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. -// - -#if canImport(AppKit) && !targetEnvironment(macCatalyst) -import AppKit - -public extension NSImage { - - /// Try to get JPEG compressed data for the AppKit image. - func jpegData(compressionQuality: CGFloat) -> Data? { - guard let image = cgImage else { return nil } - let bitmap = NSBitmapImageRep(cgImage: image) - return bitmap.representation(using: .jpeg, properties: [.compressionFactor: compressionQuality]) - } -} -#endif diff --git a/Sources/RichTextKit/Extensions/NSTextAttachment+Image.swift b/Sources/RichTextKit/Extensions/NSTextAttachment+Image.swift index 1cfbf986a..b08eb7254 100644 --- a/Sources/RichTextKit/Extensions/NSTextAttachment+Image.swift +++ b/Sources/RichTextKit/Extensions/NSTextAttachment+Image.swift @@ -3,7 +3,7 @@ // RichTextKit // // Created by Daniel Saidi on 2023-06-01. -// Copyright © 2023 Daniel Saidi. All rights reserved. +// Copyright © 2023-2024 Daniel Saidi. All rights reserved. // #if canImport(UIKit) diff --git a/Sources/RichTextKit/Extensions/String+Characters.swift b/Sources/RichTextKit/Extensions/String+Characters.swift index 467520683..57004d6aa 100644 --- a/Sources/RichTextKit/Extensions/String+Characters.swift +++ b/Sources/RichTextKit/Extensions/String+Characters.swift @@ -3,37 +3,42 @@ // RichTextKit // // Created by Daniel Saidi on 2022-05-29. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. +// Copyright © 2022-2024 Daniel Saidi. All rights reserved. // import Foundation public extension String.Element { - /// Get the string element for a `\r` carriage return. + /// An `\r` carriage return string element. static var carriageReturn: String.Element { "\r" } - /// Get the string element for a `\n` newline. + /// An `\n` newline string element. static var newLine: String.Element { "\n" } - /// Get the string element for a `\t` tab. + /// A `\t` tab string element. static var tab: String.Element { "\t" } - /// Get the string element for a ` ` space. + /// A ` ` space string element. static var space: String.Element { " " } + + /// If the string element is a new line separator. + var isNewLineSeparator: Bool { + self == .newLine || self == .carriageReturn + } } public extension String { - /// Get the string for a `\r` carriage return. + /// An `\r` carriage return string. static let carriageReturn = String(.carriageReturn) - /// Get the string for a `\n` newline. + /// An `\n` newline string. static let newLine = String(.newLine) - /// Get the string for a `\t` tab. + /// A `\t` tab string. static let tab = String(.tab) - /// Get the string for a ` ` space. + /// A ` ` space string. static let space = String(.space) } diff --git a/Sources/RichTextKit/Extensions/String+Paragraph.swift b/Sources/RichTextKit/Extensions/String+Paragraph.swift index 912d067ff..9372b9145 100644 --- a/Sources/RichTextKit/Extensions/String+Paragraph.swift +++ b/Sources/RichTextKit/Extensions/String+Paragraph.swift @@ -3,7 +3,7 @@ // RichTextKit // // Created by Daniel Saidi on 2022-05-29. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. +// Copyright © 2022-2024 Daniel Saidi. All rights reserved. // import Foundation @@ -11,11 +11,8 @@ import Foundation public extension String { /** - Backs to find the index of the first new line paragraph - before the provided location, if any. - - A new paragraph is considered to start at the character - after the newline char, not the newline itself. + Look backward to find the index of the paragraph before + the provided location, if any. */ func findIndexOfCurrentParagraph(from location: UInt) -> UInt { if isEmpty { return 0 } @@ -31,12 +28,8 @@ public extension String { } /** - Looks forward to find the next new line paragraph after - the provided location, if any. If no next paragraph can - be found, the current is returned. - - A new paragraph is considered to start at the character - after the newline char, not the newline itself. + Look forward to find the index of a paragraph after the + provided location, if any. */ func findIndexOfNextParagraph(from location: UInt) -> UInt { var index = location @@ -51,14 +44,9 @@ public extension String { } /** - Looks forward to find the next new line paragraph after - the provided location, if any. If no next paragraph can - be found, the last index of the paragraph is returned. - - A new paragraph is considered to start at the character - after the newline char, not the newline itself. + Look forward to find the index of a paragraph after the + provided location, if any. */ - func findIndexOfNextParagraphOrEndOfCurrent(from location: UInt) -> UInt { var index = location repeat { @@ -72,10 +60,7 @@ public extension String { } /** - Returns the length of the paragraph found at the location provided.. - - A new paragraph is considered to start at the character - after the newline char, not the newline itself. + Get the length of the paragraph at a provided location. */ func findLengthOfCurrentParagraph(from location: UInt) -> Int { if isEmpty { return 0 } @@ -85,7 +70,7 @@ public extension String { } /** - Returns the index of the word at the location provided.. + Get the index of the word at the provided text location. A word is considered to be a length of text between two breaking characters or space characters. diff --git a/Sources/RichTextKit/Extensions/String+Subscript.swift b/Sources/RichTextKit/Extensions/String+Subscript.swift index 2c3cd7a11..2f63ed014 100644 --- a/Sources/RichTextKit/Extensions/String+Subscript.swift +++ b/Sources/RichTextKit/Extensions/String+Subscript.swift @@ -3,17 +3,14 @@ // RichTextKit // // Created by Daniel Saidi on 2022-05-29. -// Copyright © 2022-2023 Daniel Saidi. All rights reserved. +// Copyright © 2022-2024 Daniel Saidi. All rights reserved. +// +// Original: +// https://stackoverflow.com/questions/24092884/get-nth-character-of-a-string-in-swift-programming-language // import Foundation -/** - This extension makes it possible to fetch characters from a - string, as discussed here: - - https://stackoverflow.com/questions/24092884/get-nth-character-of-a-string-in-swift-programming-language - */ public extension StringProtocol { func character(at index: Int) -> String.Element? { diff --git a/Sources/RichTextKit/Images/ImageRepresentable.swift b/Sources/RichTextKit/Images/ImageRepresentable.swift index a142adb12..321785843 100644 --- a/Sources/RichTextKit/Images/ImageRepresentable.swift +++ b/Sources/RichTextKit/Images/ImageRepresentable.swift @@ -14,6 +14,21 @@ import AppKit multi-platform support. */ public typealias ImageRepresentable = NSImage + +public extension ImageRepresentable { + + /// Try to get a CoreGraphic image from the AppKit image. + var cgImage: CGImage? { + cgImage(forProposedRect: nil, context: nil, hints: nil) + } + + /// Try to get JPEG compressed data for the AppKit image. + func jpegData(compressionQuality: CGFloat) -> Data? { + guard let image = cgImage else { return nil } + let bitmap = NSBitmapImageRep(cgImage: image) + return bitmap.representation(using: .jpeg, properties: [.compressionFactor: compressionQuality]) + } +} #endif #if canImport(UIKit) diff --git a/Sources/RichTextKit/Sharing/RichTextNSSharingMenu.swift b/Sources/RichTextKit/Sharing/RichTextNSSharingMenu.swift index c9b780d0b..2b9c23a37 100644 --- a/Sources/RichTextKit/Sharing/RichTextNSSharingMenu.swift +++ b/Sources/RichTextKit/Sharing/RichTextNSSharingMenu.swift @@ -61,7 +61,7 @@ public struct RichTextNSSharingMenu: View { ) } } label: { - Label(title, icon) + icon.label(title) } } #else @@ -93,7 +93,7 @@ private extension RichTextNSSharingMenu { } } } label: { - Label(title, icon) + icon.label(title) } }