Lucas.Xu пре 2 година
родитељ
комит
c85ab276e9

+ 41 - 0
frontend/app_flowy/packages/appflowy_editor/example/lib/main.dart

@@ -111,6 +111,47 @@ class _MyHomePageState extends State<MyHomePage> {
             if (!darkMode) ...lightEditorStyleExtension,
             if (!darkMode) ...lightPlguinStyleExtension,
           ]);
+          final delta = Delta();
+          delta.add(TextInsert('Hello '));
+          delta.add(
+            TextInsert(
+              'World',
+              attributes: {
+                BuiltInAttributeKey.bold: true,
+                BuiltInAttributeKey.italic: true,
+              },
+            ),
+          );
+          delta.add(
+            TextInsert(
+              ' ',
+            ),
+          );
+          delta.add(
+            TextInsert(
+              'Again',
+              attributes: {
+                BuiltInAttributeKey.italic: true,
+              },
+            ),
+          );
+          delta.add(
+            TextInsert(
+              ' ',
+            ),
+          );
+          delta.add(
+            TextInsert(
+              'Again',
+              attributes: {
+                BuiltInAttributeKey.href: 'https://google.com',
+                BuiltInAttributeKey.italic: true,
+                BuiltInAttributeKey.bold: true,
+                BuiltInAttributeKey.strikethrough: true,
+              },
+            ),
+          );
+          final result = DeltaMarkdownEncoder().convert(delta);
           return Container(
             color: darkMode ? Colors.black : Colors.white,
             width: MediaQuery.of(context).size.width,

+ 1 - 0
frontend/app_flowy/packages/appflowy_editor/lib/appflowy_editor.dart

@@ -33,3 +33,4 @@ export 'src/render/selection_menu/selection_menu_widget.dart';
 export 'src/l10n/l10n.dart';
 export 'src/render/style/plugin_styles.dart';
 export 'src/render/style/editor_style.dart';
+export 'src/plugins/markdown/delta_markdown_encoder.dart';

+ 88 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/plugins/markdown/delta_markdown_encoder.dart

@@ -0,0 +1,88 @@
+import 'dart:convert';
+
+import 'package:appflowy_editor/appflowy_editor.dart';
+
+/// A [Delta] encoder that encodes a [Delta] to Markdown.
+///
+/// Only support inline styles, like bold, italic, underline, strike, code.
+class DeltaMarkdownEncoder extends Converter<Delta, String> {
+  @override
+  String convert(Delta input) {
+    final buffer = StringBuffer();
+    final iterator = input.iterator;
+    while (iterator.moveNext()) {
+      final op = iterator.current;
+      if (op is TextInsert) {
+        final attributes = op.attributes;
+        if (attributes != null) {
+          buffer.write(_prefixSyntax(attributes));
+          buffer.write(op.text);
+          buffer.write(_suffixSyntax(attributes));
+        } else {
+          buffer.write(op.text);
+        }
+      }
+    }
+    return buffer.toString();
+  }
+
+  String _prefixSyntax(Attributes attributes) {
+    var syntax = '';
+
+    if (attributes[BuiltInAttributeKey.bold] == true &&
+        attributes[BuiltInAttributeKey.italic] == true) {
+      syntax += '***';
+    } else if (attributes[BuiltInAttributeKey.bold] == true) {
+      syntax += '**';
+    } else if (attributes[BuiltInAttributeKey.italic] == true) {
+      syntax += '_';
+    }
+
+    if (attributes[BuiltInAttributeKey.strikethrough] == true) {
+      syntax += '~~';
+    }
+    if (attributes[BuiltInAttributeKey.underline] == true) {
+      syntax += '<u>';
+    }
+    if (attributes[BuiltInAttributeKey.code] == true) {
+      syntax += '`';
+    }
+
+    if (attributes[BuiltInAttributeKey.href] != null) {
+      syntax += '[';
+    }
+
+    return syntax;
+  }
+
+  String _suffixSyntax(Attributes attributes) {
+    var syntax = '';
+
+    if (attributes[BuiltInAttributeKey.href] != null) {
+      syntax += '](${attributes[BuiltInAttributeKey.href]})';
+    }
+
+    if (attributes[BuiltInAttributeKey.code] == true) {
+      syntax += '`';
+    }
+
+    if (attributes[BuiltInAttributeKey.underline] == true) {
+      syntax += '</u>';
+    }
+
+    if (attributes[BuiltInAttributeKey.strikethrough] == true) {
+      syntax += '~~';
+    }
+
+    if (attributes[BuiltInAttributeKey.bold] == true &&
+        attributes[BuiltInAttributeKey.italic] == true) {
+      syntax += '***';
+    } else if (attributes[BuiltInAttributeKey.bold] == true) {
+      syntax += '**';
+    } else if (attributes[BuiltInAttributeKey.italic] == true) {
+      syntax += '_';
+    }
+
+    return syntax;
+  }
+}

+ 0 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/plugins/markdown/document_markdown_encoder.dart


+ 1 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/plugins/markdown/markdown_encoder.dart

@@ -0,0 +1 @@
+

+ 1 - 0
frontend/app_flowy/packages/appflowy_editor/pubspec.yaml

@@ -27,6 +27,7 @@ dependencies:
   intl:
   flutter_localizations:
     sdk: flutter
+  markdown: ^6.0.1
 
 dev_dependencies:
   flutter_test:

+ 100 - 0
frontend/app_flowy/packages/appflowy_editor/test/plugins/markdown/delta_markdown_encoder_test.dart

@@ -0,0 +1,100 @@
+import 'package:appflowy_editor/appflowy_editor.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() async {
+  group('delta_markdown_encoder.dart', () {
+    test('bold', () {
+      final delta = Delta(operations: [
+        TextInsert('Welcome to '),
+        TextInsert('AppFlowy', attributes: {
+          BuiltInAttributeKey.bold: true,
+        }),
+      ]);
+      final result = DeltaMarkdownEncoder().convert(delta);
+      expect(result, 'Welcome to **AppFlowy**');
+    });
+
+    test('italic', () {
+      final delta = Delta(operations: [
+        TextInsert('Welcome to '),
+        TextInsert('AppFlowy', attributes: {
+          BuiltInAttributeKey.italic: true,
+        }),
+      ]);
+      final result = DeltaMarkdownEncoder().convert(delta);
+      expect(result, 'Welcome to _AppFlowy_');
+    });
+
+    test('underline', () {
+      final delta = Delta(operations: [
+        TextInsert('Welcome to '),
+        TextInsert('AppFlowy', attributes: {
+          BuiltInAttributeKey.underline: true,
+        }),
+      ]);
+      final result = DeltaMarkdownEncoder().convert(delta);
+      expect(result, 'Welcome to <u>AppFlowy</u>');
+    });
+
+    test('strikethrough', () {
+      final delta = Delta(operations: [
+        TextInsert('Welcome to '),
+        TextInsert('AppFlowy', attributes: {
+          BuiltInAttributeKey.strikethrough: true,
+        }),
+      ]);
+      final result = DeltaMarkdownEncoder().convert(delta);
+      expect(result, 'Welcome to ~~AppFlowy~~');
+    });
+
+    test('href', () {
+      final delta = Delta(operations: [
+        TextInsert('Welcome to '),
+        TextInsert('AppFlowy', attributes: {
+          BuiltInAttributeKey.href: 'https://appflowy.io',
+        }),
+      ]);
+      final result = DeltaMarkdownEncoder().convert(delta);
+      expect(result, 'Welcome to [AppFlowy](https://appflowy.io)');
+    });
+
+    test('code', () {
+      final delta = Delta(operations: [
+        TextInsert('Welcome to '),
+        TextInsert('AppFlowy', attributes: {
+          BuiltInAttributeKey.code: true,
+        }),
+      ]);
+      final result = DeltaMarkdownEncoder().convert(delta);
+      expect(result, 'Welcome to `AppFlowy`');
+    });
+
+    test('composition', () {
+      final delta = Delta(operations: [
+        TextInsert('Welcome', attributes: {
+          BuiltInAttributeKey.code: true,
+          BuiltInAttributeKey.italic: true,
+          BuiltInAttributeKey.bold: true,
+          BuiltInAttributeKey.underline: true,
+        }),
+        TextInsert(' '),
+        TextInsert('to', attributes: {
+          BuiltInAttributeKey.italic: true,
+          BuiltInAttributeKey.bold: true,
+          BuiltInAttributeKey.strikethrough: true,
+        }),
+        TextInsert(' '),
+        TextInsert('AppFlowy', attributes: {
+          BuiltInAttributeKey.href: 'https://appflowy.io',
+          BuiltInAttributeKey.bold: true,
+          BuiltInAttributeKey.italic: true,
+        }),
+      ]);
+      final result = DeltaMarkdownEncoder().convert(delta);
+      expect(
+        result,
+        '***<u>`Welcome`</u>*** ***~~to~~*** ***[AppFlowy](https://appflowy.io)***',
+      );
+    });
+  });
+}