diff --git a/lib/src/editor/editor_component/service/ime/delta_input_on_non_text_update_impl.dart b/lib/src/editor/editor_component/service/ime/delta_input_on_non_text_update_impl.dart index 2df0b64a0..43ac55d70 100644 --- a/lib/src/editor/editor_component/service/ime/delta_input_on_non_text_update_impl.dart +++ b/lib/src/editor/editor_component/service/ime/delta_input_on_non_text_update_impl.dart @@ -59,7 +59,7 @@ Future onNonTextUpdate( // for the another keyboards (e.g. system keyboard), they will trigger the // `onFloatingCursor` event instead. AppFlowyEditorLog.input.debug('[Android] onNonTextUpdate: $nonTextUpdate'); - if (selection != null && selection != editorState.selection) { + if (selection != null) { editorState.updateSelectionWithReason( Selection.collapsed( Position( diff --git a/lib/src/plugins/markdown/decoder/document_markdown_decoder.dart b/lib/src/plugins/markdown/decoder/document_markdown_decoder.dart index 40287bd26..c2c9b9e2a 100644 --- a/lib/src/plugins/markdown/decoder/document_markdown_decoder.dart +++ b/lib/src/plugins/markdown/decoder/document_markdown_decoder.dart @@ -16,6 +16,7 @@ class DocumentMarkdownDecoder extends Converter { @override Document convert(String input) { + final formattedMarkdown = _formatMarkdown(input); final List mdNodes = md.Document( extensionSet: md.ExtensionSet.gitHubFlavored, inlineSyntaxes: [ @@ -23,7 +24,7 @@ class DocumentMarkdownDecoder extends Converter { UnderlineInlineSyntax(), ], encodeHtml: false, - ).parse(input); + ).parse(formattedMarkdown); final document = Document.blank(); final nodes = mdNodes @@ -61,4 +62,21 @@ class DocumentMarkdownDecoder extends Converter { return nodes; } + + String _formatMarkdown(String markdown) { + // Rule 1: single '\n' between text and image, add double '\n' + String result = markdown.replaceAllMapped( + RegExp(r'([^\n])\n!\[([^\]]*)\]\(([^)]+)\)', multiLine: true), + (match) { + final text = match[1] ?? ''; + final altText = match[2] ?? ''; + final url = match[3] ?? ''; + return '$text\n\n![$altText]($url)'; + }, + ); + + // Add another rules here. + + return result; + } } diff --git a/lib/src/plugins/markdown/decoder/parser/markdown_paragraph_parser.dart b/lib/src/plugins/markdown/decoder/parser/markdown_paragraph_parser.dart index 4214d41df..bec3e12fd 100644 --- a/lib/src/plugins/markdown/decoder/parser/markdown_paragraph_parser.dart +++ b/lib/src/plugins/markdown/decoder/parser/markdown_paragraph_parser.dart @@ -39,25 +39,13 @@ class MarkdownParagraphParserV2 extends CustomMarkdownParser { final splitContent = _splitByBrTag(ec); // Transform each split content into a paragraph node - final result = []; - for (final content in splitContent) { - for (final node in content) { - if (node is md.Element && node.tag == 'img') { - final image = const MarkdownImageParserV2() - .transform(node, parsers) - .firstOrNull; - if (image != null) { - result.add(image); - continue; - } - } - final deltaDecoder = DeltaMarkdownDecoder(); - final delta = deltaDecoder.convertNodes([node]); - result.add(paragraphNode(delta: delta)); - } - } + return splitContent.map((content) { + final deltaDecoder = DeltaMarkdownDecoder(); + final delta = deltaDecoder.convertNodes(content); + return paragraphNode(delta: delta); + }).toList(); - return result; + // return result; } } diff --git a/test/plugins/markdown/document_markdown_test.dart b/test/plugins/markdown/document_markdown_test.dart index c13b5d305..3c8c914b9 100644 --- a/test/plugins/markdown/document_markdown_test.dart +++ b/test/plugins/markdown/document_markdown_test.dart @@ -27,13 +27,24 @@ void main() { expect(markdown, markdownDocumentEncoded); }); - test('paragraph + image', () { + test('paragraph + image with single \n', () { const markdown = '''This is the first line ![image](https://example.com/image.png)'''; final document = markdownToDocument(markdown); final nodes = document.root.children; expect(nodes.length, 2); - expect(nodes[0].delta?.toPlainText(), 'This is the first line\n'); + expect(nodes[0].delta?.toPlainText(), 'This is the first line'); + expect(nodes[1].attributes['url'], 'https://example.com/image.png'); + }); + + test('paragraph + image with double \n', () { + const markdown = '''This is the first line + +![image](https://example.com/image.png)'''; + final document = markdownToDocument(markdown); + final nodes = document.root.children; + expect(nodes.length, 2); + expect(nodes[0].delta?.toPlainText(), 'This is the first line'); expect(nodes[1].attributes['url'], 'https://example.com/image.png'); }); });