فهرست منبع

feat: implement doubleTildeToStrikethrough ShortcutEventHandler

Alexandre Moreau 2 سال پیش
والد
کامیت
be5123ca21

+ 63 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/markdown_syntax_to_styled_text.dart

@@ -124,3 +124,66 @@ ShortcutEventHandler backquoteToCodeHandler = (editorState, event) {
 
   return KeyEventResult.handled;
 };
+
+// convert ~~abc~~ to strikethrough abc.
+ShortcutEventHandler doubleTildeToStrikethrough = (editorState, event) {
+  final selectionService = editorState.service.selectionService;
+  final selection = selectionService.currentSelection.value;
+  final textNodes = selectionService.currentSelectedNodes.whereType<TextNode>();
+  if (selection == null || !selection.isSingle || textNodes.length != 1) {
+    return KeyEventResult.ignored;
+  }
+
+  final textNode = textNodes.first;
+  final text = textNode.toRawString().substring(0, selection.end.offset);
+
+  // make sure the last two characters are ~~.
+  if (text.length < 2 || text[selection.end.offset - 1] != '~') {
+    return KeyEventResult.ignored;
+  }
+
+  // find all the index of `~`.
+  final tildeIndexes = <int>[];
+  for (var i = 0; i < text.length; i++) {
+    if (text[i] == '~') {
+      tildeIndexes.add(i);
+    }
+  }
+
+  if (tildeIndexes.length < 3) {
+    return KeyEventResult.ignored;
+  }
+
+  // make sure the second to last and third to last tildes are connected.
+  final thirdToLastTildeIndex = tildeIndexes[tildeIndexes.length - 3];
+  final secondToLastTildeIndex = tildeIndexes[tildeIndexes.length - 2];
+  final lastTildeIndex = tildeIndexes[tildeIndexes.length - 1];
+  if (secondToLastTildeIndex != thirdToLastTildeIndex + 1 ||
+      lastTildeIndex == secondToLastTildeIndex + 1) {
+    return KeyEventResult.ignored;
+  }
+
+  // delete the last three tildes.
+  // update the style of the text surround by `~~ ~~` to strikethrough.
+  // and update the cursor position.
+  TransactionBuilder(editorState)
+    ..deleteText(textNode, lastTildeIndex, 1)
+    ..deleteText(textNode, thirdToLastTildeIndex, 2)
+    ..formatText(
+      textNode,
+      thirdToLastTildeIndex,
+      selection.end.offset - thirdToLastTildeIndex - 2,
+      {
+        BuiltInAttributeKey.strikethrough: true,
+      },
+    )
+    ..afterSelection = Selection.collapsed(
+      Position(
+        path: textNode.path,
+        offset: selection.end.offset - 3,
+      ),
+    )
+    ..commit();
+
+  return KeyEventResult.handled;
+};