Skip to content

Commit 7da128c

Browse files
committed
Add support for auto horizontal margins
1 parent 1fc97f1 commit 7da128c

File tree

6 files changed

+238
-88
lines changed

6 files changed

+238
-88
lines changed

example/lib/main.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ const htmlData = r"""
5757
<p style="text-align: right;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
5858
<p style="text-align: justify;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
5959
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
60+
<div style="width: 150px; height: 20px; background-color: red; margin: auto;">Centered Div</div>
61+
<div style="width: 150px; height: 20px; background-color: yellow; margin-left: auto;">margin-left: auto div</div>
6062
<h3>Table support (with custom styling!):</h3>
6163
<p>
6264
<q>Famous quote...</q>
@@ -272,8 +274,7 @@ class _MyHomePageState extends State<MyHomePage> {
272274
"table": (context, child) {
273275
return SingleChildScrollView(
274276
scrollDirection: Axis.horizontal,
275-
child:
276-
(context.tree as TableLayoutElement).toWidget(context),
277+
child: (context.tree as TableLayoutElement).toWidget(context),
277278
);
278279
},
279280
"bird": (RenderContext context, Widget child) {
@@ -294,8 +295,7 @@ class _MyHomePageState extends State<MyHomePage> {
294295
(context, attributes, element) {
295296
return FlutterLogo(size: 36);
296297
},
297-
networkSourceMatcher(domains: ["mydomain.com"]):
298-
networkImageRender(
298+
networkSourceMatcher(domains: ["mydomain.com"]): networkImageRender(
299299
headers: {"Custom-Header": "some-value"},
300300
altWidget: (alt) => Text(alt ?? ""),
301301
loadingWidget: () => Text("Loading..."),

lib/html_parser.dart

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ class HtmlParser extends StatelessWidget {
848848
if (tree.children.isEmpty) {
849849
// Handle case (4) from above.
850850
if ((tree.style.height ?? 0) == 0) {
851-
tree.style.margin = EdgeInsets.zero;
851+
tree.style.margin = Margins.all(0);
852852
}
853853
return tree;
854854
}
@@ -864,72 +864,73 @@ class HtmlParser extends StatelessWidget {
864864
// Handle case (1) from above.
865865
// Top margins cannot collapse if the element has padding
866866
if ((tree.style.padding?.top ?? 0) == 0) {
867-
final parentTop = tree.style.margin?.top ?? 0;
868-
final firstChildTop = tree.children.first.style.margin?.top ?? 0;
867+
final parentTop = tree.style.margin?.top?.value ?? 0;
868+
final firstChildTop = tree.children.first.style.margin?.top?.value ?? 0;
869869
final newOuterMarginTop = max(parentTop, firstChildTop);
870870

871871
// Set the parent's margin
872872
if (tree.style.margin == null) {
873-
tree.style.margin = EdgeInsets.only(top: newOuterMarginTop);
873+
tree.style.margin = Margins(top: Margin(value: newOuterMarginTop));
874874
} else {
875-
tree.style.margin = tree.style.margin!.copyWith(top: newOuterMarginTop);
875+
tree.style.margin = tree.style.margin!.copyWith(top: Margin(value: newOuterMarginTop));
876876
}
877877

878878
// And remove the child's margin
879879
if (tree.children.first.style.margin == null) {
880-
tree.children.first.style.margin = EdgeInsets.zero;
880+
tree.children.first.style.margin = Margins.all(0);
881881
} else {
882882
tree.children.first.style.margin =
883-
tree.children.first.style.margin!.copyWith(top: 0);
883+
tree.children.first.style.margin!.copyWith(top: Margin(value: 0));
884884
}
885885
}
886886

887887
// Handle case (3) from above.
888888
// Bottom margins cannot collapse if the element has padding
889889
if ((tree.style.padding?.bottom ?? 0) == 0) {
890-
final parentBottom = tree.style.margin?.bottom ?? 0;
891-
final lastChildBottom = tree.children.last.style.margin?.bottom ?? 0;
890+
final parentBottom = tree.style.margin?.bottom?.value ?? 0;
891+
final lastChildBottom = tree.children.last.style.margin?.bottom?.value ?? 0;
892892
final newOuterMarginBottom = max(parentBottom, lastChildBottom);
893893

894894
// Set the parent's margin
895895
if (tree.style.margin == null) {
896-
tree.style.margin = EdgeInsets.only(bottom: newOuterMarginBottom);
896+
tree.style.margin = Margins(bottom: Margin(value: newOuterMarginBottom));
897897
} else {
898-
tree.style.margin =
899-
tree.style.margin!.copyWith(bottom: newOuterMarginBottom);
898+
tree.style.margin = tree.style.margin!.copyWith(bottom: Margin(value: newOuterMarginBottom));
900899
}
901900

902901
// And remove the child's margin
903902
if (tree.children.last.style.margin == null) {
904-
tree.children.last.style.margin = EdgeInsets.zero;
903+
tree.children.last.style.margin = Margins.all(0);
905904
} else {
906905
tree.children.last.style.margin =
907-
tree.children.last.style.margin!.copyWith(bottom: 0);
906+
tree.children.last.style.margin!.copyWith(bottom: Margin(
907+
value: 0
908+
));
908909
}
909910
}
910911

911912
// Handle case (2) from above.
912913
if (tree.children.length > 1) {
913914
for (int i = 1; i < tree.children.length; i++) {
914915
final previousSiblingBottom =
915-
tree.children[i - 1].style.margin?.bottom ?? 0;
916-
final thisTop = tree.children[i].style.margin?.top ?? 0;
916+
tree.children[i - 1].style.margin?.bottom?.value ?? 0;
917+
final thisTop = tree.children[i].style.margin?.top?.value ?? 0;
917918
final newInternalMargin = max(previousSiblingBottom, thisTop) / 2;
918919

919920
if (tree.children[i - 1].style.margin == null) {
920921
tree.children[i - 1].style.margin =
921-
EdgeInsets.only(bottom: newInternalMargin);
922+
Margins(bottom: Margin(value: newInternalMargin));
922923
} else {
923924
tree.children[i - 1].style.margin = tree.children[i - 1].style.margin!
924-
.copyWith(bottom: newInternalMargin);
925+
.copyWith(bottom: Margin(value: newInternalMargin));
925926
}
926927

927928
if (tree.children[i].style.margin == null) {
928929
tree.children[i].style.margin =
929-
EdgeInsets.only(top: newInternalMargin);
930+
Margins(top: Margin(value: newInternalMargin));
930931
} else {
931932
tree.children[i].style.margin =
932-
tree.children[i].style.margin!.copyWith(top: newInternalMargin);
933+
tree.children[i].style.margin!.copyWith(top: Margin(value: newInternalMargin));
933934
}
934935
}
935936
}
@@ -1036,15 +1037,15 @@ class ContainerSpan extends StatelessWidget {
10361037

10371038
@override
10381039
Widget build(BuildContext _) {
1039-
return Container(
1040+
Widget container = Container(
10401041
decoration: BoxDecoration(
10411042
border: style.border,
10421043
color: style.backgroundColor,
10431044
),
10441045
height: style.height,
10451046
width: style.width,
10461047
padding: style.padding,
1047-
margin: style.margin,
1048+
margin: style.margin?.asInsets,
10481049
alignment: shrinkWrap ? null : style.alignment,
10491050
child: child ??
10501051
StyledText(
@@ -1056,6 +1057,13 @@ class ContainerSpan extends StatelessWidget {
10561057
renderContext: newContext,
10571058
),
10581059
);
1060+
if(style.margin?.isAutoHorizontal ?? false) {
1061+
return Row(
1062+
mainAxisAlignment: style.margin?.alignment ?? MainAxisAlignment.start,
1063+
children: [container],
1064+
);
1065+
}
1066+
return container;
10591067
}
10601068
}
10611069

lib/src/css_parser.dart

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -209,30 +209,31 @@ Style declarationsToStyle(Map<String, List<css.Expression>> declarations) {
209209
&& !(element is css.EmTerm)
210210
&& !(element is css.RemTerm)
211211
&& !(element is css.NumberTerm)
212+
&& !(element.text == 'auto')
212213
);
213-
List<double?> margin = ExpressionMapping.expressionToPadding(marginLengths);
214-
style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
215-
left: margin[0],
216-
right: margin[1],
217-
top: margin[2],
218-
bottom: margin[3],
214+
Margins margin = ExpressionMapping.expressionToMargins(marginLengths);
215+
style.margin = (style.margin ?? Margins.all(0)).copyWith(
216+
left: margin.left,
217+
right: margin.right,
218+
top: margin.top,
219+
bottom: margin.bottom,
219220
);
220221
break;
221222
case 'margin-left':
222-
style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
223-
left: ExpressionMapping.expressionToPaddingLength(value.first));
223+
style.margin = (style.margin ?? Margins.all(0)).copyWith(
224+
left: ExpressionMapping.expressionToMargin(value.first));
224225
break;
225226
case 'margin-right':
226-
style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
227-
right: ExpressionMapping.expressionToPaddingLength(value.first));
227+
style.margin = (style.margin ?? Margins.all(0)).copyWith(
228+
right: ExpressionMapping.expressionToMargin(value.first));
228229
break;
229230
case 'margin-top':
230-
style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
231-
top: ExpressionMapping.expressionToPaddingLength(value.first));
231+
style.margin = (style.margin ?? Margins.all(0))..copyWith(
232+
top: ExpressionMapping.expressionToMargin(value.first));
232233
break;
233234
case 'margin-bottom':
234-
style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
235-
bottom: ExpressionMapping.expressionToPaddingLength(value.first));
235+
style.margin = (style.margin ?? Margins.all(0))..copyWith(
236+
bottom: ExpressionMapping.expressionToMargin(value.first));
236237
break;
237238
case 'padding':
238239
List<css.LiteralTerm>? paddingLengths = value.whereType<css.LiteralTerm>().toList();
@@ -696,6 +697,55 @@ class ExpressionMapping {
696697
return null;
697698
}
698699

700+
static Margin? expressionToMargin(css.Expression value) {
701+
if((value as dynamic).text == 'auto') {
702+
return Margin(
703+
type: MarginType.AUTO
704+
);
705+
} else {
706+
return Margin(
707+
type: MarginType.VALUE,
708+
value: expressionToPaddingLength(value)
709+
);
710+
}
711+
}
712+
713+
static Margins expressionToMargins(List<css.Expression>? lengths) {
714+
Margin? left;
715+
Margin? right;
716+
Margin? top;
717+
Margin? bottom;
718+
if (lengths != null && lengths.isNotEmpty) {
719+
top = expressionToMargin(lengths.first);
720+
if (lengths.length == 4) {
721+
right = expressionToMargin(lengths[1]);
722+
bottom = expressionToMargin(lengths[2]);
723+
left = expressionToMargin(lengths.last);
724+
}
725+
if (lengths.length == 3) {
726+
left = expressionToMargin(lengths[1]);
727+
right = expressionToMargin(lengths[1]);
728+
bottom = expressionToMargin(lengths.last);
729+
}
730+
if (lengths.length == 2) {
731+
bottom = expressionToMargin(lengths.first);
732+
left = expressionToMargin(lengths.last);
733+
right = expressionToMargin(lengths.last);
734+
}
735+
if (lengths.length == 1) {
736+
bottom = expressionToMargin(lengths.first);
737+
left = expressionToMargin(lengths.first);
738+
right = expressionToMargin(lengths.first);
739+
}
740+
}
741+
return Margins(
742+
left: left,
743+
right: right,
744+
top: top,
745+
bottom: bottom
746+
);
747+
}
748+
699749
static List<double?> expressionToPadding(List<css.Expression>? lengths) {
700750
double? left;
701751
double? right;
@@ -727,6 +777,7 @@ class ExpressionMapping {
727777
return [left, right, top, bottom];
728778
}
729779

780+
730781
static double? expressionToPaddingLength(css.Expression value) {
731782
if (value is css.NumberTerm) {
732783
return double.tryParse(value.text);

0 commit comments

Comments
 (0)