@@ -179,6 +179,7 @@ class HtmlRichTextParser extends StatelessWidget {
179
179
"br" ,
180
180
"table" ,
181
181
"tbody" ,
182
+ "caption" ,
182
183
"td" ,
183
184
"tfoot" ,
184
185
"th" ,
@@ -300,30 +301,35 @@ class HtmlRichTextParser extends StatelessWidget {
300
301
// a text only node is a child of a tag with no inner html
301
302
if (node is dom.Text ) {
302
303
// WHITESPACE CONSIDERATIONS ---
303
- // truly empty nodes, should just be ignored
304
+ // truly empty nodes should just be ignored
304
305
if (node.text.trim () == "" && node.text.indexOf (" " ) == - 1 ) {
305
306
return ;
306
307
}
307
308
308
- // if (node.text.trim() == "" &&
309
- // node.text.indexOf(" ") != -1 &&
310
- // parseContext.condenseWhitespace) {
311
- // node.text = " ";
312
- // }
313
-
314
309
// we might want to preserve internal whitespace
315
310
// 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
+ }
324
330
325
331
// if the finalText is actually empty, just return
326
- if (finalText.isEmpty) return ;
332
+ if (finalText.trim (). isEmpty) return ;
327
333
328
334
// NOW WE HAVE OUR TRULY FINAL TEXT
329
335
// debugPrint("Plain Text Node: '$finalText'");
@@ -376,7 +382,7 @@ class HtmlRichTextParser extends StatelessWidget {
376
382
.add (BlockText (child: RichText (text: span)));
377
383
}
378
384
379
- // this allows future items to be added as children
385
+ // this allows future items to be added as children of this item
380
386
parseContext.parentElement = span;
381
387
382
388
// if the parent is a LinkTextSpan, keep the main attributes of that span going.
@@ -391,8 +397,10 @@ class HtmlRichTextParser extends StatelessWidget {
391
397
));
392
398
393
399
// if the parent is a normal span, just add this to that list
394
- } else {
400
+ } else if ( ! (parseContext.parentElement.children is List < Widget >)) {
395
401
parseContext.parentElement.children.add (span);
402
+ } else {
403
+ // Doing nothing... we shouldn't ever get here
396
404
}
397
405
return ;
398
406
}
@@ -525,14 +533,21 @@ class HtmlRichTextParser extends StatelessWidget {
525
533
break ;
526
534
527
535
case "table" :
528
- case "tbody" :
529
- case "thead" :
530
536
// new block, so clear out the parent element
531
537
parseContext.parentElement = null ;
532
538
nextContext.parentElement = Column (
533
539
crossAxisAlignment: CrossAxisAlignment .start,
540
+ children: < Widget > [],
534
541
);
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" :
536
551
break ;
537
552
538
553
case "td" :
@@ -541,21 +556,49 @@ class HtmlRichTextParser extends StatelessWidget {
541
556
if (node.attributes['colspan' ] != null ) {
542
557
colspan = int .tryParse (node.attributes['colspan' ]);
543
558
}
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 > []));
544
565
Expanded cell = Expanded (
545
566
flex: colspan,
546
- child: Wrap ( ),
567
+ child: Container (padding : EdgeInsets . all ( 1.0 ), child : text ),
547
568
);
548
569
nextContext.parentElement.children.add (cell);
549
- nextContext.parentElement = cell.child ;
570
+ nextContext.parentElement = text.text ;
550
571
break ;
551
572
552
573
case "tr" :
553
574
Row row = Row (
554
575
crossAxisAlignment: CrossAxisAlignment .center,
576
+ children: < Widget > [],
555
577
);
556
578
nextContext.parentElement.children.add (row);
557
579
nextContext.parentElement = row;
558
580
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 ;
559
602
}
560
603
}
561
604
0 commit comments