Skip to content

Commit

Permalink
feat: support vertical-align in inline styles (#1266)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sub6Resources committed May 15, 2023
1 parent d7247cb commit fe896de
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 25 deletions.
26 changes: 26 additions & 0 deletions lib/src/css_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,10 @@ Style declarationsToStyle(Map<String, List<css.Expression>> declarations) {
style.textTransform = TextTransform.none;
}
break;
case 'vertical-align':
style.verticalAlign =
ExpressionMapping.expressionToVerticalAlign(value.first);
break;
case 'width':
style.width =
ExpressionMapping.expressionToWidth(value.first) ?? style.width;
Expand Down Expand Up @@ -1212,6 +1216,28 @@ class ExpressionMapping {
return finalShadows;
}

static VerticalAlign expressionToVerticalAlign(css.Expression value) {
if (value is css.LiteralTerm) {
switch (value.text) {
case "sub":
return VerticalAlign.sub;
case "super":
return VerticalAlign.sup;
case "bottom":
return VerticalAlign.bottom;
case "top":
return VerticalAlign.top;
case "middle":
return VerticalAlign.middle;
case "baseline":
default:
return VerticalAlign.baseline;
}
}

return VerticalAlign.baseline;
}

static Color stringToColor(String rawText) {
var text = rawText.replaceFirst('#', '');
if (text.length == 3) {
Expand Down
45 changes: 23 additions & 22 deletions lib/src/style.dart
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ class Style {
/// CSS attribute "`vertical-align`"
///
/// Inherited: no,
/// Default: VerticalAlign.BASELINE,
VerticalAlign? verticalAlign;
/// Default: VerticalAlign.baseline,
VerticalAlign verticalAlign;

/// CSS attribute "`white-space`"
///
Expand Down Expand Up @@ -259,7 +259,7 @@ class Style {
this.textDecorationStyle,
this.textDecorationThickness,
this.textShadow,
this.verticalAlign,
this.verticalAlign = VerticalAlign.baseline,
this.whiteSpace,
this.width,
this.wordSpacing,
Expand Down Expand Up @@ -503,25 +503,26 @@ class Style {
);
}

Style.fromTextStyle(TextStyle textStyle) {
backgroundColor = textStyle.backgroundColor;
color = textStyle.color;
textDecoration = textStyle.decoration;
textDecorationColor = textStyle.decorationColor;
textDecorationStyle = textStyle.decorationStyle;
textDecorationThickness = textStyle.decorationThickness;
fontFamily = textStyle.fontFamily;
fontFamilyFallback = textStyle.fontFamilyFallback;
fontFeatureSettings = textStyle.fontFeatures;
fontSize =
textStyle.fontSize != null ? FontSize(textStyle.fontSize!) : null;
fontStyle = textStyle.fontStyle;
fontWeight = textStyle.fontWeight;
letterSpacing = textStyle.letterSpacing;
textShadow = textStyle.shadows;
wordSpacing = textStyle.wordSpacing;
lineHeight = LineHeight(textStyle.height ?? 1.2);
textTransform = TextTransform.none;
factory Style.fromTextStyle(TextStyle textStyle) {
return Style(
backgroundColor: textStyle.backgroundColor,
color: textStyle.color,
textDecoration: textStyle.decoration,
textDecorationColor: textStyle.decorationColor,
textDecorationStyle: textStyle.decorationStyle,
textDecorationThickness: textStyle.decorationThickness,
fontFamily: textStyle.fontFamily,
fontFamilyFallback: textStyle.fontFamilyFallback,
fontFeatureSettings: textStyle.fontFeatures,
fontSize:
textStyle.fontSize != null ? FontSize(textStyle.fontSize!) : null,
fontStyle: textStyle.fontStyle,
fontWeight: textStyle.fontWeight,
letterSpacing: textStyle.letterSpacing,
textShadow: textStyle.shadows,
wordSpacing: textStyle.wordSpacing,
lineHeight: LineHeight(textStyle.height ?? 1.2),
);
}

/// Sets any dimensions set to rem or em to the computed size
Expand Down
1 change: 0 additions & 1 deletion packages/flutter_html_table/lib/flutter_html_table.dart
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ Alignment _getCellAlignment(TableCellElement cell, TextDirection alignment) {
Alignment verticalAlignment;

switch (cell.style.verticalAlign) {
case null:
case VerticalAlign.baseline:
case VerticalAlign.sub:
case VerticalAlign.sup:
Expand Down
2 changes: 1 addition & 1 deletion test/elements/a_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_test/flutter_test.dart';

import '../test_data.dart';
import '../test_utils.dart';

void main() {
testWidgets('<a> test', (WidgetTester tester) async {
Expand Down
2 changes: 1 addition & 1 deletion test/golden_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_test/flutter_test.dart';

import 'test_data.dart';
import 'test_utils.dart';

class TestApp extends StatelessWidget {
final Widget body;
Expand Down
133 changes: 133 additions & 0 deletions test/style/css_parsing/vertical_align_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_test/flutter_test.dart';

import '../../test_utils.dart';

void main() {
testWidgets(
'Tag with vertical align set inline should receive that style',
(tester) async {
await tester.pumpWidget(
TestApp(
child: Html(
data: """
<span style="vertical-align: super;">Text</span>
""",
),
),
);
expect(find.text("Text", findRichText: true), findsOneWidget);
expect(
findCssBox(find.text("Text", findRichText: true))!
.style
.verticalAlign,
equals(VerticalAlign.sup));
},
);

testWidgets(
'Tag with vertical align set in style tag should receive that style',
(tester) async {
await tester.pumpWidget(
TestApp(
child: Html(
data: """
<style>span {vertical-align: sub;}</style>
<span>Text</span>
""",
),
),
);
expect(find.text("Text", findRichText: true), findsOneWidget);
expect(
findCssBox(find.text("Text", findRichText: true))!
.style
.verticalAlign,
equals(VerticalAlign.sub));
},
);

testWidgets(
'Tag with no vertical align set should have default',
(tester) async {
await tester.pumpWidget(
TestApp(
child: Html(
data: """
<span>Text</span>
""",
),
),
);
expect(find.text("Text", findRichText: true), findsOneWidget);
expect(
findCssBox(find.text("Text", findRichText: true))!
.style
.verticalAlign,
equals(VerticalAlign.baseline));
},
);

testWidgets(
'Tag with vertical align bottom set should have that value',
(tester) async {
await tester.pumpWidget(
TestApp(
child: Html(
data: """
<div style="vertical-align: bottom;">Text</div>
""",
),
),
);
expect(find.text("Text", findRichText: true), findsOneWidget);
expect(
findCssBox(find.text("Text", findRichText: true))!
.style
.verticalAlign,
equals(VerticalAlign.bottom));
},
);

testWidgets(
'Tag with vertical align middle set should have that value',
(tester) async {
await tester.pumpWidget(
TestApp(
child: Html(
data: """
<div style="vertical-align: middle;">Text</div>
""",
),
),
);
expect(find.text("Text", findRichText: true), findsOneWidget);
expect(
findCssBox(find.text("Text", findRichText: true))!
.style
.verticalAlign,
equals(VerticalAlign.middle));
},
);

testWidgets(
'Tag with vertical align top set should have that value',
(tester) async {
await tester.pumpWidget(
TestApp(
child: Html(
data: """
<div style="vertical-align: top;">Text</div>
""",
),
),
);
expect(find.text("Text", findRichText: true), findsOneWidget);
expect(
findCssBox(find.text("Text", findRichText: true))!
.style
.verticalAlign,
equals(VerticalAlign.top));
},
);
}
17 changes: 17 additions & 0 deletions test/test_data.dart → test/test_utils.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_html/src/css_box_widget.dart';
import 'package:flutter_test/flutter_test.dart';

class TestApp extends StatelessWidget {
final Widget child;
Expand Down Expand Up @@ -124,3 +126,18 @@ const testData = <String, String>{
'u': '<u>Hello, World!</u>',
'var': '<var>Hello, World!</var>',
};

CssBoxWidget? findCssBox(Finder finder) {
final boxFinder = find.ancestor(
of: finder,
matching: find.byType(CssBoxWidget),
);

final found = boxFinder.evaluate();

if (found.isEmpty) {
return null;
} else {
return found.first.widget as CssBoxWidget;
}
}

0 comments on commit fe896de

Please sign in to comment.