Skip to content

Commit cce767f

Browse files
committed
Change BlockElement to StyledElement with Display.BLOCK and add support for all css selectors
1 parent f392917 commit cce767f

File tree

4 files changed

+41
-35
lines changed

4 files changed

+41
-35
lines changed

lib/block_element.dart

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import 'package:flutter_html/html_elements.dart';
44
import 'package:flutter_html/style.dart';
55
import 'package:html/dom.dart' as dom;
66

7-
/// A [Block] contains information about a [BlockElement] (width, height, padding, margins)
7+
/// A [Block] contains information about a [Display.BLOCK] element (width, height, padding, margins)
88
class Block {
99
EdgeInsets margin;
1010
double width;
@@ -59,22 +59,11 @@ class Block {
5959
}
6060
}
6161

62-
/// A [BlockElement] is a [StyledElement] that wraps before and after the its [children].
63-
///
64-
/// A [BlockElement] may have a margin/padding or be a set width/height.
65-
class BlockElement extends StyledElement {
66-
BlockElement({
67-
String name,
68-
List<StyledElement> children,
69-
Style style,
70-
}) : super(name: name, children: children, style: style);
71-
72-
}
73-
74-
BlockElement parseBlockElement(dom.Element node, List<StyledElement> children) {
75-
BlockElement blockElement = BlockElement(
62+
StyledElement parseBlockElement(dom.Element node, List<StyledElement> children) {
63+
StyledElement blockElement = StyledElement(
7664
name: node.localName,
7765
children: children,
66+
node: node,
7867
);
7968

8069
// Add styles to new block element.
@@ -113,6 +102,7 @@ BlockElement parseBlockElement(dom.Element node, List<StyledElement> children) {
113102
}
114103

115104
blockElement.style.block = parseBlockElementBlock(node);
105+
blockElement.style.display = Display.BLOCK;
116106

117107
return blockElement;
118108
}

lib/content_element.dart

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ abstract class ContentElement extends StyledElement {
1414
ContentElement({
1515
String name,
1616
Style style,
17-
}) : super(name: name, children: null, style: style);
17+
dom.Element node,
18+
}) : super(name: name, children: null, style: style, node: node);
1819

1920
static List<String> parseContentSources(List<dom.Element> elements) {
2021
return elements
@@ -55,12 +56,13 @@ class ImageContentElement extends ContentElement {
5556
Style style,
5657
this.src,
5758
this.alt,
58-
}) : super(name: name, style: style);
59+
dom.Element node,
60+
}) : super(name: name, style: style, node: node);
5961

6062
@override
6163
Widget toWidget() {
62-
if(src == null) return Text(alt ?? "");
63-
if(src.startsWith("data:image") && src.contains("base64,")) {
64+
if (src == null) return Text(alt ?? "");
65+
if (src.startsWith("data:image") && src.contains("base64,")) {
6466
return Image.memory(base64.decode(src.split("base64,")[1].trim()));
6567
} else {
6668
return Image.network(src);
@@ -86,7 +88,8 @@ class AudioContentElement extends ContentElement {
8688
this.autoplay,
8789
this.loop,
8890
this.muted,
89-
}) : super(name: name, style: style);
91+
dom.Element node,
92+
}) : super(name: name, style: style, node: node);
9093

9194
@override
9295
Widget toWidget() {
@@ -113,7 +116,8 @@ class VideoContentElement extends ContentElement {
113116
this.autoplay,
114117
this.loop,
115118
this.muted,
116-
}) : super(name: name, style: style);
119+
dom.Element node,
120+
}) : super(name: name, style: style, node: node);
117121

118122
@override
119123
Widget toWidget() {
@@ -139,6 +143,7 @@ ContentElement parseContentElement(dom.Element element) {
139143
loop: element.attributes['loop'] != null,
140144
autoplay: element.attributes['autoplay'] != null,
141145
muted: element.attributes['muted'] != null,
146+
node: element,
142147
);
143148
case "br":
144149
return TextContentElement(
@@ -150,6 +155,7 @@ ContentElement parseContentElement(dom.Element element) {
150155
name: "img",
151156
src: element.attributes['src'],
152157
alt: element.attributes['alt'],
158+
node: element,
153159
);
154160
case "video":
155161
return VideoContentElement(
@@ -160,6 +166,7 @@ ContentElement parseContentElement(dom.Element element) {
160166
loop: element.attributes['loop'] != null,
161167
autoplay: element.attributes['autoplay'] != null,
162168
muted: element.attributes['muted'] != null,
169+
node: element,
163170
);
164171
default:
165172
return EmptyContentElement(name: element.localName);

lib/html_parser.dart

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class HtmlParser extends StatelessWidget {
5353
StyledElement tree = StyledElement(
5454
name: "[Tree Root]",
5555
children: new List<StyledElement>(),
56+
node: html.documentElement,
5657
);
5758

5859
html.nodes.forEach((node) {
@@ -104,13 +105,15 @@ class HtmlParser extends StatelessWidget {
104105
/// widget onto the [StyledElement] tree.
105106
StyledElement _applyCustomStyles(StyledElement tree) {
106107
if (style == null) return tree;
107-
if (style.containsKey(tree.name)) {
108-
if (tree.style == null) {
109-
tree.style = style[tree.name];
110-
} else {
111-
tree.style = tree.style.merge(style[tree.name]);
108+
style.forEach((key, style) {
109+
if(tree.matchesSelector(key)) {
110+
if (tree.style == null) {
111+
tree.style = style;
112+
} else {
113+
tree.style = tree.style.merge(style);
114+
}
112115
}
113-
}
116+
});
114117
tree.children?.forEach(_applyCustomStyles);
115118

116119
return tree;
@@ -137,23 +140,23 @@ class HtmlParser extends StatelessWidget {
137140
);
138141

139142
//Return the correct InlineSpan based on the element type.
140-
if (tree is BlockElement) {
143+
if (tree.style?.display == Display.BLOCK) {
141144
return WidgetSpan(
142145
child: Container(
143146
decoration: BoxDecoration(
144147
border: tree.style?.block?.border,
145148
color: tree.style?.block?.backgroundColor,
146149
),
147-
height: tree.style.block.height,
148-
width: tree.style.block.width ?? double.infinity,
149-
margin: tree.style.block.margin,
150+
height: tree.style.block?.height,
151+
width: tree.style.block?.width ?? double.infinity,
152+
margin: tree.style.block?.margin,
150153
alignment: tree.style?.block?.alignment,
151154
child: RichText(
152155
text: TextSpan(
153156
style: context.style.merge(tree.style?.textStyle),
154157
children: tree.children
155-
.map((tree) => parseTree(newContext, tree))
156-
.toList(),
158+
?.map((tree) => parseTree(newContext, tree))
159+
?.toList() ?? [],
157160
),
158161
),
159162
),
@@ -218,7 +221,7 @@ class HtmlParser extends StatelessWidget {
218221

219222
/// [processListCharacters] adds list characters to the front of all list items.
220223
static StyledElement _processListCharacters(StyledElement tree) {
221-
if (tree is BlockElement && (tree.name == "ol" || tree.name == "ul")) {
224+
if (tree.style?.display == Display.BLOCK && (tree.name == "ol" || tree.name == "ul")) {
222225
for (int i = 0; i < tree.children?.length; i++) {
223226
if (tree.children[i].name == "li") {
224227
tree.children[i].children?.insert(

lib/styled_element.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_html/style.dart';
33
import 'package:html/dom.dart' as dom;
4+
import 'package:html/src/query_selector.dart';
45

56
/// A [StyledElement] applies a style to all of its children.
67
class StyledElement {
@@ -9,14 +10,18 @@ class StyledElement {
910
final List<String> elementClasses;
1011
List<StyledElement> children;
1112
Style style;
13+
final dom.Node _node;
1214

1315
StyledElement({
1416
this.name = "[[No name]]",
1517
this.elementId,
1618
this.elementClasses,
1719
this.children,
1820
this.style,
19-
});
21+
dom.Element node,
22+
}): this._node = node;
23+
24+
bool matchesSelector(String selector) => _node != null && matches(_node, selector);
2025

2126
@override
2227
String toString() {
@@ -37,6 +42,7 @@ StyledElement parseStyledElement(
3742
elementId: element.id,
3843
elementClasses: element.classes.toList(),
3944
children: children,
45+
node: element,
4046
);
4147

4248
switch (element.localName) {

0 commit comments

Comments
 (0)