Skip to content

Commit ff059b7

Browse files
Merge pull request Sub6Resources#1135 from Sub6Resources/enhancement/margin-values
New CSSBoxWidget and lots of bug fixes
2 parents ee9f478 + 7581ea7 commit ff059b7

33 files changed

+2543
-968
lines changed

example/lib/main.dart

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,20 @@ const htmlData = r"""
5555
<p>The should be <span style='color: rgba(0, 0, 0, 0.10);'>BLACK with 10% alpha style='color: rgba(0, 0, 0, 0.10);</span></p>
5656
<p>The should be <span style='color: rgb(0, 97, 0);'>GREEN style='color: rgb(0, 97, 0);</span></p>
5757
<p>The should be <span style='background-color: red; color: rgb(0, 97, 0);'>GREEN style='color: rgb(0, 97, 0);</span></p>
58-
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
59-
<p style="text-align: right;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
60-
<p style="text-align: justify;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
61-
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
58+
<h3>Text Alignment</h3>
59+
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">Center Aligned Text</span></p>
60+
<p style="text-align: right;"><span style="color: rgba(0, 0, 0, 0.95);">Right Aligned Text</span></p>
61+
<p style="text-align: justify;"><span style="color: rgba(0, 0, 0, 0.95);">Justified Text</span></p>
62+
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">Center Aligned Text</span></p>
63+
<h3>Auto Margins</h3>
64+
<div style="width: 150px; height: 20px; background-color: #ff9999;">Default Div</div>
65+
<div style="width: 150px; height: 20px; background-color: #99ff99; margin: auto;">margin: auto</div>
66+
<div style="width: 150px; height: 20px; background-color: #ff99ff; margin: 15px auto;">margin: 15px auto</div>
67+
<div style="width: 150px; height: 20px; background-color: #9999ff; margin-left: auto;">margin-left: auto</div>
68+
<p>With an image - non-block (should not center):</p>
69+
<img style="margin: auto;" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png">
70+
<p>block image (should center):</p>
71+
<img style="display: block; margin: auto;" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png">
6272
<h3>Table support (with custom styling!):</h3>
6373
<p>
6474
<q>Famous quote...</q>
@@ -297,7 +307,7 @@ class _MyHomePageState extends State<MyHomePage> {
297307
? FlutterLogoStyle.horizontal
298308
: FlutterLogoStyle.markOnly,
299309
textColor: context.style.color!,
300-
size: context.style.fontSize!.size! * 5,
310+
size: context.style.fontSize!.value * 5,
301311
)),
302312
tagMatcher("table"): CustomRender.widget(widget: (context, buildChildren) => SingleChildScrollView(
303313
scrollDirection: Axis.horizontal,

example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ publish_to: none
44
version: 1.0.0+1
55

66
environment:
7-
sdk: '>=2.12.0 <3.0.0'
7+
sdk: '>=2.17.0 <3.0.0'
88

99
dependencies:
1010
flutter_html:

lib/custom_render.dart

Lines changed: 118 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'dart:convert';
66
import 'package:flutter/gestures.dart';
77
import 'package:flutter/material.dart';
88
import 'package:flutter_html/flutter_html.dart';
9+
import 'package:flutter_html/src/html_elements.dart';
910
import 'package:flutter_html/src/utils.dart';
1011

1112
typedef CustomRenderMatcher = bool Function(RenderContext context);
@@ -15,7 +16,8 @@ CustomRenderMatcher tagMatcher(String tag) => (context) {
1516
};
1617

1718
CustomRenderMatcher blockElementMatcher() => (context) {
18-
return context.tree.style.display == Display.BLOCK &&
19+
return (context.tree.style.display == Display.BLOCK ||
20+
context.tree.style.display == Display.INLINE_BLOCK) &&
1921
(context.tree.children.isNotEmpty ||
2022
context.tree.element?.localName == "hr");
2123
};
@@ -116,10 +118,6 @@ CustomRender blockElementRender({Style? style, List<InlineSpan>? children}) =>
116118
children: (children as List<TextSpan>?) ??
117119
context.tree.children
118120
.expandIndexed((i, childTree) => [
119-
if (childTree.style.display == Display.BLOCK &&
120-
i > 0 &&
121-
context.tree.children[i - 1] is ReplacedElement)
122-
TextSpan(text: "\n"),
123121
context.parser.parseTree(context, childTree),
124122
if (i != context.tree.children.length - 1 &&
125123
childTree.style.display == Display.BLOCK &&
@@ -131,117 +129,109 @@ CustomRender blockElementRender({Style? style, List<InlineSpan>? children}) =>
131129
);
132130
}
133131
return WidgetSpan(
134-
child: ContainerSpan(
135-
key: context.key,
136-
newContext: context,
137-
style: style ?? context.tree.style,
138-
shrinkWrap: context.parser.shrinkWrap,
139-
children: children ??
140-
context.tree.children
141-
.expandIndexed((i, childTree) => [
142-
if (context.parser.shrinkWrap &&
143-
childTree.style.display == Display.BLOCK &&
144-
i > 0 &&
145-
context.tree.children[i - 1] is ReplacedElement)
146-
TextSpan(text: "\n"),
147-
context.parser.parseTree(context, childTree),
148-
if (i != context.tree.children.length - 1 &&
149-
childTree.style.display == Display.BLOCK &&
150-
childTree.element?.localName != "html" &&
151-
childTree.element?.localName != "body")
152-
TextSpan(text: "\n"),
153-
])
154-
.toList(),
155-
));
132+
alignment: PlaceholderAlignment.baseline,
133+
baseline: TextBaseline.alphabetic,
134+
child: CssBoxWidget.withInlineSpanChildren(
135+
key: context.key,
136+
style: style ?? context.tree.style,
137+
shrinkWrap: context.parser.shrinkWrap,
138+
childIsReplaced:
139+
REPLACED_EXTERNAL_ELEMENTS.contains(context.tree.name),
140+
children: children ??
141+
context.tree.children
142+
.expandIndexed((i, childTree) => [
143+
context.parser.parseTree(context, childTree),
144+
//TODO can this newline be added in a different step?
145+
if (i != context.tree.children.length - 1 &&
146+
childTree.style.display == Display.BLOCK &&
147+
childTree.element?.localName != "html" &&
148+
childTree.element?.localName != "body")
149+
TextSpan(text: "\n"),
150+
])
151+
.toList(),
152+
),
153+
);
156154
});
157155

158156
CustomRender listElementRender(
159157
{Style? style, Widget? child, List<InlineSpan>? children}) =>
160158
CustomRender.inlineSpan(
161-
inlineSpan: (context, buildChildren) => WidgetSpan(
162-
child: ContainerSpan(
163-
key: context.key,
164-
newContext: context,
165-
style: style ?? context.tree.style,
166-
shrinkWrap: context.parser.shrinkWrap,
167-
child: Row(
168-
crossAxisAlignment: CrossAxisAlignment.start,
169-
mainAxisSize: MainAxisSize.min,
170-
textDirection:
171-
style?.direction ?? context.tree.style.direction,
172-
children: [
173-
(style?.listStylePosition ??
174-
context.tree.style.listStylePosition) ==
175-
ListStylePosition.OUTSIDE
176-
? Padding(
177-
padding: style?.padding?.nonNegative ??
178-
context.tree.style.padding?.nonNegative ??
179-
EdgeInsets.only(
180-
left: (style?.direction ??
181-
context.tree.style.direction) !=
182-
TextDirection.rtl
183-
? 10.0
184-
: 0.0,
185-
right: (style?.direction ??
186-
context.tree.style.direction) ==
187-
TextDirection.rtl
188-
? 10.0
189-
: 0.0),
190-
child: style?.markerContent ??
191-
context.style.markerContent)
192-
: Container(height: 0, width: 0),
193-
Text("\u0020",
194-
textAlign: TextAlign.right,
195-
style: TextStyle(fontWeight: FontWeight.w400)),
196-
Expanded(
197-
child: Padding(
198-
padding: (style?.listStylePosition ??
199-
context.tree.style.listStylePosition) ==
200-
ListStylePosition.INSIDE
201-
? EdgeInsets.only(
202-
left: (style?.direction ??
203-
context.tree.style.direction) !=
204-
TextDirection.rtl
205-
? 10.0
206-
: 0.0,
207-
right: (style?.direction ??
208-
context.tree.style.direction) ==
209-
TextDirection.rtl
210-
? 10.0
211-
: 0.0)
212-
: EdgeInsets.zero,
213-
child: StyledText(
214-
textSpan: TextSpan(
215-
children: _getListElementChildren(
216-
style?.listStylePosition ??
217-
context.tree.style.listStylePosition,
218-
buildChildren)
219-
..insertAll(
220-
0,
221-
context.tree.style.listStylePosition ==
222-
ListStylePosition.INSIDE
223-
? [
224-
WidgetSpan(
225-
alignment:
226-
PlaceholderAlignment
227-
.middle,
228-
child: style?.markerContent ??
229-
context.style
230-
.markerContent ??
231-
Container(
232-
height: 0, width: 0))
233-
]
234-
: []),
235-
style: style?.generateTextStyle() ??
236-
context.style.generateTextStyle(),
237-
),
238-
style: style ?? context.style,
239-
renderContext: context,
240-
)))
241-
],
159+
inlineSpan: (context, buildChildren) => WidgetSpan(
160+
child: CssBoxWidget(
161+
key: context.key,
162+
style: style ?? context.tree.style,
163+
shrinkWrap: context.parser.shrinkWrap,
164+
child: Row(
165+
crossAxisAlignment: CrossAxisAlignment.start,
166+
mainAxisSize: MainAxisSize.min,
167+
textDirection: style?.direction ?? context.tree.style.direction,
168+
children: [
169+
(style?.listStylePosition ??
170+
context.tree.style.listStylePosition) ==
171+
ListStylePosition.OUTSIDE
172+
? Padding(
173+
padding: style?.padding?.nonNegative ??
174+
context.tree.style.padding?.nonNegative ??
175+
EdgeInsets.only(
176+
left: (style?.direction ??
177+
context.tree.style.direction) !=
178+
TextDirection.rtl
179+
? 10.0
180+
: 0.0,
181+
right: (style?.direction ??
182+
context.tree.style.direction) ==
183+
TextDirection.rtl
184+
? 10.0
185+
: 0.0),
186+
child:
187+
style?.markerContent ?? context.style.markerContent)
188+
: Container(height: 0, width: 0),
189+
Text("\u0020",
190+
textAlign: TextAlign.right,
191+
style: TextStyle(fontWeight: FontWeight.w400)),
192+
Expanded(
193+
child: Padding(
194+
padding: (style?.listStylePosition ??
195+
context.tree.style.listStylePosition) ==
196+
ListStylePosition.INSIDE
197+
? EdgeInsets.only(
198+
left: (style?.direction ??
199+
context.tree.style.direction) !=
200+
TextDirection.rtl
201+
? 10.0
202+
: 0.0,
203+
right: (style?.direction ??
204+
context.tree.style.direction) ==
205+
TextDirection.rtl
206+
? 10.0
207+
: 0.0)
208+
: EdgeInsets.zero,
209+
child: CssBoxWidget.withInlineSpanChildren(
210+
children: _getListElementChildren(
211+
style?.listStylePosition ??
212+
context.tree.style.listStylePosition,
213+
buildChildren)
214+
..insertAll(
215+
0,
216+
context.tree.style.listStylePosition ==
217+
ListStylePosition.INSIDE
218+
? [
219+
WidgetSpan(
220+
alignment: PlaceholderAlignment.middle,
221+
child: style?.markerContent ??
222+
context.style.markerContent ??
223+
Container(height: 0, width: 0))
224+
]
225+
: []),
226+
style: style ?? context.style,
227+
),
242228
),
243229
),
244-
));
230+
],
231+
),
232+
),
233+
),
234+
);
245235

246236
CustomRender replacedElementRender(
247237
{PlaceholderAlignment? alignment,
@@ -482,14 +472,9 @@ CustomRender verticalAlignRender(
482472
key: context.key,
483473
offset: Offset(
484474
0, verticalOffset ?? _getVerticalOffset(context.tree)),
485-
child: StyledText(
486-
textSpan: TextSpan(
487-
style: style?.generateTextStyle() ??
488-
context.style.generateTextStyle(),
489-
children: children ?? buildChildren.call(),
490-
),
475+
child: CssBoxWidget.withInlineSpanChildren(
476+
children: children ?? buildChildren.call(),
491477
style: context.style,
492-
renderContext: context,
493478
),
494479
),
495480
));
@@ -512,19 +497,21 @@ CustomRender fallbackRender({Style? style, List<InlineSpan>? children}) =>
512497
.toList(),
513498
));
514499

515-
final Map<CustomRenderMatcher, CustomRender> defaultRenders = {
516-
blockElementMatcher(): blockElementRender(),
517-
listElementMatcher(): listElementRender(),
518-
textContentElementMatcher(): textContentElementRender(),
519-
dataUriMatcher(): base64ImageRender(),
520-
assetUriMatcher(): assetImageRender(),
521-
networkSourceMatcher(): networkImageRender(),
522-
replacedElementMatcher(): replacedElementRender(),
523-
interactableElementMatcher(): interactableElementRender(),
524-
layoutElementMatcher(): layoutElementRender(),
525-
verticalAlignMatcher(): verticalAlignRender(),
526-
fallbackMatcher(): fallbackRender(),
527-
};
500+
Map<CustomRenderMatcher, CustomRender> generateDefaultRenders() {
501+
return {
502+
blockElementMatcher(): blockElementRender(),
503+
listElementMatcher(): listElementRender(),
504+
textContentElementMatcher(): textContentElementRender(),
505+
dataUriMatcher(): base64ImageRender(),
506+
assetUriMatcher(): assetImageRender(),
507+
networkSourceMatcher(): networkImageRender(),
508+
replacedElementMatcher(): replacedElementRender(),
509+
interactableElementMatcher(): interactableElementRender(),
510+
layoutElementMatcher(): layoutElementRender(),
511+
verticalAlignMatcher(): verticalAlignRender(),
512+
fallbackMatcher(): fallbackRender(),
513+
};
514+
}
528515

529516
List<InlineSpan> _getListElementChildren(
530517
ListStylePosition? position, Function() buildChildren) {
@@ -585,9 +572,9 @@ final _dataUriFormat = RegExp(
585572
double _getVerticalOffset(StyledElement tree) {
586573
switch (tree.style.verticalAlign) {
587574
case VerticalAlign.SUB:
588-
return tree.style.fontSize!.size! / 2.5;
575+
return tree.style.fontSize!.value / 2.5;
589576
case VerticalAlign.SUPER:
590-
return tree.style.fontSize!.size! / -2.5;
577+
return tree.style.fontSize!.value / -2.5;
591578
default:
592579
return 0;
593580
}

0 commit comments

Comments
 (0)