Procházet zdrojové kódy

fix: add a encoder for math, #1795 (#1803)

* fix: add a encoder for math, #1795

* feat: support customzie the node parser for exporting markdown

* chore: fix flutter analyze

---------

Co-authored-by: Lucas.Xu <[email protected]>
huang12zheng před 2 roky
rodič
revize
4d5063de6a

+ 6 - 1
frontend/app_flowy/lib/plugins/document/application/share_bloc.dart

@@ -1,6 +1,8 @@
 import 'dart:convert';
 import 'dart:io';
 import 'package:app_flowy/plugins/document/application/share_service.dart';
+import 'package:app_flowy/plugins/document/presentation/plugins/parsers/divider_node_parser.dart';
+import 'package:app_flowy/plugins/document/presentation/plugins/parsers/math_equation_node_parser.dart';
 import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
@@ -48,7 +50,10 @@ class DocShareBloc extends Bloc<DocShareEvent, DocShareState> {
   String _convertDocumentToMarkdown(ExportDataPB value) {
     final json = jsonDecode(value.data);
     final document = Document.fromJson(json);
-    return documentToMarkdown(document);
+    return documentToMarkdown(document, customParsers: [
+      const DividerNodeParser(),
+      const MathEquationNodeParser(),
+    ]);
   }
 }
 

+ 1 - 2
frontend/app_flowy/packages/appflowy_editor/lib/src/plugins/markdown/encoder/parser/divider_node_parser.dart → frontend/app_flowy/lib/plugins/document/presentation/plugins/parsers/divider_node_parser.dart

@@ -1,5 +1,4 @@
-import 'package:appflowy_editor/src/core/document/node.dart';
-import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/node_parser.dart';
+import 'package:appflowy_editor/appflowy_editor.dart';
 
 class DividerNodeParser extends NodeParser {
   const DividerNodeParser();

+ 13 - 0
frontend/app_flowy/lib/plugins/document/presentation/plugins/parsers/math_equation_node_parser.dart

@@ -0,0 +1,13 @@
+import 'package:appflowy_editor/appflowy_editor.dart';
+
+class MathEquationNodeParser extends NodeParser {
+  const MathEquationNodeParser();
+
+  @override
+  String get id => 'math_equation';
+
+  @override
+  String transform(Node node) {
+    return '\$\$${node.attributes[id]}\$\$';
+  }
+}

+ 31 - 10
frontend/app_flowy/packages/appflowy_editor/lib/src/plugins/markdown/document_markdown.dart

@@ -5,24 +5,45 @@ import 'dart:convert';
 import 'package:appflowy_editor/src/core/document/document.dart';
 import 'package:appflowy_editor/src/plugins/markdown/decoder/document_markdown_decoder.dart';
 import 'package:appflowy_editor/src/plugins/markdown/encoder/document_markdown_encoder.dart';
-
-/// Codec used to convert between Markdown and AppFlowy Editor Document.
-const AppFlowyEditorMarkdownCodec _kCodec = AppFlowyEditorMarkdownCodec();
-
-Document markdownToDocument(String markdown) {
-  return _kCodec.decode(markdown);
+import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/image_node_parser.dart';
+import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/node_parser.dart';
+import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/text_node_parser.dart';
+
+/// Converts a markdown to [Document].
+///
+/// [customParsers] is a list of custom parsers that will be used to parse the markdown.
+Document markdownToDocument(
+  String markdown, {
+  List<NodeParser> customParsers = const [],
+}) {
+  return const AppFlowyEditorMarkdownCodec().decode(markdown);
 }
 
-String documentToMarkdown(Document document) {
-  return _kCodec.encode(document);
+/// Converts a [Document] to markdown.
+///
+/// [customParsers] is a list of custom parsers that will be used to parse the markdown.
+String documentToMarkdown(Document document,
+    {List<NodeParser> customParsers = const []}) {
+  return AppFlowyEditorMarkdownCodec(encodeParsers: [
+    ...customParsers,
+    const TextNodeParser(),
+    const ImageNodeParser(),
+  ]).encode(document);
 }
 
 class AppFlowyEditorMarkdownCodec extends Codec<Document, String> {
-  const AppFlowyEditorMarkdownCodec();
+  const AppFlowyEditorMarkdownCodec({
+    this.encodeParsers = const [],
+  });
+
+  final List<NodeParser> encodeParsers;
 
+  // TODO: Add support for custom parsers
   @override
   Converter<String, Document> get decoder => DocumentMarkdownDecoder();
 
   @override
-  Converter<Document, String> get encoder => DocumentMarkdownEncoder();
+  Converter<Document, String> get encoder => DocumentMarkdownEncoder(
+        parsers: encodeParsers,
+      );
 }

+ 1 - 8
frontend/app_flowy/packages/appflowy_editor/lib/src/plugins/markdown/encoder/document_markdown_encoder.dart

@@ -1,18 +1,11 @@
 import 'dart:convert';
 
 import 'package:appflowy_editor/src/core/document/document.dart';
-import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/divider_node_parser.dart';
-import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/image_node_parser.dart';
 import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/node_parser.dart';
-import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/text_node_parser.dart';
 
 class DocumentMarkdownEncoder extends Converter<Document, String> {
   DocumentMarkdownEncoder({
-    this.parsers = const [
-      TextNodeParser(),
-      ImageNodeParser(),
-      DividerNodeParser(),
-    ],
+    this.parsers = const [],
   });
 
   final List<NodeParser> parsers;

+ 4 - 1
frontend/app_flowy/packages/appflowy_editor/test/plugins/markdown/encoder/document_markdown_encoder_test.dart

@@ -114,7 +114,10 @@ void main() async {
     test('parser document', () async {
       final data = Map<String, Object>.from(json.decode(example));
       final document = Document.fromJson(data);
-      final result = DocumentMarkdownEncoder().convert(document);
+      final result = DocumentMarkdownEncoder(parsers: [
+        const TextNodeParser(),
+        const ImageNodeParser(),
+      ]).convert(document);
       expect(result, '''
 ## 👋 **Welcome to** ***[AppFlowy Editor](appflowy.io)***
 

+ 0 - 15
frontend/app_flowy/packages/appflowy_editor/test/plugins/markdown/encoder/parser/divider_node_parser_test.dart

@@ -1,15 +0,0 @@
-import 'package:appflowy_editor/appflowy_editor.dart';
-import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/divider_node_parser.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-void main() async {
-  group('divider_node_parser.dart', () {
-    test('parser divider node', () {
-      final node = Node(
-        type: 'divider',
-      );
-      final result = const DividerNodeParser().transform(node);
-      expect(result, '---\n');
-    });
-  });
-}

+ 57 - 0
frontend/app_flowy/test/unit_test/editor/share_markdown_test.dart

@@ -0,0 +1,57 @@
+import 'dart:convert';
+
+import 'package:app_flowy/plugins/document/presentation/plugins/parsers/divider_node_parser.dart';
+import 'package:app_flowy/plugins/document/presentation/plugins/parsers/math_equation_node_parser.dart';
+import 'package:appflowy_editor/appflowy_editor.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+  group('share markdown', () {
+    test('math equation', () {
+      const text = '''
+{
+    "document":{
+        "type":"editor",
+        "children":[
+            {
+                "type":"math_equation",
+                "attributes":{
+                    "math_equation":"E = MC^2"
+                }
+            }
+        ]
+    }
+}
+''';
+      final document = Document.fromJson(
+        Map<String, Object>.from(json.decode(text)),
+      );
+      final result = documentToMarkdown(document, customParsers: [
+        const MathEquationNodeParser(),
+      ]);
+      expect(result, r'$$E = MC^2$$');
+    });
+
+    test('divider', () {
+      const text = '''
+{
+    "document":{
+        "type":"editor",
+        "children":[
+            {
+                "type":"divider"
+            }
+        ]
+    }
+}
+''';
+      final document = Document.fromJson(
+        Map<String, Object>.from(json.decode(text)),
+      );
+      final result = documentToMarkdown(document, customParsers: [
+        const DividerNodeParser(),
+      ]);
+      expect(result, '---\n');
+    });
+  });
+}