Skip to content

Commit

Permalink
Merge branch 'main' into native-editor-paragraph-header-actions
Browse files Browse the repository at this point in the history
  • Loading branch information
tonisevener authored Jan 8, 2024
2 parents e0df137 + 9ba2a3d commit 3670195
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,63 @@ extension WKSourceEditorFormatter {

func toggleFormatting(startingFormattingString: String, endingFormattingString: String, action: WKSourceEditorFormatterButtonAction, in textView: UITextView) {

switch action {
case .remove:
expandSelectedRangeUpToNearestFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)

if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) {
removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
if textView.selectedRange.length == 0 {
switch action {
case .remove:
expandSelectedRangeUpToNearestFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)

if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) {
removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
}
case .add:
if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) {
removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
} else {
addStringFormattingCharacters(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
}
}
case .add:
if textView.selectedRange.length == 0 &&
selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) {
removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
} else {
addStringFormattingCharacters(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
} else {

switch action {
case .remove:

if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView) {
removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
} else {

// Note the flipped formatting string params.
// For example, this takes selected 'text' from:
// Testing <s>Strikethrough text here</s>
// To:
// Testing <s>Strikethrough </s>text<s> here</s>
// We have to add formatters in reverse order to remove formatting from 'text'

addStringFormattingCharacters(startingFormattingString: endingFormattingString, endingFormattingString: startingFormattingString, in: textView)
}

case .add:

// Note: gross workaround to prevent italics misfire from continuing below
if startingFormattingString == "''" && endingFormattingString == "''" {
if selectedRangeIsSurroundedByFormattingString(formattingString: "''", in: textView) &&
selectedRangeIsSurroundedByFormattingString(formattingString: "'''", in: textView) {
addStringFormattingCharacters(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
return
}
}

// Note the flipped formatting string params.
// For example, this takes selected 'text' from:
// Testing <s>Strikethrough </s>text<s> here</s>
// To:
// Testing <s>Strikethrough text here</s>
// We have to check and remove formatters in reverse order to add formatting to 'text'

if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: endingFormattingString, endingFormattingString: startingFormattingString, in: textView) {
removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: endingFormattingString, endingFormattingString: startingFormattingString, in: textView)
} else {
addStringFormattingCharacters(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ - (instancetype)initWithColors:(WKSourceEditorColors *)colors fonts:(WKSourceEdi
WKSourceEditorCustomKeyVerticalTemplate: [NSNumber numberWithBool:YES]
};

_horizontalTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"\\{{2}[^\\{\\}\\n]*\\}{2}" options:0 error:nil];
_verticalStartTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"^\\{{2}[^\\{\\}\\n]*$" options:NSRegularExpressionAnchorsMatchLines error:nil];
_horizontalTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"\\{{2}[^\\{\\}\\n]*(?:\\{{2}[^\\{\\}\\n]*\\}{2})*[^\\{\\}\\n]*\\}{2}" options:0 error:nil];
_verticalStartTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"^(?:.*)(\\{{2}[^\\{\\}\\n]*)$" options:NSRegularExpressionAnchorsMatchLines error:nil];
_verticalParameterTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"^\\s*\\|.*$" options:NSRegularExpressionAnchorsMatchLines error:nil];
_verticalEndTemplateRegex = [[NSRegularExpression alloc] initWithPattern:@"^([^\\{\\}\n]*\\}{2})(?:.)*$" options:NSRegularExpressionAnchorsMatchLines error:nil];
}
Expand Down Expand Up @@ -64,11 +64,12 @@ - (void)addSyntaxHighlightingToAttributedString:(nonnull NSMutableAttributedStri
options:0
range:range
usingBlock:^(NSTextCheckingResult *_Nullable result, NSMatchingFlags flags, BOOL *_Nonnull stop) {
NSRange matchRange = [result rangeAtIndex:0];
NSRange fullMatch = [result rangeAtIndex:0];
NSRange openingTemplateRange = [result rangeAtIndex:1];

if (matchRange.location != NSNotFound) {
[attributedString addAttributes:self.verticalTemplateAttributes range:matchRange];
}
if (fullMatch.location != NSNotFound && openingTemplateRange.location != NSNotFound) {
[attributedString addAttributes:self.verticalTemplateAttributes range:openingTemplateRange];
}
}];

[self.verticalParameterTemplateRegex enumerateMatchesInString:attributedString.string
Expand All @@ -86,12 +87,14 @@ - (void)addSyntaxHighlightingToAttributedString:(nonnull NSMutableAttributedStri
options:0
range:range
usingBlock:^(NSTextCheckingResult *_Nullable result, NSMatchingFlags flags, BOOL *_Nonnull stop) {

NSRange fullMatch = [result rangeAtIndex:0];
NSRange closingTemplateRange = [result rangeAtIndex:1];

if (fullMatch.location != NSNotFound && closingTemplateRange.location != NSNotFound) {
[attributedString addAttributes:self.verticalTemplateAttributes range:closingTemplateRange];
}
if (fullMatch.location != NSNotFound && closingTemplateRange.location != NSNotFound) {
[attributedString addAttributes:self.verticalTemplateAttributes range:closingTemplateRange];
}

}];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase {
XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four")
}

func testSingleBoldRemove() throws {
func testCursorBoldRemove() throws {
let text = "One '''Two''' Three Four"
mediator.textView.attributedText = NSAttributedString(string: text)
mediator.textView.selectedRange = NSRange(location: 8, length: 0) // Just a cursor inside Two
mediator.boldItalicsFormatter?.toggleBoldFormatting(action: .remove, in: mediator.textView)
XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four")
}

func testSingleItalicsRemove() throws {
func testCursorItalicsRemove() throws {
let text = "One Two '''Three''' Four"
mediator.textView.attributedText = NSAttributedString(string: text)
mediator.textView.selectedRange = NSRange(location: 14, length: 0)
Expand All @@ -77,7 +77,7 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase {
XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four")
}

func testSingleBoldInsertAndRemove() throws {
func testCursorBoldInsertAndRemove() throws {
let text = "One Two Three Four"
mediator.textView.attributedText = NSAttributedString(string: text)
mediator.textView.selectedRange = NSRange(location: 4, length: 0) // Just a cursor before Two
Expand All @@ -87,7 +87,7 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase {
XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four")
}

func testSingleItalicsInsertAndRemove() throws {
func testCursorItalicsInsertAndRemove() throws {
let text = "One Two Three Four"
mediator.textView.attributedText = NSAttributedString(string: text)
mediator.textView.selectedRange = NSRange(location: 4, length: 0) // Just a cursor before Two
Expand All @@ -97,6 +97,46 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase {
XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four")
}

func testBoldInnerRemoveAndInsert() throws {
let text = "One '''Two Three Four''' Five"
mediator.textView.attributedText = NSAttributedString(string: text)
mediator.textView.selectedRange = NSRange(location: 11, length: 5) // Selected Three
mediator.boldItalicsFormatter?.toggleBoldFormatting(action: .remove, in: mediator.textView)
XCTAssertEqual(mediator.textView.attributedText.string, "One '''Two '''Three''' Four''' Five")
mediator.boldItalicsFormatter?.toggleBoldFormatting(action: .remove, in: mediator.textView)
XCTAssertEqual(mediator.textView.attributedText.string, "One '''Two Three Four''' Five")
}

func testItalicsInnerRemoveAndInsert() throws {
let text = "One ''Two Three Four'' Five"
mediator.textView.attributedText = NSAttributedString(string: text)
mediator.textView.selectedRange = NSRange(location: 10, length: 5) // Selected Three
mediator.boldItalicsFormatter?.toggleItalicsFormatting(action: .remove, in: mediator.textView)
XCTAssertEqual(mediator.textView.attributedText.string, "One ''Two ''Three'' Four'' Five")
mediator.boldItalicsFormatter?.toggleItalicsFormatting(action: .remove, in: mediator.textView)
XCTAssertEqual(mediator.textView.attributedText.string, "One ''Two Three Four'' Five")
}

func testBoldItalicsInnerRemoveBoldAndInsert() throws {
let text = "One '''''Two Three Four''''' Five"
mediator.textView.attributedText = NSAttributedString(string: text)
mediator.textView.selectedRange = NSRange(location: 13, length: 5) // Selected Three
mediator.boldItalicsFormatter?.toggleBoldFormatting(action: .remove, in: mediator.textView)
XCTAssertEqual(mediator.textView.attributedText.string, "One '''''Two '''Three''' Four''''' Five")
mediator.boldItalicsFormatter?.toggleBoldFormatting(action: .remove, in: mediator.textView)
XCTAssertEqual(mediator.textView.attributedText.string, "One '''''Two Three Four''''' Five")
}

func testBoldItalicsInnerRemoveItalicsAndInsert() throws {
let text = "One '''''Two Three Four''''' Five"
mediator.textView.attributedText = NSAttributedString(string: text)
mediator.textView.selectedRange = NSRange(location: 13, length: 5) // Selected Three
mediator.boldItalicsFormatter?.toggleItalicsFormatting(action: .remove, in: mediator.textView)
XCTAssertEqual(mediator.textView.attributedText.string, "One '''''Two ''Three'' Four''''' Five")
mediator.boldItalicsFormatter?.toggleItalicsFormatting(action: .remove, in: mediator.textView)
XCTAssertEqual(mediator.textView.attributedText.string, "One '''''Two Three Four''''' Five")
}

func testTemplateInsert() throws {
let text = "One Two Three Four"
mediator.textView.attributedText = NSAttributedString(string: text)
Expand All @@ -113,7 +153,7 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase {
XCTAssertEqual(mediator.textView.attributedText.string, "One Two Three Four")
}

func testSingleTemplateInsertAndRemove() throws {
func testCursorTemplateInsertAndRemove() throws {
let text = "One Two Three Four"
mediator.textView.attributedText = NSAttributedString(string: text)
mediator.textView.selectedRange = NSRange(location: 4, length: 0) // Just a cursor before Two
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,43 @@ final class WKSourceEditorFormatterTests: XCTestCase {
XCTAssertEqual(refClosingAttributes[.foregroundColor] as! UIColor, colors.baseForegroundColor, "Incorrect ref formatting")
}

func testVerticalStartTemplate() {
func testHorizontalNestedTemplate() {
let string = "Ford Island ({{lang-haw|Poka {{okina}}Ailana}}) is an"
let mutAttributedString = NSMutableAttributedString(string: string)

for formatter in formatters {
formatter.addSyntaxHighlighting(to: mutAttributedString, in: NSRange(location: 0, length: string.count))
}

var base1Range = NSRange(location: 0, length: 0)
let base1Attributes = mutAttributedString.attributes(at: 0, effectiveRange: &base1Range)

var templateRange = NSRange(location: 0, length: 0)
let templateAttributes = mutAttributedString.attributes(at: 13, effectiveRange: &templateRange)

var base2Range = NSRange(location: 0, length: 0)
let base2Attributes = mutAttributedString.attributes(at: 46, effectiveRange: &base2Range)

// "Ford Island ("
XCTAssertEqual(base1Range.location, 0, "Incorrect base formatting")
XCTAssertEqual(base1Range.length, 13, "Incorrect base formatting")
XCTAssertEqual(base1Attributes[.font] as! UIFont, fonts.baseFont, "Incorrect base formatting")
XCTAssertEqual(base1Attributes[.foregroundColor] as! UIColor, colors.baseForegroundColor, "Incorrect base formatting")

// "{{lang-haw|Poka {{okina}}Ailana}}"
XCTAssertEqual(templateRange.location, 13, "Incorrect template formatting")
XCTAssertEqual(templateRange.length, 33, "Incorrect template formatting")
XCTAssertEqual(templateAttributes[.font] as! UIFont, fonts.baseFont, "Incorrect template formatting")
XCTAssertEqual(templateAttributes[.foregroundColor] as! UIColor, colors.purpleForegroundColor, "Incorrect template formatting")

// ") is an"
XCTAssertEqual(base2Range.location, 46, "Incorrect base formatting")
XCTAssertEqual(base2Range.length, 7, "Incorrect base formatting")
XCTAssertEqual(base2Attributes[.font] as! UIFont, fonts.baseFont, "Incorrect base formatting")
XCTAssertEqual(base2Attributes[.foregroundColor] as! UIColor, colors.baseForegroundColor, "Incorrect base formatting")
}

func testVerticalStartTemplate1() {
let string = "{{Infobox officeholder"
let mutAttributedString = NSMutableAttributedString(string: string)

Expand All @@ -658,6 +694,33 @@ final class WKSourceEditorFormatterTests: XCTestCase {
XCTAssertEqual(templateAttributes[.foregroundColor] as! UIColor, colors.purpleForegroundColor, "Incorrect template formatting")
}

func testVerticalStartTemplate2() {
let string = "ending of previous sentence. {{cite web"
let mutAttributedString = NSMutableAttributedString(string: string)

for formatter in formatters {
formatter.addSyntaxHighlighting(to: mutAttributedString, in: NSRange(location: 0, length: string.count))
}

var baseRange = NSRange(location: 0, length: 0)
let baseAttributes = mutAttributedString.attributes(at: 0, effectiveRange: &baseRange)

var templateRange = NSRange(location: 0, length: 0)
let templateAttributes = mutAttributedString.attributes(at: 29, effectiveRange: &templateRange)

// "ending of previous sentence. "
XCTAssertEqual(baseRange.location, 0, "Incorrect base formatting")
XCTAssertEqual(baseRange.length, 29, "Incorrect base formatting")
XCTAssertEqual(baseAttributes[.font] as! UIFont, fonts.baseFont, "Incorrect base formatting")
XCTAssertEqual(baseAttributes[.foregroundColor] as! UIColor, colors.baseForegroundColor, "Incorrect base formatting")

// "ending of previous sentence. "
XCTAssertEqual(templateRange.location, 29, "Incorrect template formatting")
XCTAssertEqual(templateRange.length, 10, "Incorrect template formatting")
XCTAssertEqual(templateAttributes[.font] as! UIFont, fonts.baseFont, "Incorrect template formatting")
XCTAssertEqual(templateAttributes[.foregroundColor] as! UIColor, colors.purpleForegroundColor, "Incorrect base formatting")
}

func testVerticalParameterTemplate() {
let string = "| genus = Felis"
let mutAttributedString = NSMutableAttributedString(string: string)
Expand Down

0 comments on commit 3670195

Please sign in to comment.