Skip to content

Releases: kyle-n/HighlightedTextEditor

Markdown headings use a larger font size

24 Jan 14:59
7069ede
Compare
Choose a tag to compare

New features

  • In the Markdown preset, headers display using a larger font size.

Bug fixes

  • When typing regular-size text on a line following a line formatted with a large font size, the AppKit editor insertion point no longer jitters (appears large then small)

Emojis appear in the editor

28 May 16:43
3eff60b
Compare
Choose a tag to compare

Bug fixes:

  • Emojis appear in the editor when typed (thanks to @ceojosef)

A simpler, more powerful HighlightedTextEditor

27 May 17:25
e7f0db3
Compare
Choose a tag to compare

HighlightedTextEditor is turning 2.0! This is a huge update that gives you even more flexibility and control while dramatically simplifying the package’s code.

Quick overview

New features

  • .introspect() modifier allows access to the underlying UITextView or NSTextView
  • NSRegularExpression.all is pre-made regex for selecting an entire string
  • Nests some internal HLTE classes inside HighlightedTextEditor so they're not polluting your project namespace

Breaking changes

  • Removes modifiers now covered by .introspect() (full list below)
  • .onCommit(), .onEditingChanged(), and .onTextChange() are now modifiers, not init() arguments (just like TextEditor!)
  • Markdown presets are only accessible from [HighlightRule]. For example, [HighlightRule].markdown

There are a lot of big changes in here, so here’s why I made them.

Problem: HLTE 1.0 was slowly replicating the API for UITextView and NSTextView

Under the hood, HLTE uses a UITextView or an NSTextView inside an NSScrollView. I threw a couple modifiers into v1 to set some options on the underlying UIKit/AppKit editor. For example:

HighlightedTextEditor(text: $text, highlightRules: [])
    .multilineTextAlignment(.center)

The problem was, those options weren’t enough. A lot of users needed new HLTE modifiers to set special properties on the underlying UIKit/AppKit editor, modifiers I hadn’t thought to make.

That’s not sustainable. That means HLTE was (slowly, poorly) replicating the API for UITextView and NSTextView.

Solution: Give users the UITextView or NSTextView

My solution was inspired by SwiftUI-Introspect, a cool library that lets you "introspect" the underlying UIKit or AppKit elements. It's a great way to write SwiftUI and dip into UIKit or AppKit to customize just one thing.

HighlightedTextEditor 2.0 removes all the previous modifiers that set UIKit or AppKit properties. Now there is only one god, .introspect():

HighlightedTextEditor(text: $text, highlightRules: .markdown)
	.introspect { internals in
		internals.textView.backgroundColor = .red
	}

internals is a struct containing two properties, textView and scrollView. The latter is only used in the AppKit editor and returns nil in UIKit editors.

public struct Internals {
	public let textView: SystemTextView
	public let scrollView: SystemScrollView? // always nil in UIKit
}

#if os(macOS)
import AppKit

public typealias SystemTextView = NSTextView
public typealias SystemScrollView = NSScrollView

#else
import UIKit

public typealias SystemTextView = UITextView
public typealias SystemScrollView = UIScrollView

#endif

.introspect() runs every time SwiftUI redraws the HLTE view.

Now you have access to every property in AppKit and UIKit. Customize away!

Removed modifiers

The following modifiers have been removed. If you were using them, simply set the equivalent UIKit / AppKit property using .introspect().

  • .allowsDocumentBackgroundColorChange(_ allowsChange: Bool)
  • .autocapitalizationType(_ type: UITextAutocapitalizationType)
  • .autocorrectionType(_ type: UITextAutocorrectionType)
  • .backgroundColor(_ color: UIColor)
  • .defaultColor(_ color: UIColor)
  • .defaultFont(_ font: UIFont)
  • .drawsBackground(_ shouldDraw: Bool)
  • .keyboardType(_ type: UIKeyboardType)
  • .insertionPointColor(_ color: UIColor)
  • .multilineTextAlignment(_ alignment: TextAlignment)

Behind the scenes

  • Deletes a lot of test code covering the old modifiers
  • UIKit tests run on iPhone 12 simulators, up from 11
  • Renames source code files to reflect that UIKit runs on the Mac
  • Automatic formating and linting thanks to SwiftFormat and SwiftLint

Get the insertion point location with onSelectionChange

08 Feb 21:16
710bb6f
Compare
Choose a tag to compare

This release adds a new modifier, onSelectionChange. Now whenever the insertion point changes in HighlightedTextEditor, it will run the provided callback.

HighlightedTextEditor(text: $text, highlightRules: .markdown)
    .onSelectionChange { (range: NSRange) in
        print(range)
    }

Thanks to @santi-g-s and @ben-ole for providing the inspiration and assistance for this feature.

Dynamic formatting via callbacks

04 Feb 23:00
4df5520
Compare
Choose a tag to compare

I've added an exciting, powerful new feature to TextFormattingRules that lets you do even more formatting on the fly. Here's an example:

TextFormattingRule(key: .underlineStyle) { content, range in
    if content.count > 10 { return NSUnderlineStyle.double.rawValue }
    else { return NSUnderlineStyle.single.rawValue }
}

TextFormattingRule has a new init() option that, instead of accepting a static value, accepts a callback function. Whatever the callback returns will be applied as the value for the given NSAttributedString.Key.

This allows things like tappable links where the URL target matches a URL string inside HighlightedTextEditor. See the source code for the .url [HighlightRule] preset:

public extension Sequence where Iterator.Element == HighlightRule {
    static var url: [HighlightRule] {
        [
            HighlightRule(pattern: _urlRegex, formattingRules: [
                TextFormattingRule(key: .underlineStyle, value: NSUnderlineStyle.single.rawValue),
                TextFormattingRule(key: .link) { urlString, _ in
                    URL(string: urlString) as Any
                }
            ])
        ]
    }
}

This doesn't just apply to NSAttributedString.Key.link, though, it works on any property! Go crazy!

Behind the scenes

This release also contains substantial improvements to HighlightedTextEditor's continuous integration test suite. These changes will help ship features faster, with less brittle tests.

Bug fixes

28 Dec 21:45
d51cf90
Compare
Choose a tag to compare

UIKit Editor

  • Editor sets correct initial font if using .defaultFont(), does not change fonts after typing the first character (@mikakruschel, #21)
  • .insertionPointColor() correctly sets insertion point color in Catalyst apps (@Chryb, #19)

Infrastructure

  • CI handles branches with / in the name
  • CI boots iOS Simulator in separate step

Fixes bug with multi-stage input languages

04 Dec 16:47
Compare
Choose a tag to compare

#13 by @hstdt

  • Fixes a bug where switching from English keyboards to a keyboard with multi-stage input, such as Chinese or Japanese, would duplicate the editor content.
  • Adds a new e2e test covering this case

Markdown fixes and tests!

30 Nov 21:52
Compare
Choose a tag to compare

User-facing features

Markdown preset

  • Adds highlighting for tagged links
[link name][df]

[df]: https://daringfireball.net/
  • Adds highlighting for footnotes
This is a footnote[^1].

[1]: Yep.
  • Adds highlighting for HTML tags
Regular markdown here. 

<aside>Other HTML content here.</aside>

Infrastructure

Adds a test project, Essayist, with a suite of unit and e2e tests. This is only for me but I am very excited to not pull out my iPad and run a test project every time something changes.

As far as I can tell, test code is not included in any app that uses HighlightedTextEditor. Build sizes on Archive are the same with and without the test folder.

CocoaPods support

15 Nov 22:54
Compare
Choose a tag to compare

HighlightedTextEditor may now be installed via CocoaPods. To install, add pod 'HighlightedTextEditor' to your Podfile and run pod install.

This release also adds a GitHub Action to auto-update the HLTE CocoaPod when a new git tag release is pushed.

Presets are static variables on [HighlightRule]

14 Nov 15:51
Compare
Choose a tag to compare

This release makes HighlightRule presets static variables on [HighlightRule]. They make more sense there and don't really make sense as static variables on HighlightedTextEditor.

Recommended syntax for accessing presets is now:

HighlightedTextEditor(text: $text, highlightRules: .markdown)

This release does not remove the static preset variables from HighlightedTextEditor. Those variables will be removed in a future 2.0.0 breaking release.