11library flutter_html_svg;
22
33import 'dart:convert' ;
4-
54import 'package:flutter/material.dart' ;
65import 'package:flutter_html/flutter_html.dart' ;
76// ignore: implementation_imports
@@ -11,16 +10,18 @@ import 'package:flutter_svg/flutter_svg.dart';
1110/// The CustomRender function that renders the <svg> HTML tag.
1211CustomRender svgTagRender () =>
1312 CustomRender .widget (widget: (context, buildChildren) {
13+ final attributes =
14+ context.tree.element? .attributes.cast <String , String >() ??
15+ < String , String > {};
16+
1417 return Builder (
1518 key: context.key,
1619 builder: (buildContext) {
1720 return GestureDetector (
1821 child: SvgPicture .string (
1922 context.tree.element? .outerHtml ?? "" ,
20- width: double .tryParse (
21- context.tree.element? .attributes['width' ] ?? "" ),
22- height: double .tryParse (
23- context.tree.element? .attributes['width' ] ?? "" ),
23+ width: _width (attributes),
24+ height: _height (attributes),
2425 ),
2526 onTap: () {
2627 if (MultipleTapGestureDetector .of (buildContext) != null ) {
@@ -29,7 +30,7 @@ CustomRender svgTagRender() =>
2930 context.parser.onImageTap? .call (
3031 context.tree.element? .outerHtml ?? "" ,
3132 context,
32- context.tree.element ! . attributes. cast () ,
33+ attributes,
3334 context.tree.element);
3435 },
3536 );
@@ -39,32 +40,39 @@ CustomRender svgTagRender() =>
3940/// The CustomRender function that renders an <img> tag with hardcoded svg data.
4041CustomRender svgDataImageRender () =>
4142 CustomRender .widget (widget: (context, buildChildren) {
42- final dataUri = _dataUriFormat.firstMatch (
43- _src (context.tree.element? .attributes.cast () ?? < String , String > {})! );
43+ final attributes =
44+ context.tree.element? .attributes.cast <String , String >() ??
45+ < String , String > {};
46+ final dataUri = _dataUriFormat.firstMatch (_src (attributes)! );
4447 final data = dataUri? .namedGroup ('data' );
45- if (data == null ) return const SizedBox (height: 0 , width: 0 );
48+
49+ if (data == null || data.isEmpty) {
50+ return const SizedBox (height: 0 , width: 0 );
51+ }
4652 return Builder (
4753 key: context.key,
4854 builder: (buildContext) {
55+ final width = _width (attributes);
56+ final height = _height (attributes);
57+
4958 return GestureDetector (
5059 child: dataUri? .namedGroup ('encoding' ) == ';base64'
5160 ? SvgPicture .memory (
5261 base64.decode (data.trim ()),
53- width: _width (context.tree.element? .attributes.cast () ??
54- < String , String > {}),
55- height: _height (context.tree.element? .attributes.cast () ??
56- < String , String > {}),
62+ width: width,
63+ height: height,
5764 )
58- : SvgPicture .string (Uri .decodeFull (data)),
65+ : SvgPicture .string (
66+ Uri .decodeFull (data),
67+ width: width,
68+ height: height,
69+ ),
5970 onTap: () {
6071 if (MultipleTapGestureDetector .of (buildContext) != null ) {
6172 MultipleTapGestureDetector .of (buildContext)! .onTap? .call ();
6273 }
63- context.parser.onImageTap? .call (
64- Uri .decodeFull (data),
65- context,
66- context.tree.element! .attributes.cast (),
67- context.tree.element);
74+ context.parser.onImageTap? .call (Uri .decodeFull (data), context,
75+ attributes, context.tree.element);
6876 },
6977 );
7078 });
@@ -73,55 +81,62 @@ CustomRender svgDataImageRender() =>
7381/// The CustomRender function that renders an <img> tag with a network svg image.
7482CustomRender svgNetworkImageRender () =>
7583 CustomRender .widget (widget: (context, buildChildren) {
76- if (context.tree.element? .attributes["src" ] == null ) {
84+ final attributes =
85+ context.tree.element? .attributes.cast <String , String >() ??
86+ < String , String > {};
87+
88+ if (attributes["src" ] == null ) {
7789 return const SizedBox (height: 0 , width: 0 );
7890 }
7991 return Builder (
8092 key: context.key,
8193 builder: (buildContext) {
8294 return GestureDetector (
8395 child: SvgPicture .network (
84- context.tree.element ! . attributes["src" ]! ,
85- width: _width (context.tree.element ! . attributes. cast () ),
86- height: _height (context.tree.element ! . attributes. cast () ),
96+ attributes["src" ]! ,
97+ width: _width (attributes),
98+ height: _height (attributes),
8799 ),
88100 onTap: () {
89101 if (MultipleTapGestureDetector .of (buildContext) != null ) {
90102 MultipleTapGestureDetector .of (buildContext)! .onTap? .call ();
91103 }
92- context.parser.onImageTap? .call (
93- context.tree.element! .attributes["src" ]! ,
94- context,
95- context.tree.element! .attributes.cast (),
96- context.tree.element);
104+ context.parser.onImageTap? .call (attributes["src" ]! , context,
105+ attributes, context.tree.element);
97106 },
98107 );
99108 });
100109 });
101110
102111/// The CustomRender function that renders an <img> tag with an svg asset in your app
103- CustomRender svgAssetImageRender () =>
112+ CustomRender svgAssetImageRender ({ AssetBundle ? bundle} ) =>
104113 CustomRender .widget (widget: (context, buildChildren) {
105- if (_src (context.tree.element? .attributes.cast () ?? < String , String > {}) ==
106- null ) {
114+ final attributes =
115+ context.tree.element? .attributes.cast <String , String >() ??
116+ < String , String > {};
117+
118+ if (_src (attributes) == null ) {
107119 return const SizedBox (height: 0 , width: 0 );
108120 }
121+
109122 final assetPath = _src (context.tree.element! .attributes.cast ())!
110123 .replaceFirst ('asset:' , '' );
111124 return Builder (
112125 key: context.key,
113126 builder: (buildContext) {
114127 return GestureDetector (
115- child: SvgPicture .asset (assetPath),
128+ child: SvgPicture .asset (
129+ assetPath,
130+ bundle: bundle,
131+ width: _width (attributes),
132+ height: _height (attributes),
133+ ),
116134 onTap: () {
117135 if (MultipleTapGestureDetector .of (buildContext) != null ) {
118136 MultipleTapGestureDetector .of (buildContext)! .onTap? .call ();
119137 }
120138 context.parser.onImageTap? .call (
121- assetPath,
122- context,
123- context.tree.element! .attributes.cast (),
124- context.tree.element);
139+ assetPath, context, attributes, context.tree.element);
125140 },
126141 );
127142 });
@@ -136,10 +151,16 @@ CustomRenderMatcher svgTagMatcher() => (context) {
136151CustomRenderMatcher svgDataUriMatcher (
137152 {String ? encoding = 'base64' , String ? mime = 'image/svg+xml' }) =>
138153 (context) {
139- if (_src (context.tree.element? .attributes.cast () ?? < String , String > {}) ==
140- null ) return false ;
141- final dataUri = _dataUriFormat.firstMatch (
142- _src (context.tree.element? .attributes.cast () ?? < String , String > {})! );
154+ final attributes =
155+ context.tree.element? .attributes.cast <String , String >() ??
156+ < String , String > {};
157+
158+ if (_src (attributes) == null ) {
159+ return false ;
160+ }
161+
162+ final dataUri = _dataUriFormat.firstMatch (_src (attributes)! );
163+
143164 return context.tree.element? .localName == "img" &&
144165 dataUri != null &&
145166 (mime == null || dataUri.namedGroup ('mime' ) == mime) &&
@@ -153,11 +174,17 @@ CustomRenderMatcher svgNetworkSourceMatcher({
153174 String ? extension = "svg" ,
154175}) =>
155176 (context) {
156- if (_src (context.tree.element? .attributes.cast () ?? < String , String > {}) ==
157- null ) return false ;
177+ final attributes =
178+ context.tree.element? .attributes.cast <String , String >() ??
179+ < String , String > {};
180+
181+ if (_src (attributes) == null ) {
182+ return false ;
183+ }
184+
158185 try {
159- final src = Uri .parse (_src (
160- context.tree.element ? .attributes. cast () ?? < String , String > {}) ! );
186+ final src = Uri .parse (_src (attributes) ! );
187+
161188 return context.tree.element? .localName == "img" &&
162189 schemas.contains (src.scheme) &&
163190 (domains == null || domains.contains (src.host)) &&
@@ -168,14 +195,16 @@ CustomRenderMatcher svgNetworkSourceMatcher({
168195 };
169196
170197/// A CustomRenderMatcher for an <img> tag with an in-app svg asset
171- CustomRenderMatcher svgAssetUriMatcher () => (context) =>
172- context.tree.element? .localName == "img" &&
173- _src (context.tree.element? .attributes.cast () ?? < String , String > {}) !=
174- null &&
175- _src (context.tree.element? .attributes.cast () ?? < String , String > {})!
176- .startsWith ("asset:" ) &&
177- _src (context.tree.element? .attributes.cast () ?? < String , String > {})!
178- .endsWith (".svg" );
198+ CustomRenderMatcher svgAssetUriMatcher () => (context) {
199+ final attributes =
200+ context.tree.element? .attributes.cast <String , String >() ??
201+ < String , String > {};
202+
203+ return context.tree.element? .localName == "img" &&
204+ _src (attributes) != null &&
205+ _src (attributes)! .startsWith ("asset:" ) &&
206+ _src (attributes)! .endsWith (".svg" );
207+ };
179208
180209final _dataUriFormat = RegExp (
181210 "^(?<scheme>data):(?<mime>image\\ /[\\ w\\ +\\ -\\ .]+)(?<encoding>;base64)?\\ ,(?<data>.*)" );
0 commit comments