feat: convert = and > to ⇒ (#523)
This commit is contained in:
parent
6d163b8897
commit
51f8f791c8
4 changed files with 151 additions and 11 deletions
|
|
@ -1,13 +1,12 @@
|
|||
export 'insert_newline.dart';
|
||||
export 'slash_command.dart';
|
||||
export 'markdown_syntax_character_shortcut_events.dart';
|
||||
|
||||
export 'format_single_character/format_single_character.dart';
|
||||
export 'format_single_character/format_italic.dart';
|
||||
export 'format_single_character/format_code.dart';
|
||||
export 'format_single_character/format_strikethrough.dart';
|
||||
|
||||
export 'format_double_characters/format_double_characters.dart';
|
||||
export 'format_double_characters/format_bold.dart';
|
||||
export 'format_double_characters/format_strikethrough.dart';
|
||||
export 'format_double_characters/format_double_characters.dart';
|
||||
export 'format_double_characters/format_double_hyphen.dart';
|
||||
export 'format_double_characters/format_equal_greater_character.dart';
|
||||
export 'format_double_characters/format_strikethrough.dart';
|
||||
export 'format_single_character/format_code.dart';
|
||||
export 'format_single_character/format_italic.dart';
|
||||
export 'format_single_character/format_single_character.dart';
|
||||
export 'format_single_character/format_strikethrough.dart';
|
||||
export 'insert_newline.dart';
|
||||
export 'markdown_syntax_character_shortcut_events.dart';
|
||||
export 'slash_command.dart';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
|
||||
const _greater = '>';
|
||||
const _equals = '=';
|
||||
const _arrow = '⇒';
|
||||
|
||||
/// format '=' + '>' into an ⇒
|
||||
///
|
||||
/// - support
|
||||
/// - desktop
|
||||
/// - mobile
|
||||
/// - web
|
||||
///
|
||||
final CharacterShortcutEvent formatGreaterEqual = CharacterShortcutEvent(
|
||||
key: 'format = + > into ⇒',
|
||||
character: _greater,
|
||||
handler: (editorState) async => handleEqualGreaterReplacement(
|
||||
editorState: editorState,
|
||||
character: _greater,
|
||||
replacement: _arrow,
|
||||
),
|
||||
);
|
||||
|
||||
// TODO(Xazin): Combine two character replacement methods into
|
||||
// a helper function
|
||||
Future<bool> handleEqualGreaterReplacement({
|
||||
required EditorState editorState,
|
||||
required String character,
|
||||
required String replacement,
|
||||
}) async {
|
||||
assert(character.length == 1);
|
||||
|
||||
Selection? selection = editorState.selection;
|
||||
if (selection == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!selection.isCollapsed) {
|
||||
await editorState.deleteSelection(selection);
|
||||
}
|
||||
|
||||
selection = editorState.selection;
|
||||
if (selection == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final node = editorState.getNodeAtPath(selection.end.path);
|
||||
final delta = node?.delta;
|
||||
if (node == null || delta == null || delta.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selection.end.offset > 0) {
|
||||
final plain = delta.toPlainText();
|
||||
|
||||
final previousCharacter = plain[selection.end.offset - 1];
|
||||
if (previousCharacter != _equals) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final replace = editorState.transaction
|
||||
..replaceText(
|
||||
node,
|
||||
selection.end.offset - 1,
|
||||
1,
|
||||
_arrow,
|
||||
);
|
||||
|
||||
await editorState.apply(replace);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -32,4 +32,6 @@ final List<CharacterShortcutEvent> markdownSyntaxShortcutEvents = [
|
|||
|
||||
// format -- into em dash
|
||||
formatDoubleHyphenEmDash,
|
||||
// format = + > into ⇒
|
||||
formatGreaterEqual,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../../infra/testable_editor.dart';
|
||||
|
||||
const _greater = '>';
|
||||
const _equals = '=';
|
||||
const _arrow = '⇒';
|
||||
|
||||
void main() async {
|
||||
group('format_equal_greater.dart', () {
|
||||
testWidgets('= + > to ⇒ in empty paragraph', (tester) async {
|
||||
final editor = tester.editor..addEmptyParagraph();
|
||||
await editor.startTesting();
|
||||
|
||||
await editor.updateSelection(Selection.collapsed(Position(path: [0])));
|
||||
|
||||
await editor.ime.typeText(_equals);
|
||||
await editor.ime.typeText(_greater);
|
||||
|
||||
final delta = editor.nodeAtPath([0])!.delta!;
|
||||
expect(delta.length, 1);
|
||||
expect(delta.toPlainText(), _arrow);
|
||||
|
||||
await editor.dispose();
|
||||
});
|
||||
|
||||
testWidgets('= + > to ⇒ in non-empty paragraph, undo, redo',
|
||||
(tester) async {
|
||||
const text = 'Hello World';
|
||||
final editor = tester.editor..addParagraph(initialText: text);
|
||||
await editor.startTesting();
|
||||
|
||||
await editor.updateSelection(
|
||||
Selection.collapsed(
|
||||
Position(
|
||||
path: [0],
|
||||
offset: text.length,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await editor.ime.typeText(_equals);
|
||||
await editor.ime.typeText(_greater);
|
||||
|
||||
Delta delta = editor.nodeAtPath([0])!.delta!;
|
||||
expect(delta.toPlainText(), text + _arrow);
|
||||
|
||||
undoCommand.execute(editor.editorState);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
delta = editor.nodeAtPath([0])!.delta!;
|
||||
expect(delta.toPlainText(), text + _equals);
|
||||
|
||||
undoCommand.execute(editor.editorState);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
delta = editor.nodeAtPath([0])!.delta!;
|
||||
expect(delta.toPlainText(), text);
|
||||
|
||||
await editor.dispose();
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue