Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…_html into new-parser
  • Loading branch information
Sub6Resources committed Dec 12, 2019
2 parents 63f7bb0 + 1086f15 commit 2931bce
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 16 deletions.
34 changes: 30 additions & 4 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,24 @@ const htmlData = """
The quick brown fox jumped over the lazy dog.
</p>
<table>
<colgroup>
<col width="50%" />
<col width="25%" />
<col width="25%" />
</colgroup>
<thead>
<tr><th>One</th><th>Two</th><th>Three</th></tr>
<tr><td>Data</td><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td><td>Data</td></tr>
</thead>
<tbody>
<tr>
<td>Data</td><td>Data</td><td>Data</td>
</tr>
<tr>
<td>Data</td><td>Data</td><td>Data</td>
</tr>
</tbody>
<tfoot>
<tr><td>Data</td><td>Data</td><td>Data</td></tr>
<tr><td>fData</td><td>fData</td><td>fData</td></tr>
</tfoot>
</table>
<flutter></flutter>
Expand Down Expand Up @@ -113,6 +125,20 @@ class _MyHomePageState extends State<MyHomePage> {
"#whitespace": Style(
backgroundColor: Colors.purple,
),
"table": Style(
backgroundColor: Color.fromARGB(0x50, 0xee, 0xee, 0xee)
),
"tr": Style(
border: Border(bottom: BorderSide(color: Colors.grey))
),
"th": Style(
padding: EdgeInsets.all(6),
backgroundColor: Colors.grey
),
"td": Style(
padding: EdgeInsets.all(6),
backgroundColor: Colors.transparent
)
},
customRender: {
"flutter": (RenderContext context, Widget child, attributes) {
Expand Down
7 changes: 6 additions & 1 deletion lib/html_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class HtmlParser extends StatelessWidget {
StyledElement cascadedStyledTree = _cascadeStyles(customStyledTree);
StyledElement cleanedTree = cleanTree(cascadedStyledTree);
InlineSpan parsedTree = parseTree(
RenderContext(style: Style.fromTextStyle(Theme.of(context).textTheme.body1)),
RenderContext(parser: this, style: Style.fromTextStyle(Theme.of(context).textTheme.body1)),
cleanedTree,
);

Expand Down Expand Up @@ -99,6 +99,8 @@ class HtmlParser extends StatelessWidget {
return parseReplacedElement(node);
} else if (LAYOUT_ELEMENTS.contains(node.localName)) {
return parseLayoutElement(node, children);
} else if (TABLE_STYLE_ELEMENTS.contains(node.localName)) {
return parseTableDefinitionElement(node, children);
} else if (customRenderTags.contains(node.localName)) {
return parseStyledElement(node, children);
} else {
Expand Down Expand Up @@ -183,6 +185,7 @@ class HtmlParser extends StatelessWidget {
// Merge this element's style into the context so that children
// inherit the correct style
RenderContext newContext = RenderContext(
parser: this,
style: context.style.merge(tree.style),
);

Expand Down Expand Up @@ -515,9 +518,11 @@ class HtmlParser extends StatelessWidget {

///TODO document better
class RenderContext {
final HtmlParser parser;
final Style style;

RenderContext({
this.parser,
this.style,
});
}
Expand Down
7 changes: 7 additions & 0 deletions lib/src/html_elements.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ const STYLED_ELEMENTS = [
"strong",
"sub",
"sup",
"td",
"th",
"time",
"tt",
"u",
Expand Down Expand Up @@ -95,6 +97,11 @@ const LAYOUT_ELEMENTS = [
"thead",
];

const TABLE_STYLE_ELEMENTS = [
"col",
"colgroup"
];

/**
Here is a list of elements with planned support:
a - i [x]
Expand Down
130 changes: 119 additions & 11 deletions lib/src/layout_element.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_html/html_parser.dart';
import 'package:flutter_html/src/html_elements.dart';
import 'package:flutter_html/src/styled_element.dart';
import 'package:flutter_html/style.dart';
import 'package:html/dom.dart' as dom;
Expand All @@ -19,47 +20,154 @@ abstract class LayoutElement extends StyledElement {

class TableLayoutElement extends LayoutElement {
TableLayoutElement({
String name,
Style style,
@required List<StyledElement> children,
dom.Element node,
}) : super(name: name, style: style, children: children, node: node);

@override
Widget toWidget(RenderContext context) {

final colWidths = children.where((c) => c.name == "colgroup").map((group) {
return group.children.where((c) => c.name == "col").map((c) {
final widthStr = c.attributes["width"] ?? "";
if (widthStr.endsWith("%")) {
final width = double.tryParse(widthStr.substring(0, widthStr.length - 1)) * 0.01;
return FractionColumnWidth(width);
} else {
final width = double.tryParse(widthStr);
return FixedColumnWidth(width);
}
});
}).expand((i) => i).toList().asMap();

return Container(
decoration: BoxDecoration(
color: style.backgroundColor
),
child: Table(
columnWidths: colWidths,
children: children.map((c) {
if (c is TableSectionLayoutElement) {
return c.toTableRows(context);
}
return null;
})
.where((t) {
return t != null;
})
.toList()
.expand((i) => i)
.toList(),
));
}
}

class TableSectionLayoutElement extends LayoutElement {
TableSectionLayoutElement({
String name,
@required List<StyledElement> children,
}) : super(children: children);
}) : super(name: name, children: children);

@override
Widget toWidget(RenderContext context) {
return Table(
// children: children.where((e) => e.name == 'tr').map(),
);
return Container(child: Text("TABLE SECTION"));
}

List<TableRow> toTableRows(RenderContext context) {
return children.map((c) {
if (c is TableRowLayoutElement) {
return c.toTableRow(context);
}
return null;
}).where((t) {
return t != null;
}).toList();
}
}

class TableRowLayoutElement extends LayoutElement {
TableRowLayoutElement({
String name,
@required List<StyledElement> children,
}) : super(children: children);
dom.Element node,
}) : super(name: name, children: children, node: node);

@override
Widget toWidget(RenderContext context) {
return Container(child: Text("TABLE ROW"));
}

TableRow toTableRow(RenderContext context) {

return TableRow(
decoration: BoxDecoration(
border: style.border,
),
children: children.map((c) {
if (c is StyledElement && c.name == 'td' || c.name == 'th') {
return TableCell(
child: Container(
padding: c.style.padding,
decoration: BoxDecoration(
color: c.style.backgroundColor
),
child: RichText(text: context.parser.parseTree(context, c))));
}
return null;
}).where((c) => c != null).toList());
}
}

LayoutElement parseLayoutElement(dom.Element element, List<StyledElement> children) {
class TableStyleElement extends StyledElement {
TableStyleElement({
String name,
List<StyledElement> children,
Style style,
dom.Element node,
}) : super(name: name, children: children, style: style, node: node);
}

TableStyleElement parseTableDefinitionElement(
dom.Element element, List<StyledElement> children) {
switch (element.localName) {
case "colgroup":
case "col":
return TableStyleElement(
name: element.localName,
children: children,
node: element
);
default:
return TableStyleElement();
}
}
LayoutElement parseLayoutElement(
dom.Element element, List<StyledElement> children) {
switch (element.localName) {
case "table":
return TableLayoutElement(
name: element.localName,
children: children,
node: element,
);
break;
case "thead":
case "tbody":
case "tfoot":
return TableSectionLayoutElement(
name: element.localName,
children: children,
);
break;
case "tr":
return TableLayoutElement(
return TableRowLayoutElement(
name: element.localName,
children: children,
node: element
);
break;
default:
return TableLayoutElement(
children: children
);
return TableLayoutElement(children: children);
}
}

0 comments on commit 2931bce

Please sign in to comment.