Skip to content

Release 2.2.0 #909

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Dec 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
1a1b331
Added multiplatform support (pub.dev badges)
SergeShkurko Oct 23, 2021
9cc8a56
Prevent crash on empty <table> tags; fixes #893
erickok Nov 26, 2021
39d94b0
Merge remote-tracking branch 'upstream/master' into everything
erickok Nov 26, 2021
a81ba31
Fix merge conflict in list markers
erickok Nov 26, 2021
3da05e5
Fix whitespace rendering between list items; fixes #878
erickok Nov 26, 2021
06912e8
Merge branch 'bugfix/878-list-item-whitespace' into everything
erickok Nov 26, 2021
f2b80b1
Handle tables with both colspan and rowspan properly; fixes #889
erickok Nov 26, 2021
7c2c99f
Merge branch 'bugfix/889-irregular-tables' into everything
erickok Nov 26, 2021
2523233
Fix crashing on negative margins (which we do not support); fixes #838
erickok Nov 26, 2021
33242a5
Merge branch 'bugfix/838-negative-margins' into everything
erickok Nov 26, 2021
974933e
Merge remote-tracking branch 'tneotia/feature/scroll-physics' into ev…
erickok Nov 29, 2021
46006b9
Merge remote-tracking branch 'tneotia/bugfix/784-nested-header-font' …
erickok Nov 29, 2021
7fd6fb4
Merge remote-tracking branch 'tneotia/feature/text-transform' into ev…
erickok Nov 29, 2021
ab2266e
Prepare 2.2.0 release
erickok Nov 29, 2021
5026bb3
Merge remote-tracking branch 'upstream/master' into feature/release-216
erickok Nov 29, 2021
31eeeff
Merge remote-tracking branch 'upstream/master' into feature/multiplat…
erickok Nov 29, 2021
e1db945
Merge branch 'feature/multiplatform-support' into feature/release-216
erickok Nov 29, 2021
aec5e5e
Merge remote-tracking branch 'upstream/master' into feature/release-216
erickok Nov 29, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## [2.2.0] - November 29, 2021:
* Explicitly declare multiplatform support
* Extended and fixed list-style (marker) support
* Basic support for height/width css properties
* Support changing scroll physics of SelectableText.rich
* Support text transform css property
* Bumped minimum flutter_math_fork version for Flutter 2.5 compatibility
* Fix styling of iframes
* Fix nested font tag application
* Fix whitespace rendering between list items
* Prevent crash on empty <table> tag and tables with both colspan/rowspan
* Prevent crash on use of negative margins in css

## [2.1.5] - October 7, 2021:
* Ignore unsupported custom style selectors when using fromCss
* Fix SVG tag usage inside tables
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ A Flutter widget for rendering HTML and CSS as Flutter widgets.
Add the following to your `pubspec.yaml` file:

dependencies:
flutter_html: ^2.1.5
flutter_html: ^2.2.0

## Currently Supported HTML Tags:
| | | | | | | | | | | |
Expand Down
3 changes: 2 additions & 1 deletion lib/flutter_html.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:flutter_html/image_render.dart';
import 'package:flutter_html/src/html_elements.dart';
import 'package:flutter_html/style.dart';
import 'package:html/dom.dart' as dom;
import 'package:webview_flutter/webview_flutter.dart';
import 'package:flutter_html/src/navigation_delegate.dart';

//export render context api
export 'package:flutter_html/html_parser.dart';
Expand All @@ -18,6 +18,7 @@ export 'package:flutter_html/src/interactable_element.dart';
export 'package:flutter_html/src/layout_element.dart';
export 'package:flutter_html/src/replaced_element.dart';
export 'package:flutter_html/src/styled_element.dart';
export 'package:flutter_html/src/navigation_delegate.dart';
//export style api
export 'package:flutter_html/style.dart';

Expand Down
7 changes: 3 additions & 4 deletions lib/html_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import 'package:flutter_html/src/anchor.dart';
import 'package:flutter_html/src/css_parser.dart';
import 'package:flutter_html/src/html_elements.dart';
import 'package:flutter_html/src/layout_element.dart';
import 'package:flutter_html/src/navigation_delegate.dart';
import 'package:flutter_html/src/utils.dart';
import 'package:flutter_html/style.dart';
import 'package:html/dom.dart' as dom;
import 'package:html/parser.dart' as htmlparser;
import 'package:numerus/numerus.dart';
import 'package:webview_flutter/webview_flutter.dart';

typedef OnTap = void Function(
String? url,
Expand Down Expand Up @@ -737,7 +737,6 @@ class HtmlParser extends StatelessWidget {
String marker = "";
switch (tree.style.listStyleType!) {
case ListStyleType.NONE:
tree.style.markerContent = '';
break;
case ListStyleType.CIRCLE:
marker = '○';
Expand Down Expand Up @@ -959,7 +958,7 @@ class HtmlParser extends StatelessWidget {
if (child is EmptyContentElement || child is EmptyLayoutElement) {
toRemove.add(child);
} else if (child is TextContentElement
&& tree.name == "body"
&& (tree.name == "body" || tree.name == "ul")
&& child.text!.replaceAll(' ', '').isEmpty) {
toRemove.add(child);
} else if (child is TextContentElement
Expand Down Expand Up @@ -1054,7 +1053,7 @@ class ContainerSpan extends StatelessWidget {
height: style.height,
width: style.width,
padding: style.padding,
margin: style.margin,
margin: style.margin?.clamp(EdgeInsets.zero, const EdgeInsets.all(double.infinity)),
alignment: shrinkWrap ? null : style.alignment,
child: child ??
StyledText(
Expand Down
15 changes: 11 additions & 4 deletions lib/src/layout_element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,19 @@ class TableLayoutElement extends LayoutElement {
// Place the cells in the rows/columns
final cells = <GridPlacement>[];
final columnRowOffset = List.generate(columnMax, (_) => 0);
final columnColspanOffset = List.generate(columnMax, (_) => 0);
int rowi = 0;
for (var row in rows) {
int columni = 0;
for (var child in row.children) {
if (columni > columnMax - 1 ) {
break;
}
while (columnRowOffset[columni] > 0) {
columnRowOffset[columni] = columnRowOffset[columni] - 1;
columni++;
}
if (child is TableCellElement) {
while (columnRowOffset[columni] > 0) {
columnRowOffset[columni] = columnRowOffset[columni] - 1;
columni += columnColspanOffset[columni].clamp(1, columnMax - columni - 1);
}
cells.add(GridPlacement(
child: Container(
width: double.infinity,
Expand Down Expand Up @@ -139,6 +140,7 @@ class TableLayoutElement extends LayoutElement {
rowSpan: min(child.rowspan, rows.length - rowi),
));
columnRowOffset[columni] = child.rowspan - 1;
columnColspanOffset[columni] = child.colspan;
columni += child.colspan;
}
}
Expand All @@ -155,6 +157,11 @@ class TableLayoutElement extends LayoutElement {
max(0, columnMax - finalColumnSizes.length),
(_) => IntrinsicContentTrackSize());

if (finalColumnSizes.isEmpty || rowSizes.isEmpty) {
// No actual cells to show
return SizedBox();
}

return LayoutGrid(
gridFit: GridFit.loose,
columnSizes: finalColumnSizes,
Expand Down
35 changes: 35 additions & 0 deletions lib/src/navigation_delegate.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'dart:async';

/// Information about a navigation action that is about to be executed.
class NavigationRequest {
NavigationRequest({required this.url, required this.isForMainFrame});

/// The URL that will be loaded if the navigation is executed.
final String url;

/// Whether the navigation request is to be loaded as the main frame.
final bool isForMainFrame;

@override
String toString() {
return '$runtimeType(url: $url, isForMainFrame: $isForMainFrame)';
}
}

/// A decision on how to handle a navigation request.
enum NavigationDecision {
/// Prevent the navigation from taking place.
prevent,

/// Allow the navigation to take place.
navigate,
}

/// Decides how to handle a specific navigation request.
///
/// The returned [NavigationDecision] determines how the navigation described by
/// `navigation` should be handled.
///
/// See also: [WebView.navigationDelegate].
typedef FutureOr<NavigationDecision> NavigationDelegate(
NavigationRequest navigation);
2 changes: 1 addition & 1 deletion lib/src/replaced_element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_html/html_parser.dart';
import 'package:flutter_html/src/anchor.dart';
import 'package:flutter_html/src/html_elements.dart';
import 'package:flutter_html/src/navigation_delegate.dart';
import 'package:flutter_html/src/utils.dart';
import 'package:flutter_html/src/widgets/iframe_unsupported.dart'
if (dart.library.io) 'package:flutter_html/src/widgets/iframe_mobile.dart'
Expand All @@ -16,7 +17,6 @@ import 'package:flutter_math_fork/flutter_math.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:html/dom.dart' as dom;
import 'package:video_player/video_player.dart';
import 'package:webview_flutter/webview_flutter.dart';

/// A [ReplacedElement] is a type of [StyledElement] that does not require its [children] to be rendered.
///
Expand Down
21 changes: 16 additions & 5 deletions lib/src/widgets/iframe_mobile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/html_parser.dart';
import 'package:flutter_html/src/navigation_delegate.dart';
import 'package:flutter_html/src/replaced_element.dart';
import 'package:flutter_html/style.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter/webview_flutter.dart' as webview;
import 'package:html/dom.dart' as dom;

/// [IframeContentElement is a [ReplacedElement] with web content.
Expand Down Expand Up @@ -33,13 +34,23 @@ class IframeContentElement extends ReplacedElement {
child: ContainerSpan(
style: context.style,
newContext: context,
child: WebView(
child: webview.WebView(
initialUrl: src,
key: key,
javascriptMode: sandboxMode == null || sandboxMode == "allow-scripts"
? JavascriptMode.unrestricted
: JavascriptMode.disabled,
navigationDelegate: navigationDelegate,
? webview.JavascriptMode.unrestricted
: webview.JavascriptMode.disabled,
navigationDelegate: (request) async {
final result = await navigationDelegate!(NavigationRequest(
url: request.url,
isForMainFrame: request.isForMainFrame,
));
if (result == NavigationDecision.prevent) {
return webview.NavigationDecision.prevent;
} else {
return webview.NavigationDecision.navigate;
}
},
gestureRecognizers: {
Factory<VerticalDragGestureRecognizer>(() => VerticalDragGestureRecognizer())
},
Expand Down
4 changes: 2 additions & 2 deletions lib/src/widgets/iframe_unsupported.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_html/html_parser.dart';
import 'package:flutter_html/src/navigation_delegate.dart';
import 'package:flutter_html/src/replaced_element.dart';
import 'package:flutter_html/style.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:html/dom.dart' as dom;

/// [IframeContentElement is a [ReplacedElement] with web content.
Expand Down Expand Up @@ -30,4 +30,4 @@ class IframeContentElement extends ReplacedElement {
child: Text("Iframes are currently not supported in this environment"),
);
}
}
}
2 changes: 1 addition & 1 deletion lib/src/widgets/iframe_web.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_html/html_parser.dart';
import 'package:flutter_html/shims/dart_ui.dart' as ui;
import 'package:flutter_html/src/navigation_delegate.dart';
import 'package:flutter_html/src/replaced_element.dart';
import 'package:flutter_html/src/utils.dart';
import 'package:flutter_html/style.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:html/dom.dart' as dom;
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html;
Expand Down
15 changes: 1 addition & 14 deletions lib/style.dart
Original file line number Diff line number Diff line change
Expand Up @@ -548,20 +548,7 @@ class ListStyleType {
static const LOWER_ROMAN = ListStyleType("LOWER_ROMAN");
static const UPPER_ROMAN = ListStyleType("UPPER_ROMAN");
static const SQUARE = ListStyleType("SQUARE");
}

enum ListStyleType {
LOWER_ALPHA,
UPPER_ALPHA,
LOWER_LATIN,
UPPER_LATIN,
CIRCLE,
DISC,
DECIMAL,
LOWER_ROMAN,
UPPER_ROMAN,
SQUARE,
NONE,
static const NONE = ListStyleType("NONE");
}

enum ListStylePosition {
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: flutter_html
description: A Flutter widget rendering static HTML and CSS as Flutter widgets.
version: 2.1.5
version: 2.2.0
homepage: https://github.com/Sub6Resources/flutter_html

environment:
Expand Down