Skip to content

Commit 1c51d62

Browse files
authored
Merge pull request #532 from vrtdev/feature/146-image-base-url
Support relative paths for network image rendering
2 parents 252f784 + 077cf1d commit 1c51d62

File tree

3 files changed

+21
-24
lines changed

3 files changed

+21
-24
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ The default image renders are:
425425
```dart
426426
final Map<ImageSourceMatcher, ImageRender> defaultImageRenders = {
427427
base64UriMatcher(): base64ImageRender(),
428+
assetUriMatcher(): assetImageRender(),
428429
networkSourceMatcher(extension: "svg"): svgNetworkImageRender(),
429430
networkSourceMatcher(): networkImageRender(),
430431
};
@@ -536,12 +537,16 @@ Widget html = Html(
536537
altWidget: (alt) => Text(alt),
537538
loadingWidget: () => Text("Loading..."),
538539
),
540+
(attr, _) => attr["src"] != null && attr["src"].startsWith("/wiki"):
541+
networkImageRender(
542+
mapUrl: (url) => "https://upload.wikimedia.org" + url),
539543
},
540544
);
541545
```
542546

543-
Above, there are two `networkSourceMatcher`s. One is overriden to only apply to images on the URL `flutter.dev`, while the other covers the rest of the cases.
544-
When an image with URL `flutter.dev` is detected, rather than displaying the image, the render will display the flutter logo. If the image is any other image, it keeps the default widget, but just sets the headers and the alt text in case that image happens to be broken.
547+
Above, there are three custom `networkSourceMatcher`s, which will be applied - in order - before the default implementations.
548+
549+
When an image with URL `flutter.dev` is detected, rather than displaying the image, the render will display the flutter logo. If the image is any other image, it keeps the default widget, but just sets the headers and the alt text in case that image happens to be broken. The final render handles relative paths by rewriting them, specifically prefixing them with a base url. Note that the customizations of the previous custom renders do not apply. For example, the headers that the second render would apply are not applied in this third render.
545550

546551
2. Creating your own renders:
547552
```dart

example/lib/main.dart

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -127,31 +127,15 @@ const htmlData = """
127127
<img src='asset:assets/mac.svg' width='100' />
128128
<h3>Base64</h3>
129129
<img alt='Red dot' src='data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==' />
130+
<h3>Custom source matcher (relative paths)</h3>
131+
<img src='/wikipedia/commons/thumb/e/ef/Octicons-logo-github.svg/200px-Octicons-logo-github.svg.png' />
130132
<h3>Custom image render (flutter.dev)</h3>
131133
<img src='https://flutter.dev/images/flutter-mono-81x100.png' />
132134
<h3>No image source</h3>
133135
<img alt='No source' />
134136
<img alt='Empty source' src='' />
135137
<h3>Broken network image</h3>
136138
<img alt='Broken image' src='https://www.notgoogle.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' />
137-
<h3>Used inside a table</h3>
138-
<table>
139-
<tr>
140-
<td><img alt='Google' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' /></td>
141-
<td><img alt='Google' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' /></td>
142-
<td><img alt='Google' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' /></td>
143-
</tr>
144-
</table>
145-
<h3>Video support:</h3>
146-
<video controls>
147-
<source src="https://www.w3schools.com/html/mov_bbb.mp4" />
148-
</video>
149-
<h3>Audio support:</h3>
150-
<audio controls>
151-
<source src="https://www.w3schools.com/html/mov_bbb.mp4" />
152-
</audio>
153-
<h3>IFrame support:</h3>
154-
<iframe src="https://google.com"></iframe>
155139
""";
156140

157141
class _MyHomePageState extends State<MyHomePage> {
@@ -176,6 +160,12 @@ class _MyHomePageState extends State<MyHomePage> {
176160
altWidget: (alt) => Text(alt),
177161
loadingWidget: () => Text("Loading..."),
178162
),
163+
// On relative paths starting with /wiki, prefix with a base url
164+
(attr, _) => attr["src"] != null && attr["src"].startsWith("/wiki"):
165+
networkImageRender(
166+
mapUrl: (url) => "https://upload.wikimedia.org" + url),
167+
// Custom placeholder image for broken links
168+
networkSourceMatcher(): networkImageRender(altWidget: (_) => FlutterLogo()),
179169
},
180170
onLinkTap: (url) {
181171
print("Opening $url...");

lib/image_render.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,17 @@ ImageRender assetImageRender({
9090

9191
ImageRender networkImageRender({
9292
Map<String, String> headers,
93+
String Function(String) mapUrl,
9394
double width,
9495
double height,
9596
Widget Function(String) altWidget,
9697
Widget Function() loadingWidget,
9798
}) =>
9899
(context, attributes, element) {
100+
final src = mapUrl?.call(_src(attributes)) ?? _src(attributes);
99101
precacheImage(
100102
NetworkImage(
101-
_src(attributes),
103+
src,
102104
headers: headers,
103105
),
104106
context.buildContext,
@@ -108,7 +110,7 @@ ImageRender networkImageRender({
108110
);
109111
Completer<Size> completer = Completer();
110112
Image image =
111-
Image.network(_src(attributes), frameBuilder: (ctx, child, frame, _) {
113+
Image.network(src, frameBuilder: (ctx, child, frame, _) {
112114
if (frame == null) {
113115
if (!completer.isCompleted) {
114116
completer.completeError("error");
@@ -138,7 +140,7 @@ ImageRender networkImageRender({
138140
builder: (BuildContext buildContext, AsyncSnapshot<Size> snapshot) {
139141
if (snapshot.hasData) {
140142
return Image.network(
141-
_src(attributes),
143+
src,
142144
headers: headers,
143145
width: width ?? _width(attributes) ?? snapshot.data.width,
144146
height: height ?? _height(attributes),
@@ -152,7 +154,7 @@ ImageRender networkImageRender({
152154
},
153155
);
154156
} else if (snapshot.hasError) {
155-
return Text(_alt(attributes) ?? "",
157+
return altWidget?.call(_alt(attributes)) ?? Text(_alt(attributes) ?? "",
156158
style: context.style.generateTextStyle());
157159
} else {
158160
return loadingWidget?.call() ?? const CircularProgressIndicator();

0 commit comments

Comments
 (0)