feat: add toggle list and callout node parser (#3700)

This commit is contained in:
Lucas.Xu 2023-10-16 10:09:33 +08:00 committed by GitHub
parent aa70885b21
commit 7406c5e6a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 180 additions and 19 deletions

View File

@ -4,6 +4,7 @@ import 'package:appflowy/plugins/document/presentation/share/share_button.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:path/path.dart' as p;
import 'util/mock/mock_file_picker.dart';
import 'util/util.dart';
@ -78,7 +79,7 @@ void main() {
});
}
const expectedMarkdown = r'''
const expectedMarkdown = '''
# Welcome to AppFlowy!
## Here are the basics
- [ ] Click anywhere and just start typing.
@ -105,6 +106,15 @@ fn main() {
## Have a question
> Click `?` at the bottom right for help and support.
> 🥰
>
> Like AppFlowy? Follow us:
> [GitHub](https://github.com/AppFlowy-IO/AppFlowy)
> [Twitter](https://twitter.com/appflowy): @appflowy
> [Newsletter](https://blog-appflowy.ghost.io/)
>
''';

View File

@ -0,0 +1,27 @@
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
class CalloutNodeParser extends NodeParser {
const CalloutNodeParser();
@override
String get id => CalloutBlockKeys.type;
@override
String transform(Node node, DocumentMarkdownEncoder? encoder) {
assert(node.children.isEmpty);
final icon = node.attributes[CalloutBlockKeys.icon];
final delta = node.delta ?? Delta()
..insert('');
final String markdown = DeltaMarkdownEncoder()
.convert(delta)
.split('\n')
.map((e) => '> $e')
.join('\n');
return '''
> $icon
$markdown
''';
}
}

View File

@ -7,7 +7,7 @@ class CodeBlockNodeParser extends NodeParser {
String get id => 'code_block';
@override
String transform(Node node) {
String transform(Node node, DocumentMarkdownEncoder? encoder) {
return '```\n${node.attributes['code_block']}\n```';
}
}

View File

@ -7,7 +7,7 @@ class DividerNodeParser extends NodeParser {
String get id => 'divider';
@override
String transform(Node node) {
String transform(Node node, DocumentMarkdownEncoder? encoder) {
return '---\n';
}
}

View File

@ -0,0 +1,5 @@
export 'callout_node_parser.dart';
export 'code_block_node_parser.dart';
export 'divider_node_parser.dart';
export 'math_equation_node_parser.dart';
export 'toggle_list_node_parser.dart';

View File

@ -0,0 +1,5 @@
export 'callout_node_parser.dart';
export 'code_block_node_parser.dart';
export 'divider_node_parser.dart';
export 'math_equation_node_parser.dart';
export 'toggle_list_node_parser.dart';

View File

@ -8,7 +8,7 @@ class MathEquationNodeParser extends NodeParser {
String get id => MathEquationBlockKeys.type;
@override
String transform(Node node) {
String transform(Node node, DocumentMarkdownEncoder? encoder) {
return '\$\$${node.attributes[id]}\$\$';
}
}

View File

@ -0,0 +1,44 @@
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
enum ToggleListExportStyle {
github,
markdown,
}
class ToggleListNodeParser extends NodeParser {
const ToggleListNodeParser({
this.exportStyle = ToggleListExportStyle.markdown,
});
final ToggleListExportStyle exportStyle;
@override
String get id => ToggleListBlockKeys.type;
@override
String transform(Node node, DocumentMarkdownEncoder? encoder) {
final delta = node.delta ?? Delta()
..insert('');
String markdown = DeltaMarkdownEncoder().convert(delta);
final details = encoder?.convertNodes(
node.children,
withIndent: true,
);
switch (exportStyle) {
case ToggleListExportStyle.github:
return '''<details>
<summary>$markdown</summary>
$details
</details>
''';
case ToggleListExportStyle.markdown:
markdown = '- $markdown\n';
if (details != null && details.isNotEmpty) {
markdown += details;
}
return markdown;
}
}
}

View File

@ -28,6 +28,7 @@ export 'openai/widgets/auto_completion_node_widget.dart';
export 'openai/widgets/smart_edit_node_widget.dart';
export 'openai/widgets/smart_edit_toolbar_item.dart';
export 'outline/outline_block_component.dart';
export 'parsers/markdown_parsers.dart';
export 'table/table_menu.dart';
export 'table/table_option_action.dart';
export 'toggle/toggle_block_component.dart';

View File

@ -3,15 +3,21 @@ import 'dart:convert';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/application/document_data_pb_extension.dart';
import 'package:appflowy/plugins/document/application/prelude.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/code_block_node_parser.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/divider_node_parser.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/math_equation_node_parser.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/markdown_parsers.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:dartz/dartz.dart';
import 'package:easy_localization/easy_localization.dart';
const List<NodeParser> _customParsers = [
DividerNodeParser(),
MathEquationNodeParser(),
CodeBlockNodeParser(),
CalloutNodeParser(),
ToggleListNodeParser(),
];
enum DocumentExportType {
json,
markdown,
@ -43,11 +49,7 @@ class DocumentExporter {
case DocumentExportType.markdown:
final markdown = documentToMarkdown(
document,
customParsers: [
const DividerNodeParser(),
const MathEquationNodeParser(),
const CodeBlockNodeParser(),
],
customParsers: _customParsers,
);
return right(markdown);
case DocumentExportType.text:

View File

@ -54,8 +54,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: d1027c4
resolved-ref: d1027c4d83a8cf78227e7d742c050ca945cef23a
ref: "9ae85ea"
resolved-ref: "9ae85ea162606b79483c49550266c154c0cb500c"
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
source: git
version: "1.4.4"

View File

@ -47,7 +47,7 @@ dependencies:
appflowy_editor:
git:
url: https://github.com/AppFlowy-IO/appflowy-editor.git
ref: "d1027c4"
ref: "9ae85ea"
appflowy_popover:
path: packages/appflowy_popover

View File

@ -1,8 +1,6 @@
import 'dart:convert';
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/code_block_node_parser.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/divider_node_parser.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/math_equation_node_parser.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/document_markdown_parsers.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter_test/flutter_test.dart';
@ -35,7 +33,7 @@ void main() {
);
expect(result, r'$$E = MC^2$$');
});
// Changes
test('code block', () {
const text = '''
{
@ -63,6 +61,7 @@ void main() {
);
expect(result, '```\nSome Code\n```');
});
test('divider', () {
const text = '''
{
@ -87,5 +86,73 @@ void main() {
);
expect(result, '---\n');
});
test('callout', () {
const text = '''
{
"document":{
"type":"page",
"children":[
{
"type":"callout",
"data":{
"icon": "😁",
"delta": [
{
"insert": "Callout"
}
]
}
}
]
}
}
''';
final document = Document.fromJson(
Map<String, Object>.from(json.decode(text)),
);
final result = documentToMarkdown(
document,
customParsers: [
const CalloutNodeParser(),
],
);
expect(result, '''> 😁
> Callout
''');
});
test('toggle list', () {
const text = '''
{
"document":{
"type":"page",
"children":[
{
"type":"toggle_list",
"data":{
"delta": [
{
"insert": "Toggle list"
}
]
}
}
]
}
}
''';
final document = Document.fromJson(
Map<String, Object>.from(json.decode(text)),
);
final result = documentToMarkdown(
document,
customParsers: [
const ToggleListNodeParser(),
],
);
expect(result, '- Toggle list\n');
});
});
}