Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ class _MyHomePageState extends State<MyHomePage> {
<h1>Second header</h1>
<h1>Third header</h1>
<div>Fourth div</div>
<details>
<Summary open>Details summary</summary>
<p>Nested P1 of details</p>
<p>Nested P2 of details</p>
</details>
""",
//Optional parameters:
padding: EdgeInsets.all(8.0),
Expand Down
46 changes: 46 additions & 0 deletions lib/html_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:html/dom.dart' as dom;

typedef CustomRender = Widget Function(dom.Node node, List<Widget> children);
typedef OnLinkTap = void Function(String url);
typedef ParseNodeFunction = List<Widget> Function(List<dom.Node> nodeList);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than creating a custom callback to parse widgets, just pass in the list of children Widgets to the Widget.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left it after refactoring because it is also needed to build

node content, but we cannot know in advance if there is a "summary" tag, or have to determine the content of the tag outside the class, which seems to me not the best way to structure the code.


class HtmlParser {
HtmlParser({
Expand Down Expand Up @@ -39,6 +40,7 @@ class HtmlParser {
"data",
"dd",
"del",
"details",
"dfn",
"div",
"dl",
Expand Down Expand Up @@ -294,6 +296,8 @@ class HtmlParser {
decoration: TextDecoration.lineThrough,
),
);
case "details":
return DetailsWidget(node, _parseNodeList);
case "dfn":
return DefaultTextStyle.merge(
child: Wrap(
Expand Down Expand Up @@ -800,3 +804,45 @@ class HtmlParser {
return false;
}
}

class DetailsWidget extends StatefulWidget {
final ParseNodeFunction parseFunc;
final dom.Element node;
DetailsWidget(this.node, this.parseFunc);
_DetailsWidgetState createState() => _DetailsWidgetState();
}

class _DetailsWidgetState extends State<DetailsWidget> {
dom.Node _summaryNode;
bool _isOpen = false;

void initState() {
super.initState();
_summaryNode = widget.node.children
.firstWhere((el) => el.localName == "summary", orElse: () => null);
_isOpen = _summaryNode != null
? _summaryNode.attributes.containsKey("open")
: false;
}

@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () {
setState(() {
_isOpen = !_isOpen;
});
},
child: Text(_summaryNode != null ? _summaryNode.text : ""),
),
Wrap(
children:
_isOpen ? widget.parseFunc(widget.node.nodes) : [Container()],
)
],
);
}
}