From 7d6aa7e1f97444381a4cfebacc50ad7a99a46dbd Mon Sep 17 00:00:00 2001 From: Morn Date: Fri, 7 Feb 2025 15:03:42 +0800 Subject: [PATCH] chore: add some testing for markdown parser --- .../multi_image_block_component.dart | 5 +- .../parsers/custom_image_node_parser.dart | 2 +- .../lib/shared/markdown_to_document.dart | 33 ++++--- .../markdown/markdown_parser_test.dart | 92 ++++++++++++++++++- 4 files changed, 114 insertions(+), 18 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/multi_image_block_component/multi_image_block_component.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/multi_image_block_component/multi_image_block_component.dart index 272b492835ec0..88f60db494954 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/multi_image_block_component/multi_image_block_component.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/multi_image_block_component/multi_image_block_component.dart @@ -13,10 +13,11 @@ import 'package:universal_platform/universal_platform.dart'; const kMultiImagePlaceholderKey = 'multiImagePlaceholderKey'; -Node multiImageNode() => Node( +Node multiImageNode({List? images}) => Node( type: MultiImageBlockKeys.type, attributes: { - MultiImageBlockKeys.images: MultiImageData(images: []).toJson(), + MultiImageBlockKeys.images: + MultiImageData(images: images ?? []).toJson(), MultiImageBlockKeys.layout: MultiImageLayout.browser.toIntValue(), }, ); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/parsers/custom_image_node_parser.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/parsers/custom_image_node_parser.dart index 3f49c3da68f88..d4b6bb444fc23 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/parsers/custom_image_node_parser.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/parsers/custom_image_node_parser.dart @@ -76,7 +76,7 @@ class CustomMultiImageNodeFileParser extends NodeParser { ); markdownImages.add('![]($filePath)'); } else { - markdownImages.add('![]($url})'); + markdownImages.add('![]($url)'); } } return markdownImages.join('\n'); diff --git a/frontend/appflowy_flutter/lib/shared/markdown_to_document.dart b/frontend/appflowy_flutter/lib/shared/markdown_to_document.dart index d84fad83efe61..ceb57d6f49ade 100644 --- a/frontend/appflowy_flutter/lib/shared/markdown_to_document.dart +++ b/frontend/appflowy_flutter/lib/shared/markdown_to_document.dart @@ -5,6 +5,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.da import 'package:appflowy_backend/log.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:archive/archive.dart'; +import 'package:flutter/foundation.dart'; import 'package:path/path.dart' as p; import 'package:share_plus/share_plus.dart'; @@ -36,7 +37,11 @@ String customDocumentToMarkdown(Document document) { ); } -Future documentToMarkdownFiles(Document document, String path) async { +Future documentToMarkdownFiles( + Document document, + String path, { + AsyncValueSetter? onArchive, +}) async { final List> fileFutures = []; /// create root Archive and directory @@ -75,18 +80,22 @@ Future documentToMarkdownFiles(Document document, String path) async { archive.addFile(await fileFuture); } if (archive.isNotEmpty) { - final zipEncoder = ZipEncoder(); - final zip = zipEncoder.encode(archive); - if (zip != null) { - final zipFile = await File(path).writeAsBytes(zip); - if (Platform.isIOS) { - await Share.shareUri(zipFile.uri); - await zipFile.delete(); - } else if (Platform.isAndroid) { - await Share.shareXFiles([XFile(zipFile.path)]); - await zipFile.delete(); + if (onArchive == null) { + final zipEncoder = ZipEncoder(); + final zip = zipEncoder.encode(archive); + if (zip != null) { + final zipFile = await File(path).writeAsBytes(zip); + if (Platform.isIOS) { + await Share.shareUri(zipFile.uri); + await zipFile.delete(); + } else if (Platform.isAndroid) { + await Share.shareXFiles([XFile(zipFile.path)]); + await zipFile.delete(); + } + Log.info('documentToMarkdownFiles to $path'); } - Log.info('documentToMarkdownFiles to $path'); + } else { + await onArchive.call(archive); } } return markdown; diff --git a/frontend/appflowy_flutter/test/unit_test/markdown/markdown_parser_test.dart b/frontend/appflowy_flutter/test/unit_test/markdown/markdown_parser_test.dart index 70775612e2a7e..1a87998a2604d 100644 --- a/frontend/appflowy_flutter/test/unit_test/markdown/markdown_parser_test.dart +++ b/frontend/appflowy_flutter/test/unit_test/markdown/markdown_parser_test.dart @@ -1,10 +1,19 @@ +import 'package:appflowy/plugins/document/presentation/editor_plugins/image/common.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy/shared/markdown_to_document.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { + Future emptyCallback(_) async { + return; + } + + const testDirectory = 'test/'; + group('export markdown to document', () { test('file block', () async { final document = Document.blank() @@ -17,21 +26,98 @@ void main() { ), ], ); - final markdown = customDocumentToMarkdown(document); + final markdown = await documentToMarkdownFiles( + document, + testDirectory, + onArchive: emptyCallback, + ); expect(markdown, '[file.txt](https://file.com)\n'); }); - test('link preview', () { + test('link preview', () async { final document = Document.blank() ..insert( [0], [linkPreviewNode(url: 'https://www.link_preview.com')], ); - final markdown = customDocumentToMarkdown(document); + final markdown = await documentToMarkdownFiles( + document, + testDirectory, + onArchive: emptyCallback, + ); expect( markdown, '[https://www.link_preview.com](https://www.link_preview.com)\n', ); }); + + test('multiple images', () async { + const png1 = 'https://www.appflowy.png', + png2 = 'https://www.appflowy2.png'; + final document = Document.blank() + ..insert( + [0], + [ + multiImageNode( + images: [ + ImageBlockData( + url: png1, + type: CustomImageType.external, + ), + ImageBlockData( + url: png2, + type: CustomImageType.external, + ), + ], + ), + ], + ); + final markdown = await documentToMarkdownFiles( + document, + testDirectory, + onArchive: emptyCallback, + ); + expect( + markdown, + '![]($png1)\n![]($png2)', + ); + }); + + test('subpage block', () async { + const testSubpageId = 'testSubpageId'; + final subpageNode = pageMentionNode(testSubpageId); + final document = Document.blank() + ..insert( + [0], + [subpageNode], + ); + final markdown = await documentToMarkdownFiles( + document, + testDirectory, + onArchive: emptyCallback, + ); + expect( + markdown, + '[]($testSubpageId)\n', + ); + }); + + test('date or reminder', () async { + final dateTime = DateTime.now(); + final document = Document.blank() + ..insert( + [0], + [dateMentionNode()], + ); + final markdown = await documentToMarkdownFiles( + document, + testDirectory, + onArchive: emptyCallback, + ); + expect( + markdown, + '${DateFormat.yMMMd().format(dateTime)}\n', + ); + }); }); }