Skip to content

Commit cf9c684

Browse files
committed
Reshuffle <details> tag rendering to layout_element.dart to accomodate interactable_element.dart fixes by @erickok
1 parent 3f89d81 commit cf9c684

File tree

4 files changed

+93
-120
lines changed

4 files changed

+93
-120
lines changed

lib/html_parser.dart

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -338,24 +338,36 @@ class HtmlParser extends StatelessWidget {
338338
} else if (tree is InteractableElement) {
339339
return TextSpan(
340340
children: tree.children
341-
.map((tree) => parseTree(newContext, tree))
342-
.map((childSpan) {
343-
if (childSpan is TextSpan) {
344-
return TextSpan(
345-
text: childSpan.text,
346-
children: childSpan.children,
347-
style: (childSpan.style ?? TextStyle())
348-
.merge(newContext.style.generateTextStyle()),
349-
semanticsLabel: childSpan.semanticsLabel,
350-
recognizer: TapGestureRecognizer()
351-
..onTap = () => onLinkTap?.call(tree.href),
352-
);
353-
} else {
354-
return WidgetSpan(
355-
child: tree.toWidget(context, childSpan: childSpan),
356-
);
357-
}
358-
}).toList() ??
341+
.map((tree) => parseTree(newContext, tree))
342+
.map((childSpan) {
343+
if (childSpan is TextSpan) {
344+
return TextSpan(
345+
text: childSpan.text,
346+
children: childSpan.children,
347+
style: (childSpan.style ?? TextStyle())
348+
.merge(newContext.style.generateTextStyle()),
349+
semanticsLabel: childSpan.semanticsLabel,
350+
recognizer: TapGestureRecognizer()
351+
..onTap = () => onLinkTap?.call(tree.href),
352+
);
353+
} else {
354+
return WidgetSpan(
355+
child: RawGestureDetector(
356+
gestures: {
357+
MultipleTapGestureRecognizer:
358+
GestureRecognizerFactoryWithHandlers<
359+
MultipleTapGestureRecognizer>(
360+
() => MultipleTapGestureRecognizer(),
361+
(instance) {
362+
instance..onTap = () => onLinkTap?.call(tree.href);
363+
},
364+
),
365+
},
366+
child: (childSpan as WidgetSpan).child,
367+
),
368+
);
369+
}
370+
}).toList() ??
359371
[],
360372
);
361373
} else if (tree is LayoutElement) {

lib/src/html_elements.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ const STYLED_ELEMENTS = [
7272

7373
const INTERACTABLE_ELEMENTS = [
7474
"a",
75-
"details",
7675
];
7776

7877
const REPLACED_ELEMENTS = [
@@ -90,6 +89,7 @@ const REPLACED_ELEMENTS = [
9089
];
9190

9291
const LAYOUT_ELEMENTS = [
92+
"details",
9393
"table",
9494
"tr",
9595
"tbody",

lib/src/interactable_element.dart

Lines changed: 14 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import 'package:flutter/material.dart';
2-
import 'package:flutter_html/html_parser.dart';
32
import 'package:flutter_html/src/html_elements.dart';
4-
import 'package:flutter_html/src/utils.dart';
53
import 'package:flutter_html/style.dart';
64
import 'package:html/dom.dart' as dom;
75

86
/// An [InteractableElement] is a [StyledElement] that takes user gestures (e.g. tap).
9-
abstract class InteractableElement extends StyledElement {
7+
class InteractableElement extends StyledElement {
108
String href;
119

1210
InteractableElement({
@@ -16,114 +14,30 @@ abstract class InteractableElement extends StyledElement {
1614
this.href,
1715
dom.Node node,
1816
}) : super(name: name, children: children, style: style, node: node);
19-
20-
Widget toWidget(RenderContext context, {InlineSpan childSpan});
2117
}
2218

2319
/// A [Gesture] indicates the type of interaction by a user.
2420
enum Gesture {
2521
TAP,
2622
}
2723

28-
class LinkedContentElement extends InteractableElement {
29-
String href;
30-
Style style;
31-
32-
LinkedContentElement({
33-
dom.Node node,
34-
String name,
35-
List<StyledElement> children,
36-
this.href,
37-
this.style,
38-
}) : super(name: name, node: node, children: children);
39-
40-
@override
41-
Widget toWidget(RenderContext context, {InlineSpan childSpan}) {
42-
return RawGestureDetector(
43-
gestures: {
44-
MultipleTapGestureRecognizer: GestureRecognizerFactoryWithHandlers<
45-
MultipleTapGestureRecognizer>(
46-
() => MultipleTapGestureRecognizer(),
47-
(instance) {
48-
instance..onTap = () => context.parser.onLinkTap?.call(href);
49-
},
50-
),
51-
},
52-
child: (childSpan as WidgetSpan).child,
53-
);
54-
}
55-
}
56-
57-
class DetailsContentElement extends InteractableElement {
58-
List<dom.Element> title;
59-
60-
DetailsContentElement({
61-
dom.Node node,
62-
String name,
63-
List<StyledElement> children,
64-
this.title,
65-
}) : super(name: name, node: node, children: children);
66-
67-
@override
68-
Widget toWidget(RenderContext context, {InlineSpan childSpan}) {
69-
return ExpansionTile(
70-
title: title.first.localName == "summary" ? StyledText(
71-
textSpan: TextSpan(
72-
style: style.generateTextStyle(),
73-
children: [children
74-
.map((tree) => context.parser.parseTree(context, tree))
75-
.toList().first] ??
76-
[],
77-
),
78-
style: style,
79-
) : Text("Details"),
80-
children: [
81-
StyledText(
82-
textSpan: TextSpan(
83-
style: style.generateTextStyle(),
84-
children: children
85-
.map((tree) => context.parser.parseTree(context, tree))
86-
.toList() ??
87-
[],
88-
),
89-
style: style,
90-
),
91-
]
92-
);
93-
}
94-
95-
}
96-
97-
class EmptyInteractableElement extends InteractableElement {
98-
EmptyInteractableElement({String name = "empty"}) : super(name: name);
99-
100-
@override
101-
Widget toWidget(_, {InlineSpan childSpan}) => null;
102-
}
103-
10424
InteractableElement parseInteractableElement(
10525
dom.Element element, List<StyledElement> children) {
26+
InteractableElement interactableElement = InteractableElement(
27+
name: element.localName,
28+
children: children,
29+
node: element,
30+
);
10631

10732
switch (element.localName) {
10833
case "a":
109-
return LinkedContentElement(
110-
node: element,
111-
name: element.localName,
112-
children: children,
113-
href: element.attributes['href'],
114-
style: Style(
115-
color: Colors.blue,
116-
textDecoration: TextDecoration.underline,
117-
)
34+
interactableElement.href = element.attributes['href'];
35+
interactableElement.style = Style(
36+
color: Colors.blue,
37+
textDecoration: TextDecoration.underline,
11838
);
119-
case "details":
120-
return DetailsContentElement(
121-
node: element,
122-
name: element.localName,
123-
children: element.children.first.localName == "summary" ? children : children,
124-
title: element.children
125-
);
126-
default:
127-
return EmptyInteractableElement(name: element.localName);
39+
break;
12840
}
129-
}
41+
42+
return interactableElement;
43+
}

lib/src/layout_element.dart

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,57 @@ TableStyleElement parseTableDefinitionElement(dom.Element element,
244244
}
245245
}
246246

247-
LayoutElement parseLayoutElement(dom.Element element,
247+
class DetailsContentElement extends LayoutElement {
248+
List<dom.Element> title;
249+
250+
DetailsContentElement({
251+
String name,
252+
List<StyledElement> children,
253+
dom.Element node,
254+
this.title,
255+
}) : super(name: name, node: node, children: children);
256+
257+
@override
258+
Widget toWidget(RenderContext context) {
259+
return ExpansionTile(
260+
title: title.first.localName == "summary" && children != null ? StyledText(
261+
textSpan: TextSpan(
262+
style: style.generateTextStyle(),
263+
children: [children
264+
.map((tree) => context.parser.parseTree(context, tree))
265+
.toList().first] ??
266+
[],
267+
),
268+
style: style,
269+
) : Text("Details"),
270+
children: [
271+
StyledText(
272+
textSpan: TextSpan(
273+
style: style.generateTextStyle(),
274+
children: children
275+
.map((tree) => context.parser.parseTree(context, tree))
276+
.toList() ??
277+
[],
278+
),
279+
style: style,
280+
),
281+
]
282+
);
283+
}
284+
}
285+
286+
LayoutElement parseLayoutElement(
287+
dom.Element element,
248288
List<StyledElement> children,
249289
) {
250290
switch (element.localName) {
291+
case "details":
292+
return DetailsContentElement(
293+
node: element,
294+
name: element.localName,
295+
children: element.children.first.localName == "summary" ? children : children,
296+
title: element.children
297+
);
251298
case "table":
252299
return TableLayoutElement(
253300
name: element.localName,

0 commit comments

Comments
 (0)