Skip to content

Commit 6cc6c37

Browse files
authored
Merge pull request Sub6Resources#603 from vrtdev/feature/200
Prepare 2.0.0 non-preview release
2 parents 3313d5a + 3b72002 commit 6cc6c37

File tree

4 files changed

+75
-21
lines changed

4 files changed

+75
-21
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
## [2.0.0] - April 29, 2021:
2+
* Stable release with all 2.0.0-nullsafety.X changes
3+
4+
## [2.0.0-nullsafety.1] - April 29, 2021:
5+
* Support basic MathML
6+
* Support inner links
7+
* Supply full context tree to custom render
8+
* Include or exclude specific tags via `tagsList` parameter
9+
* Fixed lists not rendering correctly
10+
* Fixes for colspans in tables
11+
* Fixed various exceptions when using inline styles
12+
* Fixed text decoration not cascading between parent and child
13+
* [BREAKING] support whitelisting tags
14+
* See the README for details on how to migrate `blacklistedElements` (deprecated) to `tagsList`
15+
* Fixed `failed assertion` error when tap-scrolling on any link
16+
* Updated dependencies
17+
118
## [2.0.0-nullsafety.0] - March 5, 2021:
219
* Nullsafety support
320
* Official Flutter Web support

README.md

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ A Flutter widget for rendering HTML and CSS as Flutter widgets.
9696
Add the following to your `pubspec.yaml` file:
9797

9898
dependencies:
99-
flutter_html: ^1.3.0
99+
flutter_html: ^2.0.0
100100

101101
## Currently Supported HTML Tags:
102102
| | | | | | | | | | | |
@@ -242,17 +242,18 @@ Widget html = Html(
242242
);
243243
```
244244

245+
Inner links (such as `<a href="#top">Back to the top</a>` will work out of the box by scrolling the viewport, as long as your `Html` widget is wrapped in a scroll container such as a `SingleChildScrollView`.
246+
245247
### customRender:
246248

247-
A powerful API that allows you to customize everything when rendering a specific HTML tag. This means you can add support for HTML elements that aren't supported natively. You can also make up your own custom tags in your HTML!
249+
A powerful API that allows you to customize everything when rendering a specific HTML tag. This means you can change the default behaviour or add support for HTML elements that aren't supported natively. You can also make up your own custom tags in your HTML!
248250

249-
`customRender` accepts a `Map<String, CustomRender>`. The `CustomRender` type is a function that requires a `Widget` to be returned. It exposes `RenderContext`, the `Widget` that would have been rendered by `Html` without a `customRender` defined, the `attributes` of the HTML element as a `Map<String, String>`, and the HTML element itself as `Element`.
251+
`customRender` accepts a `Map<String, CustomRender>`. The `CustomRender` type is a function that requires a `Widget` or `InlineSpan` to be returned. It exposes `RenderContext` and the `Widget` that would have been rendered by `Html` without a `customRender` defined. The `RenderContext` contains the build context, styling and the HTML element, with attrributes and its subtree,.
250252

251-
To use this API, set the key as the tag of the HTML element you wish to provide a custom implementation for, and create a function with the above parameters that returns a `Widget`.
253+
To use this API, set the key as the tag of the HTML element you wish to provide a custom implementation for, and create a function with the above parameters that returns a `Widget` or `InlineSpan`.
252254

253255
#### Example Usages - customRender:
254256
1. Simple example - rendering custom HTML tags
255-
<details><summary>View code</summary>
256257

257258
```dart
258259
Widget html = Html(
@@ -262,24 +263,48 @@ Widget html = Html(
262263
<flutter horizontal></flutter>
263264
""",
264265
customRender: {
265-
"bird": (RenderContext context, Widget child, Map<String, String> attributes, dom.Element? element) {
266+
"bird": (RenderContext context, Widget child) {
266267
return TextSpan(text: "🐦");
267268
},
268-
"flutter": (RenderContext context, Widget child, Map<String, String> attributes, dom.Element? element) {
269+
"flutter": (RenderContext context, Widget child) {
269270
return FlutterLogo(
270-
style: (attributes['horizontal'] != null)
271+
style: (context.tree.element!.attributes['horizontal'] != null)
271272
? FlutterLogoStyle.horizontal
272273
: FlutterLogoStyle.markOnly,
273274
textColor: context.style.color,
274-
size: context.style.fontSize.size * 5,
275+
size: context.style.fontSize!.size! * 5,
275276
);
276277
},
277278
},
278279
);
279280
```
280-
</details>
281281

282-
2. Complex example - rendering an `iframe` differently based on whether it is an embedded youtube video or some other embedded content
282+
2. Complex example - wrapping the default widget with your own, in this case placing a horizontal scroll around a (potentially too wide) table.
283+
284+
<details><summary>View code</summary>
285+
286+
```dart
287+
Widget html = Html(
288+
data: """
289+
<table style="width:100%">
290+
<caption>Monthly savings</caption>
291+
<tr> <th>January</th> <th>February</th> <th>March</th> <th>April</th> <th>May</th> <th>June</th> <th>July</th> <th>August</th> <th>September</th> <th>October</th> <th>November</th> <th>December</th> </tr>
292+
<tr> <td>\$100</td> <td>\$50</td> <td>\$80</td> <td>\$60</td> <td>\$90</td> <td>\$140</td> <td>\$110</td> <td>\$80</td> <td>\$90</td> <td>\$60</td> <td>\$40</td> <td>\$70</td> </tr>
293+
<tr> <td>\90</td> <td>\$60</td> <td>\$80</td> <td>\$80</td> <td>\$100</td> <td>\$160</td> <td>\$150</td> <td>\$110</td> <td>\$100</td> <td>\$60</td> <td>\$30</td> <td>\$80</td> </tr>
294+
</table>
295+
""",
296+
customRender: {
297+
"table": (context, child) {
298+
return SingleChildScrollView(
299+
scrollDirection: Axis.horizontal,
300+
child: (context.tree as TableLayoutElement).toWidget(context),
301+
);
302+
}
303+
},
304+
);
305+
```
306+
307+
3. Complex example - rendering an `iframe` differently based on whether it is an embedded youtube video or some other embedded content.
283308

284309
<details><summary>View code</summary>
285310

@@ -292,25 +317,26 @@ Widget html = Html(
292317
<iframe src="https://www.youtube.com/embed/tgbNymZ7vqY"></iframe>
293318
""",
294319
customRender: {
295-
"iframe": (RenderContext context, Widget child, Map<String, String> attributes, dom.Element? element) {
296-
if (attributes != null) {
297-
double width = double.tryParse(attributes['width'] ?? "");
298-
double height = double.tryParse(attributes['height'] ?? "");
320+
"iframe": (RenderContext context, Widget child) {
321+
final attrs = context.tree.element?.attributes;
322+
if (attrs != null) {
323+
double? width = double.tryParse(attrs['width'] ?? "");
324+
double? height = double.tryParse(attrs['height'] ?? "");
299325
return Container(
300326
width: width ?? (height ?? 150) * 2,
301327
height: height ?? (width ?? 300) / 2,
302328
child: WebView(
303-
initialUrl: attributes['src'] ?? "about:blank",
329+
initialUrl: attrs['src'] ?? "about:blank",
304330
javascriptMode: JavascriptMode.unrestricted,
305331
//no need for scrolling gesture recognizers on embedded youtube, so set gestureRecognizers null
306332
//on other iframe content scrolling might be necessary, so use VerticalDragGestureRecognizer
307-
gestureRecognizers: attributes['src'] != null && attributes['src']!.contains("youtube.com/embed") ? null : [
333+
gestureRecognizers: attrs['src'] != null && attrs['src']!.contains("youtube.com/embed") ? null : [
308334
Factory(() => VerticalDragGestureRecognizer())
309335
].toSet(),
310336
navigationDelegate: (NavigationRequest request) async {
311337
//no need to load any url besides the embedded youtube url when displaying embedded youtube, so prevent url loading
312338
//on other iframe content allow all url loading
313-
if (attributes['src'] != null && attributes['src']!.contains("youtube.com/embed")) {
339+
if (attrs['src'] != null && attrs['src']!.contains("youtube.com/embed")) {
314340
if (!request.url.contains("youtube.com/embed")) {
315341
return NavigationDecision.prevent;
316342
} else {

example/lib/main.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,19 @@ class _MyHomePageState extends State<MyHomePage> {
272272
child:
273273
(context.tree as TableLayoutElement).toWidget(context),
274274
);
275-
}
275+
},
276+
"bird": (RenderContext context, Widget child) {
277+
return TextSpan(text: "🐦");
278+
},
279+
"flutter": (RenderContext context, Widget child) {
280+
return FlutterLogo(
281+
style: (context.tree.element!.attributes['horizontal'] != null)
282+
? FlutterLogoStyle.horizontal
283+
: FlutterLogoStyle.markOnly,
284+
textColor: context.style.color!,
285+
size: context.style.fontSize!.size! * 5,
286+
);
287+
},
276288
},
277289
customImageRenders: {
278290
networkSourceMatcher(domains: ["flutter.dev"]):

pubspec.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: flutter_html
22
description: A Flutter widget rendering static HTML and CSS as Flutter widgets.
3-
version: 2.0.0-nullsafety.0
3+
version: 2.0.0-nullsafety.1
44
homepage: https://github.com/Sub6Resources/flutter_html
55

66
environment:
@@ -44,4 +44,3 @@ dev_dependencies:
4444
sdk: flutter
4545

4646
flutter:
47-

0 commit comments

Comments
 (0)