mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-10-31 01:54:37 +00:00 
			
		
		
		
	feat: delta to markdown
This commit is contained in:
		
							parent
							
								
									ab664ebb2f
								
							
						
					
					
						commit
						c85ab276e9
					
				| @ -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, | ||||
|  | ||||
| @ -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'; | ||||
|  | ||||
| @ -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 +1 @@ | ||||
| 
 | ||||
| @ -27,6 +27,7 @@ dependencies: | ||||
|   intl: | ||||
|   flutter_localizations: | ||||
|     sdk: flutter | ||||
|   markdown: ^6.0.1 | ||||
| 
 | ||||
| dev_dependencies: | ||||
|   flutter_test: | ||||
|  | ||||
| @ -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)***', | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Lucas.Xu
						Lucas.Xu