Skip to content

Commit d3bc7bb

Browse files
Merge pull request Sub6Resources#60 from jeffmikels/jeffmikels
Added support for tables using RichText.
2 parents c818dd2 + 27fc0b0 commit d3bc7bb

File tree

1 file changed

+66
-23
lines changed

1 file changed

+66
-23
lines changed

lib/html_parser.dart

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ class HtmlRichTextParser extends StatelessWidget {
179179
"br",
180180
"table",
181181
"tbody",
182+
"caption",
182183
"td",
183184
"tfoot",
184185
"th",
@@ -300,30 +301,35 @@ class HtmlRichTextParser extends StatelessWidget {
300301
// a text only node is a child of a tag with no inner html
301302
if (node is dom.Text) {
302303
// WHITESPACE CONSIDERATIONS ---
303-
// truly empty nodes, should just be ignored
304+
// truly empty nodes should just be ignored
304305
if (node.text.trim() == "" && node.text.indexOf(" ") == -1) {
305306
return;
306307
}
307308

308-
// if (node.text.trim() == "" &&
309-
// node.text.indexOf(" ") != -1 &&
310-
// parseContext.condenseWhitespace) {
311-
// node.text = " ";
312-
// }
313-
314309
// we might want to preserve internal whitespace
315310
// empty strings of whitespace might be significant or not, condense it by default
316-
String finalText = parseContext.condenseWhitespace
317-
? condenseHtmlWhitespace(node.text)
318-
: node.text;
319-
320-
// if this is part of a string of spans, we will preserve leading and trailing whitespace
321-
if (!(parseContext.parentElement is TextSpan ||
322-
parseContext.parentElement is LinkTextSpan))
323-
finalText = finalText.trim();
311+
String finalText = node.text;
312+
if (parseContext.condenseWhitespace) {
313+
finalText = condenseHtmlWhitespace(node.text);
314+
315+
// if this is part of a string of spans, we will preserve leading
316+
// and trailing whitespace unless the previous character is whitespace
317+
if (parseContext.parentElement == null)
318+
finalText = finalText.trimLeft();
319+
else if (parseContext.parentElement is TextSpan ||
320+
parseContext.parentElement is LinkTextSpan) {
321+
String lastString = parseContext.parentElement.text ?? '';
322+
if (!parseContext.parentElement.children.isEmpty) {
323+
lastString = parseContext.parentElement.children.last.text ?? '';
324+
}
325+
if (lastString == '' ||
326+
lastString.endsWith(' ') ||
327+
lastString.endsWith('\n')) finalText = finalText.trimLeft();
328+
}
329+
}
324330

325331
// if the finalText is actually empty, just return
326-
if (finalText.isEmpty) return;
332+
if (finalText.trim().isEmpty) return;
327333

328334
// NOW WE HAVE OUR TRULY FINAL TEXT
329335
// debugPrint("Plain Text Node: '$finalText'");
@@ -376,7 +382,7 @@ class HtmlRichTextParser extends StatelessWidget {
376382
.add(BlockText(child: RichText(text: span)));
377383
}
378384

379-
// this allows future items to be added as children
385+
// this allows future items to be added as children of this item
380386
parseContext.parentElement = span;
381387

382388
// if the parent is a LinkTextSpan, keep the main attributes of that span going.
@@ -391,8 +397,10 @@ class HtmlRichTextParser extends StatelessWidget {
391397
));
392398

393399
// if the parent is a normal span, just add this to that list
394-
} else {
400+
} else if (!(parseContext.parentElement.children is List<Widget>)) {
395401
parseContext.parentElement.children.add(span);
402+
} else {
403+
// Doing nothing... we shouldn't ever get here
396404
}
397405
return;
398406
}
@@ -525,14 +533,21 @@ class HtmlRichTextParser extends StatelessWidget {
525533
break;
526534

527535
case "table":
528-
case "tbody":
529-
case "thead":
530536
// new block, so clear out the parent element
531537
parseContext.parentElement = null;
532538
nextContext.parentElement = Column(
533539
crossAxisAlignment: CrossAxisAlignment.start,
540+
children: <Widget>[],
534541
);
535-
nextContext.rootWidgetList.add(nextContext.parentElement);
542+
nextContext.rootWidgetList.add(Container(
543+
margin: EdgeInsets.symmetric(vertical: 12.0),
544+
child: nextContext.parentElement));
545+
break;
546+
547+
// we don't handle tbody, thead, or tfoot elements separately for now
548+
case "tbody":
549+
case "thead":
550+
case "tfoot":
536551
break;
537552

538553
case "td":
@@ -541,21 +556,49 @@ class HtmlRichTextParser extends StatelessWidget {
541556
if (node.attributes['colspan'] != null) {
542557
colspan = int.tryParse(node.attributes['colspan']);
543558
}
559+
nextContext.childStyle = nextContext.childStyle.merge(TextStyle(
560+
fontWeight: (node.localName == 'th')
561+
? FontWeight.bold
562+
: FontWeight.normal));
563+
RichText text =
564+
RichText(text: TextSpan(text: '', children: <TextSpan>[]));
544565
Expanded cell = Expanded(
545566
flex: colspan,
546-
child: Wrap(),
567+
child: Container(padding: EdgeInsets.all(1.0), child: text),
547568
);
548569
nextContext.parentElement.children.add(cell);
549-
nextContext.parentElement = cell.child;
570+
nextContext.parentElement = text.text;
550571
break;
551572

552573
case "tr":
553574
Row row = Row(
554575
crossAxisAlignment: CrossAxisAlignment.center,
576+
children: <Widget>[],
555577
);
556578
nextContext.parentElement.children.add(row);
557579
nextContext.parentElement = row;
558580
break;
581+
582+
// treat captions like a row with one expanded cell
583+
case "caption":
584+
// create the row
585+
Row row = Row(
586+
crossAxisAlignment: CrossAxisAlignment.center,
587+
children: <Widget>[],
588+
);
589+
590+
// create an expanded cell
591+
RichText text = RichText(
592+
textAlign: TextAlign.center,
593+
textScaleFactor: 1.2,
594+
text: TextSpan(text: '', children: <TextSpan>[]));
595+
Expanded cell = Expanded(
596+
child: Container(padding: EdgeInsets.all(2.0), child: text),
597+
);
598+
row.children.add(cell);
599+
nextContext.parentElement.children.add(row);
600+
nextContext.parentElement = text.text;
601+
break;
559602
}
560603
}
561604

0 commit comments

Comments
 (0)