Skip to content

Commit 3e026f5

Browse files
author
Nguyen Dat
committed
rename maxLine to maxLines
2 parents b5a4516 + 4b153dd commit 3e026f5

File tree

8 files changed

+94
-79
lines changed

8 files changed

+94
-79
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/main.dart

Lines changed: 5 additions & 5 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

@@ -308,18 +305,21 @@ class _MyHomePageState extends State<MyHomePage> {
308305
print(exception);
309306
},
310307
),
308+
Text('h3 tag with maxLines = 1'),
311309
Html(
312310
data: htmlDataLines,
313311
style: {
314-
'html': Style(maxLine: 1, textOverflow: TextOverflow.ellipsis),
312+
'h3': Style(maxLines: 1, textOverflow: TextOverflow.ellipsis),
315313
},
316314
),
315+
Text('h3 tag with maxLines = 2'),
317316
Html(
318317
data: htmlDataLines,
319318
style: {
320-
'html': Style(maxLine: 2, textOverflow: TextOverflow.ellipsis),
319+
'h3': Style(maxLines: 2, textOverflow: TextOverflow.ellipsis),
321320
},
322321
),
322+
Text('h3 tag with unlimit lines'),
323323
Html(
324324
data: htmlDataLines,
325325
)

lib/flutter_html.dart

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
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_html/html_parser.dart';
517
import 'package:flutter_html/image_render.dart';
18+
import 'package:flutter_html/src/html_elements.dart';
619
import 'package:flutter_html/style.dart';
720
import 'package:webview_flutter/webview_flutter.dart';
821
import 'package:html/dom.dart' as dom;
@@ -29,7 +42,7 @@ class Html extends StatelessWidget {
2942
///
3043
/// **onImageTap** This is called whenever an image is tapped.
3144
///
32-
/// **blacklistedElements** Tag names in this array are ignored during parsing and rendering.
45+
/// **tagsList** Tag names in this array will be the only tags rendered. By default all tags are rendered.
3346
///
3447
/// **style** Pass in the style information for the Html here.
3548
/// See [its wiki page](https://github.com/Sub6Resources/flutter_html/wiki/Style) for more info.
@@ -43,7 +56,7 @@ class Html extends StatelessWidget {
4356
this.onMathError,
4457
this.shrinkWrap = false,
4558
this.onImageTap,
46-
this.blacklistedElements = const [],
59+
this.tagsList = const [],
4760
this.style = const {},
4861
this.navigationDelegateForIframe,
4962
}) : document = null,
@@ -60,7 +73,7 @@ class Html extends StatelessWidget {
6073
this.onMathError,
6174
this.shrinkWrap = false,
6275
this.onImageTap,
63-
this.blacklistedElements = const [],
76+
this.tagsList = const [],
6477
this.style = const {},
6578
this.navigationDelegateForIframe,
6679
}) : data = null,
@@ -96,7 +109,7 @@ class Html extends StatelessWidget {
96109
final OnTap? onImageTap;
97110

98111
/// A list of HTML tags that defines what elements are not rendered
99-
final List<String> blacklistedElements;
112+
final List<String> tagsList;
100113

101114
/// Either return a custom widget for specific node types or return null to
102115
/// fallback to the default rendering.
@@ -110,6 +123,13 @@ class Html extends StatelessWidget {
110123
/// to use NavigationDelegate.
111124
final NavigationDelegate? navigationDelegateForIframe;
112125

126+
static List<String> get tags => new List<String>.from(STYLED_ELEMENTS)
127+
..addAll(INTERACTABLE_ELEMENTS)
128+
..addAll(REPLACED_ELEMENTS)
129+
..addAll(LAYOUT_ELEMENTS)
130+
..addAll(TABLE_CELL_ELEMENTS)
131+
..addAll(TABLE_DEFINITION_ELEMENTS);
132+
113133
@override
114134
Widget build(BuildContext context) {
115135
final dom.Document doc = data != null ? HtmlParser.parseHTML(data!) : document!;
@@ -129,7 +149,7 @@ class Html extends StatelessWidget {
129149
imageRenders: {}
130150
..addAll(customImageRenders)
131151
..addAll(defaultImageRenders),
132-
blacklistedElements: blacklistedElements,
152+
tagsList: tagsList.isEmpty ? Html.tags : tagsList,
133153
navigationDelegateForIframe: navigationDelegateForIframe,
134154
),
135155
);

lib/html_parser.dart

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class HtmlParser extends StatelessWidget {
4343
final Map<String, Style> style;
4444
final Map<String, CustomRender> customRender;
4545
final Map<ImageSourceMatcher, ImageRender> imageRenders;
46-
final List<String> blacklistedElements;
46+
final List<String> tagsList;
4747
final NavigationDelegate? navigationDelegateForIframe;
4848

4949
HtmlParser({
@@ -56,7 +56,7 @@ class HtmlParser extends StatelessWidget {
5656
required this.style,
5757
required this.customRender,
5858
required this.imageRenders,
59-
required this.blacklistedElements,
59+
required this.tagsList,
6060
required this.navigationDelegateForIframe,
6161
});
6262

@@ -65,7 +65,7 @@ class HtmlParser extends StatelessWidget {
6565
StyledElement lexedTree = lexDomTree(
6666
htmlData,
6767
customRender.keys.toList(),
68-
blacklistedElements,
68+
tagsList,
6969
navigationDelegateForIframe,
7070
);
7171
StyledElement inlineStyledTree = applyInlineStyles(lexedTree);
@@ -113,7 +113,7 @@ class HtmlParser extends StatelessWidget {
113113
static StyledElement lexDomTree(
114114
dom.Document html,
115115
List<String> customRenderTags,
116-
List<String> blacklistedElements,
116+
List<String> tagsList,
117117
NavigationDelegate? navigationDelegateForIframe,
118118
) {
119119
StyledElement tree = StyledElement(
@@ -127,7 +127,7 @@ class HtmlParser extends StatelessWidget {
127127
tree.children.add(_recursiveLexer(
128128
node,
129129
customRenderTags,
130-
blacklistedElements,
130+
tagsList,
131131
navigationDelegateForIframe,
132132
));
133133
});
@@ -142,7 +142,7 @@ class HtmlParser extends StatelessWidget {
142142
static StyledElement _recursiveLexer(
143143
dom.Node node,
144144
List<String> customRenderTags,
145-
List<String> blacklistedElements,
145+
List<String> tagsList,
146146
NavigationDelegate? navigationDelegateForIframe,
147147
) {
148148
List<StyledElement> children = <StyledElement>[];
@@ -151,14 +151,14 @@ class HtmlParser extends StatelessWidget {
151151
children.add(_recursiveLexer(
152152
childNode,
153153
customRenderTags,
154-
blacklistedElements,
154+
tagsList,
155155
navigationDelegateForIframe,
156156
));
157157
});
158158

159159
//TODO(Sub6Resources): There's probably a more efficient way to look this up.
160160
if (node is dom.Element) {
161-
if (blacklistedElements.contains(node.localName)) {
161+
if (!tagsList.contains(node.localName)) {
162162
return EmptyContentElement();
163163
}
164164
if (STYLED_ELEMENTS.contains(node.localName)) {
@@ -800,7 +800,7 @@ class StyledText extends StatelessWidget {
800800
textAlign: style.textAlign,
801801
textDirection: style.direction,
802802
textScaleFactor: textScaleFactor,
803-
maxLines: style.maxLine,
803+
maxLines: style.maxLines,
804804
overflow: style.textOverflow,
805805
),
806806
);

lib/src/css_parser.dart

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'dart:ui';
22

3+
import 'package:collection/collection.dart';
34
import 'package:csslib/visitor.dart' as css;
45
import 'package:csslib/parser.dart' as cssparser;
56
import 'package:flutter/cupertino.dart';
@@ -70,14 +71,8 @@ Style declarationsToStyle(Map<String?, List<css.Expression>> declarations) {
7071
&& element.text != "overline" && element.text != "underline" && element.text != "line-through");
7172
List<css.Expression?>? nullableList = value;
7273
css.Expression? textDecorationColor;
73-
/// orElse: will not allow me to return null (even if the compiler says its okay, it errors on runtime).
74-
/// try/catch is a workaround for this.
75-
try {
76-
textDecorationColor = nullableList.firstWhere(
77-
(css.Expression? element) => element is css.HexColorTerm || element is css.FunctionTerm);
78-
} catch (e) {
79-
textDecorationColor = null;
80-
}
74+
textDecorationColor = nullableList.firstWhereOrNull(
75+
(element) => element is css.HexColorTerm || element is css.FunctionTerm);
8176
List<css.LiteralTerm?>? potentialStyles = value.whereType<css.LiteralTerm>().toList();
8277
/// List<css.LiteralTerm> might include other values than the ones we want for [textDecorationStyle], so make sure to remove those before passing it to [ExpressionMapping]
8378
potentialStyles.removeWhere((element) => element != null && element.text != "solid"

lib/src/utils.dart

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -49,38 +49,9 @@ class Context<T> {
4949
// This class is a workaround so that both an image
5050
// and a link can detect taps at the same time.
5151
class MultipleTapGestureRecognizer extends TapGestureRecognizer {
52-
bool _ready = false;
53-
54-
@override
55-
void addAllowedPointer(PointerDownEvent event) {
56-
if (state == GestureRecognizerState.ready) {
57-
_ready = true;
58-
}
59-
super.addAllowedPointer(event);
60-
}
61-
62-
@override
63-
void handlePrimaryPointer(PointerEvent event) {
64-
if (event is PointerCancelEvent) {
65-
_ready = false;
66-
}
67-
super.handlePrimaryPointer(event);
68-
}
69-
70-
@override
71-
void resolve(GestureDisposition disposition) {
72-
if (_ready && disposition == GestureDisposition.rejected) {
73-
_ready = false;
74-
}
75-
super.resolve(disposition);
76-
}
77-
7852
@override
7953
void rejectGesture(int pointer) {
80-
if (_ready) {
81-
acceptGesture(pointer);
82-
_ready = false;
83-
}
54+
acceptGesture(pointer);
8455
}
8556
}
8657

0 commit comments

Comments
 (0)