A simple, powerful SwiftUI text editor for iOS and macOS with live syntax highlighting.
Highlight what's important as your users type.
Supports iOS 13.0+ and macOS 10.15+.
File -> Swift Packages -> Add Package Dependency and use the URL https://github.com/kyle-n/HighlightedTextEditor
.
Add pod 'HighlightedTextEditor'
to your Podfile
and run pod install
.
HighlightedTextEditor applies styles to text matching regex patterns you provide. You can apply multiple styles to each regex pattern, as shown in the example below.
import HighlightedTextEditor
// matches text between underscores
let betweenUnderscores = try! NSRegularExpression(pattern: "_[^_]+_", options: [])
struct ContentView: View {
@State private var text: String = ""
private let rules: [HighlightRule] = [
HighlightRule(pattern: betweenUnderscores, formattingRules: [
TextFormattingRule(fontTraits: [.traitItalic, .traitBold]),
TextFormattingRule(key: .foregroundColor, value: UIColor.red),
TextFormattingRule(key: .underlineStyle) { content, range in
if content.count > 10 { return NSUnderlineStyle.double.rawValue }
else { return NSUnderlineStyle.single.rawValue }
}
])
]
var body: some View {
VStack {
HighlightedTextEditor(text: $text, highlightRules: rules)
// optional modifiers
.onCommit { print("commited") }
.onEditingChanged { print("editing changed") }
.onTextChange { print("latest text value", $0) }
.onSelectionChange { (range: NSRange) in
print(range)
}
.introspect { editor in
// access underlying UITextView or NSTextView
editor.textView.backgroundColor = .green
}
}
}
}
Notice the NSRegularExpression is instantiated once. It should not be recreated every time the view is redrawn. This helps performance.
I've included a few useful presets for syntax highlighting as static vars on [HighlightRule]
. If you have ideas for other useful presets, please feel free to open a pull request with your preset code.
Current presets include:
markdown
url
Example of using a preset:
HighlightedTextEditor(text: $text, highlightRules: .markdown)
I've also added a preset variable, NSRegularExpression.all
, for easily selecting a whole string.
Example of using it:
HighlightedTextEditor(text: $text, highlightRules: [
HighlightRule(pattern: .all, formattingRule: TextFormattingRule(key: .underlineStyle, value: NSUnderlineStyle.single.rawValue))
])
Parameter | Type | Description |
---|---|---|
text |
Binding<String> | Text content of the field |
highlightRules |
[HighlightRule] | Patterns and formatting for those patterns |
.introspect(callback: (_ editor: HighlightedTextEditorInternals) -> Void)
: Allows you the developer to access the underlying UIKit or AppKit objects used by HighlightedTextEditor.onCommit(_ callback: @escaping () -> Void)
: Called when the user stops editing.onEditingChanged(_ callback: @escaping () -> Void)
: Called when the user begins editing.onTextChange(_ callback: @escaping (_ editorContent: String) -> Void)
: Called whenevertext
changes.onSelectionChange(_ callback: @escaping (_ selectedRange: NSRange) -> Void)
.onSelectionChange(_ callback: @escaping (_ selectedRanges: [NSRange]) -> Void)
(AppKit only)
Passed as a parameter to .introspect()
callbacks. Useful for customizing editor behavior in some way not supported by the HLTE API.
Property | Type | Description |
---|---|---|
textView |
UITextView or NSTextView | For customizing the UIKit/AppKit text editor |
scrollView |
NSScrollView? | For customizing the NSScrollView wrapper. Returns nil in UIKit |
Parameter | Type | Description |
---|---|---|
pattern |
NSRegularExpression | The content you want to highlight. Should be instantiated once for performance. |
formattingRule |
TextFormattingRule | Style applying to all text matching the pattern |
formattingRules |
[TextFormattingRule] | Array of styles applying to all text matching the pattern |
TextFormattingRule offers three different initializers that each set one style. To set multiple styles, use multiple TextFormattingRules.
Parameter | Type | Description |
---|---|---|
key |
NSAttributedString.Key | The style to set (e.x. .foregroundColor , .underlineStyle ) |
value |
Any | The actual style applied to the key (e.x. for key = .foregroundColor , value is UIColor.red or NSColor.red ) |
Parameter | Type | Description |
---|---|---|
key |
NSAttributedString.Key | The style to set (e.x. .foregroundColor , .underlineStyle ) |
calculateValue |
(String, Range<String.Index>) -> Any | A callback that calculates the value for key . First parameter is the text content matched by the regex, second is the match's range in the overall string. |
value
uses an older, untyped API so you'll have to check the documentation for what type can be passed in for a given key
.
Parameter | Type | Description |
---|---|---|
fontTraits |
UIFontDescriptor.SymbolicTraits or NSFontDescriptor.SymbolicTraits | Text formatting attributes (e.x. [.traitBold] in UIKit and .bold in AppKit) |
If you are targeting iOS 14 / macOS 11, you can use a convenience initializer taking advantage of new SwiftUI APIs for converting Colors to UIColors or NSColors.
Parameter | Type | Description |
---|---|---|
foregroundColor |
Color | Color of the text |
fontTraits |
UIFontDescriptor.SymbolicTraits or NSFontDescriptor.SymbolicTraits | Text formatting attributes (e.x. [.traitBold] in UIKit and .bold in AppKit) |
Apple, in its wisdom, has not enabled these features for the XCode 12 GM. If you are using the XCode beta and want to enable this initializer, go to project_name -> Targets -> specified platform -> Build Settings -> Swift Compiler - Custom Flags and add flag -DBETA
.
<
Are you using HighlightedTextEditor in your app? I would love to feature you here! Please open a pull request that adds a new bullet to the list below with your app's name and a link to its TestFlight or App Store page.
AppKit text editor code based on MacEditorTextView by Thiago Holanda.
Created by Kyle Nazario.