mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: document to markdown
This commit is contained in:
parent
c85ab276e9
commit
9eaa79b558
@ -33,4 +33,8 @@ 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';
|
||||
export 'src/plugins/markdown/encoder/delta_markdown_encoder.dart';
|
||||
export 'src/plugins/markdown/encoder/document_markdown_encoder.dart';
|
||||
export 'src/plugins/markdown/encoder/parser/node_parser.dart';
|
||||
export 'src/plugins/markdown/encoder/parser/text_node_parser.dart';
|
||||
export 'src/plugins/markdown/encoder/parser/image_node_parser.dart';
|
||||
|
@ -0,0 +1,39 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:appflowy_editor/src/core/document/document.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(),
|
||||
],
|
||||
});
|
||||
|
||||
final List<NodeParser> parsers;
|
||||
|
||||
@override
|
||||
String convert(Document input) {
|
||||
final buffer = StringBuffer();
|
||||
for (final node in input.root.children) {
|
||||
NodeParser? parser =
|
||||
parsers.firstWhereOrNull((element) => element.id == node.type);
|
||||
if (parser != null) {
|
||||
buffer.write(parser.transform(node));
|
||||
}
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
extension IterableExtension<T> on Iterable<T> {
|
||||
T? firstWhereOrNull(bool Function(T element) test) {
|
||||
for (var element in this) {
|
||||
if (test(element)) return element;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import 'package:appflowy_editor/src/core/document/node.dart';
|
||||
import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/node_parser.dart';
|
||||
|
||||
class ImageNodeParser extends NodeParser {
|
||||
const ImageNodeParser();
|
||||
|
||||
@override
|
||||
String get id => 'image';
|
||||
|
||||
@override
|
||||
String transform(Node node) {
|
||||
return '![](${node.attributes['image_src']})';
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import 'package:appflowy_editor/src/core/document/node.dart';
|
||||
|
||||
abstract class NodeParser {
|
||||
const NodeParser();
|
||||
|
||||
String get id;
|
||||
String transform(Node node);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
import 'package:appflowy_editor/src/core/document/node.dart';
|
||||
import 'package:appflowy_editor/src/core/legacy/built_in_attribute_keys.dart';
|
||||
import 'package:appflowy_editor/src/plugins/markdown/encoder/delta_markdown_encoder.dart';
|
||||
import 'package:appflowy_editor/src/plugins/markdown/encoder/parser/node_parser.dart';
|
||||
|
||||
class TextNodeParser extends NodeParser {
|
||||
const TextNodeParser();
|
||||
|
||||
@override
|
||||
String get id => 'text';
|
||||
|
||||
@override
|
||||
String transform(Node node) {
|
||||
assert(node is TextNode);
|
||||
final textNode = node as TextNode;
|
||||
final markdown = DeltaMarkdownEncoder().convert(textNode.delta);
|
||||
final attributes = textNode.attributes;
|
||||
var result = markdown;
|
||||
var suffix = '\n';
|
||||
if (attributes.isNotEmpty &&
|
||||
attributes.containsKey(BuiltInAttributeKey.subtype)) {
|
||||
final subtype = attributes[BuiltInAttributeKey.subtype];
|
||||
if (subtype == 'heading') {
|
||||
final heading = attributes[BuiltInAttributeKey.heading];
|
||||
if (heading == 'h1') {
|
||||
result = '# $markdown';
|
||||
} else if (heading == 'h2') {
|
||||
result = '## $markdown';
|
||||
} else if (heading == 'h3') {
|
||||
result = '### $markdown';
|
||||
} else if (heading == 'h4') {
|
||||
result = '#### $markdown';
|
||||
} else if (heading == 'h5') {
|
||||
result = '##### $markdown';
|
||||
} else if (heading == 'h6') {
|
||||
result = '###### $markdown';
|
||||
}
|
||||
} else if (subtype == 'quote') {
|
||||
result = '> $markdown';
|
||||
} else if (subtype == 'code-block') {
|
||||
result = '```\n$markdown\n```';
|
||||
} else if (subtype == 'bulleted-list') {
|
||||
result = '* $markdown';
|
||||
} else if (subtype == 'number-list') {
|
||||
final number = attributes['number'];
|
||||
result = '$number. $markdown';
|
||||
} else if (subtype == 'checkbox') {
|
||||
if (attributes[BuiltInAttributeKey.checkbox] == true) {
|
||||
result = '- [x] $markdown';
|
||||
} else {
|
||||
result = '- [ ] $markdown';
|
||||
}
|
||||
}
|
||||
}
|
||||
return '$result$suffix';
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user