From 8b0d76a1a167cfd635fdf8d9732091c184d349fd Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Mon, 17 Mar 2025 05:06:22 +0700 Subject: [PATCH 1/4] `void flatten(Flattened f) {` --- packages/core/lib/src/internal/core_build_tree.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/lib/src/internal/core_build_tree.dart b/packages/core/lib/src/internal/core_build_tree.dart index ef067714e..1e9ce690b 100644 --- a/packages/core/lib/src/internal/core_build_tree.dart +++ b/packages/core/lib/src/internal/core_build_tree.dart @@ -154,7 +154,7 @@ class CoreBuildTree extends BuildTree { } @override - void flatten(Flattened _) { + void flatten(Flattened f) { final scopedBuildOps = _buildOps; if (scopedBuildOps != null) { for (final op in scopedBuildOps) { From a3d262ae9264de2aee0628da5db4ecb70e21cd0d Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Mon, 17 Mar 2025 05:08:16 +0700 Subject: [PATCH 2/4] Replace Codecov badge with SonarCloud's --- README.md | 2 +- packages/core/README.md | 2 +- packages/enhanced/README.md | 2 +- packages/fwfh_cached_network_image/README.md | 2 +- packages/fwfh_chewie/README.md | 2 +- packages/fwfh_just_audio/README.md | 2 +- packages/fwfh_svg/README.md | 2 +- packages/fwfh_url_launcher/README.md | 2 +- packages/fwfh_webview/README.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 2cf4a933e..5731675aa 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # HtmlWidget monorepo [![Flutter](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml/badge.svg)](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml) -[![codecov](https://codecov.io/gh/daohoangson/flutter_widget_from_html/branch/master/graph/badge.svg)](https://codecov.io/gh/daohoangson/flutter_widget_from_html) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=daohoangson_flutter_widget_from_html&metric=coverage)](https://sonarcloud.io/summary/new_code?id=daohoangson_flutter_widget_from_html) This repo contains the source code for everything `HtmlWidget`-related. diff --git a/packages/core/README.md b/packages/core/README.md index 8665350eb..06c540730 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -1,7 +1,7 @@ # Flutter Widget from HTML (core) [![Flutter](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml/badge.svg)](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml) -[![codecov](https://codecov.io/gh/daohoangson/flutter_widget_from_html/branch/master/graph/badge.svg)](https://codecov.io/gh/daohoangson/flutter_widget_from_html) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=daohoangson_flutter_widget_from_html&metric=coverage)](https://sonarcloud.io/summary/new_code?id=daohoangson_flutter_widget_from_html) [![Pub](https://img.shields.io/pub/v/flutter_widget_from_html_core.svg)](https://pub.dev/packages/flutter_widget_from_html_core) Flutter package to render html as widgets that focuses on correctness and extensibility. diff --git a/packages/enhanced/README.md b/packages/enhanced/README.md index b229755fb..6efaba4c3 100644 --- a/packages/enhanced/README.md +++ b/packages/enhanced/README.md @@ -1,7 +1,7 @@ # Flutter Widget from HTML [![Flutter](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml/badge.svg)](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml) -[![codecov](https://codecov.io/gh/daohoangson/flutter_widget_from_html/branch/master/graph/badge.svg)](https://codecov.io/gh/daohoangson/flutter_widget_from_html) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=daohoangson_flutter_widget_from_html&metric=coverage)](https://sonarcloud.io/summary/new_code?id=daohoangson_flutter_widget_from_html) [![Pub](https://img.shields.io/pub/v/flutter_widget_from_html.svg)](https://pub.dev/packages/flutter_widget_from_html) Flutter package to render html as widgets that supports hyperlink, image, audio, video, iframe diff --git a/packages/fwfh_cached_network_image/README.md b/packages/fwfh_cached_network_image/README.md index 7186f83b6..89b4ad387 100644 --- a/packages/fwfh_cached_network_image/README.md +++ b/packages/fwfh_cached_network_image/README.md @@ -1,7 +1,7 @@ # CachedNetworkImageFactory [![Flutter](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml/badge.svg)](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml) -[![codecov](https://codecov.io/gh/daohoangson/flutter_widget_from_html/branch/master/graph/badge.svg)](https://codecov.io/gh/daohoangson/flutter_widget_from_html) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=daohoangson_flutter_widget_from_html&metric=coverage)](https://sonarcloud.io/summary/new_code?id=daohoangson_flutter_widget_from_html) [![Pub](https://img.shields.io/pub/v/fwfh_cached_network_image.svg)](https://pub.dev/packages/fwfh_cached_network_image) WidgetFactory extension to render IMG with [cached_network_image](https://pub.dev/packages/cached_network_image) plugin. diff --git a/packages/fwfh_chewie/README.md b/packages/fwfh_chewie/README.md index 5c47beda3..4dc95c1cf 100644 --- a/packages/fwfh_chewie/README.md +++ b/packages/fwfh_chewie/README.md @@ -1,7 +1,7 @@ # ChewieFactory [![Flutter](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml/badge.svg)](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml) -[![codecov](https://codecov.io/gh/daohoangson/flutter_widget_from_html/branch/master/graph/badge.svg)](https://codecov.io/gh/daohoangson/flutter_widget_from_html) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=daohoangson_flutter_widget_from_html&metric=coverage)](https://sonarcloud.io/summary/new_code?id=daohoangson_flutter_widget_from_html) [![Pub](https://img.shields.io/pub/v/fwfh_chewie.svg)](https://pub.dev/packages/fwfh_chewie) WidgetFactory extension to render VIDEO with the [chewie](https://pub.dev/packages/chewie) plugin. diff --git a/packages/fwfh_just_audio/README.md b/packages/fwfh_just_audio/README.md index 8e7a41e17..0f457ee79 100644 --- a/packages/fwfh_just_audio/README.md +++ b/packages/fwfh_just_audio/README.md @@ -1,7 +1,7 @@ # JustAudioFactory [![Flutter](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml/badge.svg)](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml) -[![codecov](https://codecov.io/gh/daohoangson/flutter_widget_from_html/branch/master/graph/badge.svg)](https://codecov.io/gh/daohoangson/flutter_widget_from_html) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=daohoangson_flutter_widget_from_html&metric=coverage)](https://sonarcloud.io/summary/new_code?id=daohoangson_flutter_widget_from_html) [![Pub](https://img.shields.io/pub/v/fwfh_just_audio.svg)](https://pub.dev/packages/fwfh_just_audio) WidgetFactory extension to render AUDIO with the [just_audio](https://pub.dev/packages/just_audio) plugin. diff --git a/packages/fwfh_svg/README.md b/packages/fwfh_svg/README.md index 1e6a0a679..6ae9c6966 100644 --- a/packages/fwfh_svg/README.md +++ b/packages/fwfh_svg/README.md @@ -1,7 +1,7 @@ # SvgFactory [![Flutter](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml/badge.svg)](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml) -[![codecov](https://codecov.io/gh/daohoangson/flutter_widget_from_html/branch/master/graph/badge.svg)](https://codecov.io/gh/daohoangson/flutter_widget_from_html) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=daohoangson_flutter_widget_from_html&metric=coverage)](https://sonarcloud.io/summary/new_code?id=daohoangson_flutter_widget_from_html) [![Pub](https://img.shields.io/pub/v/fwfh_svg.svg)](https://pub.dev/packages/fwfh_svg) WidgetFactory extension to render SVG with [flutter_svg](https://pub.dev/packages/flutter_svg) plugin. diff --git a/packages/fwfh_url_launcher/README.md b/packages/fwfh_url_launcher/README.md index b69f48b5c..f20f138b7 100644 --- a/packages/fwfh_url_launcher/README.md +++ b/packages/fwfh_url_launcher/README.md @@ -1,7 +1,7 @@ # UrlLauncherFactory [![Flutter](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml/badge.svg)](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml) -[![codecov](https://codecov.io/gh/daohoangson/flutter_widget_from_html/branch/master/graph/badge.svg)](https://codecov.io/gh/daohoangson/flutter_widget_from_html) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=daohoangson_flutter_widget_from_html&metric=coverage)](https://sonarcloud.io/summary/new_code?id=daohoangson_flutter_widget_from_html) [![Pub](https://img.shields.io/pub/v/fwfh_url_launcher.svg)](https://pub.dev/packages/fwfh_url_launcher) WidgetFactory extension to launch A tag via [url_launcher](https://pub.dev/packages/url_launcher) plugin. diff --git a/packages/fwfh_webview/README.md b/packages/fwfh_webview/README.md index 84a382fec..3a56fcdcc 100644 --- a/packages/fwfh_webview/README.md +++ b/packages/fwfh_webview/README.md @@ -1,7 +1,7 @@ # WebViewFactory [![Flutter](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml/badge.svg)](https://github.com/daohoangson/flutter_widget_from_html/actions/workflows/flutter.yml) -[![codecov](https://codecov.io/gh/daohoangson/flutter_widget_from_html/branch/master/graph/badge.svg)](https://codecov.io/gh/daohoangson/flutter_widget_from_html) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=daohoangson_flutter_widget_from_html&metric=coverage)](https://sonarcloud.io/summary/new_code?id=daohoangson_flutter_widget_from_html) [![Pub](https://img.shields.io/pub/v/fwfh_webview.svg)](https://pub.dev/packages/fwfh_webview) WidgetFactory extension to render IFRAME with the official WebView plugin. From 20c9bb925e0ab5ceb4d064ec186f3db723511067 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Mon, 17 Mar 2025 05:28:41 +0700 Subject: [PATCH 3/4] Extract this nested ternary operation into an independent statement --- packages/core/lib/src/core_helpers.dart | 16 +++++--- packages/core/lib/src/core_html_widget.dart | 15 +++++--- packages/core/lib/src/data/css.dart | 21 +++++----- .../lib/src/internal/margin_vertical.dart | 7 +++- .../core/lib/src/internal/ops/tag_li.dart | 25 ++++++++---- .../core/lib/src/internal/ops/tag_table.dart | 21 +++++----- .../core/lib/src/internal/parser/color.dart | 38 ++++++++++++------- 7 files changed, 88 insertions(+), 55 deletions(-) diff --git a/packages/core/lib/src/core_helpers.dart b/packages/core/lib/src/core_helpers.dart index 25cb3221e..79b99ccd9 100644 --- a/packages/core/lib/src/core_helpers.dart +++ b/packages/core/lib/src/core_helpers.dart @@ -189,13 +189,17 @@ Uint8List? bytesFromDataUri(String dataUri) { final prefix = match[0]!; final encoding = match[1]; final data = dataUri.substring(prefix.length); - final bytes = encoding == 'base64' - ? base64.decode(data) - : encoding == 'utf8' - ? Uint8List.fromList(data.codeUnits) - : null; - return bytes?.isNotEmpty == true ? bytes : null; + final Uint8List bytes; + if (encoding == 'base64') { + bytes = base64.decode(data); + } else if (encoding == 'utf8') { + bytes = Uint8List.fromList(data.codeUnits); + } else { + return null; + } + + return bytes.isNotEmpty == true ? bytes : null; } /// Parses [key] from [map] as an double literal and return its value. diff --git a/packages/core/lib/src/core_html_widget.dart b/packages/core/lib/src/core_html_widget.dart index b60546cc6..ad1cb43bf 100644 --- a/packages/core/lib/src/core_html_widget.dart +++ b/packages/core/lib/src/core_html_widget.dart @@ -261,12 +261,15 @@ class HtmlWidgetState extends State { return built; } - Widget _sliverToBoxAdapterIfNeeded(Widget child) => - widget.renderMode == RenderMode.sliverList - ? child == widget0 - ? const SliverToBoxAdapter(child: widget0) - : SliverToBoxAdapter(child: child) - : child; + Widget _sliverToBoxAdapterIfNeeded(Widget child) { + if (widget.renderMode != RenderMode.sliverList) { + return child; + } + + return child == widget0 + ? const SliverToBoxAdapter(child: widget0) + : SliverToBoxAdapter(child: child); + } Widget _wrapper(Widget child) => _RootWidget(resolved: _rootProperties, child: child); diff --git a/packages/core/lib/src/data/css.dart b/packages/core/lib/src/data/css.dart index 18f2ae78e..aecac0608 100644 --- a/packages/core/lib/src/data/css.dart +++ b/packages/core/lib/src/data/css.dart @@ -217,15 +217,18 @@ class CssBorderSide { } static CssBorderSide? _copyWith(CssBorderSide? base, CssBorderSide? value) { - final copied = base == null || value == none - ? value - : value == null - ? base - : CssBorderSide( - color: value.color ?? base.color, - style: value.style ?? base.style, - width: value.width ?? base.width, - ); + final CssBorderSide? copied; + if (base == null || value == none) { + copied = value; + } else if (value == null) { + copied = base; + } else { + copied = CssBorderSide( + color: value.color ?? base.color, + style: value.style ?? base.style, + width: value.width ?? base.width, + ); + } if (copied?.isNoOp == true) { return none; diff --git a/packages/core/lib/src/internal/margin_vertical.dart b/packages/core/lib/src/internal/margin_vertical.dart index 36daf6e64..950d82c43 100644 --- a/packages/core/lib/src/internal/margin_vertical.dart +++ b/packages/core/lib/src/internal/margin_vertical.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flutter/widgets.dart'; import '../core_data.dart'; @@ -65,8 +67,9 @@ extension SkipBuildHeightPlaceholder on BuildContext { /// This type of placeholder has special merging logic so they need /// to be preserved during column contents traversal. set skipBuildHeightPlaceholder(bool newValue) { - final v = _skipBuildOrZero; - _skipBuild[this] = newValue ? (v + 1) : (v > 0 ? v - 1 : 0); + final delta = newValue ? 1 : -1; + final newCounter = _skipBuildOrZero + delta; + _skipBuild[this] = max(0, newCounter); } int get _skipBuildOrZero => _skipBuild[this] ?? 0; diff --git a/packages/core/lib/src/internal/ops/tag_li.dart b/packages/core/lib/src/internal/ops/tag_li.dart index 048836d9d..9ee04a9d4 100644 --- a/packages/core/lib/src/internal/ops/tag_li.dart +++ b/packages/core/lib/src/internal/ops/tag_li.dart @@ -91,14 +91,23 @@ class TagLi { static StylesMap _defaultStyles(dom.Element element) { final attrs = element.attributes; final depth = element.elementDepth; - final listStyleType = element.localName == kTagOrderedList - ? (_listStyleTypeFromAttributeType(attrs[kAttributeLiType] ?? '') ?? - kCssListStyleTypeDecimal) - : depth == 0 - ? kCssListStyleTypeDisc - : depth == 1 - ? kCssListStyleTypeCircle - : kCssListStyleTypeSquare; + + final String listStyleType; + if (element.localName == kTagOrderedList) { + listStyleType = + _listStyleTypeFromAttributeType(attrs[kAttributeLiType] ?? '') ?? + kCssListStyleTypeDecimal; + } else { + switch (depth) { + case 0: + listStyleType = kCssListStyleTypeDisc; + case 1: + listStyleType = kCssListStyleTypeCircle; + default: + listStyleType = kCssListStyleTypeSquare; + } + } + return { kCssDisplay: kCssDisplayBlock, kCssListStyleType: listStyleType, diff --git a/packages/core/lib/src/internal/ops/tag_table.dart b/packages/core/lib/src/internal/ops/tag_table.dart index e34faa603..55ec640ce 100644 --- a/packages/core/lib/src/internal/ops/tag_table.dart +++ b/packages/core/lib/src/internal/ops/tag_table.dart @@ -156,13 +156,10 @@ class TagTable { } final columnSpan = cell.columnSpan > 0 ? cell.columnSpan : 1; + final rowSpanDefault = cell.rowSpan == 0 ? group.rows.length : 1; final rowSpan = min( rowSpanMax, - cell.rowSpan > 0 - ? cell.rowSpan - : cell.rowSpan == 0 - ? group.rows.length - : 1, + cell.rowSpan > 0 ? cell.rowSpan : rowSpanDefault, ); final builderIndex = data.builders.length; @@ -310,11 +307,15 @@ class TagTable { case kCssDisplayTableHeaderGroup: case kCssDisplayTableRowGroup: case kCssDisplayTableFooterGroup: - final group = which == kCssDisplayTableHeaderGroup - ? data.header - : which == kCssDisplayTableRowGroup - ? data.newBody() - : data.footer; + final _TagTableRowGroup group; + switch (which) { + case kCssDisplayTableHeaderGroup: + group = data.header; + case kCssDisplayTableRowGroup: + group = data.newBody(); + default: + group = data.footer; + } subTree.register(group._groupOp); case kCssDisplayTableRow: subTree.register(data.newBody().newRow()._rowOp); diff --git a/packages/core/lib/src/internal/parser/color.dart b/packages/core/lib/src/internal/parser/color.dart index 12d589eec..acd14df8e 100644 --- a/packages/core/lib/src/internal/parser/color.dart +++ b/packages/core/lib/src/internal/parser/color.dart @@ -15,20 +15,30 @@ CssColor? tryParseColor(css.Expression? expression) { case 'hsla': final params = expression.params; if (params.length >= 3) { - final param0 = params[0]; - final h = param0 is css.NumberTerm - ? _parseColorHue(param0.number) - : param0 is css.AngleTerm - ? _parseColorHue(param0.angle, param0.unit) - : null; - final param1 = params[1]; - final s = param1 is css.PercentageTerm - ? param1.valueAsDouble.clamp(0.0, 1.0) - : null; - final param2 = params[2]; - final l = param2 is css.PercentageTerm - ? param2.valueAsDouble.clamp(0.0, 1.0) - : null; + final [param0, param1, param2] = params; + final double? h; + if (param0 is css.NumberTerm) { + h = _parseColorHue(param0.number); + } else if (param0 is css.AngleTerm) { + h = _parseColorHue(param0.angle, param0.unit); + } else { + h = null; + } + + final double? s; + if (param1 is css.PercentageTerm) { + s = param1.valueAsDouble.clamp(0.0, 1.0); + } else { + s = null; + } + + final double? l; + if (param2 is css.PercentageTerm) { + l = param2.valueAsDouble.clamp(0.0, 1.0); + } else { + l = null; + } + final hslA = params.length >= 4 ? _parseColorAlpha(params[3]) : 1.0; if (h != null && s != null && l != null && hslA != null) { final hslValue = HSLColor.fromAHSL(hslA, h, s, l).toColor(); From 5e74a278a03bf72fc90d2872e4dfefcf6bd342b1 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Mon, 17 Mar 2025 05:39:49 +0700 Subject: [PATCH 4/4] Fix tests --- packages/core/lib/src/internal/parser/color.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/lib/src/internal/parser/color.dart b/packages/core/lib/src/internal/parser/color.dart index acd14df8e..cd95dbbf3 100644 --- a/packages/core/lib/src/internal/parser/color.dart +++ b/packages/core/lib/src/internal/parser/color.dart @@ -15,7 +15,7 @@ CssColor? tryParseColor(css.Expression? expression) { case 'hsla': final params = expression.params; if (params.length >= 3) { - final [param0, param1, param2] = params; + final param0 = params[0]; final double? h; if (param0 is css.NumberTerm) { h = _parseColorHue(param0.number); @@ -25,6 +25,7 @@ CssColor? tryParseColor(css.Expression? expression) { h = null; } + final param1 = params[1]; final double? s; if (param1 is css.PercentageTerm) { s = param1.valueAsDouble.clamp(0.0, 1.0); @@ -32,6 +33,7 @@ CssColor? tryParseColor(css.Expression? expression) { s = null; } + final param2 = params[2]; final double? l; if (param2 is css.PercentageTerm) { l = param2.valueAsDouble.clamp(0.0, 1.0);