8000 Add support for auto horizontal margins by zbarbuto · Pull Request #879 · Sub6Resources/flutter_html · GitHub
[go: up one dir, main page]

Skip to content

Add support for auto horizontal margins #879

New issue

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

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

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,20 @@ const htmlData = r"""
<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>
<p>The should be <span style='color: rgb(0, 97, 0);'>GREEN style='color: rgb(0, 97, 0);</span></p>
<p>The should be <span style='background-color: red; color: rgb(0, 97, 0);'>GREEN style='color: rgb(0, 97, 0);</span></p>
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<p style="text-align: right;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<p style="text-align: justify;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<h3>Text Alignment</h3>
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">Center Aligned Text</span></p>
<p style="text-align: right;"><span style="color: rgba(0, 0, 0, 0.95);">Right Aligned Text</span></p>
<p style="text-align: justify;"><span style="color: rgba(0, 0, 0, 0.95);">Justified Text</span></p>
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">Center Aligned Text</span></p>
<h3>Auto Margins</h3>
<div style="width: 150px; height: 20px; background-color: #ff9999;">Default Div</div>
<div style="width: 150px; height: 20px; background-color: #99ff99; margin: auto;">margin: auto</div>
<div style="width: 150px; height: 20px; background-color: #ff99ff; margin: 15px auto;">margin: 15px auto</div>
<div style="width: 150px; height: 20px; background-color: #9999ff; margin-left: auto;">margin-left: auto</div>
<p>With an image - non-block (should not center):</p>
<img style="margin: auto;" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png">
<p>block image (should center):</p>
<img style="display: block; margin: auto;" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png">
<h3>Table support (with custom styling!):</h3>
<p>
<q>Famous quote...</q>
Expand Down
53 changes: 31 additions & 22 deletions lib/html_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ class HtmlParser extends StatelessWidget {
if (tree.children.isEmpty) {
// Handle case (4) from above.
if ((tree.style.height ?? 0) == 0) {
tree.style.margin = EdgeInsets.zero;
tree.style.margin = tree.style.margin?.collapse() ?? Margins.zero;
}
return tree;
}
Expand All @@ -668,72 +668,72 @@ class HtmlParser extends StatelessWidget {
// Handle case (1) from above.
// Top margins cannot collapse if the element has padding
if ((tree.style.padding?.top ?? 0) == 0) {
final parentTop = tree.style.margin?.top ?? 0;
final firstChildTop = tree.children.first.style.margin?.top ?? 0;
final parentTop = tree.style.margin?.top?.value ?? 0;
final firstChildTop = tree.children.first.style.margin?.top?.value ?? 0;
final newOuterMarginTop = max(parentTop, firstChildTop);

// Set the parent's margin
if (tree.style.margin == null) {
tree.style.margin = EdgeInsets.only(top: newOuterMarginTop);
tree.style.margin = Margins.only(top: newOuterMarginTop);
} else {
tree.style.margin = tree.style.margin!.copyWith(top: newOuterMarginTop);
tree.style.margin = tree.style.margin!.copyWithEdge(top: newOuterMarginTop);
}

// And remove the child's margin
if (tree.children.first.style.margin == null) {
tree.children.first.style.margin = EdgeInsets.zero;
tree.children.first.style.margin = Margins.zero;
} else {
tree.children.first.style.margin =
tree.children.first.style.margin!.copyWith(top: 0);
tree.children.first.style.margin!.copyWithEdge(top: 0);
}
}

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

// Set the parent's margin
if (tree.style.margin == null) {
tree.style.margin = EdgeInsets.only(bottom: newOuterMarginBottom);
tree.style.margin = Margins.only(bottom: newOuterMarginBottom);
} else {
tree.style.margin =
tree.style.margin!.copyWith(bottom: newOuterMarginBottom);
tree.style.margin!.copyWithEdge(bottom: newOuterMarginBottom);
}

// And remove the child's margin
if (tree.children.last.style.margin == null) {
tree.children.last.style.margin = EdgeInsets.zero;
tree.children.last.style.margin = Margins.zero;
} else {
tree.children.last.style.margin =
tree.children.last.style.margin!.copyWith(bottom: 0);
tree.children.last.style.margin!.copyWithEdge(bottom: 0);
}
}

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

if (tree.children[i - 1].style.margin == null) {
tree.children[i - 1].style.margin =
EdgeInsets.only(bottom: newInternalMargin);
Margins.only(bottom: newInternalMargin);
} else {
tree.children[i - 1].style.margin = tree.children[i - 1].style.margin!
.copyWith(bottom: newInternalMargin);
.copyWithEdge(bottom: newInternalMargin);
}

if (tree.children[i].style.margin == null) {
tree.children[i].style.margin =
EdgeInsets.only(top: newInternalMargin);
Margins.only(top: newInternalMargin);
} else {
tree.children[i].style.margin =
tree.children[i].style.margin!.copyWith(top: newInternalMargin);
tree.children[i].style.margin!.copyWithEdge(top: newInternalMargin);
}
}
}
Expand Down Expand Up @@ -847,16 +847,23 @@ class ContainerSpan extends StatelessWidget {

@override
Widget build(BuildContext _) {
return Container(

// Elements that are inline should ignore margin: auto for alignment.
var alignment = shrinkWrap ? null : style.alignment;
if(style.display == Display.BLOCK) {
alignment = style.margin?.alignment ?? alignment;
}

Widget container = Container(
decoration: BoxDecoration(
border: style.border,
color: style.backgroundColor,
),
height: style.height,
width: style.width,
padding: style.padding?.nonNegative,
margin: style.margin?.nonNegative,
alignment: shrinkWrap ? null : style.alignment,
margin: style.margin?.asInsets.nonNegative,
alignment: alignment,
child: child ??
StyledText(
textSpan: TextSpan(
Expand All @@ -867,6 +874,8 @@ class ContainerSpan extends StatelessWidget {
renderContext: newContext,
),
);

return container;
}
}

Expand Down
68 changes: 54 additions & 14 deletions lib/src/css_parser.dart
2364
Original file line number Diff line number Diff line change
Expand Up @@ -244,30 +244,31 @@ Style declarationsToStyle(Map<String, List<css.Expression>> declarations) {
&& !(element is css.EmTerm)
&& !(element is css.RemTerm)
&& !(element is css.NumberTerm)
&& !(element.text == 'auto')
);
List<double?> margin = ExpressionMapping.expressionToPadding(marginLengths);
style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
left: margin[0],
right: margin[1],
top: margin[2],
bottom: margin[3],
Margins margin = ExpressionMapping.expressionToMargins(marginLengths);
style.margin = (style.margin ?? Margins.all(0)).copyWith(
left: margin.left,
right: margin.right,
top: margin.top,
bottom: margin.bottom,
);
break;
case 'margin-left':
style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
left: ExpressionMapping.expressionToPaddingLength(value.first));
style.margin = (style.margin ?? Margins.zero).copyWith(
left: ExpressionMapping.expressionToMargin(value.first));
break;
case 'margin-right':
style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
right: ExpressionMapping.expressionToPaddingLength(value.first));
style.margin = (style.margin ?? Margins.zero).copyWith(
right: ExpressionMapping.expressionToMargin(value.first));
break;
case 'margin-top':
style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
top: ExpressionMapping.expressionToPaddingLength(value.first));
style.margin = (style.margin ?? Margins.zero).copyWith(
top: ExpressionMapping.expressionToMargin(value.first));
break;
case 'margin-bottom':
style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
bottom: ExpressionMapping.expressionToPaddingLength(value.first));
style.margin = (style.margin ?? Margins.zero).copyWith(
bottom: ExpressionMapping.expressionToMargin(value.first));
break;
case 'padding':
List<css.LiteralTerm>? paddingLengths = value.whereType<css.LiteralTerm>().toList();
Expand Down Expand Up @@ -748,6 +749,45 @@ class ExpressionMapping {
return null;
}

static Margin? expressionToMargin(css.Expression value) {
if ((value is css.LiteralTerm) && value.text == 'auto') {
return AutoMargin();
} else {
return InsetMargin(expressionToPaddingLength(value) ?? 0);
}
}

static Margins expressionToMargins(List<css.Expression>? lengths) {
Margin? left;
Margin? right;
Margin? top;
Margin? bottom;
if (lengths != null && lengths.isNotEmpty) {
top = expressionToMargin(lengths.first);
if (lengths.length == 4) {
right = expressionToMargin(lengths[1]);
bottom = expressionToMargin(lengths[2]);
left = expressionToMargin(lengths.last);
}
if (lengths.length == 3) {
left = expressionToMargin(lengths[1]);
right = expressionToMargin(lengths[1]);
bottom = expressionToMargin(lengths.last);
}
if (lengths.length == 2) {
bottom = expressionToMargin(lengths.first);
left = expressionToMargin(lengths.last);
right = expressionToMargin(lengths.last);
}
if (lengths.length == 1) {
bottom = expressionToMargin(lengths.first);
left = expressionToMargin(lengths.first);
right = expressionToMargin(lengths.first);
}
}
return Margins(left: left, right: right, top: top, bottom: bottom);
}

static List<double?> expressionToPadding(List<css.Expression>? lengths) {
double? left;
double? right;
Expand Down
32 changes: 16 additions & 16 deletions lib/src/styled_element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,19 @@ StyledElement parseStyledElement(
//TODO(Sub6Resources) this is a workaround for collapsing margins. Remove.
if (element.parent!.localName == "blockquote") {
styledElement.style = Style(
margin: const EdgeInsets.only(left: 40.0, right: 40.0, bottom: 14.0),
margin: Margins.only(left: 40.0, right: 40.0, bottom: 14.0),
display: Display.BLOCK,
);
} else {
styledElement.style = Style(
margin: const EdgeInsets.symmetric(horizontal: 40.0, vertical: 14.0),
margin: Margins.symmetric(horizontal: 40.0, vertical: 14.0),
display: Display.BLOCK,
);
}
break;
case "body":
styledElement.style = Style(
margin: EdgeInsets.all(8.0),
margin: Margins.all(8.0),
display: Display.BLOCK,
);
break;
Expand All @@ -134,7 +134,7 @@ StyledElement parseStyledElement(
break;
case "dd":
styledElement.style = Style(
margin: EdgeInsets.only(left: 40.0),
margin: Margins.only(left: 40.0),
display: Display.BLOCK,
);
break;
Expand All @@ -148,13 +148,13 @@ StyledElement parseStyledElement(
continue italics;
case "div":
styledElement.style = Style(
margin: EdgeInsets.all(0),
margin: Margins.all(0),
display: Display.BLOCK,
);
break;
case "dl":
styledElement.style = Style(
margin: EdgeInsets.symmetric(vertical: 14.0),
margin: Margins.symmetric(vertical: 14.0),
display: Display.BLOCK,
);
break;
Expand All @@ -172,7 +172,7 @@ StyledElement parseStyledElement(
break;
case "figure":
styledElement.style = Style(
margin: EdgeInsets.symmetric(vertical: 14.0, horizontal: 40.0),
margin: Margins.symmetric(vertical: 14.0, horizontal: 40.0),
display: Display.BLOCK,
);
break;
Expand All @@ -196,47 +196,47 @@ StyledElement parseStyledElement(
styledElement.style = Style(
fontSize: FontSize.xxLarge,
fontWeight: FontWeight.bold,
margin: EdgeInsets.symmetric(vertical: 18.67),
margin: Margins.symmetric(vertical: 18.67),
display: Display.BLOCK,
);
break;
case "h2":
styledElement.style = Style(
fontSize: FontSize.xLarge,
fontWeight: FontWeight.bold,
margin: EdgeInsets.symmetric(vertical: 17.5),
margin: Margins.symmetric(vertical: 17.5),
display: Display.BLOCK,
);
break;
case "h3":
styledElement.style = Style(
fontSize: FontSize(16.38),
fontWeight: FontWeight.bold,
margin: EdgeInsets.symmetric(vertical: 16.5),
margin: Margins.symmetric(vertical: 16.5),
display: Display.BLOCK,
);
break;
case "h4":
styledElement.style = Style(
fontSize: FontSize.medium,
fontWeight: FontWeight.bold,
margin: EdgeInsets.symmetric(vertical: 18.5),
margin: Margins.symmetric(vertical: 18.5),
display: Display.BLOCK,
);
break;
case "h5":
styledElement.style = Style(
fontSize: FontSize(11.62),
fontWeight: FontWeight.bold,
margin: EdgeInsets.symmetric(vertical: 19.25),
margin: Margins.symmetric(vertical: 19.25),
display: Display.BLOCK,
);
break;
case "h6":
styledElement.style = Style(
fontSize: FontSize(9.38),
fontWeight: FontWeight.bold,
margin: EdgeInsets.symmetric(vertical: 22),
margin: Margins.symmetric(vertical: 22),
display: Display.BLOCK,
);
break;
Expand All @@ -247,7 +247,7 @@ StyledElement parseStyledElement(
break;
case "hr":
styledElement.style = Style(
margin: EdgeInsets.symmetric(vertical: 7.0),
margin: Margins.symmetric(vertical: 7.0),
width: double.infinity,
height: 1,
backgroundColor: Colors.black,
Expand Down Expand Up @@ -318,14 +318,14 @@ StyledElement parseStyledElement(
break;
case "p":
styledElement.style = Style(
margin: EdgeInsets.symmetric(vertical: 14.0),
margin: Margins.symmetric(vertical: 14.0),
display: Display.BLOCK,
);
break;
case "pre":
styledElement.style = Style(
fontFamily: 'monospace',
margin: EdgeInsets.symmetric(vertical: 14.0),
margin: Margins.symmetric(vertical: 14.0),
whiteSpace: WhiteSpace.PRE,
display: Display.BLOCK,
);
Expand Down
Loading
0