Skip to content

Commit

Permalink
chore: refactor the html_node_parser.dart
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasXu0 committed Jul 19, 2023
1 parent 83488dc commit b8eedfc
Show file tree
Hide file tree
Showing 17 changed files with 221 additions and 219 deletions.
4 changes: 3 additions & 1 deletion lib/src/plugins/html/encoder/delta_html_encoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import 'dart:convert';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:html/dom.dart' as dom;

final deltaHTMLEncoder = DeltaHTMLEncoder();

/// A [Delta] encoder that encodes a [Delta] to html.
///
/// supported nested styles.
class DeltaHtmlEncoder extends Converter<Delta, List<dom.Node>> {
class DeltaHTMLEncoder extends Converter<Delta, List<dom.Node>> {
@override
List<dom.Node> convert(Delta input) {
return input
Expand Down
46 changes: 22 additions & 24 deletions lib/src/plugins/html/encoder/parser/bulleted_list_node_parser.dart
Original file line number Diff line number Diff line change
@@ -1,43 +1,41 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:html/dom.dart' as dom;

class HtmlBulletedListNodeParser extends HtmlNodeParser {
class HtmlBulletedListNodeParser extends HTMLNodeParser {
const HtmlBulletedListNodeParser();

@override
String get id => BulletedListBlockKeys.type;

@override
String transform(Node node, {required List<HtmlNodeParser> encodeParsers}) {
String transformNodeToHTMLString(
Node node, {
required List<HTMLNodeParser> encodeParsers,
}) {
assert(node.type == BulletedListBlockKeys.type);

return toHTMLString(htmlNodes(node, encodeParsers: encodeParsers));
return toHTMLString(
transformNodeToDomNodes(node, encodeParsers: encodeParsers),
);
}

@override
List<dom.Node> htmlNodes(
List<dom.Node> transformNodeToDomNodes(
Node node, {
required List<HtmlNodeParser> encodeParsers,
required List<HTMLNodeParser> encodeParsers,
}) {
final List<dom.Node> result = [];
final delta = node.delta;
if (delta == null) {
throw Exception('Delta is null');
}
final convertedNodes = DeltaHtmlEncoder().convert(delta);
const tagName = HTMLTags.list;
if (node.children.isNotEmpty) {
convertedNodes.addAll(
childrenNodes(node.children.toList(), encodeParsers: encodeParsers),
);
}
final element = insertText(tagName, childNodes: convertedNodes);

final stashListContainer = dom.Element.tag(
HTMLTags.unorderedList,
final delta = node.delta ?? Delta();
final domNodes = deltaHTMLEncoder.convert(delta);
domNodes.addAll(
childrenNodes(
node.children,
encodeParsers: encodeParsers,
),
);
stashListContainer.append(element);
result.add(stashListContainer);
return result;

final element = insertText(HTMLTags.list, childNodes: domNodes);
return [
dom.Element.tag(HTMLTags.unorderedList)..append(element),
];
}
}
38 changes: 17 additions & 21 deletions lib/src/plugins/html/encoder/parser/heading_node_parser.dart
Original file line number Diff line number Diff line change
@@ -1,38 +1,34 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:html/dom.dart' as dom;

class HtmlHeadingNodeParser extends HtmlNodeParser {
class HtmlHeadingNodeParser extends HTMLNodeParser {
const HtmlHeadingNodeParser();

@override
String get id => HeadingBlockKeys.type;

@override
String transform(Node node, {required List<HtmlNodeParser> encodeParsers}) {
return toHTMLString(htmlNodes(node, encodeParsers: encodeParsers));
String transformNodeToHTMLString(
Node node, {
required List<HTMLNodeParser> encodeParsers,
}) {
return toHTMLString(
transformNodeToDomNodes(node, encodeParsers: encodeParsers),
);
}

@override
List<dom.Node> htmlNodes(
List<dom.Node> transformNodeToDomNodes(
Node node, {
required List<HtmlNodeParser> encodeParsers,
required List<HTMLNodeParser> encodeParsers,
}) {
final delta = node.delta;
final attribute = node.attributes;
final List<dom.Node> result = [];
if (delta == null) {
assert(false, 'Delta is null');
}
final convertedNodes = DeltaHtmlEncoder().convert(delta!);
if (node.children.isNotEmpty) {
convertedNodes.addAll(
childrenNodes(node.children.toList(), encodeParsers: encodeParsers),
);
}
String tagName = "h${attribute[HeadingBlockKeys.level]}";

final delta = node.delta ?? Delta();
final convertedNodes = deltaHTMLEncoder.convert(delta);
convertedNodes.addAll(
childrenNodes(node.children, encodeParsers: encodeParsers),
);
final tagName = 'h${node.attributes[HeadingBlockKeys.level]}';
final element = insertText(tagName, childNodes: convertedNodes);
result.add(element);
return result;
return [element];
}
}
78 changes: 42 additions & 36 deletions lib/src/plugins/html/encoder/parser/html_node_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,56 @@ import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:collection/collection.dart';
import 'package:html/dom.dart' as dom;

abstract class HtmlNodeParser {
const HtmlNodeParser();
abstract class HTMLNodeParser {
const HTMLNodeParser();

/// The id of the node parser.
///
/// Basically, it's the type of the node.
String get id;
String transform(Node node, {required List<HtmlNodeParser> encodeParsers});
List<dom.Node> htmlNodes(

/// Transform the [node] to html string.
String transformNodeToHTMLString(
Node node, {
required List<HtmlNodeParser> encodeParsers,
required List<HTMLNodeParser> encodeParsers,
});

/// Convert the [node] to html nodes.
List<dom.Node> transformNodeToDomNodes(
Node node, {
required List<HTMLNodeParser> encodeParsers,
});
}

dom.Element insertText(
String tagName, {
required List<dom.Node> childNodes,
}) {
final p = dom.Element.tag(tagName);
for (final node in childNodes) {
p.append(node);
dom.Element insertText(
String tagName, {
required List<dom.Node> childNodes,
}) {
final p = dom.Element.tag(tagName);
for (final node in childNodes) {
p.append(node);
}
return p;
}
return p;
}

//iterate over its childrens if exist
List<dom.Node> childrenNodes(
List<Node> nodes, {
required List<HtmlNodeParser> encodeParsers,
}) {
final result = <dom.Node>[];
for (final node in nodes) {
HtmlNodeParser? parser = encodeParsers.firstWhereOrNull(
(element) => element.id == node.type,
);
if (parser != null) {
result.addAll(parser.htmlNodes(node, encodeParsers: encodeParsers));
//iterate over its children if exist
List<dom.Node> childrenNodes(
Iterable<Node> nodes, {
required List<HTMLNodeParser> encodeParsers,
}) {
final result = <dom.Node>[];
for (final node in nodes) {
final parser = encodeParsers.firstWhereOrNull(
(element) => element.id == node.type,
);
if (parser != null) {
result.addAll(
parser.transformNodeToDomNodes(node, encodeParsers: encodeParsers),
);
}
}
return result;
}
return result;
}

String toHTMLString(List<dom.Node> nodes) {
final elements = nodes;
final copyString = elements.fold<String>(
'',
(previousValue, element) => previousValue + stringify(element),
);
return copyString.replaceAll("\n", "");
String toHTMLString(List<dom.Node> nodes) =>
nodes.map((e) => stringify(e)).join().replaceAll('\n', '');
}
48 changes: 27 additions & 21 deletions lib/src/plugins/html/encoder/parser/image_node_parser.dart
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:html/dom.dart' as dom;

class HtmlImageNodeParser extends HtmlNodeParser {
class HtmlImageNodeParser extends HTMLNodeParser {
const HtmlImageNodeParser();

@override
String get id => ImageBlockKeys.type;

@override
String transform(Node node, {required List<HtmlNodeParser> encodeParsers}) {
return toHTMLString(htmlNodes(node, encodeParsers: encodeParsers));
String transformNodeToHTMLString(
Node node, {
required List<HTMLNodeParser> encodeParsers,
}) {
return toHTMLString(
transformNodeToDomNodes(node, encodeParsers: encodeParsers),
);
}

@override
List<dom.Node> htmlNodes(
List<dom.Node> transformNodeToDomNodes(
Node node, {
required List<HtmlNodeParser> encodeParsers,
required List<HTMLNodeParser> encodeParsers,
}) {
final List<dom.Node> result = [];

final anchor = dom.Element.tag(HTMLTags.image);
anchor.attributes["src"] = node.attributes[ImageBlockKeys.url];
if (node.attributes[ImageBlockKeys.height] != null) {
anchor.attributes["height"] = node.attributes[ImageBlockKeys.height];
}
if (node.attributes[ImageBlockKeys.width] != null) {
anchor.attributes["width"] = node.attributes[ImageBlockKeys.width];
anchor.attributes['src'] = node.attributes[ImageBlockKeys.url];

final height = node.attributes[ImageBlockKeys.height];
if (height != null) {
anchor.attributes['height'] = height;
}
if (node.attributes[ImageBlockKeys.align] != null) {
anchor.attributes["align"] = node.attributes[ImageBlockKeys.align];

final width = node.attributes[ImageBlockKeys.width];
if (width != null) {
anchor.attributes['width'] = width;
}
result.add(anchor);

if (node.children.isNotEmpty) {
result.addAll(
childrenNodes(node.children.toList(), encodeParsers: encodeParsers),
);
final align = node.attributes[ImageBlockKeys.align];
if (align != null) {
anchor.attributes['align'] = align;
}
return result;

return [
anchor,
...childrenNodes(node.children.toList(), encodeParsers: encodeParsers),
];
}
}
43 changes: 19 additions & 24 deletions lib/src/plugins/html/encoder/parser/numbered_list_node_parser.dart
Original file line number Diff line number Diff line change
@@ -1,43 +1,38 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:html/dom.dart' as dom;

class HtmlNumberedListNodeParser extends HtmlNodeParser {
class HtmlNumberedListNodeParser extends HTMLNodeParser {
const HtmlNumberedListNodeParser();

@override
String get id => NumberedListBlockKeys.type;

@override
String transform(Node node, {required List<HtmlNodeParser> encodeParsers}) {
String transformNodeToHTMLString(
Node node, {
required List<HTMLNodeParser> encodeParsers,
}) {
assert(node.type == NumberedListBlockKeys.type);

return toHTMLString(htmlNodes(node, encodeParsers: encodeParsers));
return toHTMLString(
transformNodeToDomNodes(node, encodeParsers: encodeParsers),
);
}

@override
List<dom.Node> htmlNodes(
List<dom.Node> transformNodeToDomNodes(
Node node, {
required List<HtmlNodeParser> encodeParsers,
required List<HTMLNodeParser> encodeParsers,
}) {
final List<dom.Node> result = [];
final delta = node.delta;
if (delta == null) {
throw Exception('Delta is null');
}
final convertedNodes = DeltaHtmlEncoder().convert(delta);
const tagName = HTMLTags.list;
if (node.children.isNotEmpty) {
convertedNodes.addAll(
childrenNodes(node.children.toList(), encodeParsers: encodeParsers),
);
}
final element = insertText(tagName, childNodes: convertedNodes);

final stashListContainer = dom.Element.tag(
HTMLTags.orderedList,
final delta = node.delta ?? Delta();
final domNodes = deltaHTMLEncoder.convert(delta);
domNodes.addAll(
childrenNodes(node.children, encodeParsers: encodeParsers),
);
stashListContainer.append(element);
result.add(stashListContainer);
return result;

final element = insertText(HTMLTags.list, childNodes: domNodes);
return [
dom.Element.tag(HTMLTags.orderedList)..append(element),
];
}
}
Loading

0 comments on commit b8eedfc

Please sign in to comment.