Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: nested elements getting ignored #178

Merged
merged 3 commits into from
Jun 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 46 additions & 25 deletions lib/src/plugins/html/html_document_decoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ class DocumentHTMLDecoder extends Converter<String, Document> {
final localName = element.localName;
switch (localName) {
case HTMLTags.h1:
return [_parseHeadingElement(element, level: 1)];
return _parseHeadingElement(element, level: 1);
case HTMLTags.h2:
return [_parseHeadingElement(element, level: 2)];
return _parseHeadingElement(element, level: 2);
case HTMLTags.h3:
return [_parseHeadingElement(element, level: 3)];
return _parseHeadingElement(element, level: 3);
case HTMLTags.unorderedList:
return _parseUnOrderListElement(element);
case HTMLTags.orderedList:
Expand All @@ -79,18 +79,21 @@ class DocumentHTMLDecoder extends Converter<String, Document> {
)
];
case HTMLTags.paragraph:
return [_parseParagraphElement(element)];
return _parseParagraphElement(element);
case HTMLTags.blockQuote:
return _parseBlockQuoteElement(element);
return [_parseBlockQuoteElement(element)];
case HTMLTags.image:
return [_parseImageElement(element)];
default:
return [paragraphNode(text: element.text)];
return _parseParagraphElement(element);
}
}

Attributes _parserFormattingElementAttributes(dom.Element element) {
Attributes _parserFormattingElementAttributes(
dom.Element element,
) {
final localName = element.localName;

Attributes attributes = {};
switch (localName) {
case HTMLTags.bold || HTMLTags.strong:
Expand Down Expand Up @@ -129,21 +132,26 @@ class DocumentHTMLDecoder extends Converter<String, Document> {
return attributes;
}

Node _parseHeadingElement(
Iterable<Node> _parseHeadingElement(
dom.Element element, {
required int level,
}) {
final delta = _parseDeltaElement(element);
return headingNode(
level: level,
delta: delta,
);
final (delta, specialNodes) = _parseDeltaElement(element);
return [
headingNode(
level: level,
delta: delta,
),
...specialNodes
];
}

Iterable<Node> _parseBlockQuoteElement(dom.Element element) {
return element.children
.map((child) => _parseListElement(child, type: QuoteBlockKeys.type))
.toList();
Node _parseBlockQuoteElement(dom.Element element) {
final (delta, nodes) = _parseDeltaElement(element);
return quoteNode(
delta: delta,
children: nodes,
);
}

Iterable<Node> _parseUnOrderListElement(dom.Element element) {
Expand All @@ -166,16 +174,17 @@ class DocumentHTMLDecoder extends Converter<String, Document> {
dom.Element element, {
required String type,
}) {
final delta = _parseDeltaElement(element);
final (delta, node) = _parseDeltaElement(element);
return Node(
type: type != ParagraphBlockKeys.type ? type : BulletedListBlockKeys.type,
children: node,
attributes: {ParagraphBlockKeys.delta: delta.toJson()},
);
}

Node _parseParagraphElement(dom.Element element) {
final delta = _parseDeltaElement(element);
return paragraphNode(delta: delta);
Iterable<Node> _parseParagraphElement(dom.Element element) {
final (delta, specialNodes) = _parseDeltaElement(element);
return [paragraphNode(delta: delta), ...specialNodes];
}

Node _parseImageElement(dom.Element element) {
Expand All @@ -185,18 +194,30 @@ class DocumentHTMLDecoder extends Converter<String, Document> {
);
}

Delta _parseDeltaElement(dom.Element element) {
(Delta, Iterable<Node>) _parseDeltaElement(dom.Element element) {
final delta = Delta();
final nodes = <Node>[];
final children = element.nodes.toList();
for (final child in children) {
if (child is dom.Element) {
final attributes = _parserFormattingElementAttributes(child);
delta.insert(child.text, attributes: attributes);
if (child.children.isNotEmpty) {
for (final seocondChild in child.children) {
nodes.addAll(
_parseSpecialElements(
seocondChild,
type: ParagraphBlockKeys.type,
),
);
}
} else {
final attributes = _parserFormattingElementAttributes(child);
delta.insert(child.text, attributes: attributes);
}
} else {
delta.insert(child.text ?? '');
}
}
return delta;
return (delta, nodes);
}

Attributes? _getDeltaAttributesFromHTMLAttributes(
Expand Down
30 changes: 24 additions & 6 deletions lib/src/plugins/html/html_document_encoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class DocumentHTMLEncoder extends Converter<Document, String> {
return _deltaToHtml(
Delta.fromJson(documentNode.attributes[ParagraphBlockKeys.delta]),
type: documentNode.type,
children: documentNode.children,
attributes: documentNode.attributes,
);
}
Expand Down Expand Up @@ -129,8 +130,10 @@ class DocumentHTMLEncoder extends Converter<Document, String> {
Delta delta, {
required String type,
required Attributes attributes,
required Iterable<Node> children,
}) {
final childNodes = <dom.Node>[];

String tagName = HTMLTags.paragraph;

if (type == BulletedListBlockKeys.type ||
Expand Down Expand Up @@ -176,17 +179,32 @@ class DocumentHTMLEncoder extends Converter<Document, String> {
}
}
}
if (children.isNotEmpty) {
for (var node in children) {
if (node.type != ImageBlockKeys.type) {
childNodes.add(
_deltaToHtml(
node.attributes[ParagraphBlockKeys.delta],
type: node.type,
attributes: node.attributes,
children: node.children,
),
);
} else {
final anchor = dom.Element.tag(HTMLTags.image);
anchor.attributes["src"] = node.attributes[ImageBlockKeys.url];

childNodes.add(_insertText(HTMLTag.span, childNodes: [anchor]));
}
}
}

if (tagName == HTMLTags.blockQuote) {
final blockQuote = dom.Element.tag(tagName);
blockQuote.append(_insertText(HTMLTag.paragraph, childNodes: childNodes));
return blockQuote;
return _insertText(HTMLTag.blockQuote, childNodes: childNodes);
} else if (tagName == HTMLTags.checkbox) {
return _insertText(HTMLTag.div, childNodes: childNodes);
} else if (!HTMLTags.isTopLevel(tagName)) {
final result = dom.Element.tag(HTMLTags.list);
result.append(_insertText(HTMLTag.paragraph, childNodes: childNodes));
return result;
return _insertText(HTMLTag.list, childNodes: childNodes);
} else {
return _insertText(tagName, childNodes: childNodes);
}
Expand Down
Loading