diff --git a/Components/Sources/Components/Components/Editors/Source Editor/Formatter Extensions/WKSourceEditorFormatter+ButtonActions.swift b/Components/Sources/Components/Components/Editors/Source Editor/Formatter Extensions/WKSourceEditorFormatter+ButtonActions.swift
index 8c464dea60c..daf676df290 100644
--- a/Components/Sources/Components/Components/Editors/Source Editor/Formatter Extensions/WKSourceEditorFormatter+ButtonActions.swift
+++ b/Components/Sources/Components/Components/Editors/Source Editor/Formatter Extensions/WKSourceEditorFormatter+ButtonActions.swift
@@ -15,35 +15,71 @@ extension WKSourceEditorFormatter {
}
func toggleFormatting(startingFormattingString: String, wildcardStartingFormattingString: String? = nil, endingFormattingString: String, action: WKSourceEditorFormatterButtonAction, in textView: UITextView) {
-
- switch action {
- case .remove:
-
- var resolvedStartingFormattingString = startingFormattingString
- if let wildcardStartingFormattingString {
- resolvedStartingFormattingString = getModifiedStartingFormattingStringForSingleWildcard(startingFormattingString: wildcardStartingFormattingString, textView: textView)
- }
-
- expandSelectedRangeUpToNearestFormattingStrings(startingFormattingString: resolvedStartingFormattingString, endingFormattingString: endingFormattingString, in: textView)
+
+ var resolvedStartingFormattingString = startingFormattingString
+ if let wildcardStartingFormattingString {
+ resolvedStartingFormattingString = getModifiedStartingFormattingStringForSingleWildcard(startingFormattingString: wildcardStartingFormattingString, textView: textView)
+ }
+
+ if textView.selectedRange.length == 0 {
- if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: resolvedStartingFormattingString, endingFormattingString: endingFormattingString, in: textView) {
- removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: resolvedStartingFormattingString, endingFormattingString: endingFormattingString, in: textView)
- }
- case .add:
- if textView.selectedRange.length == 0 {
+ switch action {
+ case .remove:
+
+ expandSelectedRangeUpToNearestFormattingStrings(startingFormattingString: resolvedStartingFormattingString, endingFormattingString: endingFormattingString, in: textView)
- var resolvedStartingFormattingString = startingFormattingString
- if let wildcardStartingFormattingString {
- resolvedStartingFormattingString = getModifiedStartingFormattingStringForSingleWildcard(startingFormattingString: wildcardStartingFormattingString, textView: textView)
+ if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: resolvedStartingFormattingString, endingFormattingString: endingFormattingString, in: textView) {
+ removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: resolvedStartingFormattingString, endingFormattingString: endingFormattingString, in: textView)
}
+ case .add:
+ if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: resolvedStartingFormattingString, endingFormattingString: endingFormattingString, in: textView) {
+ removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: resolvedStartingFormattingString, endingFormattingString: endingFormattingString, in: textView)
+ } else {
+ addStringFormattingCharacters(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
+ }
+ }
+ } else {
+
+ switch action {
+ case .remove:
if selectedRangeIsSurroundedByFormattingStrings(startingFormattingString: resolvedStartingFormattingString, endingFormattingString: endingFormattingString, in: textView) {
removeSurroundingFormattingStringsFromSelectedRange(startingFormattingString: resolvedStartingFormattingString, endingFormattingString: endingFormattingString, in: textView)
} else {
+
+ // Note the flipped formatting string params.
+ // For example, this takes selected 'text' from:
+ // Testing Strikethrough text here
+ // To:
+ // Testing Strikethrough text here
+ // 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 Strikethrough text here
+ // To:
+ // Testing Strikethrough text here
+ // 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)
}
- } else {
- addStringFormattingCharacters(startingFormattingString: startingFormattingString, endingFormattingString: endingFormattingString, in: textView)
}
}
}
diff --git a/Components/Tests/ComponentsTests/WKSourceEditorFormatterButtonActionTests.swift b/Components/Tests/ComponentsTests/WKSourceEditorFormatterButtonActionTests.swift
index a82b76b6e04..a8343cc0e16 100644
--- a/Components/Tests/ComponentsTests/WKSourceEditorFormatterButtonActionTests.swift
+++ b/Components/Tests/ComponentsTests/WKSourceEditorFormatterButtonActionTests.swift
@@ -42,7 +42,7 @@ 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
@@ -50,7 +50,7 @@ final class WKSourceEditorFormatterButtonActionTests: XCTestCase {
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)
@@ -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
@@ -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
@@ -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)
@@ -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