浏览代码

Merge pull request #1696 from abichinger/feat/md-blockquote

feat: greater to blockquote
Lucas.Xu 2 年之前
父节点
当前提交
73ad789bf0

+ 23 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/whitespace_handler.dart

@@ -20,6 +20,8 @@ const _bulletedListSymbols = ['*', '-'];
 const _checkboxListSymbols = ['[x]', '-[x]'];
 const _checkboxListSymbols = ['[x]', '-[x]'];
 const _unCheckboxListSymbols = ['[]', '-[]'];
 const _unCheckboxListSymbols = ['[]', '-[]'];
 
 
+const _quoteSymbols = ['>'];
+
 final _numberRegex = RegExp(r'^(\d+)\.');
 final _numberRegex = RegExp(r'^(\d+)\.');
 
 
 ShortcutEventHandler whiteSpaceHandler = (editorState, event) {
 ShortcutEventHandler whiteSpaceHandler = (editorState, event) {
@@ -49,6 +51,8 @@ ShortcutEventHandler whiteSpaceHandler = (editorState, event) {
     return _toBulletedList(editorState, textNode);
     return _toBulletedList(editorState, textNode);
   } else if (_countOfSign(text, selection) != 0) {
   } else if (_countOfSign(text, selection) != 0) {
     return _toHeadingStyle(editorState, textNode, selection);
     return _toHeadingStyle(editorState, textNode, selection);
+  } else if (_quoteSymbols.contains(text)) {
+    return _toQuoteStyle(editorState, textNode);
   } else if (numberMatch != null) {
   } else if (numberMatch != null) {
     final matchText = numberMatch.group(0);
     final matchText = numberMatch.group(0);
     final numText = numberMatch.group(1);
     final numText = numberMatch.group(1);
@@ -196,3 +200,22 @@ int _countOfSign(String text, Selection selection) {
   }
   }
   return 0;
   return 0;
 }
 }
+
+KeyEventResult _toQuoteStyle(EditorState editorState, TextNode textNode) {
+  if (textNode.subtype == BuiltInAttributeKey.quote) {
+    return KeyEventResult.ignored;
+  }
+  final transaction = editorState.transaction
+    ..deleteText(textNode, 0, 1)
+    ..updateNode(textNode, {
+      BuiltInAttributeKey.subtype: BuiltInAttributeKey.quote,
+    })
+    ..afterSelection = Selection.collapsed(
+      Position(
+        path: textNode.path,
+        offset: 0,
+      ),
+    );
+  editorState.apply(transaction);
+  return KeyEventResult.handled;
+}

+ 64 - 0
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/white_space_handler_test.dart

@@ -184,6 +184,10 @@ void main() async {
         Selection.single(path: [0], startOffset: 0),
         Selection.single(path: [0], startOffset: 0),
       );
       );
 
 
+      await editor.insertText(textNode, '>', 0);
+      await editor.pressLogicKey(LogicalKeyboardKey.space);
+      expect(textNode.subtype, BuiltInAttributeKey.quote);
+
       await editor.insertText(textNode, '*', 0);
       await editor.insertText(textNode, '*', 0);
       await editor.pressLogicKey(LogicalKeyboardKey.space);
       await editor.pressLogicKey(LogicalKeyboardKey.space);
       expect(textNode.subtype, BuiltInAttributeKey.bulletedList);
       expect(textNode.subtype, BuiltInAttributeKey.bulletedList);
@@ -227,5 +231,65 @@ void main() async {
       expect(textNode.subtype, null);
       expect(textNode.subtype, null);
       expect(textNode.toPlainText(), text);
       expect(textNode.toPlainText(), text);
     });
     });
+
+    group('convert geater to blockquote', () {
+      testWidgets('> AppFlowy to blockquote AppFlowy', (tester) async {
+        const text = 'AppFlowy';
+        final editor = tester.editor..insertTextNode('');
+        await editor.startTesting();
+        await editor.updateSelection(
+          Selection.single(path: [0], startOffset: 0),
+        );
+
+        final textNode = editor.nodeAtPath([0]) as TextNode;
+        await editor.insertText(textNode, '>', 0);
+        await editor.pressLogicKey(LogicalKeyboardKey.space);
+        expect(textNode.subtype, BuiltInAttributeKey.quote);
+        for (var i = 0; i < text.length; i++) {
+          await editor.insertText(textNode, text[i], i);
+        }
+        expect(textNode.toPlainText(), 'AppFlowy');
+      });
+
+      testWidgets('AppFlowy > nothing changes', (tester) async {
+        const text = 'AppFlowy >';
+        final editor = tester.editor..insertTextNode('');
+        await editor.startTesting();
+        await editor.updateSelection(
+          Selection.single(path: [0], startOffset: 0),
+        );
+
+        final textNode = editor.nodeAtPath([0]) as TextNode;
+        for (var i = 0; i < text.length; i++) {
+          await editor.insertText(textNode, text[i], i);
+        }
+        await editor.pressLogicKey(LogicalKeyboardKey.space);
+        final isQuote = textNode.subtype == BuiltInAttributeKey.quote;
+        expect(isQuote, false);
+        expect(textNode.toPlainText(), text);
+      });
+
+      testWidgets('> in front of text to blockquote', (tester) async {
+        const text = 'AppFlowy';
+        final editor = tester.editor..insertTextNode('');
+        await editor.startTesting();
+        await editor.updateSelection(
+          Selection.single(path: [0], startOffset: 0),
+        );
+        final textNode = editor.nodeAtPath([0]) as TextNode;
+        for (var i = 0; i < text.length; i++) {
+          await editor.insertText(textNode, text[i], i);
+        }
+        await editor.updateSelection(
+          Selection.single(path: [0], startOffset: 0),
+        );
+        await editor.insertText(textNode, '>', 0);
+        await editor.pressLogicKey(LogicalKeyboardKey.space);
+
+        final isQuote = textNode.subtype == BuiltInAttributeKey.quote;
+        expect(isQuote, true);
+        expect(textNode.toPlainText(), text);
+      });
+    });
   });
   });
 }
 }