1
1
library flutter_html_svg;
2
2
3
3
import 'dart:convert' ;
4
-
5
4
import 'package:flutter/material.dart' ;
6
5
import 'package:flutter_html/flutter_html.dart' ;
7
6
// ignore: implementation_imports
@@ -11,16 +10,18 @@ import 'package:flutter_svg/flutter_svg.dart';
11
10
/// The CustomRender function that renders the <svg> HTML tag.
12
11
CustomRender svgTagRender () =>
13
12
CustomRender .widget (widget: (context, buildChildren) {
13
+ final attributes =
14
+ context.tree.element? .attributes.cast <String , String >() ??
15
+ < String , String > {};
16
+
14
17
return Builder (
15
18
key: context.key,
16
19
builder: (buildContext) {
17
20
return GestureDetector (
18
21
child: SvgPicture .string (
19
22
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),
24
25
),
25
26
onTap: () {
26
27
if (MultipleTapGestureDetector .of (buildContext) != null ) {
@@ -29,7 +30,7 @@ CustomRender svgTagRender() =>
29
30
context.parser.onImageTap? .call (
30
31
context.tree.element? .outerHtml ?? "" ,
31
32
context,
32
- context.tree.element ! . attributes. cast () ,
33
+ attributes,
33
34
context.tree.element);
34
35
},
35
36
);
@@ -39,32 +40,39 @@ CustomRender svgTagRender() =>
39
40
/// The CustomRender function that renders an <img> tag with hardcoded svg data.
40
41
CustomRender svgDataImageRender () =>
41
42
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)! );
44
47
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
+ }
46
52
return Builder (
47
53
key: context.key,
48
54
builder: (buildContext) {
55
+ final width = _width (attributes);
56
+ final height = _height (attributes);
57
+
49
58
return GestureDetector (
50
59
child: dataUri? .namedGroup ('encoding' ) == ';base64'
51
60
? SvgPicture .memory (
52
61
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,
57
64
)
58
- : SvgPicture .string (Uri .decodeFull (data)),
65
+ : SvgPicture .string (
66
+ Uri .decodeFull (data),
67
+ width: width,
68
+ height: height,
69
+ ),
59
70
onTap: () {
60
71
if (MultipleTapGestureDetector .of (buildContext) != null ) {
61
72
MultipleTapGestureDetector .of (buildContext)! .onTap? .call ();
62
73
}
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);
68
76
},
69
77
);
70
78
});
@@ -73,55 +81,62 @@ CustomRender svgDataImageRender() =>
73
81
/// The CustomRender function that renders an <img> tag with a network svg image.
74
82
CustomRender svgNetworkImageRender () =>
75
83
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 ) {
77
89
return const SizedBox (height: 0 , width: 0 );
78
90
}
79
91
return Builder (
80
92
key: context.key,
81
93
builder: (buildContext) {
82
94
return GestureDetector (
83
95
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),
87
99
),
88
100
onTap: () {
89
101
if (MultipleTapGestureDetector .of (buildContext) != null ) {
90
102
MultipleTapGestureDetector .of (buildContext)! .onTap? .call ();
91
103
}
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);
97
106
},
98
107
);
99
108
});
100
109
});
101
110
102
111
/// The CustomRender function that renders an <img> tag with an svg asset in your app
103
- CustomRender svgAssetImageRender () =>
112
+ CustomRender svgAssetImageRender ({ AssetBundle ? bundle} ) =>
104
113
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 ) {
107
119
return const SizedBox (height: 0 , width: 0 );
108
120
}
121
+
109
122
final assetPath = _src (context.tree.element! .attributes.cast ())!
110
123
.replaceFirst ('asset:' , '' );
111
124
return Builder (
112
125
key: context.key,
113
126
builder: (buildContext) {
114
127
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
+ ),
116
134
onTap: () {
117
135
if (MultipleTapGestureDetector .of (buildContext) != null ) {
118
136
MultipleTapGestureDetector .of (buildContext)! .onTap? .call ();
119
137
}
120
138
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);
125
140
},
126
141
);
127
142
});
@@ -136,10 +151,16 @@ CustomRenderMatcher svgTagMatcher() => (context) {
136
151
CustomRenderMatcher svgDataUriMatcher (
137
152
{String ? encoding = 'base64' , String ? mime = 'image/svg+xml' }) =>
138
153
(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
+
143
164
return context.tree.element? .localName == "img" &&
144
165
dataUri != null &&
145
166
(mime == null || dataUri.namedGroup ('mime' ) == mime) &&
@@ -153,11 +174,17 @@ CustomRenderMatcher svgNetworkSourceMatcher({
153
174
String ? extension = "svg" ,
154
175
}) =>
155
176
(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
+
158
185
try {
159
- final src = Uri .parse (_src (
160
- context.tree.element ? .attributes. cast () ?? < String , String > {}) ! );
186
+ final src = Uri .parse (_src (attributes) ! );
187
+
161
188
return context.tree.element? .localName == "img" &&
162
189
schemas.contains (src.scheme) &&
163
190
(domains == null || domains.contains (src.host)) &&
@@ -168,14 +195,16 @@ CustomRenderMatcher svgNetworkSourceMatcher({
168
195
};
169
196
170
197
/// 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
+ };
179
208
180
209
final _dataUriFormat = RegExp (
181
210
"^(?<scheme>data):(?<mime>image\\ /[\\ w\\ +\\ -\\ .]+)(?<encoding>;base64)?\\ ,(?<data>.*)" );
0 commit comments