@@ -83,31 +83,25 @@ class BlockText extends StatelessWidget {
8383 final RichText child;
8484 final EdgeInsets padding;
8585 final EdgeInsets margin;
86- final String leadingChar;
8786 final Decoration decoration;
87+ final bool shrinkToFit;
8888
8989 BlockText ({
9090 @required this .child,
91+ @required this .shrinkToFit,
9192 this .padding,
9293 this .margin,
93- this .leadingChar = '' ,
9494 this .decoration,
9595 });
9696
9797 @override
9898 Widget build (BuildContext context) {
9999 return Container (
100- width: double .infinity,
100+ width: shrinkToFit ? null : double .infinity,
101101 padding: this .padding,
102102 margin: this .margin,
103103 decoration: this .decoration,
104- child: Row (
105- crossAxisAlignment: CrossAxisAlignment .start,
106- children: < Widget > [
107- leadingChar.isNotEmpty ? Text (leadingChar) : Container (),
108- Expanded (child: child),
109- ],
110- ),
104+ child: child,
111105 );
112106 }
113107}
@@ -155,7 +149,7 @@ class ParseContext {
155149
156150class HtmlRichTextParser extends StatelessWidget {
157151 HtmlRichTextParser ({
158- @required this .width ,
152+ this .shrinkToFit ,
159153 this .onLinkTap,
160154 this .renderNewlines = false ,
161155 this .html,
@@ -175,7 +169,7 @@ class HtmlRichTextParser extends StatelessWidget {
175169
176170 final double indentSize = 10.0 ;
177171
178- final double width ;
172+ final bool shrinkToFit ;
179173 final onLinkTap;
180174 final bool renderNewlines;
181175 final String html;
@@ -223,6 +217,7 @@ class HtmlRichTextParser extends StatelessWidget {
223217 "time" ,
224218 "span" ,
225219 "big" ,
220+ "sub" ,
226221 ];
227222
228223 // specialty elements require unique handling
@@ -425,6 +420,7 @@ class HtmlRichTextParser extends StatelessWidget {
425420 ));
426421 }
427422 BlockText blockText = BlockText (
423+ shrinkToFit: shrinkToFit,
428424 margin: EdgeInsets .only (
429425 top: 8.0 ,
430426 bottom: 8.0 ,
@@ -438,8 +434,10 @@ class HtmlRichTextParser extends StatelessWidget {
438434 );
439435 parseContext.rootWidgetList.add (blockText);
440436 } else {
441- parseContext.rootWidgetList
442- .add (BlockText (child: RichText (text: span)));
437+ parseContext.rootWidgetList.add (BlockText (
438+ child: RichText (text: span),
439+ shrinkToFit: shrinkToFit,
440+ ));
443441 }
444442
445443 // this allows future items to be added as children of this item
@@ -522,6 +520,13 @@ class HtmlRichTextParser extends StatelessWidget {
522520 childStyle = childStyle.merge (
523521 TextStyle (backgroundColor: Colors .yellow, color: Colors .black));
524522 break ;
523+ case "sub" :
524+ childStyle = childStyle.merge (
525+ TextStyle (
526+ fontSize: childStyle.fontSize * OFFSET_TAGS_FONT_SIZE_FACTOR ,
527+ ),
528+ );
529+ break ;
525530 case "del" :
526531 case "s" :
527532 case "strike" :
@@ -599,6 +604,7 @@ class HtmlRichTextParser extends StatelessWidget {
599604 } else {
600605 // start a new block element for this link and its text
601606 BlockText blockElement = BlockText (
607+ shrinkToFit: shrinkToFit,
602608 margin: EdgeInsets .only (
603609 left: parseContext.indentLevel * indentSize, top: 10.0 ),
604610 child: RichText (text: span),
@@ -732,6 +738,15 @@ class HtmlRichTextParser extends StatelessWidget {
732738 case "img" :
733739 if (showImages) {
734740 if (node.attributes['src' ] != null ) {
741+ final width = imageProperties? .width ??
742+ ((node.attributes['width' ] != null )
743+ ? double .tryParse (node.attributes['width' ])
744+ : null );
745+ final height = imageProperties? .height ??
746+ ((node.attributes['height' ] != null )
747+ ? double .tryParse (node.attributes['height' ])
748+ : null );
749+
735750 if (node.attributes['src' ].startsWith ("data:image" ) &&
736751 node.attributes['src' ].contains ("base64," )) {
737752 precacheImage (
@@ -741,20 +756,14 @@ class HtmlRichTextParser extends StatelessWidget {
741756 ),
742757 ),
743758 buildContext,
744- onError: onImageError,
759+ onError: onImageError ?? (_, __) {} ,
745760 );
746761 parseContext.rootWidgetList.add (GestureDetector (
747762 child: Image .memory (
748763 base64.decode (
749764 node.attributes['src' ].split ("base64," )[1 ].trim ()),
750- width: imageProperties? .width ??
751- ((node.attributes['width' ] != null )
752- ? double .tryParse (node.attributes['width' ])
753- : null ),
754- height: imageProperties? .height ??
755- ((node.attributes['height' ] != null )
756- ? double .tryParse (node.attributes['height' ])
757- : null ),
765+ width: (width ?? - 1 ) > 0 ? width : null ,
766+ height: (height ?? - 1 ) > 0 ? width : null ,
758767 scale: imageProperties? .scale ?? 1.0 ,
759768 matchTextDirection:
760769 imageProperties? .matchTextDirection ?? false ,
@@ -782,19 +791,31 @@ class HtmlRichTextParser extends StatelessWidget {
782791 precacheImage (
783792 NetworkImage (node.attributes['src' ]),
784793 buildContext,
785- onError: onImageError,
794+ onError: onImageError ?? (_, __) {} ,
786795 );
787796 parseContext.rootWidgetList.add (GestureDetector (
788797 child: Image .network (
789798 node.attributes['src' ],
790- width: imageProperties? .width ??
791- ((node.attributes['width' ] != null )
792- ? double .parse (node.attributes['width' ])
793- : null ),
794- height: imageProperties? .height ??
795- ((node.attributes['height' ] != null )
796- ? double .parse (node.attributes['height' ])
797- : null ),
799+ frameBuilder: (context, child, frame, _) {
800+ if (node.attributes['alt' ] != null && frame == null ) {
801+ return BlockText (
802+ child: RichText (
803+ textAlign: TextAlign .center,
804+ text: TextSpan (
805+ text: node.attributes['alt' ],
806+ style: nextContext.childStyle,
807+ ),
808+ ),
809+ shrinkToFit: shrinkToFit,
810+ );
811+ }
812+ if (frame != null ) {
813+ return child;
814+ }
815+ return Container ();
816+ },
817+ width: (width ?? - 1 ) > 0 ? width : null ,
818+ height: (height ?? - 1 ) > 0 ? height : null ,
798819 scale: imageProperties? .scale ?? 1.0 ,
799820 matchTextDirection:
800821 imageProperties? .matchTextDirection ?? false ,
@@ -819,19 +840,6 @@ class HtmlRichTextParser extends StatelessWidget {
819840 },
820841 ));
821842 }
822- if (node.attributes['alt' ] != null ) {
823- parseContext.rootWidgetList.add (BlockText (
824- margin:
825- EdgeInsets .symmetric (horizontal: 0.0 , vertical: 10.0 ),
826- padding: EdgeInsets .all (0.0 ),
827- child: RichText (
828- textAlign: TextAlign .center,
829- text: TextSpan (
830- text: node.attributes['alt' ],
831- style: nextContext.childStyle,
832- children: < TextSpan > [],
833- ))));
834- }
835843 }
836844 }
837845 break ;
@@ -844,16 +852,18 @@ class HtmlRichTextParser extends StatelessWidget {
844852 leadingChar = parseContext.listCount.toString () + '.' ;
845853 }
846854 BlockText blockText = BlockText (
855+ shrinkToFit: shrinkToFit,
847856 margin: EdgeInsets .only (
848857 left: parseContext.indentLevel * indentSize, top: 3.0 ),
849858 child: RichText (
850859 text: TextSpan (
851- text: '' ,
852- style: nextContext.childStyle,
853- children: < TextSpan > [],
860+ text: '$leadingChar ' ,
861+ style: DefaultTextStyle .of (buildContext).style,
862+ children: < TextSpan > [
863+ TextSpan (text: '' , style: nextContext.childStyle)
864+ ],
854865 ),
855866 ),
856- leadingChar: '$leadingChar ' ,
857867 );
858868 parseContext.rootWidgetList.add (blockText);
859869 nextContext.parentElement = blockText.child.text;
@@ -914,6 +924,7 @@ class HtmlRichTextParser extends StatelessWidget {
914924 ));
915925 }
916926 BlockText blockText = BlockText (
927+ shrinkToFit: shrinkToFit,
917928 margin: node.localName != 'body'
918929 ? _customEdgeInsets ??
919930 EdgeInsets .only (
@@ -953,39 +964,11 @@ class HtmlRichTextParser extends StatelessWidget {
953964 }
954965 }
955966
956- Paint _getPaint (Color color) {
957- Paint paint = new Paint ();
958- paint.color = color;
959- return paint;
960- }
961-
962967 String condenseHtmlWhitespace (String stringToTrim) {
963968 stringToTrim = stringToTrim.replaceAll ("\n " , " " );
964969 while (stringToTrim.indexOf (" " ) != - 1 ) {
965970 stringToTrim = stringToTrim.replaceAll (" " , " " );
966971 }
967972 return stringToTrim;
968973 }
969-
970- bool _isNotFirstBreakTag (dom.Node node) {
971- int index = node.parentNode.nodes.indexOf (node);
972- if (index == 0 ) {
973- if (node.parentNode == null ) {
974- return false ;
975- }
976- return _isNotFirstBreakTag (node.parentNode);
977- } else if (node.parentNode.nodes[index - 1 ] is dom.Element ) {
978- if ((node.parentNode.nodes[index - 1 ] as dom.Element ).localName == "br" ) {
979- return true ;
980- }
981- return false ;
982- } else if (node.parentNode.nodes[index - 1 ] is dom.Text ) {
983- if ((node.parentNode.nodes[index - 1 ] as dom.Text ).text.trim () == "" ) {
984- return _isNotFirstBreakTag (node.parentNode.nodes[index - 1 ]);
985- } else {
986- return false ;
987- }
988- }
989- return false ;
990- }
991974}
0 commit comments