11import 'package:flutter/material.dart' ;
2- import 'package:flutter_html/html_parser.dart' ;
32import 'package:flutter_html/src/html_elements.dart' ;
4- import 'package:flutter_html/src/utils.dart' ;
53import 'package:flutter_html/style.dart' ;
64import '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.
2420enum 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-
10424InteractableElement 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+ }
0 commit comments