mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-10-31 10:03:18 +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) ...lightEditorStyleExtension, | ||||||
|             if (!darkMode) ...lightPlguinStyleExtension, |             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( |           return Container( | ||||||
|             color: darkMode ? Colors.black : Colors.white, |             color: darkMode ? Colors.black : Colors.white, | ||||||
|             width: MediaQuery.of(context).size.width, |             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/l10n/l10n.dart'; | ||||||
| export 'src/render/style/plugin_styles.dart'; | export 'src/render/style/plugin_styles.dart'; | ||||||
| export 'src/render/style/editor_style.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: |   intl: | ||||||
|   flutter_localizations: |   flutter_localizations: | ||||||
|     sdk: flutter |     sdk: flutter | ||||||
|  |   markdown: ^6.0.1 | ||||||
| 
 | 
 | ||||||
| dev_dependencies: | dev_dependencies: | ||||||
|   flutter_test: |   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