Skip to content

Commit 8a28f93

Browse files
committed
Merge branch 'master' of https://github.com/Sub6Resources/flutter_html into feature/improve-linking
� Conflicts: � lib/flutter_html.dart
2 parents 8dca91b + b785705 commit 8a28f93

File tree

6 files changed

+71
-23
lines changed

6 files changed

+71
-23
lines changed

README.md

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ A Flutter widget for rendering HTML and CSS as Flutter widgets.
3636
- [Constructors](#constructors)
3737

3838
- [Parameters Table](#parameters)
39+
40+
- [Getters](#getters)
3941

4042
- [Data](#data)
4143

@@ -51,7 +53,7 @@ A Flutter widget for rendering HTML and CSS as Flutter widgets.
5153

5254
- [onImageTap](#onimagetap)
5355

54-
- [blacklistedElements](#blacklistedelements)
56+
- [tagsList](#tagslist)
5557

5658
- [style](#style)
5759

@@ -161,11 +163,15 @@ If you would like to modify or sanitize the HTML before rendering it, then `Html
161163
| `omMathError` | A function that defines what the widget should do when a math fails to render. The function exposes the parsed Tex `String`, as well as the error and error with type from `flutter_math` as a `String`. |
162164
| `shrinkWrap` | A `bool` used while rendering different widgets to specify whether they should be shrink-wrapped or not, like `ContainerSpan` |
163165
| `onImageTap` | A function that defines what the widget should do when an image is tapped. The function exposes the `src` of the image as a `String` to use in your implementation. |
164-
| `blacklistedElements` | A list of elements the `Html` widget should not render. The list should contain the tags of the HTML elements you wish to blacklist. |
166+
| `tagsList` | A list of elements the `Html` widget should render. The list should contain the tags of the HTML elements you wish to include. |
165167
| `style` | A powerful API that allows you to customize the style that should be used when rendering a specific HTMl tag. |
166168
| `navigationDelegateForIframe` | Allows you to set the `NavigationDelegate` for the `WebView`s of all the iframes rendered by the `Html` widget. |
167169
| `customImageRender` | A powerful API that allows you to fully customize how images are loaded. |
168170

171+
### Getters:
172+
173+
Currently the only getter is `Html.tags`. This provides a list of all the tags the package renders. The main use case is to assist in blacklisting elements using `tagsList`. See an [example](#example-usage---tagslist---excluding-tags) below.
174+
169175
### Data:
170176

171177
The HTML data passed to the `Html` widget as a `String`. This is required and cannot be null when using `Html`.
@@ -375,25 +381,43 @@ Widget html = Html(
375381
);
376382
```
377383

378-
### blacklistedElements:
384+
### tagsList:
379385

380-
A list of elements the `Html` widget should not render. The list should contain the tags of the HTML elements you wish to blacklist.
386+
A list of elements the `Html` widget should render. The list should contain the tags of the HTML elements you wish to whitelist.
381387

382-
#### Example Usage - blacklistedElements:
388+
#### Example Usage - tagsList - Excluding Tags:
383389
You may have instances where you can choose between two different types of HTML tags to display the same content. In the example below, the `<video>` and `<iframe>` elements are going to display the same content.
384390

385391
The `blacklistedElements` parameter allows you to change which element is rendered. Iframes can be advantageous because they allow parallel loading - Flutter just has to wait for the webview to be initialized before rendering the page, possibly cutting down on load time. Video can be advantageous because it provides a 100% native experience with Flutter widgets, but it may take more time to render the page. You may know that Flutter webview is a little janky in its current state on Android, so using `blacklistedElements` and a simple condition, you can get the best of both worlds - choose the video widget to render on Android and the iframe webview to render on iOS.
392+
386393
```dart
387394
Widget html = Html(
388395
data: """
389396
<video controls>
390397
<source src="https://www.w3schools.com/html/mov_bbb.mp4" />
391398
</video>
392399
<iframe src="https://www.w3schools.com/html/mov_bbb.mp4"></iframe>""",
393-
blacklistedElements: [Platform.isAndroid ? "iframe" : "video"]
400+
tagsList: Html.tags..remove(Platform.isAndroid ? "iframe" : "video")
394401
);
395402
```
396403

404+
`Html.tags` provides easy access to a list of all the tags the package can render, and you can remove specific tags from this list to blacklist them.
405+
406+
#### Example Usage - tagsList - Allowing Tags:
407+
You may also have instances where you would only like the package to render a handful of html tags. You can do that like so:
408+
```dart
409+
Widget html = Html(
410+
data: """
411+
<p>Render this item</p>
412+
<span>Do not render this item or any other item</span>
413+
<img src='https://flutter.dev/images/flutter-mono-81x100.png'/>
414+
""",
415+
tagsList: ['p']
416+
);
417+
```
418+
419+
Here, the package will only ever render `<p>` and ignore all other tags.
420+
397421
### style:
398422

399423
A powerful API that allows you to customize the style that should be used when rendering a specific HTMl tag.

example/lib/generated_plugin_registrant.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44

55
// ignore_for_file: lines_longer_than_80_chars
66

7+
import 'package:url_launcher_web/url_launcher_web.dart';
78
import 'package:video_player_web/video_player_web.dart';
89
import 'package:wakelock_web/wakelock_web.dart';
910

1011
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
1112

1213
// ignore: public_member_api_docs
1314
void registerPlugins(Registrar registrar) {
15+
UrlLauncherPlugin.registerWith(registrar);
1416
VideoPlayerPlugin.registerWith(registrar);
1517
WakelockWeb.registerWith(registrar);
1618
registrar.registerMessageHandler();

example/lib/main.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_html/flutter_html.dart';
3-
import 'package:flutter_html/image_render.dart';
4-
import 'package:flutter_html/src/layout_element.dart';
5-
import 'package:flutter_html/style.dart';
63

74
void main() => runApp(new MyApp());
85

lib/flutter_html.dart

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
11
library flutter_html;
22

3+
//export image render api
4+
export 'package:flutter_html/image_render.dart';
5+
//export style api
6+
export 'package:flutter_html/style.dart';
7+
//export render context api
8+
export 'package:flutter_html/html_parser.dart';
9+
//export src for advanced custom render uses (e.g. casting context.tree)
10+
export 'package:flutter_html/src/layout_element.dart';
11+
export 'package:flutter_html/src/replaced_element.dart';
12+
export 'package:flutter_html/src/styled_element.dart';
13+
export 'package:flutter_html/src/interactable_element.dart';
14+
315
import 'package:flutter/material.dart';
416
import 'package:flutter/rendering.dart';
517
import 'package:flutter_html/html_parser.dart';
618
import 'package:flutter_html/image_render.dart';
19+
import 'package:flutter_html/src/html_elements.dart';
720
import 'package:flutter_html/style.dart';
821
import 'package:webview_flutter/webview_flutter.dart';
922
import 'package:html/dom.dart' as dom;
@@ -30,7 +43,7 @@ class Html extends StatelessWidget {
3043
///
3144
/// **onImageTap** This is called whenever an image is tapped.
3245
///
33-
/// **blacklistedElements** Tag names in this array are ignored during parsing and rendering.
46+
/// **tagsList** Tag names in this array will be the only tags rendered. By default all tags are rendered.
3447
///
3548
/// **style** Pass in the style information for the Html here.
3649
/// See [its wiki page](https://github.com/Sub6Resources/flutter_html/wiki/Style) for more info.
@@ -44,7 +57,7 @@ class Html extends StatelessWidget {
4457
this.onMathError,
4558
this.shrinkWrap = false,
4659
this.onImageTap,
47-
this.blacklistedElements = const [],
60+
this.tagsList = const [],
4861
this.style = const {},
4962
this.navigationDelegateForIframe,
5063
}) : document = null,
@@ -62,7 +75,7 @@ class Html extends StatelessWidget {
6275
this.onMathError,
6376
this.shrinkWrap = false,
6477
this.onImageTap,
65-
this.blacklistedElements = const [],
78+
this.tagsList = const [],
6679
this.style = const {},
6780
this.navigationDelegateForIframe,
6881
}) : data = null,
@@ -102,7 +115,7 @@ class Html extends StatelessWidget {
102115
final OnTap? onImageTap;
103116

104117
/// A list of HTML tags that defines what elements are not rendered
105-
final List<String> blacklistedElements;
118+
final List<String> tagsList;
106119

107120
/// Either return a custom widget for specific node types or return null to
108121
/// fallback to the default rendering.
@@ -116,6 +129,13 @@ class Html extends StatelessWidget {
116129
/// to use NavigationDelegate.
117130
final NavigationDelegate? navigationDelegateForIframe;
118131

132+
static List<String> get tags => new List<String>.from(STYLED_ELEMENTS)
133+
..addAll(INTERACTABLE_ELEMENTS)
134+
..addAll(REPLACED_ELEMENTS)
135+
..addAll(LAYOUT_ELEMENTS)
136+
..addAll(TABLE_CELL_ELEMENTS)
137+
..addAll(TABLE_DEFINITION_ELEMENTS);
138+
119139
@override
120140
Widget build(BuildContext context) {
121141
final dom.Document doc = data != null ? HtmlParser.parseHTML(data!) : document!;
@@ -133,8 +153,10 @@ class Html extends StatelessWidget {
133153
shrinkWrap: shrinkWrap,
134154
style: style,
135155
customRender: customRender,
136-
imageRenders: {}..addAll(customImageRenders)..addAll(defaultImageRenders),
137-
blacklistedElements: blacklistedElements,
156+
imageRenders: {}
157+
..addAll(customImageRenders)
158+
..addAll(defaultImageRenders),
159+
tagsList: tagsList.isEmpty ? Html.tags : tagsList,
138160
navigationDelegateForIframe: navigationDelegateForIframe,
139161
),
140162
);

lib/html_parser.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class HtmlParser extends StatelessWidget {
4545
final Map<String, Style> style;
4646
final Map<String, CustomRender> customRender;
4747
final Map<ImageSourceMatcher, ImageRender> imageRenders;
48-
final List<String> blacklistedElements;
48+
final List<String> tagsList;
4949
final NavigationDelegate? navigationDelegateForIframe;
5050
final OnTap? _onAnchorTap;
5151

@@ -60,7 +60,7 @@ class HtmlParser extends StatelessWidget {
6060
required this.style,
6161
required this.customRender,
6262
required this.imageRenders,
63-
required this.blacklistedElements,
63+
required this.tagsList,
6464
required this.navigationDelegateForIframe,
6565
}): this._onAnchorTap = key != null ? _handleAnchorTap(key, onLinkTap): null, super(key: key);
6666

@@ -69,7 +69,7 @@ class HtmlParser extends StatelessWidget {
6969
StyledElement lexedTree = lexDomTree(
7070
htmlData,
7171
customRender.keys.toList(),
72-
blacklistedElements,
72+
tagsList,
7373
navigationDelegateForIframe,
7474
);
7575
StyledElement inlineStyledTree = applyInlineStyles(lexedTree);
@@ -117,7 +117,7 @@ class HtmlParser extends StatelessWidget {
117117
static StyledElement lexDomTree(
118118
dom.Document html,
119119
List<String> customRenderTags,
120-
List<String> blacklistedElements,
120+
List<String> tagsList,
121121
NavigationDelegate? navigationDelegateForIframe,
122122
) {
123123
StyledElement tree = StyledElement(
@@ -131,7 +131,7 @@ class HtmlParser extends StatelessWidget {
131131
tree.children.add(_recursiveLexer(
132132
node,
133133
customRenderTags,
134-
blacklistedElements,
134+
tagsList,
135135
navigationDelegateForIframe,
136136
));
137137
});
@@ -146,7 +146,7 @@ class HtmlParser extends StatelessWidget {
146146
static StyledElement _recursiveLexer(
147147
dom.Node node,
148148
List<String> customRenderTags,
149-
List<String> blacklistedElements,
149+
List<String> tagsList,
150150
NavigationDelegate? navigationDelegateForIframe,
151151
) {
152152
List<StyledElement> children = <StyledElement>[];
@@ -155,14 +155,14 @@ class HtmlParser extends StatelessWidget {
155155
children.add(_recursiveLexer(
156156
childNode,
157157
customRenderTags,
158-
blacklistedElements,
158+
tagsList,
159159
navigationDelegateForIframe,
160160
));
161161
});
162162

163163
//TODO(Sub6Resources): There's probably a more efficient way to look this up.
164164
if (node is dom.Element) {
165-
if (blacklistedElements.contains(node.localName)) {
165+
if (!tagsList.contains(node.localName)) {
166166
return EmptyContentElement();
167167
}
168168
if (STYLED_ELEMENTS.contains(node.localName)) {

lib/style.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,9 @@ class Style {
307307
listStyleType: child.listStyleType ?? listStyleType,
308308
listStylePosition: child.listStylePosition ?? listStylePosition,
309309
textAlign: child.textAlign ?? textAlign,
310+
textDecoration: TextDecoration.combine(
311+
[child.textDecoration ?? TextDecoration.none,
312+
textDecoration ?? TextDecoration.none]),
310313
textShadow: child.textShadow ?? textShadow,
311314
whiteSpace: child.whiteSpace ?? whiteSpace,
312315
wordSpacing: child.wordSpacing ?? wordSpacing,

0 commit comments

Comments
 (0)