Skip to content

Commit

Permalink
Clicks (#29)
Browse files Browse the repository at this point in the history
* Accepts callbacks for NSAttributedString.Key values

* URL preset is now tappable

* Typo

* Documents new initializer

* CI Saves snapshots differently

* Focuses macOS path

* URL preset test snapshot reflects color to indicate clickability

* UIKit url snapshot reflects new color

* e2e tests link taps

* e2e tests link clicks in AppKit

* Updates autocorrection snapshots

* Does not crash if tests start in full screen

* Less brittle test

* Updates snapshot for Catalina
  • Loading branch information
kyle-n authored Feb 4, 2021
1 parent 51fec64 commit 4df5520
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 19 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
name: macOS-failing-snapshots
path: /var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/com.kylenazario.macOS-EssayistUITests.xctrunner/macOS_EssayistUITests
if-no-files-found: ignore
- name: Save new macOS snapshots
- name: Save existing/new macOS snapshots
if: failure()
uses: actions/upload-artifact@v2
with:
Expand Down Expand Up @@ -91,7 +91,7 @@ jobs:
name: iOS-failing-snapshots
path: /Users/runner/Library/Developer/CoreSimulator/Devices/**/test*.png
if-no-files-found: ignore
- name: Save new iOS snapshots
- name: Save existing/new iOS snapshots
if: failure()
uses: actions/upload-artifact@v2
with:
Expand Down
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ struct ContentView: View {
private let rules: [HighlightRule] = [
HighlightRule(pattern: betweenUnderscores, formattingRules: [
TextFormattingRule(fontTraits: [.traitItalic, .traitBold]),
TextFormattingRule(key: .foregroundColor, value: UIColor.red)
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 }
}
])
]

Expand Down Expand Up @@ -110,13 +114,18 @@ HighlightedTextEditor(text: $text, highlightRules: .markdown)

### TextFormattingRule

TextFormattingRule uses two different initializers that each set one style.
TextFormattingRule offers three different initializers that each set one style. To set multiple styles, use multiple TextFormattingRules.

| Parameter | Type | Description |
| --- | --- | --- |
| `key` | [NSAttributedString.Key](2) | 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](2) | 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](2) for what type can be passed in for a given `key`.

| Parameter | Type | Description |
Expand Down
22 changes: 15 additions & 7 deletions Sources/HighlightedTextEditor/HighlightingTextEditor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,31 @@ let defaultEditorTextColor = UIColor.label

public struct TextFormattingRule {

public typealias AttributedKeyCallback = (String, Range<String.Index>) -> Any

let key: NSAttributedString.Key?
let value: Any?
let calculateValue: AttributedKeyCallback?
let fontTraits: SymbolicTraits

// ------------------- convenience ------------------------

public init(key: NSAttributedString.Key, value: Any) {
self.init(key: key, value: value, fontTraits: [])
self.init(key: key, calculateValue: { _, _ in value }, fontTraits: [])
}

public init(key: NSAttributedString.Key, calculateValue: @escaping AttributedKeyCallback) {
self.init(key: key, calculateValue: calculateValue, fontTraits: [])
}

public init(fontTraits: SymbolicTraits) {
self.init(key: nil, value: nil, fontTraits: fontTraits)
self.init(key: nil, fontTraits: fontTraits)
}

// ------------------ most powerful initializer ------------------

init(key: NSAttributedString.Key? = nil, value: Any? = nil, fontTraits: SymbolicTraits = []) {
init(key: NSAttributedString.Key? = nil, calculateValue: AttributedKeyCallback? = nil, fontTraits: SymbolicTraits = []) {
self.key = key
self.value = value
self.calculateValue = calculateValue
self.fontTraits = fontTraits
}
}
Expand Down Expand Up @@ -109,8 +115,10 @@ extension HighlightingTextEditor {
}
highlightedString.addAttribute(.font, value: font, range: match.range)

guard let key = formattingRule.key, let value = formattingRule.value else { return }
highlightedString.addAttribute(key, value: value, range: match.range)
let matchRange = Range<String.Index>(match.range, in: text)!
let matchContent = String(text[matchRange])
guard let key = formattingRule.key, let calculateValue = formattingRule.calculateValue else { return }
highlightedString.addAttribute(key, value: calculateValue(matchContent, matchRange), range: match.range)
}
}
}
Expand Down
17 changes: 15 additions & 2 deletions Sources/HighlightedTextEditor/Presets/URL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation
import SwiftUI

fileprivate let urlRegexPattern = "((?:http|https)://)?(?:www\\.)?[\\w\\d\\-_]+\\.\\w{2,3}(\\.\\w{2})?(/(?<=/)(?:[\\w\\d\\-./_]+)?)?"
fileprivate let urlRegex = try! NSRegularExpression(pattern: urlRegexPattern, options: [])
fileprivate let _urlRegex = try! NSRegularExpression(pattern: urlRegexPattern, options: [])

// HighlightedTextEditor.markdown will only be accessible via [HighlightRule].markdown in a future 2.0.0 breaking release
// It does not really make any sense to have it here
Expand All @@ -19,6 +19,19 @@ public extension HighlightedTextEditor {

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

public extension HighlightRule {
static var urlRegex: NSRegularExpression {
_urlRegex
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions Tests/Essayist/iOS-EssayistUITests/iOS_EssayistUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,17 @@ class iOS_EssayistUITests: XCTestCase {

selectKeyboard(.englishUS)
}

func testURLPresetLinkTaps() {
let app = XCUIApplication()
app.launch()

selectEditor(.url)
app.textViews["hlte"].links.firstMatch.tap()

let safari = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari")
let safariLaunched = safari.wait(for: .runningForeground, timeout: 5)

XCTAssertTrue(safariLaunched)
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 25 additions & 6 deletions Tests/Essayist/macOS-EssayistUITests/macOS_EssayistUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ class macOS_EssayistUITests: XCTestCase {

let app = XCUIApplication()
app.launch()
app.windows.firstMatch.buttons[XCUIIdentifierFullScreenWindow].click()
let fullScreenButton = app.windows.firstMatch.buttons[XCUIIdentifierFullScreenWindow]
let _ = fullScreenButton.waitForExistence(timeout: 1)
if fullScreenButton.exists {
fullScreenButton.click()
}
}

private func selectEditor(_ editorType: EditorType) {
Expand Down Expand Up @@ -111,23 +115,38 @@ class macOS_EssayistUITests: XCTestCase {
app.buttons["Toggle drawsBackground"].click()
assertSnapshot(matching: screenshot, as: .image)
}

func testBackgroundColorChanges() {
let app = XCUIApplication()
app.activate()

selectEditor(.backgroundChanges)

let toggleBackgroundColorButton = app.buttons["Toggle backgroundColor"]
let toggleChangesButton = app.buttons["Toggle allowsDocumentBackgroundColorChange"]

toggleBackgroundColorButton.click()
assertSnapshot(matching: screenshot, as: .image)
toggleBackgroundColorButton.click()

toggleChangesButton.click()
toggleBackgroundColorButton.click()
assertSnapshot(matching: screenshot, as: .image)
}

func testURLPresetLinkClicks() {
let app = XCUIApplication()
app.launch()

selectEditor(.url)

let window = XCUIApplication().windows.firstMatch
window.textViews.links["https://www.google.com/"].click()

let safari = XCUIApplication(bundleIdentifier: "com.apple.Safari")
let safariLaunched = safari.wait(for: .runningForeground, timeout: 5)

XCTAssertTrue(safariLaunched)
}

}

0 comments on commit 4df5520

Please sign in to comment.