From 41b8e841fe201feb96f2564446a10f7bc87a56d9 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sat, 28 Oct 2023 21:21:23 +0700 Subject: [PATCH 01/16] Split background tests into their own file --- packages/core/test/_.dart | 25 +-- packages/core/test/core_test.dart | 149 +----------------- packages/core/test/style_background_test.dart | 145 +++++++++++++++++ packages/core/test/style_border_test.dart | 2 +- packages/core/test/style_padding_test.dart | 2 +- packages/core/test/style_sizing_test.dart | 6 +- packages/core/test/tag_img_test.dart | 6 +- packages/core/test/tag_table_test.dart | 10 +- .../cached_network_image_factory_test.dart | 3 +- .../fwfh_chewie/test/chewie_factory_test.dart | 3 +- packages/fwfh_svg/test/svg_factory_test.dart | 19 +-- 11 files changed, 180 insertions(+), 190 deletions(-) create mode 100644 packages/core/test/style_background_test.dart diff --git a/packages/core/test/_.dart b/packages/core/test/_.dart index 5f817f4a2..9e7690103 100644 --- a/packages/core/test/_.dart +++ b/packages/core/test/_.dart @@ -155,10 +155,13 @@ Future explainWithoutPumping({ return 'null'; } - return Explainer( + var str = Explainer( key.currentContext!, explainer: explainer, ).explain(built); + + str = str.replaceAll(RegExp('String#[^,]+,'), 'String,'); + return str.replaceAll(RegExp('Uint8List#[0-9a-f]+,'), 'bytes,'); } final _explainMarginRegExp = RegExp( @@ -269,24 +272,24 @@ class Explainer { final attr = []; if (d is BoxDecoration) { - final color = d.color; - if (color != null) { - attr.add('bg=${_color(color)}'); - } - final border = d.border; if (border != null) { attr.add('border=${_boxBorder(border)}'); } - final borderRadius = d.borderRadius; - if (borderRadius != null && borderRadius is BorderRadius) { - attr.add('radius=${_borderRadius(borderRadius)}'); + final color = d.color; + if (color != null) { + attr.add('color=${_color(color)}'); } final image = d.image; if (image != null) { - attr.add("bgimage=$image"); + attr.add("image=${image.image}"); + } + + final borderRadius = d.borderRadius; + if (borderRadius != null && borderRadius is BorderRadius) { + attr.add('radius=${_borderRadius(borderRadius)}'); } } @@ -465,7 +468,7 @@ class Explainer { final bg = style.background; if (bg != null) { - s += 'bg=${_color(bg.color)}'; + s += 'color=${_color(bg.color)}'; } final color = style.color; diff --git a/packages/core/test/core_test.dart b/packages/core/test/core_test.dart index a1b8136c4..c9173378a 100644 --- a/packages/core/test/core_test.dart +++ b/packages/core/test/core_test.dart @@ -598,153 +598,6 @@ Future main() async { }); }); - group('background-color', () { - testWidgets('renders MARK tag', (WidgetTester tester) async { - const html = 'Foo'; - final explained = await explain(tester, html); - expect(explained, equals('[RichText:(bg=#FFFFFF00#FF000000:Foo)]')); - }); - - testWidgets('renders block', (WidgetTester tester) async { - const html = '
Foo
'; - final explained = await explain(tester, html); - expect( - explained, - equals( - '[Container:bg=#FFFF0000,child=' - '[CssBlock:child=' - '[RichText:(:Foo)]]]', - ), - ); - }); - - testWidgets('renders with margins and paddings', (tester) async { - const html = '
Foo
'; - final explained = await explainMargin(tester, html); - expect( - explained, - equals( - '[SizedBox:0.0x1.0],' - '[HorizontalMargin:left=1,right=1,child=' - '[Container:bg=#FFFF0000,child=' - '[Padding:(2,2,2,2),child=' - '[CssBlock:child=' - '[RichText:(:Foo)]]]' - ']],[SizedBox:0.0x1.0]', - ), - ); - }); - - testWidgets('renders blocks', (WidgetTester tester) async { - const h = '

A

B

'; - final explained = await explain(tester, h); - expect( - explained, - equals( - '[Container:bg=#FFFF0000,child=' - '[CssBlock:child=' - '[Column:children=' - '[CssBlock:child=[RichText:(:A)]],' - '[SizedBox:0.0x10.0],' - '[CssBlock:child=[RichText:(:B)]]' - ']]]', - ), - ); - }); - - testWidgets('renders inline', (WidgetTester tester) async { - const html = 'Foo bar'; - final explained = await explain(tester, html); - expect(explained, equals('[RichText:(:Foo (bg=#FFFF0000:bar))]')); - }); - - testWidgets('renders background', (WidgetTester tester) async { - const html = 'Foo bar'; - final explained = await explain(tester, html); - expect(explained, equals('[RichText:(:Foo (bg=#FFFF0000:bar))]')); - }); - - group('renders without erroneous white spaces', () { - testWidgets('before', (WidgetTester tester) async { - const html = 'Foo bar'; - final explained = await explain(tester, html); - expect(explained, equals('[RichText:(:Foo (bg=#FFFF0000:bar))]')); - }); - - testWidgets('after', (WidgetTester tester) async { - const html = 'Foo bar '; - final explained = await explain(tester, html); - expect(explained, equals('[RichText:(:Foo (bg=#FFFF0000:bar))]')); - }); - }); - - testWidgets('resets in continuous SPANs (#155)', (tester) async { - const html = - 'Foo' - 'bar'; - final explained = await explain(tester, html); - expect( - explained, - equals( - '[RichText:(:(bg=#FF0000FF#FFFFFF00:Foo)(#FFFF0000:bar))]', - ), - ); - }); - }); - - group('background-image', () { - testWidgets('asset', (WidgetTester tester) async { - const assetName = 'test/images/logo.png'; - const html = - '
Foo
'; - final explained = await explain(tester, html); - - expect( - explained, - equals( - '[Container:bgimage=' - 'DecorationImage(' - 'AssetImage(bundle: null, name: "test/images/logo.png"), Alignment.center, scale 1.0, opacity 1.0, FilterQuality.low),child=' - '[CssBlock:child=' - '[RichText:(:Foo)]]]', - ), - ); - }); - - testWidgets('data uri', (WidgetTester tester) async { - const html = '
Foo
'; - final explained = await explain(tester, html); - - expect( - explained, - matches( - r'^\[Container:bgimage=DecorationImage\(MemoryImage\(Uint8List#[0-9a-fA-F]+, scale: 1\.0\), ' - r'Alignment\.center, scale 1\.0, opacity 1\.0, FilterQuality\.low\),child=' - r'\[CssBlock:child=' - r'\[RichText:\(:Foo\)\]\]\]$'), - ); - }); - - testWidgets('file', (WidgetTester tester) async { - const fileName = 'test/images/logo.png'; - const html = - '
Foo
'; - final explained = await explain(tester, html); - - expect( - explained, - equals( - '[Container:bgimage=' - 'DecorationImage(' - 'FileImage("/test/images/logo.png", scale: 1.0), Alignment.center, scale 1.0, opacity 1.0, FilterQuality.low),child=' - '[CssBlock:child=' - '[RichText:(:Foo)]]]', - ), - ); - }); - }); - group('color (inline style)', () { testWidgets('renders hex values', (WidgetTester tester) async { const html = 'red' @@ -1053,7 +906,7 @@ Future main() async { const html = 'Foo'; final e = await explain(tester, html); - expect(e, equals('[Container:bg=#FFFF6600,child=[RichText:(:Foo)]]')); + expect(e, equals('[Container:color=#FFFF6600,child=[RichText:(:Foo)]]')); }); testWidgets('renders display: none', (WidgetTester tester) async { diff --git a/packages/core/test/style_background_test.dart b/packages/core/test/style_background_test.dart new file mode 100644 index 000000000..da64829c9 --- /dev/null +++ b/packages/core/test/style_background_test.dart @@ -0,0 +1,145 @@ +import 'package:flutter_test/flutter_test.dart'; + +import '_.dart'; + +void main() { + group('background-color', () { + testWidgets('renders MARK tag', (WidgetTester tester) async { + const html = 'Foo'; + final explained = await explain(tester, html); + expect(explained, equals('[RichText:(color=#FFFFFF00#FF000000:Foo)]')); + }); + + testWidgets('renders block', (WidgetTester tester) async { + const html = '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:color=#FFFF0000,child=' + '[CssBlock:child=' + '[RichText:(:Foo)]]]', + ), + ); + }); + + testWidgets('renders with margins and paddings', (tester) async { + const html = '
Foo
'; + final explained = await explainMargin(tester, html); + expect( + explained, + equals( + '[SizedBox:0.0x1.0],' + '[HorizontalMargin:left=1,right=1,child=' + '[Container:color=#FFFF0000,child=' + '[Padding:(2,2,2,2),child=' + '[CssBlock:child=' + '[RichText:(:Foo)]]]' + ']],[SizedBox:0.0x1.0]', + ), + ); + }); + + testWidgets('renders blocks', (WidgetTester tester) async { + const h = '

A

B

'; + final explained = await explain(tester, h); + expect( + explained, + equals( + '[Container:color=#FFFF0000,child=' + '[CssBlock:child=' + '[Column:children=' + '[CssBlock:child=[RichText:(:A)]],' + '[SizedBox:0.0x10.0],' + '[CssBlock:child=[RichText:(:B)]]' + ']]]', + ), + ); + }); + + testWidgets('renders inline', (WidgetTester tester) async { + const html = 'Foo bar'; + final explained = await explain(tester, html); + expect(explained, equals('[RichText:(:Foo (color=#FFFF0000:bar))]')); + }); + + testWidgets('renders background', (WidgetTester tester) async { + const html = 'Foo bar'; + final explained = await explain(tester, html); + expect(explained, equals('[RichText:(:Foo (color=#FFFF0000:bar))]')); + }); + + group('renders without erroneous white spaces', () { + testWidgets('before', (WidgetTester tester) async { + const html = 'Foo bar'; + final explained = await explain(tester, html); + expect(explained, equals('[RichText:(:Foo (color=#FFFF0000:bar))]')); + }); + + testWidgets('after', (WidgetTester tester) async { + const html = 'Foo bar '; + final explained = await explain(tester, html); + expect(explained, equals('[RichText:(:Foo (color=#FFFF0000:bar))]')); + }); + }); + + testWidgets('resets in continuous SPANs (#155)', (tester) async { + const html = + 'Foo' + 'bar'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[RichText:(:(color=#FF0000FF#FFFFFF00:Foo)(#FFFF0000:bar))]', + ), + ); + }); + }); + + group('background-image', () { + testWidgets('asset', (WidgetTester tester) async { + const assetName = 'test/images/logo.png'; + const html = + '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:image=AssetImage(bundle: null, name: "$assetName"),child=' + '[CssBlock:child=[RichText:(:Foo)]]' + ']', + ), + ); + }); + + testWidgets('data uri', (WidgetTester tester) async { + const html = '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:image=MemoryImage(bytes, scale: 1.0),child=' + '[CssBlock:child=[RichText:(:Foo)]]' + ']', + ), + ); + }); + + testWidgets('file', (WidgetTester tester) async { + const fileName = '/test/images/logo.png'; + const html = + '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:image=FileImage("$fileName", scale: 1.0),child=' + '[CssBlock:child=[RichText:(:Foo)]]' + ']', + ), + ); + }); + }); +} diff --git a/packages/core/test/style_border_test.dart b/packages/core/test/style_border_test.dart index dab605e5b..a11061782 100644 --- a/packages/core/test/style_border_test.dart +++ b/packages/core/test/style_border_test.dart @@ -1163,7 +1163,7 @@ void main() { expect( explained, equals( - '[Container:bg=#FFFF0000,border=$_border1,child=' + '[Container:border=$_border1,color=#FFFF0000,child=' '[Column:children=' '[SizedBox:0.0x12.4],' '[CssBlock:child=[RichText:(@15.0+b:Foo)]],' diff --git a/packages/core/test/style_padding_test.dart b/packages/core/test/style_padding_test.dart index b6a0d62e9..b363b0ad5 100644 --- a/packages/core/test/style_padding_test.dart +++ b/packages/core/test/style_padding_test.dart @@ -611,7 +611,7 @@ void main() { expect( explained, equals( - '[Container:bg=#FFFF0000,child=' + '[Container:color=#FFFF0000,child=' '[Padding:(5,5,5,5),child=' '[Column:children=' '[SizedBox:0.0x12.4],' diff --git a/packages/core/test/style_sizing_test.dart b/packages/core/test/style_sizing_test.dart index e5ef0c688..ca83033f8 100644 --- a/packages/core/test/style_sizing_test.dart +++ b/packages/core/test/style_sizing_test.dart @@ -426,14 +426,14 @@ Future main() async { expect( explained, equals( - '[Container:bg=#FFFF0000,child=' + '[Container:color=#FFFF0000,child=' '[Padding:(20,20,20,20),child=' '[Column:children=[SizedBox:0.0x15.0],' '[CssBlock:child=' - '[Container:bg=#FF008000,child=' + '[Container:color=#FF008000,child=' '[CssBlock:child=' '[HorizontalMargin:left=15,right=15,child=' - '[Container:bg=#FF0000FF,child=' + '[Container:color=#FF0000FF,child=' '[Padding:(5,5,5,5),child=' '[CssSizing:height=100.0,width=100.0,child=' '[RichText:(#FFFFFFFF:Foo)]' diff --git a/packages/core/test/tag_img_test.dart b/packages/core/test/tag_img_test.dart index 6c69c3afb..257e2c3a5 100644 --- a/packages/core/test/tag_img_test.dart +++ b/packages/core/test/tag_img_test.dart @@ -215,8 +215,7 @@ void main() { testWidgets('renders data uri', (WidgetTester tester) async { const html = ''; - final explained = (await explain(tester, html)) - .replaceAll(RegExp('Uint8List#[0-9a-f]+,'), 'bytes,'); + final explained = await explain(tester, html); expect( explained, equals( @@ -253,8 +252,7 @@ void main() { testWidgets('renders file uri', (WidgetTester tester) async { final html = ''; - final explained = (await explain(tester, html)) - .replaceAll(RegExp('Uint8List#[0-9a-f]+,'), 'bytes,'); + final explained = await explain(tester, html); expect( explained, equals( diff --git a/packages/core/test/tag_table_test.dart b/packages/core/test/tag_table_test.dart index c9bbafa48..4b8318f74 100644 --- a/packages/core/test/tag_table_test.dart +++ b/packages/core/test/tag_table_test.dart @@ -654,7 +654,7 @@ Future main() async { equals( '[SingleChildScrollView:child=[HtmlTable:children=' '[HtmlTableCell:child=' - '[Container:bg=#FFFF0000,child=' + '[Container:color=#FFFF0000,child=' '[Padding:(1,1,1,1),child=' '[Align:alignment=centerLeft,widthFactor=1.0,child=' '[RichText:(:Foo)]' @@ -674,13 +674,13 @@ Future main() async { equals( '[SingleChildScrollView:child=[HtmlTable:children=' '[HtmlTableCell:child=' - '[Container:bg=#FFFF0000,child=' + '[Container:color=#FFFF0000,child=' '[Padding:(1,1,1,1),child=' '[Align:alignment=centerLeft,widthFactor=1.0,child=' '[RichText:(:Foo)]' ']]]],' '[HtmlTableCell:child=' - '[Container:bg=#FFFF0000,child=' + '[Container:color=#FFFF0000,child=' '[Padding:(1,1,1,1),child=' '[Align:alignment=centerLeft,widthFactor=1.0,child=' '[RichText:(:Bar)]' @@ -700,13 +700,13 @@ Future main() async { equals( '[SingleChildScrollView:child=[HtmlTable:children=' '[HtmlTableCell:child=' - '[Container:bg=#FFFF0000,child=' + '[Container:color=#FFFF0000,child=' '[Padding:(1,1,1,1),child=' '[Align:alignment=centerLeft,widthFactor=1.0,child=' '[RichText:(:Foo)]' ']]]],' '[HtmlTableCell:child=' - '[Container:bg=#FF00FF00,child=' + '[Container:color=#FF00FF00,child=' '[Padding:(1,1,1,1),child=' '[Align:alignment=centerLeft,widthFactor=1.0,child=' '[RichText:(:Bar)]' diff --git a/packages/fwfh_cached_network_image/test/cached_network_image_factory_test.dart b/packages/fwfh_cached_network_image/test/cached_network_image_factory_test.dart index 4f2e86b83..ba22dc64d 100644 --- a/packages/fwfh_cached_network_image/test/cached_network_image_factory_test.dart +++ b/packages/fwfh_cached_network_image/test/cached_network_image_factory_test.dart @@ -21,8 +21,7 @@ void main() { testWidgets('renders Image for data uri', (WidgetTester tester) async { const html = ''; - final explained = (await explain(tester, html)) - .replaceAll(RegExp('Uint8List#[0-9a-f]+,'), 'bytes,'); + final explained = await explain(tester, html); expect( explained, equals( diff --git a/packages/fwfh_chewie/test/chewie_factory_test.dart b/packages/fwfh_chewie/test/chewie_factory_test.dart index 7115e8653..1f990f9ad 100644 --- a/packages/fwfh_chewie/test/chewie_factory_test.dart +++ b/packages/fwfh_chewie/test/chewie_factory_test.dart @@ -160,8 +160,7 @@ void main() { testWidgets('renders video player with data uri', (tester) async { const h = ''; - final e = await explain(tester, h); - final explained = e.replaceAll(RegExp('Uint8List#[0-9a-f]+,'), 'bytes,'); + final explained = await explain(tester, h); expect( explained, equals( diff --git a/packages/fwfh_svg/test/svg_factory_test.dart b/packages/fwfh_svg/test/svg_factory_test.dart index 649caf2d8..46fbcd35c 100644 --- a/packages/fwfh_svg/test/svg_factory_test.dart +++ b/packages/fwfh_svg/test/svg_factory_test.dart @@ -12,7 +12,7 @@ import 'package:golden_toolkit/golden_toolkit.dart'; import 'package:mocktail/mocktail.dart'; import '../../core/test/_.dart' as core; -import '_.dart' as helper; +import '_.dart'; const redTriangle = ''' @@ -35,18 +35,15 @@ Future main() async { SVG support is not enabled. '''; - final explained = await helper.explain(tester, html); - expect( - explained.replaceAll(RegExp('String#[^,]+,'), 'String,'), - equals('[SvgPicture:bytesLoader=SvgStringLoader]'), - ); + final explained = await explain(tester, html); + expect(explained, equals('[SvgPicture:bytesLoader=SvgStringLoader]')); }); group('IMG', () { testWidgets('renders asset picture', (WidgetTester tester) async { const assetName = 'test/images/icon.svg'; const html = ''; - final explained = await helper.explain(tester, html); + final explained = await explain(tester, html); expect( explained, equals( @@ -61,7 +58,7 @@ Future main() async { testWidgets('renders file picture', (WidgetTester tester) async { final filePath = '${Directory.current.path}/test/images/icon.svg'; final html = ''; - final explained = await helper.explain(tester, html); + final explained = await explain(tester, html); expect( explained, equals( @@ -74,10 +71,6 @@ Future main() async { }); group('MemoryPicture', () { - Future explain(WidgetTester tester, String html) => helper - .explain(tester, html) - .then((e) => e.replaceAll(RegExp(r'\(Uint8List#.+\)'), '(bytes)')); - testWidgets('renders bad data uri', (WidgetTester tester) async { const html = ''; final explained = await explain(tester, html); @@ -121,7 +114,7 @@ Future main() async { const html = ''; const expectedLoading = 'â””CircularProgressIndicator'; final loading = await HttpOverrides.runZoned( - () => helper.explain(tester, html, useExplainer: false), + () => explain(tester, html, useExplainer: false), createHttpClient: (_) => _createMockSvgImageHttpClient(), ); expect(loading, contains('â””SvgPicture')); From d11b954af3aebca58cac78d52b7fe1457b7c55a6 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sat, 28 Oct 2023 22:11:18 +0700 Subject: [PATCH 02/16] Add more `background-image` tests --- packages/core/test/style_background_test.dart | 71 ++++++++++++++++--- 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/packages/core/test/style_background_test.dart b/packages/core/test/style_background_test.dart index da64829c9..68b4509f3 100644 --- a/packages/core/test/style_background_test.dart +++ b/packages/core/test/style_background_test.dart @@ -1,4 +1,7 @@ +import 'dart:io'; + import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail_image_network/mocktail_image_network.dart'; import '_.dart'; @@ -99,21 +102,53 @@ void main() { }); group('background-image', () { - testWidgets('asset', (WidgetTester tester) async { - const assetName = 'test/images/logo.png'; - const html = - '
Foo
'; - final explained = await explain(tester, html); + testWidgets('renders network', (WidgetTester tester) async { + const src = 'http://domain.com/image.png'; + const html = '
Foo
'; + final explained = await mockNetworkImages(() => explain(tester, html)); expect( explained, equals( - '[Container:image=AssetImage(bundle: null, name: "$assetName"),child=' + '[Container:image=NetworkImage("$src", scale: 1.0),child=' '[CssBlock:child=[RichText:(:Foo)]]' ']', ), ); }); + group('asset', () { + const assetName = 'test/images/logo.png'; + + testWidgets('renders asset', (WidgetTester tester) async { + const html = + '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:image=AssetImage(bundle: null, name: "$assetName"),child=' + '[CssBlock:child=[RichText:(:Foo)]]' + ']', + ), + ); + }); + + testWidgets('renders asset (specified package)', (tester) async { + const package = 'flutter_widget_from_html_core'; + const html = + '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:image=AssetImage(bundle: null, name: "packages/$package/$assetName"),child=' + '[CssBlock:child=[RichText:(:Foo)]]' + ']', + ), + ); + }); + }); + testWidgets('data uri', (WidgetTester tester) async { const html = '
Foo
'; final explained = await explain(tester, html); @@ -127,15 +162,29 @@ void main() { ); }); - testWidgets('file', (WidgetTester tester) async { - const fileName = '/test/images/logo.png'; - const html = - '
Foo
'; + testWidgets('file uri', (WidgetTester tester) async { + final filePath = '${Directory.current.path}/test/images/logo.png'; + final fileUri = 'file://$filePath'; + final html = '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:image=FileImage("$filePath", scale: 1.0),child=' + '[CssBlock:child=[RichText:(:Foo)]]' + ']', + ), + ); + }); + + testWidgets('renders background', (WidgetTester tester) async { + const assetName = 'test/images/logo.png'; + const html = '
Foo
'; final explained = await explain(tester, html); expect( explained, equals( - '[Container:image=FileImage("$fileName", scale: 1.0),child=' + '[Container:image=AssetImage(bundle: null, name: "$assetName"),child=' '[CssBlock:child=[RichText:(:Foo)]]' ']', ), From 561886944da8da87cf51c04d2639229198d66098 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sat, 28 Oct 2023 22:24:13 +0700 Subject: [PATCH 03/16] Add more params to `WidgetFactory.buildDecorationImage` --- .../core/lib/src/core_widget_factory.dart | 21 ++++++++++++++----- .../src/internal/ops/style_background.dart | 11 +++++++--- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/core/lib/src/core_widget_factory.dart b/packages/core/lib/src/core_widget_factory.dart index 56c42bd57..2da65cff3 100644 --- a/packages/core/lib/src/core_widget_factory.dart +++ b/packages/core/lib/src/core_widget_factory.dart @@ -147,12 +147,12 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory { BoxBorder? border, BorderRadius? borderRadius, Color? color, - String? bgImageUrl, + DecorationImage? image, }) { if (border == null && borderRadius == null && color == null && - bgImageUrl == null) { + image == null) { return child; } @@ -164,7 +164,7 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory { var decoration = baseDeco.copyWith( border: border, color: color, - image: buildDecorationImage(bgImageUrl), + image: image, ); var clipBehavior = Clip.none; @@ -187,7 +187,13 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory { } /// Builds decoration image from [url] - DecorationImage? buildDecorationImage(String? url) { + DecorationImage? buildDecorationImage( + BuildTree tree, + String? url, { + AlignmentGeometry alignment = Alignment.center, + BoxFit? fit, + ImageRepeat repeat = ImageRepeat.noRepeat, + }) { if (url == null) { return null; } @@ -208,7 +214,12 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory { return null; } - return DecorationImage(image: provider); + return DecorationImage( + alignment: alignment, + fit: fit, + image: provider, + repeat: repeat, + ); } /// Builds [Flex]. diff --git a/packages/core/lib/src/internal/ops/style_background.dart b/packages/core/lib/src/internal/ops/style_background.dart index a825edd75..a97655593 100644 --- a/packages/core/lib/src/internal/ops/style_background.dart +++ b/packages/core/lib/src/internal/ops/style_background.dart @@ -14,18 +14,23 @@ class StyleBackground { debugLabel: kCssBackground, onRenderBlock: (tree, placeholder) { final color = _parseColor(tree); - final bgImageUrl = _parseBackgroundImageUrl(wf, tree); + final imageUrl = _parseBackgroundImageUrl(wf, tree); - if (color == null && bgImageUrl == null) { + if (color == null && imageUrl == null) { return placeholder; } + final image = wf.buildDecorationImage( + tree, + imageUrl, + ); + return placeholder.wrapWith( (_, child) => wf.buildDecoration( tree, child, color: color, - bgImageUrl: bgImageUrl, + image: image, ), ); }, From 3e897d0356ce9e023cd805263001a4c6b72aae36 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sat, 28 Oct 2023 22:32:41 +0700 Subject: [PATCH 04/16] Add test to make sure background/border ops have the expected priorities --- packages/core/lib/src/internal/ops/priorities.dart | 8 ++++++-- packages/core/test/src/internal/ops/priorities_test.dart | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/core/lib/src/internal/ops/priorities.dart b/packages/core/lib/src/internal/ops/priorities.dart index d15655a87..77952a45e 100644 --- a/packages/core/lib/src/internal/ops/priorities.dart +++ b/packages/core/lib/src/internal/ops/priorities.dart @@ -8,12 +8,16 @@ part of '../core_ops.dart'; /// User's build op has a default priority of 10 so they should run /// after our early ops and before our normal ops. class Priority { + static const max = 9007199254740991; + + @visibleForTesting + static const step = 1000000000; + static const _baseEarly00 = -3000000000000000; static const _baseNormal00 = 1000000000000000; static const _baseBoxModel = 5000000000000000; static const _baseLate0000 = 9000000000000000; - static const _step = 1000000000; - static const max = 9007199254740991; + static const _step = step; static const first = _baseNormal00; static const tagA = first + _step; diff --git a/packages/core/test/src/internal/ops/priorities_test.dart b/packages/core/test/src/internal/ops/priorities_test.dart index 6e2e564f7..32f401a97 100644 --- a/packages/core/test/src/internal/ops/priorities_test.dart +++ b/packages/core/test/src/internal/ops/priorities_test.dart @@ -12,6 +12,11 @@ void main() { expect(BoxModel.first, greaterThan(kPriorityDefault)); }); + test('background and border should be next to each other', () { + // they both uses `WidgetFactory.buildDecoration` + expect(BoxModel.background - BoxModel.border, equals(Priority.step)); + }); + test('Late.displayInlineBlock is before inline block default', () { expect(Late.displayInlineBlock, lessThan(kPriorityInlineBlockDefault)); }); From cc13347442b94ebfb3754198f012b6bf83397633 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sat, 28 Oct 2023 22:44:34 +0700 Subject: [PATCH 05/16] Define `_StyleBackgroundData` --- .../core/lib/src/core_widget_factory.dart | 10 +-- .../src/internal/ops/style_background.dart | 77 ++++++++++++------- 2 files changed, 54 insertions(+), 33 deletions(-) diff --git a/packages/core/lib/src/core_widget_factory.dart b/packages/core/lib/src/core_widget_factory.dart index 2da65cff3..679ca392d 100644 --- a/packages/core/lib/src/core_widget_factory.dart +++ b/packages/core/lib/src/core_widget_factory.dart @@ -1037,12 +1037,6 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory { void parseStyle(BuildTree tree, css.Declaration style) { final key = style.property; switch (key) { - case kCssBackground: - case kCssBackgroundColor: - case kCssBackgroundImage: - tree.register(_styleBackground ??= StyleBackground(this).buildOp); - break; - case kCssColor: final color = tryParseColor(style.value); if (color != null) { @@ -1145,6 +1139,10 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory { break; } + if (key.startsWith(kCssBackground)) { + tree.register(_styleBackground ??= StyleBackground(this).buildOp); + } + if (key.startsWith(kCssBorder)) { tree.register(_styleBorder ??= StyleBorder(this).buildOp); } diff --git a/packages/core/lib/src/internal/ops/style_background.dart b/packages/core/lib/src/internal/ops/style_background.dart index a97655593..9c5f1613e 100644 --- a/packages/core/lib/src/internal/ops/style_background.dart +++ b/packages/core/lib/src/internal/ops/style_background.dart @@ -13,8 +13,9 @@ class StyleBackground { alwaysRenderBlock: false, debugLabel: kCssBackground, onRenderBlock: (tree, placeholder) { - final color = _parseColor(tree); - final imageUrl = _parseBackgroundImageUrl(wf, tree); + final data = tree.backgroundData; + final color = data.color; + final imageUrl = data.imageUrl; if (color == null && imageUrl == null) { return placeholder; @@ -35,7 +36,7 @@ class StyleBackground { ); }, onRenderInline: (tree) { - final color = _parseColor(tree); + final color = tree.backgroundData.color; if (color == null) { return; } @@ -55,45 +56,67 @@ class StyleBackground { debugLabel: 'fwfh: $kCssBackgroundColor', ), ); +} + +extension on BuildTree { + _StyleBackgroundData get backgroundData => + getNonInherited<_StyleBackgroundData>() ?? + setNonInherited<_StyleBackgroundData>(_parse()); - static Color? _parseColor(BuildTree tree) { - Color? color; - for (final style in tree.styles) { + _StyleBackgroundData _parse() { + var data = const _StyleBackgroundData(); + for (final style in styles) { switch (style.property) { case kCssBackground: for (final expression in style.values) { - color = tryParseColor(expression) ?? color; + data = data.copyWithColor(expression); + data = data.copyWithImageUrl(expression); } break; case kCssBackgroundColor: - color = tryParseColor(style.value) ?? color; + data = data.copyWithColor(style.value); + break; + case kCssBackgroundImage: + data = data.copyWithImageUrl(style.value); break; } } - return color; + return data; } +} - /// Attempts to parse the background image URL from the [tree] styles. - String? _parseBackgroundImageUrl(WidgetFactory wf, BuildTree tree) { - for (final style in tree.styles) { - final styleValue = style.value; - if (styleValue == null) { - continue; - } +@immutable +class _StyleBackgroundData { + final Color? color; + final String? imageUrl; + const _StyleBackgroundData({ + this.color, + this.imageUrl, + }); - switch (style.property) { - case kCssBackground: - case kCssBackgroundImage: - for (final expression in style.values) { - if (expression is css.UriTerm) { - return expression.text; - } - } - break; - } + _StyleBackgroundData copyWith({ + Color? color, + String? imageUrl, + }) => + _StyleBackgroundData( + color: color ?? this.color, + imageUrl: imageUrl ?? this.imageUrl, + ); + + _StyleBackgroundData copyWithColor(css.Expression? expression) { + final newColor = tryParseColor(expression) ?? color; + if (newColor == color) { + return this; } + return copyWith(color: newColor); + } - return null; + _StyleBackgroundData copyWithImageUrl(css.Expression? expression) { + final newImageUrl = expression is css.UriTerm ? expression.text : imageUrl; + if (newImageUrl == imageUrl) { + return this; + } + return copyWith(imageUrl: newImageUrl); } } From 5d1acf4b7a91cfb5282be71ce85de54fbb724e66 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sat, 28 Oct 2023 23:24:39 +0700 Subject: [PATCH 06/16] Add support for position, repeat & size --- .../core/lib/src/core_widget_factory.dart | 2 +- .../src/internal/ops/style_background.dart | 73 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/packages/core/lib/src/core_widget_factory.dart b/packages/core/lib/src/core_widget_factory.dart index 679ca392d..824c73bc7 100644 --- a/packages/core/lib/src/core_widget_factory.dart +++ b/packages/core/lib/src/core_widget_factory.dart @@ -191,7 +191,7 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory { BuildTree tree, String? url, { AlignmentGeometry alignment = Alignment.center, - BoxFit? fit, + BoxFit fit = BoxFit.scaleDown, ImageRepeat repeat = ImageRepeat.noRepeat, }) { if (url == null) { diff --git a/packages/core/lib/src/internal/ops/style_background.dart b/packages/core/lib/src/internal/ops/style_background.dart index 9c5f1613e..8df7c9c1a 100644 --- a/packages/core/lib/src/internal/ops/style_background.dart +++ b/packages/core/lib/src/internal/ops/style_background.dart @@ -4,6 +4,24 @@ const kCssBackground = 'background'; const kCssBackgroundColor = 'background-color'; const kCssBackgroundImage = 'background-image'; +const kCssBackgroundPosition = 'background-position'; +const kCssBackgroundPositionBottom = 'bottom'; +const kCssBackgroundPositionCenter = 'center'; +const kCssBackgroundPositionLeft = 'left'; +const kCssBackgroundPositionRight = 'right'; +const kCssBackgroundPositionTop = 'top'; + +const kCssBackgroundRepeat = 'background-repeat'; +const kCssBackgroundRepeatNo = 'no-repeat'; +const kCssBackgroundRepeatX = 'repeat-x'; +const kCssBackgroundRepeatY = 'repeat-y'; +const kCssBackgroundRepeatYes = 'repeat'; + +const kCssBackgroundSize = 'background-size'; +const kCssBackgroundSizeAuto = 'auto'; +const kCssBackgroundSizeContain = 'contain'; +const kCssBackgroundSizeCover = 'cover'; + class StyleBackground { final WidgetFactory wf; @@ -24,6 +42,9 @@ class StyleBackground { final image = wf.buildDecorationImage( tree, imageUrl, + alignment: data.alignment, + fit: data.size, + repeat: data.repeat, ); return placeholder.wrapWith( @@ -71,6 +92,7 @@ extension on BuildTree { for (final expression in style.values) { data = data.copyWithColor(expression); data = data.copyWithImageUrl(expression); + data = data.copyWithTerm(expression); } break; case kCssBackgroundColor: @@ -79,6 +101,10 @@ extension on BuildTree { case kCssBackgroundImage: data = data.copyWithImageUrl(style.value); break; + case kCssBackgroundPosition: + case kCssBackgroundRepeat: + case kCssBackgroundSize: + data = data.copyWithTerm(style.value); } } @@ -88,20 +114,32 @@ extension on BuildTree { @immutable class _StyleBackgroundData { + final AlignmentGeometry alignment; final Color? color; final String? imageUrl; + final ImageRepeat repeat; + final BoxFit size; const _StyleBackgroundData({ + this.alignment = Alignment.center, this.color, this.imageUrl, + this.repeat = ImageRepeat.noRepeat, + this.size = BoxFit.scaleDown, }); _StyleBackgroundData copyWith({ + AlignmentGeometry? alignment, Color? color, String? imageUrl, + ImageRepeat? repeat, + BoxFit? size, }) => _StyleBackgroundData( + alignment: alignment ?? this.alignment, color: color ?? this.color, imageUrl: imageUrl ?? this.imageUrl, + repeat: repeat ?? this.repeat, + size: size ?? this.size, ); _StyleBackgroundData copyWithColor(css.Expression? expression) { @@ -119,4 +157,39 @@ class _StyleBackgroundData { } return copyWith(imageUrl: newImageUrl); } + + _StyleBackgroundData copyWithTerm(css.Expression? expression) { + if (expression is! css.LiteralTerm) { + return this; + } + + switch (expression.valueAsString) { + case kCssBackgroundPositionBottom: + return copyWith(alignment: Alignment.bottomCenter); + case kCssBackgroundPositionCenter: + return copyWith(alignment: Alignment.center); + case kCssBackgroundPositionLeft: + return copyWith(alignment: Alignment.centerLeft); + case kCssBackgroundPositionRight: + return copyWith(alignment: Alignment.centerRight); + case kCssBackgroundPositionTop: + return copyWith(alignment: Alignment.topCenter); + case kCssBackgroundRepeatNo: + return copyWith(repeat: ImageRepeat.noRepeat); + case kCssBackgroundRepeatX: + return copyWith(repeat: ImageRepeat.repeatX); + case kCssBackgroundRepeatY: + return copyWith(repeat: ImageRepeat.repeatY); + case kCssBackgroundRepeatYes: + return copyWith(repeat: ImageRepeat.repeat); + case kCssBackgroundSizeAuto: + return copyWith(size: BoxFit.scaleDown); + case kCssBackgroundSizeContain: + return copyWith(size: BoxFit.contain); + case kCssBackgroundSizeCover: + return copyWith(size: BoxFit.cover); + } + + return this; + } } From e46b01f03d37f5fbd798a99934cf43219f61d7b8 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sat, 28 Oct 2023 23:32:21 +0700 Subject: [PATCH 07/16] Add tests --- packages/core/test/_.dart | 9 ++ packages/core/test/style_background_test.dart | 84 ++++++++++++++++--- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/packages/core/test/_.dart b/packages/core/test/_.dart index 9e7690103..fe9e9d536 100644 --- a/packages/core/test/_.dart +++ b/packages/core/test/_.dart @@ -285,6 +285,15 @@ class Explainer { final image = d.image; if (image != null) { attr.add("image=${image.image}"); + if (image.alignment != Alignment.center) { + attr.add(_alignment(image.alignment)); + } + if (image.fit != BoxFit.scaleDown) { + attr.add('fit=${image.fit?.name}'); + } + if (image.repeat != ImageRepeat.noRepeat) { + attr.add('repeat=${image.repeat.name}'); + } } final borderRadius = d.borderRadius; diff --git a/packages/core/test/style_background_test.dart b/packages/core/test/style_background_test.dart index 68b4509f3..c6f1c537d 100644 --- a/packages/core/test/style_background_test.dart +++ b/packages/core/test/style_background_test.dart @@ -67,12 +67,6 @@ void main() { expect(explained, equals('[RichText:(:Foo (color=#FFFF0000:bar))]')); }); - testWidgets('renders background', (WidgetTester tester) async { - const html = 'Foo bar'; - final explained = await explain(tester, html); - expect(explained, equals('[RichText:(:Foo (color=#FFFF0000:bar))]')); - }); - group('renders without erroneous white spaces', () { testWidgets('before', (WidgetTester tester) async { const html = 'Foo bar'; @@ -87,7 +81,8 @@ void main() { }); }); - testWidgets('resets in continuous SPANs (#155)', (tester) async { + testWidgets('resets in continuous SPANs', (tester) async { + // https://github.com/daohoangson/flutter_widget_from_html/issues/155 const html = 'Foo' 'bar'; @@ -176,19 +171,88 @@ void main() { ), ); }); + }); - testWidgets('renders background', (WidgetTester tester) async { - const assetName = 'test/images/logo.png'; + group('shorthand', () { + const assetName = 'test/images/logo.png'; + const assetImage = 'AssetImage(bundle: null, name: "$assetName")'; + + testWidgets('renders color', (WidgetTester tester) async { + const html = 'Foo bar'; + final explained = await explain(tester, html); + expect(explained, equals('[RichText:(:Foo (color=#FFFF0000:bar))]')); + }); + + testWidgets('renders image', (WidgetTester tester) async { const html = '
Foo
'; final explained = await explain(tester, html); expect( explained, equals( - '[Container:image=AssetImage(bundle: null, name: "$assetName"),child=' + '[Container:image=$assetImage,child=' + '[CssBlock:child=[RichText:(:Foo)]]' + ']', + ), + ); + }); + + testWidgets('renders position', (WidgetTester tester) async { + const html = + '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:image=$assetImage,alignment=centerRight,child=' + '[CssBlock:child=[RichText:(:Foo)]]' + ']', + ), + ); + }); + + testWidgets('renders repeat', (WidgetTester tester) async { + const html = + '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:image=$assetImage,repeat=repeat,child=' '[CssBlock:child=[RichText:(:Foo)]]' ']', ), ); }); + + testWidgets('renders size', (WidgetTester tester) async { + const html = + '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:image=$assetImage,fit=cover,child=' + '[CssBlock:child=[RichText:(:Foo)]]' + ']', + ), + ); + }); + + testWidgets('renders everything', (WidgetTester tester) async { + const html = '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:color=#FFFF0000,' + 'image=$assetImage,' + 'alignment=centerRight,' + 'fit=cover,' + 'repeat=repeat,' + 'child=[CssBlock:child=[RichText:(:Foo)]]]', + ), + ); + }); }); } From aba139cc1e514b0a87a2e4d781c78dda8892f9f4 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sun, 29 Oct 2023 07:28:33 +0700 Subject: [PATCH 08/16] [skip ci] Add golden tests --- packages/core/test/images/44px.png | Bin 0 -> 754 bytes packages/core/test/images/logo.png | Bin 1443 -> 1697 bytes packages/core/test/style_background_test.dart | 97 +++++++++++++++++- 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 packages/core/test/images/44px.png diff --git a/packages/core/test/images/44px.png b/packages/core/test/images/44px.png new file mode 100644 index 0000000000000000000000000000000000000000..dcd13812147a0d0ea361d97b9c0743ecd7cd0a5c GIT binary patch literal 754 zcmVkl4PCY#<1P= zchUt(5(Ry1OupO{)UN0hT!N>E^qub92M-Y}z$x4qwwwM*I(m&f?PudPXmI75-bcG# z=g&fISK~!+AE7p58WM|dtGMx?$k@h*_u}sP6NdirJI|net24Gt{1~K(0AyK4EEZ$t zBuPRxo5g<@o zvy*gT8O=%93AbP>_QJx8zu#xBKZcWVwdOVtm)EfPZXM58s_G6qi6z05iwjGRi=|jD zYuyk_;S%g0^rG8v3BGbRWN4@LIX-g;PQWEtIv7COKy*49!o|*;$JS8(J6kvAEGFN kOYly`eKp&SE7)%S0PWGrCy|5`6aWAK07*qoM6N<$f)MFV)Bpeg literal 0 HcmV?d00001 diff --git a/packages/core/test/images/logo.png b/packages/core/test/images/logo.png index 4d6372eebdb28e45604e46eeda8dd24651419bc0..33414d1fd6ab0410289a2cb7f747fdb316504b98 100644 GIT binary patch literal 1697 zcmbuAc~H^`6vuz$4Xdt$A$eq0n{K79Y0#l2%8{9QP;O!A;%y4pdLja5<9KDBWoBi8 zS%a==39XuGwx({YLRM=E9@u)Vq6R?<>e9b^^hZ1MdGF18@4xSx@4Ot}V>o@VDHs3% zeb2*ae|2sD6uR2#>@SSfQ5U_q!>8f_00R9KAmG|{xOxbR_s6*db$#YD>P9mX<&6S> zh60F+s09Gp2v0QXcnWA<ve`hk(f>t&%^p>)PYP`ZVcBp@KvYEe@AFDg2`C6U8RrM zPZNFLYNfFirN$IMx^7L?su;iBA#{O8U6)`GWEstoA|I zG-7Q5w%QhuKdWf#2(BtL(tW85d{M(mE$VQKCg_`iaBO%sE$w z4X7^`i{O+e9*u4ay+7wfaeY!$|L3Db$;-N(*MKDB(H8{XN{c&cU|XyT3_rgmANWFS zi~6UKidM;a(?tUyTJyhox?mXhP4YnB(Y~vcECuf*WpWc_rsFkL8M1P1`3*j8bGcah zEe=t^Eh;jSl2TFzi+id%?NR`*nq@Io`fyqPy5QlJXi5W5Du`z67Vq$W5Z0r^q5L|S-qyK&m0|}o_d2jSY|kvG9+Yy|mu4B{XNF73 zzDxmK*PtPiF)`rjVa|fw8e#MK`>~Z*(Ny@We0PaQ1BLv|a%E3UHm-40Lv~}eT1Fm& zvVGE6`ePE}kzhDoZ2STF6k0|el)c_xvytudn006)i&881>(0k#<7J>y`N&kwD6Iu= zQ5|`fX@UwZ-nXfb9(|(M=6H;ARN9`%3jvPcbIl&AunqSTC=zUC>h+nN=Ucg(ZwdXf z1-L9>#?`fc=HOy7oSx9F6&Eg_Y^Eh+Ep3avwu)?IOj?Sk)GbgF0h#a%#q+G%P4Wj$wDmf@4zqs<;h~B z%WjvfXCtK=42)5G&$js(T~?VkqC8e4$PgM;BW| z-R`jYzWpeyCCDEV@~cIra2dT|@isEMQkYwxkG(xP9~iU3zu1ehOILSm>}af|RdGy) z$i^v7*0!rj_#Ugi*@HZ>PA;3j#_L*NMZPfG>lwUJJmS|)QeAXSty2493%8~*Y0IPf z(+4t5Q{Pbv$FKOgo0vS$aN3amPa4s#mG&pyylSW|*Ok3#L%}Mnf*8b!OO5DDgDH9u#~&$#w)t98K4yI77ftbMQkD1ayC7`o2=hm5}f DYx>fA literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` diff --git a/packages/core/test/style_background_test.dart b/packages/core/test/style_background_test.dart index c6f1c537d..78b906f98 100644 --- a/packages/core/test/style_background_test.dart +++ b/packages/core/test/style_background_test.dart @@ -1,11 +1,17 @@ import 'dart:io'; +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart'; +import 'package:flutter_widget_from_html_core/src/internal/core_ops.dart'; +import 'package:golden_toolkit/golden_toolkit.dart'; import 'package:mocktail_image_network/mocktail_image_network.dart'; import '_.dart'; -void main() { +Future main() async { + await loadAppFonts(); + group('background-color', () { testWidgets('renders MARK tag', (WidgetTester tester) async { const html = 'Foo'; @@ -255,4 +261,93 @@ void main() { ); }); }); + + final goldenSkipEnvVar = Platform.environment['GOLDEN_SKIP']; + final goldenSkip = goldenSkipEnvVar == null + ? Platform.isLinux + ? null + : 'Linux only' + : 'GOLDEN_SKIP=$goldenSkipEnvVar'; + + GoldenToolkit.runWithConfiguration( + () { + group( + 'background-image', + () { + const image44 = 'background-image: url(asset:test/images/44px.png)'; + const size100x75 = 'width: 100px; height: 75px'; + const size100x100 = 'width: 100px; height: 100px'; + const testCases = { + 'position/bottom': + '
Foo
', + 'position/center': + '
Foo
', + 'position/left': + '
Foo
', + 'position/right': + '
Foo
', + 'position/top': + '
Foo
', + 'repeat/no': + '
Foo
', + 'repeat/x': + '
Foo
', + 'repeat/y': + '
Foo
', + 'repeat/yes': + '
Foo
', + 'size/auto': + '
Foo
', + 'size/contain': + '
Foo
', + 'size/cover': + '
Foo
', + }; + + for (final testCase in testCases.entries) { + testGoldens( + testCase.key, + (tester) async { + await tester.pumpWidgetBuilder( + _Golden(testCase.value), + wrapper: materialAppWrapper(theme: ThemeData.light()), + surfaceSize: const Size(116, 116), + ); + + await screenMatchesGolden(tester, testCase.key); + }, + skip: goldenSkip != null, + ); + } + }, + skip: goldenSkip, + ); + }, + config: GoldenToolkitConfiguration( + fileNameFactory: (name) => '$kGoldenFilePrefix/background/$name.png', + ), + ); +} + +class _Golden extends StatelessWidget { + final String html; + + const _Golden(this.html); + + @override + Widget build(BuildContext _) => Scaffold( + body: Padding( + padding: const EdgeInsets.all(8.0), + child: HtmlWidget( + html, + customStylesBuilder: (element) { + if (element.localName == 'div') { + return const {kCssBackgroundColor: 'lightgray'}; + } + + return null; + }, + ), + ), + ); } From 0b40d5d4c55d9f63c4cae171a3545d4b9f68a991 Mon Sep 17 00:00:00 2001 From: Cirrus CI Date: Sun, 29 Oct 2023 00:38:10 +0000 Subject: [PATCH 09/16] Update golden images --- demo_app/test/li/img_block.png | Bin 6836 -> 6772 bytes demo_app/test/li/img_block_between_text.png | Bin 8526 -> 8417 bytes demo_app/test/li/img_block_then_text.png | Bin 7576 -> 7476 bytes demo_app/test/li/img_inline.png | Bin 6836 -> 6772 bytes demo_app/test/li/img_inline_between_text.png | Bin 8838 -> 8496 bytes demo_app/test/li/img_inline_then_text.png | Bin 8010 -> 7753 bytes .../child_height_gt_max_height.png | Bin 5068 -> 2911 bytes .../child_width_gt_max_width.png | Bin 5230 -> 3010 bytes .../sizing/_guessChildSize/native_192x192.png | Bin 5230 -> 3010 bytes demo_app/test/table/aspect_ratio_img.png | Bin 3750 -> 3488 bytes 10 files changed, 0 insertions(+), 0 deletions(-) diff --git a/demo_app/test/li/img_block.png b/demo_app/test/li/img_block.png index 09a17db5f71bbe2058845a5faceba9e99073d6ac..208ccb28ce7f10066be7dec86d5e2c27efdb2536 100644 GIT binary patch literal 6772 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 HH}3rdzF?{0 diff --git a/demo_app/test/li/img_block_between_text.png b/demo_app/test/li/img_block_between_text.png index 7990a40d187c0bf8376b6bd19c1275b8f353ef06..ab4fe684ba0b32fb9e9ab70b3df7e345ddbac973 100644 GIT binary patch literal 8417 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 literal 0 HcmV?d00001 diff --git a/demo_app/test/background/size/cover.png b/demo_app/test/background/size/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..4f9189e7d9812d1678b7d4df3d88d1f04bd1fca1 GIT binary patch literal 3710 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 literal 0 HcmV?d00001 diff --git a/packages/core/test/style_background_test.dart b/packages/core/test/style_background_test.dart index 78b906f98..b61d4aac4 100644 --- a/packages/core/test/style_background_test.dart +++ b/packages/core/test/style_background_test.dart @@ -288,13 +288,13 @@ Future main() async { '
Foo
', 'position/top': '
Foo
', - 'repeat/no': + 'repeat/no-repeat': '
Foo
', - 'repeat/x': + 'repeat/repeat-x': '
Foo
', - 'repeat/y': + 'repeat/repeat-y': '
Foo
', - 'repeat/yes': + 'repeat/repeat': '
Foo
', 'size/auto': '
Foo
', From d71d6f9049c83d65977ffbe34f3dfceb03f9a5ab Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sun, 29 Oct 2023 10:20:15 +0700 Subject: [PATCH 11/16] Expand support for `background-position` --- .../core/lib/src/core_widget_factory.dart | 2 +- .../src/internal/ops/style_background.dart | 224 +++++++++++++++--- packages/core/test/_.dart | 2 +- packages/core/test/style_background_test.dart | 126 +++++++++- 4 files changed, 319 insertions(+), 35 deletions(-) diff --git a/packages/core/lib/src/core_widget_factory.dart b/packages/core/lib/src/core_widget_factory.dart index 824c73bc7..687f73e58 100644 --- a/packages/core/lib/src/core_widget_factory.dart +++ b/packages/core/lib/src/core_widget_factory.dart @@ -190,7 +190,7 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory { DecorationImage? buildDecorationImage( BuildTree tree, String? url, { - AlignmentGeometry alignment = Alignment.center, + AlignmentGeometry alignment = Alignment.topLeft, BoxFit fit = BoxFit.scaleDown, ImageRepeat repeat = ImageRepeat.noRepeat, }) { diff --git a/packages/core/lib/src/internal/ops/style_background.dart b/packages/core/lib/src/internal/ops/style_background.dart index 8df7c9c1a..31a9fab55 100644 --- a/packages/core/lib/src/internal/ops/style_background.dart +++ b/packages/core/lib/src/internal/ops/style_background.dart @@ -86,25 +86,48 @@ extension on BuildTree { _StyleBackgroundData _parse() { var data = const _StyleBackgroundData(); - for (final style in styles) { + for (final style_ in styles) { + final style = _StyleBackgroundDeclaration(style_); switch (style.property) { case kCssBackground: - for (final expression in style.values) { - data = data.copyWithColor(expression); - data = data.copyWithImageUrl(expression); - data = data.copyWithTerm(expression); + while (style.hasValue) { + final prev = data; + data = data.copyWithColor(style); + if (style.hasValue) { + data = data.copyWithImageUrl(style); + } + if (style.hasValue) { + data = data.copyWithPosition(style); + } + if (style.hasValue) { + data = data.copyWithRepeatOrSize(style); + } + if (identical(data, prev)) { + // unrecognized value, ignore it + style.increaseIndex(); + } } break; case kCssBackgroundColor: - data = data.copyWithColor(style.value); + data = data.copyWithColor(style); break; case kCssBackgroundImage: - data = data.copyWithImageUrl(style.value); + data = data.copyWithImageUrl(style); break; case kCssBackgroundPosition: + while (style.hasValue) { + final prev = data; + data = data.copyWithPosition(style); + if (identical(data, prev)) { + // unrecognized value, ignore it + style.increaseIndex(); + } + } + break; case kCssBackgroundRepeat: case kCssBackgroundSize: - data = data.copyWithTerm(style.value); + data = data.copyWithRepeatOrSize(style); + break; } } @@ -112,6 +135,27 @@ extension on BuildTree { } } +extension on css.Expression { + _StyleBackgroundPosition? get position { + final self = this; + final term = self is css.LiteralTerm ? self.valueAsString : null; + switch (term) { + case kCssBackgroundPositionBottom: + return _StyleBackgroundPosition.bottom; + case kCssBackgroundPositionCenter: + return _StyleBackgroundPosition.center; + case kCssBackgroundPositionLeft: + return _StyleBackgroundPosition.left; + case kCssBackgroundPositionRight: + return _StyleBackgroundPosition.right; + case kCssBackgroundPositionTop: + return _StyleBackgroundPosition.top; + } + + return null; + } +} + @immutable class _StyleBackgroundData { final AlignmentGeometry alignment; @@ -120,7 +164,7 @@ class _StyleBackgroundData { final ImageRepeat repeat; final BoxFit size; const _StyleBackgroundData({ - this.alignment = Alignment.center, + this.alignment = Alignment.topLeft, this.color, this.imageUrl, this.repeat = ImageRepeat.noRepeat, @@ -142,38 +186,130 @@ class _StyleBackgroundData { size: size ?? this.size, ); - _StyleBackgroundData copyWithColor(css.Expression? expression) { - final newColor = tryParseColor(expression) ?? color; - if (newColor == color) { + _StyleBackgroundData copyWithColor(_StyleBackgroundDeclaration style) { + final color = tryParseColor(style.value); + if (color == null) { return this; } - return copyWith(color: newColor); + + style.increaseIndex(); + return copyWith(color: color); } - _StyleBackgroundData copyWithImageUrl(css.Expression? expression) { - final newImageUrl = expression is css.UriTerm ? expression.text : imageUrl; - if (newImageUrl == imageUrl) { + _StyleBackgroundData copyWithImageUrl(_StyleBackgroundDeclaration style) { + final value = style.value; + final imageUrl = value is css.UriTerm ? value.text : null; + if (imageUrl == null) { return this; } - return copyWith(imageUrl: newImageUrl); + + style.increaseIndex(); + return copyWith(imageUrl: imageUrl); } - _StyleBackgroundData copyWithTerm(css.Expression? expression) { - if (expression is! css.LiteralTerm) { + _StyleBackgroundData copyWithPosition(_StyleBackgroundDeclaration style) { + final value1 = style.value; + final position1 = value1?.position; + if (position1 == null) { return this; } - switch (expression.valueAsString) { - case kCssBackgroundPositionBottom: - return copyWith(alignment: Alignment.bottomCenter); - case kCssBackgroundPositionCenter: - return copyWith(alignment: Alignment.center); - case kCssBackgroundPositionLeft: - return copyWith(alignment: Alignment.centerLeft); - case kCssBackgroundPositionRight: - return copyWith(alignment: Alignment.centerRight); - case kCssBackgroundPositionTop: - return copyWith(alignment: Alignment.topCenter); + final value2 = style.valuePlus1; + final position2 = value2?.position; + if (position2 == null) { + // single keyword position + style.increaseIndex(); + switch (position1) { + case _StyleBackgroundPosition.bottom: + return copyWith(alignment: Alignment.bottomCenter); + case _StyleBackgroundPosition.center: + return copyWith(alignment: Alignment.center); + case _StyleBackgroundPosition.left: + return copyWith(alignment: Alignment.centerLeft); + case _StyleBackgroundPosition.right: + return copyWith(alignment: Alignment.centerRight); + case _StyleBackgroundPosition.top: + return copyWith(alignment: Alignment.topCenter); + } + } else { + // double keywords position + style.increaseIndex(2); + switch (position1) { + case _StyleBackgroundPosition.bottom: + switch (position2) { + case _StyleBackgroundPosition.left: + return copyWith(alignment: Alignment.bottomLeft); + case _StyleBackgroundPosition.right: + return copyWith(alignment: Alignment.bottomRight); + case _StyleBackgroundPosition.bottom: + case _StyleBackgroundPosition.center: + case _StyleBackgroundPosition.top: + return copyWith(alignment: Alignment.bottomCenter); + } + case _StyleBackgroundPosition.center: + switch (position2) { + case _StyleBackgroundPosition.bottom: + return copyWith(alignment: Alignment.bottomCenter); + case _StyleBackgroundPosition.center: + return copyWith(alignment: Alignment.center); + case _StyleBackgroundPosition.left: + return copyWith(alignment: Alignment.centerLeft); + case _StyleBackgroundPosition.right: + return copyWith(alignment: Alignment.centerRight); + case _StyleBackgroundPosition.top: + return copyWith(alignment: Alignment.topCenter); + } + case _StyleBackgroundPosition.left: + switch (position2) { + case _StyleBackgroundPosition.bottom: + return copyWith(alignment: Alignment.bottomLeft); + case _StyleBackgroundPosition.top: + return copyWith(alignment: Alignment.topLeft); + case _StyleBackgroundPosition.center: + case _StyleBackgroundPosition.left: + case _StyleBackgroundPosition.right: + return copyWith(alignment: Alignment.centerLeft); + } + case _StyleBackgroundPosition.right: + switch (position2) { + case _StyleBackgroundPosition.bottom: + return copyWith(alignment: Alignment.bottomRight); + case _StyleBackgroundPosition.top: + return copyWith(alignment: Alignment.topRight); + case _StyleBackgroundPosition.left: + case _StyleBackgroundPosition.right: + case _StyleBackgroundPosition.center: + return copyWith(alignment: Alignment.centerRight); + } + case _StyleBackgroundPosition.top: + switch (position2) { + case _StyleBackgroundPosition.left: + return copyWith(alignment: Alignment.topLeft); + case _StyleBackgroundPosition.right: + return copyWith(alignment: Alignment.topRight); + case _StyleBackgroundPosition.bottom: + case _StyleBackgroundPosition.center: + case _StyleBackgroundPosition.top: + return copyWith(alignment: Alignment.topCenter); + } + } + } + } + + _StyleBackgroundData copyWithRepeatOrSize(_StyleBackgroundDeclaration style) { + final value = style.value; + final term = value is css.LiteralTerm ? value.valueAsString : null; + final copied = copyWithTerm(term); + if (identical(copied, this)) { + return this; + } + + style.increaseIndex(); + return copied; + } + + _StyleBackgroundData copyWithTerm(String? term) { + switch (term) { case kCssBackgroundRepeatNo: return copyWith(repeat: ImageRepeat.noRepeat); case kCssBackgroundRepeatX: @@ -193,3 +329,31 @@ class _StyleBackgroundData { return this; } } + +class _StyleBackgroundDeclaration { + final String property; + final List values; + + var _i = 0; + + _StyleBackgroundDeclaration(css.Declaration style) + : property = style.property, + values = style.values; + + bool get hasValue => _i < values.length; + + css.Expression? get value => hasValue ? values[_i] : null; + + css.Expression? get valuePlus1 => + _i + 1 < values.length ? values[_i + 1] : null; + + void increaseIndex([int delta = 1]) => _i += delta; +} + +enum _StyleBackgroundPosition { + bottom, + center, + left, + right, + top, +} diff --git a/packages/core/test/_.dart b/packages/core/test/_.dart index fe9e9d536..5d3b6a314 100644 --- a/packages/core/test/_.dart +++ b/packages/core/test/_.dart @@ -285,7 +285,7 @@ class Explainer { final image = d.image; if (image != null) { attr.add("image=${image.image}"); - if (image.alignment != Alignment.center) { + if (image.alignment != Alignment.topLeft) { attr.add(_alignment(image.alignment)); } if (image.fit != BoxFit.scaleDown) { diff --git a/packages/core/test/style_background_test.dart b/packages/core/test/style_background_test.dart index b61d4aac4..99b845583 100644 --- a/packages/core/test/style_background_test.dart +++ b/packages/core/test/style_background_test.dart @@ -177,6 +177,79 @@ Future main() async { ), ); }); + + group('background-position', () { + const backgroundAssetImage = + 'background-image: url(asset:test/images/logo.png)'; + + final positionTestCases = ValueVariant<_PositionTestCase>( + { + // bottom + 'bottom'.position(Alignment.bottomCenter), + 'bottom bottom'.position(Alignment.bottomCenter), + 'bottom center'.position(Alignment.bottomCenter), + 'bottom left'.position(Alignment.bottomLeft), + 'bottom right'.position(Alignment.bottomRight), + 'bottom top'.position(Alignment.bottomCenter), + + // center + 'center'.position(Alignment.center), + 'center bottom'.position(Alignment.bottomCenter), + 'center center'.position(Alignment.center), + 'center left'.position(Alignment.centerLeft), + 'center right'.position(Alignment.centerRight), + 'center top'.position(Alignment.topCenter), + + // left + 'left'.position(Alignment.centerLeft), + 'left bottom'.position(Alignment.bottomLeft), + 'left center'.position(Alignment.centerLeft), + 'left left'.position(Alignment.centerLeft), + 'left right'.position(Alignment.centerLeft), + 'left top'.position(Alignment.topLeft), + + // right + 'right'.position(Alignment.centerRight), + 'right bottom'.position(Alignment.bottomRight), + 'right center'.position(Alignment.centerRight), + 'right left'.position(Alignment.centerRight), + 'right right'.position(Alignment.centerRight), + 'right top'.position(Alignment.topRight), + + // top + 'top'.position(Alignment.topCenter), + 'top bottom'.position(Alignment.topCenter), + 'top center'.position(Alignment.topCenter), + 'top left'.position(Alignment.topLeft), + 'top right'.position(Alignment.topRight), + 'top top'.position(Alignment.topCenter), + + // default + 'foo'.position(Alignment.topLeft), + }, + ); + + testWidgets( + 'renders alignment', + (WidgetTester tester) async { + final testCase = positionTestCases.currentValue!; + final html = '
Foo
'; + + await explain(tester, html); + final container = tester.widget(find.byType(Container)); + expect( + container.decoration, + isA().having( + (deco) => deco.image?.alignment, + 'image.alignment', + equals(testCase.alignment), + ), + ); + }, + variant: positionTestCases, + ); + }); }); group('shorthand', () { @@ -202,7 +275,7 @@ Future main() async { ); }); - testWidgets('renders position', (WidgetTester tester) async { + testWidgets('renders position (single)', (WidgetTester tester) async { const html = '
Foo
'; final explained = await explain(tester, html); @@ -216,6 +289,20 @@ Future main() async { ); }); + testWidgets('renders position (double)', (WidgetTester tester) async { + const html = + '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:image=$assetImage,alignment=bottomRight,child=' + '[CssBlock:child=[RichText:(:Foo)]]' + ']', + ), + ); + }); + testWidgets('renders repeat', (WidgetTester tester) async { const html = '
Foo
'; @@ -246,14 +333,32 @@ Future main() async { testWidgets('renders everything', (WidgetTester tester) async { const html = '
Foo
'; + 'url(asset:$assetName) bottom right repeat cover">Foo'; final explained = await explain(tester, html); expect( explained, equals( '[Container:color=#FFFF0000,' 'image=$assetImage,' - 'alignment=centerRight,' + 'alignment=bottomRight,' + 'fit=cover,' + 'repeat=repeat,' + 'child=[CssBlock:child=[RichText:(:Foo)]]]', + ), + ); + }); + + testWidgets('renders unrecognized values', (WidgetTester tester) async { + const html = '
Foo
'; + final explained = await explain(tester, html); + expect( + explained, + equals( + '[Container:color=#FFFF0000,' + 'image=$assetImage,' + 'alignment=bottomRight,' 'fit=cover,' 'repeat=repeat,' 'child=[CssBlock:child=[RichText:(:Foo)]]]', @@ -329,6 +434,11 @@ Future main() async { ); } +extension on String { + _PositionTestCase position(AlignmentGeometry alignment) => + _PositionTestCase(this, alignment); +} + class _Golden extends StatelessWidget { final String html; @@ -351,3 +461,13 @@ class _Golden extends StatelessWidget { ), ); } + +@immutable +class _PositionTestCase { + final String value; + final AlignmentGeometry alignment; + const _PositionTestCase(this.value, this.alignment); + + @override + String toString() => value; +} From 8d2f9cf9d4753f2cb5b1c8324b02745074655d74 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sun, 29 Oct 2023 10:22:26 +0700 Subject: [PATCH 12/16] [skip ci] Adjust position golden tests --- packages/core/test/style_background_test.dart | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/core/test/style_background_test.dart b/packages/core/test/style_background_test.dart index 99b845583..cb42f851e 100644 --- a/packages/core/test/style_background_test.dart +++ b/packages/core/test/style_background_test.dart @@ -383,16 +383,24 @@ Future main() async { const size100x75 = 'width: 100px; height: 75px'; const size100x100 = 'width: 100px; height: 100px'; const testCases = { - 'position/bottom': - '
Foo
', 'position/center': '
Foo
', - 'position/left': - '
Foo
', - 'position/right': - '
Foo
', 'position/top': '
Foo
', + 'position/top_right': + '
Foo
', + 'position/right': + '
Foo
', + 'position/bottom_right': + '
Foo
', + 'position/bottom': + '
Foo
', + 'position/bottom_left': + '
Foo
', + 'position/left': + '
Foo
', + 'position/top_left': + '
Foo
', 'repeat/no-repeat': '
Foo
', 'repeat/repeat-x': From 658af742e67c4538287a1971940d9f2cddd014a4 Mon Sep 17 00:00:00 2001 From: Cirrus CI Date: Sun, 29 Oct 2023 03:29:36 +0000 Subject: [PATCH 13/16] Update golden images --- .../test/background/position/bottom_left.png | Bin 0 -> 1384 bytes .../test/background/position/bottom_right.png | Bin 0 -> 1368 bytes .../test/background/position/top_left.png | Bin 0 -> 1458 bytes .../test/background/position/top_right.png | Bin 0 -> 1377 bytes demo_app/test/background/repeat/no-repeat.png | Bin 1401 -> 1458 bytes demo_app/test/background/repeat/repeat-x.png | Bin 1432 -> 1583 bytes demo_app/test/background/repeat/repeat-y.png | Bin 1545 -> 1568 bytes demo_app/test/background/repeat/repeat.png | Bin 1721 -> 1692 bytes demo_app/test/background/size/auto.png | Bin 1399 -> 1458 bytes demo_app/test/background/size/contain.png | Bin 3191 -> 3138 bytes demo_app/test/background/size/cover.png | Bin 3710 -> 3151 bytes 11 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 demo_app/test/background/position/bottom_left.png create mode 100644 demo_app/test/background/position/bottom_right.png create mode 100644 demo_app/test/background/position/top_left.png create mode 100644 demo_app/test/background/position/top_right.png diff --git a/demo_app/test/background/position/bottom_left.png b/demo_app/test/background/position/bottom_left.png new file mode 100644 index 0000000000000000000000000000000000000000..03499969d56b9c8d76c3dcc8b9d06f17b3eb18c5 GIT binary patch literal 1384 zcmeAS@N?(olHy`uVBq!ia0vp^B_Pbf1|&mfiKzoA#^NA%Cx&(BWL^R}EX7WqAsj$Z z!;#X#z`!cx>EaktG3V`Fe~;PaGRHsq-z<*Hz0Oz-PQCe|IB zj=Ow*a#H_R?dQr^uloJ*v)S+2?0@bl*SRc2Ybsl3VA)-Ehb+St20U6k&0L2U95Mhg z&z#;V=Cb(WY74$gD_5?3d8u;V!b4ANoEa5l_>$}D?2>JSIuAVls9~>RmAR!~; z;_cm?b|!7JroDnz&$|Uvr%qk5a;4_8jT4x5HOHmZ*2+$vJUJpZw)Oa9M+E_gEMH#cV4{E$T6F}uJV-sy6w8Vw%_^pukNhx#H(4X3^}>E2cLh= zyteCZo{p~W%USAMx%O!q%|5H4efiy;mnBl|?d`jsd9H0*ztC^F@a);MXKn25<=qjZ z7yEfh*g?lyJNaeHmv7v$qvP(~SREamgtRm^Sy@@24&A%vu6Fa^AL6)}A@ca~V^lyYKMH!@6wsqbKLn|1aYiHmH+;)6OrKi z^}t_v-yh%Vrteqf7O(gFU3+T2jo#t+?P_OlY&ZAkI)B9X$A{^E%sbD|?i1A5|D}4i zx7hZWM2QdyHc_{e`kSq{ew6uPw@}twZssQaV<&ri_s3Q1&be_iroQeh@9K}qQ~WY7 z9Q|vg^X_$g{q2dza*zL9pr5+t_oA0OE;wsT-YIHL3;-Fn^!kOiq6G(6?N$5t<4lW+ zeq*>><^}7}ne#>V{?3-1bX@%Y%Slmi)rYTNs51UAEw*}Z&WTSRulsmC?c6eF%QT&)|^1Te?K8tf@z|xYz)78&qol`;+ E021Al761SM literal 0 HcmV?d00001 diff --git a/demo_app/test/background/position/bottom_right.png b/demo_app/test/background/position/bottom_right.png new file mode 100644 index 0000000000000000000000000000000000000000..6e4198a87511b224c63ac4a5f601effd5c5f0af4 GIT binary patch literal 1368 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 T=Qd+tG0EWR>gTe~DWM4f#hQQ} literal 0 HcmV?d00001 diff --git a/demo_app/test/background/repeat/no-repeat.png b/demo_app/test/background/repeat/no-repeat.png index 1300262ae84e387e4ce8fb6a6231ca95d03ba39c..60a8728485d79eb0bd31a2737a207ae6edd80ba0 100644 GIT binary patch literal 1458 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 MTiRJPn0Y7t1DX2SxBvhE literal 1432 zcmeAS@N?(olHy`uVBq!ia0vp^B_Pbf1|&mfiKzoA#^NA%Cx&(BWL^R}EX7WqAsj$Z z!;#X#z`*L{>EaktG3V`Ee-GtwndAFUnrU4W_~>sNv1LZrnhhU=CVur_5D@voadv~a z>zkz)^g51Tb9UsqwoSm>zjbe=W6X#orp z5)ux{$%_|0E86M9@3P4`IwLVr(aYO=y%Dz|WA4J25%KZIuUruc3l9&BkMDO-Xt;GN z>TOw)T%>+iS$VmkiAl?}X<|KneT#PPlyr7>?r>3xdV3@$XVvZWhXoRc4E_c_T8qAOLFds>0Kcf4d!=`)n1P&^7gKZ6a6z`hJnQsF6ZB~kL=q2M~?ltp>yt%-=!6+y#;#R zE?&Kwn(?`6F9%!mvn4DB+qbp*FQ3M{b=4-Pny-1?OFy+aE!^@qi&J)H#IY}z{DS^I zIRBY}ot=Hg+_|P(jy`_Y_r!Xl^O?1_zN_x9)H?XLdONSF_7mUMq7!#JWs+1L&YkAn z5eW_rpuOrhW!G^o#j|U3*SU;X8ZecNQm`e&xh9bHaCOyvqB!VEJ3q9-p+bbz3%V zYWnu=oA>Qszkgr6cyZ#ze?f*483(>Bmi@Eivo*tOp!f)?>W47zg%D~JMH9buB8`ZWOfOy)YCt-;6C?u?kIreox4(Szyh#C_&-`yYjY1O>)!~QxP&CcuK z$-M28&6NIAr*wa;(CLPhD0uS#j;w(p{6W616*;TGbJ!o|*9x;@LX2WA14~y1Pgg&e IbxsLQ0C>EuiU0rr diff --git a/demo_app/test/background/repeat/repeat-y.png b/demo_app/test/background/repeat/repeat-y.png index 4d2504318e6b616e2e3b24f161aedcfeb915790a..10352f06671fce1c61e9432417f863fd4e752a53 100644 GIT binary patch delta 1521 zcma)6c~H^`7==ho#Wj!A#)A$kJTf!ZE0Vm;Jj!Iv8>>mvybUy|pI3OC?4ybS^}COur^z}&Fnw>{`=-T-uq_Wyi^z&cFO{2KVfa*7E`du z1{|}ms7roa(});LU}w-NQmzQHi9vZrURlSUR3jBfA!KHn9Xb1&%uo8<);X>$R1Fql z>RBwfp_-SwbJFdDpQP8@;E;uQXV(%Ax=8ctbd^Bq9*za=7{jcL^1R7oV z<~2eQoD*jbt?pld0IB{3%ivp{FgI1G4h*t`m>}JD{Dwc7fkJX1r$Vq;EG=a_rlFzX zSsi!Vj{OyTYfDR^i;Iik;VgC2LkBOyawe z@^b0Q%1Zl_C#`&*%N+3IKR-0;nPNWEvZ{|tY%H3-?z8H=q@^>_V6WsjAnqg*p_hkh z=a%~WQvfs=w6PSJ6vD-!Hh5fn2am+wURO6aH*#gAEGV4sCK$n;Sy8yJ)Jnc|fXXnp z3=R(dS;b~#^5z&1RM-Kr_wXy7yO*0QnbHOZ)vupKE3jHrYlW%yw$2uFG=yQ3Y`mnw z>wGLJwTH)FCw#ox0s>LALs>Xi-H8J>Hw}Sb=tl;!{wxXj#ML0T$r55&Qc+ibGGoVU z3w;Gj58tO26sYTENVbOzMHLH)yRq;i0=Vfk_LmsV8L&`%pLgy%)Dd;-i z9cm|vD=J?0gxyZ-2w&%{zWhL7&!gplhTJ(G_yio1tv zTqHD$Rg9CD(2DSPcMuM_T{RO46();d;7blzvvA9@+Jl5Dr-GN6ZXx6*{hi}^u;$1I zvt!x1f18XVP!GB(QTPl9?8^19$f;%NLs5$3oSmHn9qTBHz?>&eTPxN|Thi|D!9&7; z9?D>y-aas#)~p{WZkKaDcfqlV(R+4XN!swvIIihw$gq)uK3lOK{%v^F;2;eMR+>#!)^&epbjaPZM3F0gL>o79rp)R|C9i(Qmf zBhjwMWYWHL_O#~go4YEQ6k4kwZqSQUHY(A%N2l6S9gUaB6fJyy7YnHx?+N^nXh|As zIv6K+!UYGViInK2*|#kcmCaETN%3BRBlmp?LaxiuO_bQu>9M5}SS9Z~LtKa#iT( zj3UZgx=L{H#;_>gS`o4{u_J&n>pO0ML=DlXos5?NVU`7aNjdrA+YLPNY} zW!Q}my%+Sx=jMv?@*d$4NZE(p{;FjL{|O0$Q~ud~U+&dtvBV1Rqmw4%18h^13D3kw zgN2V&A}U+waQC;;UW|mlBKe7XX)lgpkdrT;Bv3_4liz&+Pmx0h60kH9Rh0eDWSb|zc)}_&D2V(TPn*nV7hF_XU*hObSez~2n-%;6uwbFo z|0})C6^TJqk)}Zf|2aLp{om}{JpSXiR8g{jCEDL)>RU8^Rk2BwUhlr5VpeGNP0kM+ Z({M9Vu>4(r83%GMD_>Igp%eYUT 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 delta 1676 zcmZ8hX;70_8x0CbO2Q5k0tz_Au?h{4iY!%RNid?7ei-%=3j#JsNf0Oo;k78KfS>3W zWRak@&`%UkUJI~xX_nzmRJI`SvTaY(A zfhdBH=c!cY0+Vz+jA+@zw=Yn{a&I{t_0j$j=_bzcu?%5umOl?>*r&jIx7pmZ-IEM| z{k7w=*0oydw}c? zpG1}GHEzaqTWz9E;-zncN8a++e?kz)8!=~9h0)@KBfl;7sYvHHjBY>PTR1oZ=E$)5 zC?VDawx?};Y5GG#SKj^;Wj_@6y!MQbkB`iEjPvUAhlxe+cil;SZwu?39`_E&1b&Gm zT-z7(Tn8!Pnm6Bsi$8I$;55Ks{=v zetuW&CiYXvRBMA`ac%ABLW-qFMtJB+j#5uw-*;!wocG|H?*OZ*T+$VGr`h)7)q?+{ zWWbd!cp5>JcJgjiAF;kS)Yfh(jr*<~B-=0(c^wzRJLH!I`ABckYq>`eM*|kaHOE(| z9rj~xjGn^-cs#xS=g3vs>@HM5I~Rf{HM(K{lkGEaik`c;*;WfG6p6=Ao@9+d9(IAf zy#!o*WaKteQ&aZL$fuNpI;uLWt~?x#aiSdjq$a#E;V@Y;nzkq$uX5!vb26>kl`M(j;_iximun- zddkp)(7M>EE=rkO$*!mJEs}l~U6MG8`jI)PW^U=B$__=v3Y)Oi&@0eguo)O+= zz^#?M8auOGtw7cR?c!I>Lf(_VhxZ?G}?TZbn${$qme}n$S2z36lWHcXx9e z+GmbSci=zvIYa2H$QKjod9-<_x%(`Vb@K6NzPG;CZ>u{U;l z_C%x3#+xr4Q~PY`$`r5q(F?R;i^2we(y#r)B@y-zXb8GDQF&2B;>a63Z0Gycep)W` zi#BHfCo`9MjAn6k?wx0vP_>&0*3h{d&IbKzu?#Q3u;8usIIWkzFQWp`|mi1 dUb?oaVKoUiI2*6egF%ac`%25_f!FEGKL9xVQ}qA< diff --git a/demo_app/test/background/size/auto.png b/demo_app/test/background/size/auto.png index f8b3c366e3a6c84e83fce61f7ee8791a6a42f6c6..94b3aa78f6f59681527cbecfeed368e149f7a483 100644 GIT binary patch delta 1336 zcmbu9{Xf$Q0LSOCGqkQIPc_NIJd{W-PiHpl66Tp=4Cl2Nwq$G-`^rN_!lj%%O~|1( z7b2C7mR2npT~ww#WJFtyWx}|+yZ_)mKfQnYe17=6UT+z=RlOJqU_ITDLDWjo7;s3C zx`QhjiLVxu-$viH6~=cpRn+ppvHd=+-nPY;yAV4bY|$g`(vw?n=oF~EhM=XP4!dWI z@(js#*f2Gp7QuR1J`1I(Dk>|n^X56hAtA&0Qv$bKH3B3l zG0~kwY8hB~{v7juW+uVKJYe6f8!;ilGCw~b$}2$E3Afeqm3JO+ae?9694b=`H5*xG zC-y1^cHXDsS~qe6;fTJz-xkfN`wdc4Qy)Khq5y!r$5he#s9X_e=9Wm3em|M-M3a+x z#9{J|z}hqYHiTnV6>~M&BV_8vVP#@u^`oNxFNY9h=%&rALN5NS9}ZWL^q5`)lyeJrx+Nz|hPWeegaT+SdLB5_ zMK*xZR!%;I6H!Nx>NYnw^IyDB0^M=u-#ftceU3#?H#C^`c?@=q>PJx& zm>)ci#a5v=E2^qAEBaMIcb4XrV<_FTl(jrRJcic9GTU#TnyG&N{E(ZrZqt#GDM^ng zO$oGHI%ru~(t)A{wD-1ZF`Lwk0jTo@98n>w z@QV+rR%f(1(v$Y!j-`+r+e$6p*La?OYP0mlx1fh`ySA=QX?w{gm4<1gQAUS^I2_aX0(%felWHendY1qrg9+IuO!UVq z-OG!K2CYT3g0fhz9?8;D+L1k_#c*F1nE-fx4F5yc;c>C06fFYG>Tyi!Nfr1NN-=@xKdp_zbg5{D|)@gsqp}1>;+aR6AE*F59ZW7ux_+& z9=Ikn8+WK%NWUtcxdIG7znD3X`Ak9c=-|P*MixZQp3E@It6eEh(5Lr};tDKEubV!a zH><^mG2t?8PI<2paYc%KmxhD>wJx*#Xv{-WI3KZXzik?7S z$~RT9C(!adgHo0iFt5)zh_w8HM@Ln{)-^lwZY;lbQRfO!_CFyNazv!?%~d+F&+N8z zjBbB~)h}1I)2nS?ORLXnK)y?lKlg6BDeqRJxuABs!3^Y+E&RDWb34L6+=8-euQ`V2 z;}0swL4n&rB3Id;O4>UB1rPz;8MPs1#I-TSk>tcg4HFX+8dpzG&(Gig#|5kjm={d^ zWy;pfc}TO)5WM%wI)o#eB0FYO!^VQc!}Xs^-POJL?e+HULBifR{-WP%X0FIZdOSYu z4$F>_*)ovhFV7l1$q_9&K8xdXV)-}106c&o<$54yj^$D1TM)rSiYWz=xG+O^tVI*dwZc+qpB~~i?OAsoC by5IK<=C_f-cdHwMK;Po&fpKS|qO$%5uGx_3 delta 1241 zcmV;~1Sb2k3-=0;L4P4hL_t(|obB9CNF!$)#_=b%NhC2O_@^GWB*j!@g^icWvi=Da zDhoYm6Y!#ly_9Yj#AEBBAcfSnprxn6-nLa9(lOCY%+%!l`Ft+RzV9p!ewlY(C+nD!$z%#7MoFPhfPaj|pu#YyFbpaTg9^i- z!Z4^XFK0U-5{X>Jd5}(Zb#)ic^9mIv>lF$Bp->3(^Ydxr!^6XtQlduhW9$oWf zth|Hz{eDbOPh)X$5j#6OSXfxV%*+g0TU&L_ld*Jfiu`{6xe+3f2*$_9vAVhnpU;Ot zAONq|t9zdG%eE=f6_knxAI@Jh3@VHvkN%95ZAmFM#db^L6)Fsa3d5knFsLv^w<$VL z;t1Gyp?@8F#SB!NwPPE91BpZJ*e%=fpU?jR9w&1D+OJxH8>PAbyFySV=)*rv`0_XH zg3?`igzhTsbCFM;l;HORlV-U}zT(~m!U%zq8*<@PFebsqIZ8S zLE`BAovw6Ta)n_~VHi{xW$vNXX5cNS_I_ED;Uld(4j^%;|C5okPlZ&cOi-Ua1)n|p zH-G>A>fE-tDnAvv-}TiG*xgTR#)i7yfX`Eo zcs!2I&Q8so&*#JN@UXEbT>#1ijmGvcxB4t?{Fb{M_wU}+j17%1V`?dycI@t7$ANcu zcQHFVtC>rsWZX-YUvh^gmNi#mG`5GKGk;g|b)tOG-Tfr)JySHQC=JY|;L zi%dUyg1MicVgB(pqOlx4AQebNPyqPg!NY4G6A-ZEo?y&lN(Xh?%-IjRW|R*4(K`(p z$K927bhTX1U-?%$sPDCM3}lEp5NLp>s;mHKRCvm7iUxuWn0ge&PtiXB09`F!bbq(L zj-iR%eimI>SwUM{TgJJ*zCN_Kx95GXS3&up0Ps!!n`rrX3Qn6D1A)xTa5nLHJniYx ziT}RVuGonP>ZvNjK)?s5&2nv*+7lvz0>J&de6u#7_@;=`72S)c&U*_=d_S4?ahTI) zfy-vO)bU$eTe{E5>2$*7a%G$=mL>1c31yaC*9Gw|bG+1-M{>y(hCzj4P+=HUn4;Sh z72CV>RKqKiVFe`!ChLC^Ben1flWzqrlW+wo7npwm+g*>z#qVLX00000NkvXXu0mjf DyI^?j diff --git a/demo_app/test/background/size/contain.png b/demo_app/test/background/size/contain.png index 96ea08ee84479cef5bbf6b8c4ed09ece7cf5b71b..9e8a0ca34467f0158b028fe89ecc2dd4673e80df 100644 GIT binary patch literal 3138 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 PI{*MPvM{VQxD)*kO>X}^ literal 3191 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 diff --git a/demo_app/test/background/size/cover.png b/demo_app/test/background/size/cover.png index 4f9189e7d9812d1678b7d4df3d88d1f04bd1fca1..4191950de2ecaffe616e2ec380b61f90932e14ca 100644 GIT binary patch literal 3151 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 KgG%WAn12AN?HEM> literal 3710 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 From a64130ff2ce6505caf31147017cb7c4f476cee6c Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sun, 29 Oct 2023 13:38:15 +0700 Subject: [PATCH 14/16] [skip ci] Update READMEs --- packages/core/README.md | 12 ++++++++---- packages/enhanced/README.md | 10 +++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/core/README.md b/packages/core/README.md index 22c42b5b6..968a58c94 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -126,17 +126,21 @@ These tags and their contents will be ignored: ### Inline stylings - background: 1 value (color) - - background-color + - background-color: hex values, `rgb()`, `hsl()` or named colors + - background-image: `url()` with support for asset (`asset://`), data uri, local file (`file://`) and network image + - background-repeat: no-repeat/repeat/repeat-x/repeat-y + - background-position: single or double instances of bottom/center/left/right/top (e.g. `top left`) + - background-size: auto/contain/cover - border: 3 values (width style color), 2 values (width style) or 1 value (width) - border-top, border-right, border-bottom, border-left - border-block-start, border-block-end - border-inline-start, border-inline-end -- border-radius: 4, 3, 2 or 1 values with slash support (e.g. `10px / 20px`) +- border-radius: 4, 3, 2 or 1 value with slash support (e.g. `10px / 20px`) - border-top-left-radius: 2 values or 1 value in `em`, `pt` and `px` - border-top-right-radius: 2 values or 1 value in `em`, `pt` and `px` - border-bottom-right-radius: 2 values or 1 value in `em`, `pt` and `px` - border-bottom-left-radius: 2 values or 1 value in `em`, `pt` and `px` -- color: hex values, `rgb()`, `hsl()` or named colors +- color (similar to `background-color` inline styling) - direction (similar to `dir` attribute) - display: block/flex/inline/inline-block/none - In `flex` mode: @@ -171,7 +175,7 @@ These tags and their contents will be ignored: ## Extensibility -This package implements widget building logic with high testing coverage to ensure correctness. It tries to render an optimal tree by using `RichText` with specific `TextStyle`, merging text spans together, showing images in sized box, etc. The idea is to build a solid foundation for apps to customize. +This package implements widget building logic with high testing coverage to ensure correctness. It tries to render an optimal tree by using `RichText` with specific `TextStyle`, collapsing margins, proper whitespace handling, etc. The idea is to build a solid foundation for apps to customize. The [enhanced](https://pub.dev/packages/flutter_widget_from_html) package uses a custom `WidgetFactory` with pre-built mixins for easy usage: diff --git a/packages/enhanced/README.md b/packages/enhanced/README.md index c00594f51..07c123101 100644 --- a/packages/enhanced/README.md +++ b/packages/enhanced/README.md @@ -146,17 +146,21 @@ These tags and their contents will be ignored: ### Inline stylings - background: 1 value (color) - - background-color + - background-color: hex values, `rgb()`, `hsl()` or named colors + - background-image: `url()` with support for asset (`asset://`), data uri, local file (`file://`) and network image + - background-repeat: no-repeat/repeat/repeat-x/repeat-y + - background-position: single or double instances of bottom/center/left/right/top (e.g. `top left`) + - background-size: auto/contain/cover - border: 3 values (width style color), 2 values (width style) or 1 value (width) - border-top, border-right, border-bottom, border-left - border-block-start, border-block-end - border-inline-start, border-inline-end -- border-radius: 4, 3, 2 or 1 values with slash support (e.g. `10px / 20px`) +- border-radius: 4, 3, 2 or 1 value with slash support (e.g. `10px / 20px`) - border-top-left-radius: 2 values or 1 value in `em`, `pt` and `px` - border-top-right-radius: 2 values or 1 value in `em`, `pt` and `px` - border-bottom-right-radius: 2 values or 1 value in `em`, `pt` and `px` - border-bottom-left-radius: 2 values or 1 value in `em`, `pt` and `px` -- color: hex values, `rgb()`, `hsl()` or named colors +- color (similar to `background-color` inline styling) - direction (similar to `dir` attribute) - display: block/flex/inline/inline-block/none - In `flex` mode: From ee75f0a6d7dffaa0543896441edb7d48b10ab408 Mon Sep 17 00:00:00 2001 From: Dao Hoang Son Date: Sun, 29 Oct 2023 13:39:17 +0700 Subject: [PATCH 15/16] [skip ci] Clean up unused golden images --- demo_app/test/fwfh_text_style/Text.png | Bin 4983 -> 0 bytes demo_app/test/fwfh_text_style/Text.rich.png | Bin 4114 -> 0 bytes demo_app/test/fwfh_text_style/TextSpan.png | Bin 4612 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 demo_app/test/fwfh_text_style/Text.png delete mode 100644 demo_app/test/fwfh_text_style/Text.rich.png delete mode 100644 demo_app/test/fwfh_text_style/TextSpan.png diff --git a/demo_app/test/fwfh_text_style/Text.png b/demo_app/test/fwfh_text_style/Text.png deleted file mode 100644 index 6345fe2ab3618824205b5da9e89361455744b8df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4983 zcmeI0TU1k59)}O0K#PDbR&@jeDywx_r7l`h1jL}C$e^G=K<;Y5ltc^=!X+`p(izkW zWUL69LJ%2*BoM9vNw{dSfy!_Za)AH>4HroY5keBeEweK(eVT`Pn}?j2z0NuNoU`}$ z|MqXMb?#sC_p$uc_EQLgEPc;=2SSj^eh4zYVr~kq&{DG!L1Tmu^f?W&`}WO)lWq9Z zzQN|;xNRPL4}xqC_)3;DH}^rv#okl>D!y z+MQoI?>PA7!Q5>&f359gM|xZQ-S)eO797X8Y`cq3Xh*YloJuxMaE4bhGP-pKizr)N zT}AXIn|>vw?W)(}I&Fe5&YtZh$7pKA@5+1vc0-WYtL?fKV+gvVvp3!bLHBlnaeL)J zMi6v;n>hsSbo2uE{$d1ryfNPiLHp0$0i$>Rv+IQt{9eJ}V4%hBqsQe>gsf0;WBd>? z_VT!DrZ7gt&$VNfmzU?kJVKhslKpy%+!}7RsYG9)Jlx$e<6HtKuBQNl#j>1He8I~6 z5UaGbbZy10LT3d*lQ@|uW~>3-&;A+LuFaWax6IP)!!D&IjJ>QYI2soC=!=U?H~g$% z`<}>44we@F+;HbzYw=*YA671^R&_g4gHb3Hr>RNw)8~Gee!8b> z7)9N56oZ-QoVcIuxB22ifMrq%oeLXw!srWNvbEChAZ= z3B$Fe?W?~(aL-tdy-0Im&}cNw%7=I8;yEUZ&3t?$l%5o++uCF?WxrS)t70;34*3h3 z5=JpH0Yk`3Qw;Ix#M?JDi{lhI(FnSOACjhdsTC730f^0%>MM26Z*k{e5Le#$U{^m* zac+*(6Bk?NWZe%PD{^%o%BYz4tr;AWW|4-VWcEJ&rlNgK#=>AQ%!JXVVgfr!$`_8c z;N?FaVSh+ol-G2ycR8LDaKzCONaS5B7*nlQbN{IC;pQxeYho;6?v0YsQQe+UAjHOF z`wo-Av9ZV!vO26ftl`Bi-a=EK6xEei{kdO(;AN83eWH?+rg$G-cl~Vd6X&vMP`f^! zV{UG)YE?=VFVFN~fpX}a>;|oR6vt|5X(>1s^IrS3D-Q-pBx|JkMkb~y_Z=bV8JZxs z>Tc*i8Byj#U0hZ!@)RLRVNJ(YcyDj7aA06y=ChZUmX`30@$-z70~GwB)hD@ZOpU9|>kOIDo^CH+k z^ePY6p?Lco+>&FFNDhaCB#}tD4v2Q5N=8`oCa($p_KA&57#dSeURMi28#O`JL?My6 zws2+-nl2I7Va05G^aQSBGlUgV&2*q_)QQ+pBnf{7zf^(+K|~B`Hjdp`T|$#B6|a9V z19M*PIfjsGgQ$Tp_moN|GgCWLX!~{S`MK;RgojEt2J|c%l4R;OHQ{YULUl|>yQnHG z$aO5SGk$Jey#OlKMRh<(6%OF(uUe*m!qb4Jt0ZEI%^CwSsZmT&_)3Is1CQKXxBQRm zpt$b0R}%~CDo&yRpg9-KD6S(4*Sd7BZTanyiUm)tQj%>2leA8ra^^FP;}(Nr3(9gcU8K0 z8zzU{y+vZw8S6Vn}) zzdqO_&bGAU-n7>NYvjs)M2%KC7g}t^7hQ}8E^$)k2g4h`yX?6#a0U${b-~htBO)Raz+jZazdbsH?aa0WvN+y=pjX-< zY0VV*<7+cH$T)`n%g@g~!01;MsAV`WH39zZw{-Ol=C#gjp~bP*O97s$U_wfYK)?u+ z1Lss*>k4sSu?JQq6T;I!PU@1_C7EjsddBQiCezmWy0`w-=zVEG6eLoZe>e#9Hvh0{ z`cZ&L|Il#lHK9Zj4ib`eh@Spj>2U@my|PTdG3b`Z8=Rb+I9Fe1fe;jixt5kBPrmwI zQhV(Td2PNzzq)O|xp83}-|wjpO74f}54btFgoJ99Tr5^EjIt=YExqVm-PXFCZ-+Y} zKjD%3M`ea`c5{Z9x;QqXRcx+n#2$*)AbpN`lGJ+lv1=>y`o)!j2C^PU^c@CU4@5jo zT{HsaKW_Km_n`k_yE1e&5HJuh5HJuh5HJuh5HJuh5HJw<|0kd`PS5;AZPouZ_$LKH NzGwZt*{82&{Tri1Wc>gD diff --git a/demo_app/test/fwfh_text_style/Text.rich.png b/demo_app/test/fwfh_text_style/Text.rich.png deleted file mode 100644 index cbcc959816a2820574c53f0a2c43e7463a7103ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4114 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 Q{$~IYq0u`zA^Qve0XWlzJ^%m! From 3b0fb18fb48e3a5de8953aeedbb6a4662cddabdf Mon Sep 17 00:00:00 2001 From: Cirrus CI Date: Sun, 29 Oct 2023 06:43:59 +0000 Subject: [PATCH 16/16] Clean up unused golden images --- demo_app/test/li/computeDryLayout.png | Bin 8226 -> 0 bytes demo_app/test/li/issue460/control_group.png | Bin 2906 -> 0 bytes demo_app/test/li/issue460/default_text_style.png | Bin 674 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 demo_app/test/li/computeDryLayout.png delete mode 100644 demo_app/test/li/issue460/control_group.png delete mode 100644 demo_app/test/li/issue460/default_text_style.png diff --git a/demo_app/test/li/computeDryLayout.png b/demo_app/test/li/computeDryLayout.png deleted file mode 100644 index e67420d8cfa9189f4ffb7dcde06a75adb4696726..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8226 zcmeHMX;f3^y57`QY89x*R*Fnj8R`U;c?`!|#fU&#lzC8@WR`@%KpwL!5%SsjhOgeq9aojmJ$zx$ zjJ(ztj{`pb^_wBpZ%04g_WRyXx9n2PjOR7nIkewsPtx}d=R&ufZ}=$KKQUYW9a~w6 zr!JAg+0|guVMyz83FY+^GR#(JYqqsPcdM$Ze!;NsPL0OZVpxpkuFD@`-`#%v0ru6Y zvl7^6YQ-4#$qrb@&sz>+F@NZ-l}T7;=&kz|Y|_JrhK9;VZo$aX{ZHWQQ(L#&Z@A2H6tdrDj$~cqjvYM=h zYddUgY?3`&Z*i`vXElWl2BfO^4A+qI^7BhC&Aolq)8qC0hMb_;I-07&eDjO^4^B?i zEki|htG-GR?|$3E8;V+fJ>RC?agV{!xW4m{V}NsGyyC_O6%~5r<>hHcp}t08Q}zp{ zD-T}YHTQn=$IrP%MIC-cwYTVEAva|WXQE(89B-qM`OQ8(1rED*?b0HzyiahE!N|98 z`j@+5@#qK~iq9U|dC)%b`@6?I^9w5mMo5w}O0?nHNN@gFvmuv8)beb(xiItE*qa^| z=6MQmqa83%=6vbR&#+{xnJOM5Wb)O%y~l4fJ-)oD>-S^Vx5;VU)2aiAr0M$EZkATK zJ<*lJZ8Q@FTbax?3|$(H6L2&sX@!-;MqD~Y@_GlS2P-@3 zMZ9`7d|=f?_EaT1TF_k-ow8N4=4+=wrl&^r)Wh=VY59jN9-~?#V6dXSuf&}=UEb@} z>k{t55oH9`85++#a%WUc=E0+=6gpM1u5RDkW6--=BdOe-V@;=pbmEz_b!&tk2X9Wd zotvdtv~IVxM9DP5L%1^MP!-~16gqh`zo;&vP;85R*U26K^v%eVE5y}_9J}b*{!(v1 zNRQEJoYnHoYi(~9O(A;a4IbBrPcw}SLu+≠taalIF)b5AMe2nPd~WtlYf3mKcdm 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 `4D12@OWd=w^Qv}^Tf5Ak4@=dHVYpgjr zS;hVNjb?bd`tN%;VQ!yg2(KO2e+5F?6EOwR>_D&9(5Lsu`@d6m#pJQCcw0-ZbXNwk z+cJ&y7Z(>dj0;5HGc!d10jjFSL*P=Ar9O9`R}a4D)FmkC@nH18U+_n+$c$%(591+4 zj<=;H?@ch#YL--&4!CgPfe%F=#kqadK_StpR`oMu_Yc0cXOQ9Kh1(6jpdOKv& zM*}9xxDDfi8Xr`4T-U6-tt@&Un?gd33@jd1JZZ+^foK{|(Q)hUVx|9H>9~wO`g{G9 z2Ht8T_xSZ3gaC}dR3#Kh#MBr6Yd=GkVTi-WlFY}G%$1r|Q=O^D<96MLd__0lS{YB@ zMC!Y~x@ggQ>ktu0oDn?qxt(*;czZ?;MJ$p#eE!=dU=U{zR6G@NN24-@3{RxDYq?jAxUVzq)dM|ji+o=p19VXljnc%V@HV*!d#KD-FqGMJXu<>=^SV2r#d5ZS0uS5Dp8c-b!HfLd$5$d~nYFgw{hu6dmC%c-z{V z4$z>KqNr&WD)gp|XP)8%$bQ425q!4e=Z!!HbqIsomhI2j^w z0l$Vql6ZG*hx$11q*G3LjcApJT%?_0L+?F&vTl47Xen}6Wxn0}_nOBS2r~}5ANT6W zTEEs|vuCqJjEq13vM$gMI&Wm(VRwFTamjQE>%UL9`W`Bp)|u+rEPyf!@636YG3pkr zY4a%0B0V|4c(e!XVh6Fqv~nQ+1&{`UBl5xM%rQoub@${BT>3lG|nqs~tugn!2*?RG6F$@PHRus+wNcwP_HrNwn3{}u{Z-~%M z8>{AhIW#Kt7aow_fjW?>-Kz2E%R^2TZLOO1w9A_$fjW-Ky4)14uX#fVaHu1bP_KZ# zgx@d~pgUHTfv*WD=mY$k5YKFg%?y+4SYL;Z2gQ2uR9UDLCV{5TLor5~itj?7&5bs0 z2;&xYT4Jvo#k3c^7+M|>xZ&i3yPZJx{w2?LG9f~DmAISBYHyBNeDQ$6nAwpa6}512 zP}T)?(oo28AUU=}Eu+6g*biZ?2=ZPbe+?$?Z602D`8%qsnUi_>|M8_a zpYHa@Vn0Tg6*>KcVRZcu{-K-y>&uG|cVd4%_vhFC`8Maz4f!vxxBg8xBw)#B6I6qu zT|5k1`J?#Czj{OWZ@Pqyw}*c|+y4)|{drjb)4T8g3wp&eyI&|oHHfc$1n>DV{4uL< J8Q+}!@o)D!c$WYG diff --git a/demo_app/test/li/issue460/control_group.png b/demo_app/test/li/issue460/control_group.png deleted file mode 100644 index b409935a73c2d5a2698d5e757bc29df987ff1586..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2906 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 a%dAYjkRay^^tSqA!1)l)zS1`E%0B=?S|@D) diff --git a/demo_app/test/li/issue460/default_text_style.png b/demo_app/test/li/issue460/default_text_style.png deleted file mode 100644 index ba0f3cc9157916df157a71dc2cba931b568beb23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 674 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>1_mY{PZ!6KiaBrZ81fx55MXeWe)^xk?NE(El!}1L0iU;r&c5QBZ*yHDn_;(} zdpyHA9|ZvxCPz4tSY44+d(!yi9QXST@+nOY0vs%jxQQ9@|5tbBCf_^3(x@Q7!9)?U z!Pe&C`{;i&IFVd~a2JA=xXy51{Pn+Imc74sY#o*C{&4I5o)3?GFuZX4ZI$gWzJe$< hyrF#