Skip to content

Commit fe896de

Browse files
feat: support vertical-align in inline styles (Sub6Resources#1266)
1 parent d7247cb commit fe896de

File tree

7 files changed

+201
-25
lines changed

7 files changed

+201
-25
lines changed

lib/src/css_parser.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,10 @@ Style declarationsToStyle(Map<String, List<css.Expression>> declarations) {
538538
style.textTransform = TextTransform.none;
539539
}
540540
break;
541+
case 'vertical-align':
542+
style.verticalAlign =
543+
ExpressionMapping.expressionToVerticalAlign(value.first);
544+
break;
541545
case 'width':
542546
style.width =
543547
ExpressionMapping.expressionToWidth(value.first) ?? style.width;
@@ -1212,6 +1216,28 @@ class ExpressionMapping {
12121216
return finalShadows;
12131217
}
12141218

1219+
static VerticalAlign expressionToVerticalAlign(css.Expression value) {
1220+
if (value is css.LiteralTerm) {
1221+
switch (value.text) {
1222+
case "sub":
1223+
return VerticalAlign.sub;
1224+
case "super":
1225+
return VerticalAlign.sup;
1226+
case "bottom":
1227+
return VerticalAlign.bottom;
1228+
case "top":
1229+
return VerticalAlign.top;
1230+
case "middle":
1231+
return VerticalAlign.middle;
1232+
case "baseline":
1233+
default:
1234+
return VerticalAlign.baseline;
1235+
}
1236+
}
1237+
1238+
return VerticalAlign.baseline;
1239+
}
1240+
12151241
static Color stringToColor(String rawText) {
12161242
var text = rawText.replaceFirst('#', '');
12171243
if (text.length == 3) {

lib/src/style.dart

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ class Style {
177177
/// CSS attribute "`vertical-align`"
178178
///
179179
/// Inherited: no,
180-
/// Default: VerticalAlign.BASELINE,
181-
VerticalAlign? verticalAlign;
180+
/// Default: VerticalAlign.baseline,
181+
VerticalAlign verticalAlign;
182182

183183
/// CSS attribute "`white-space`"
184184
///
@@ -259,7 +259,7 @@ class Style {
259259
this.textDecorationStyle,
260260
this.textDecorationThickness,
261261
this.textShadow,
262-
this.verticalAlign,
262+
this.verticalAlign = VerticalAlign.baseline,
263263
this.whiteSpace,
264264
this.width,
265265
this.wordSpacing,
@@ -503,25 +503,26 @@ class Style {
503503
);
504504
}
505505

506-
Style.fromTextStyle(TextStyle textStyle) {
507-
backgroundColor = textStyle.backgroundColor;
508-
color = textStyle.color;
509-
textDecoration = textStyle.decoration;
510-
textDecorationColor = textStyle.decorationColor;
511-
textDecorationStyle = textStyle.decorationStyle;
512-
textDecorationThickness = textStyle.decorationThickness;
513-
fontFamily = textStyle.fontFamily;
514-
fontFamilyFallback = textStyle.fontFamilyFallback;
515-
fontFeatureSettings = textStyle.fontFeatures;
516-
fontSize =
517-
textStyle.fontSize != null ? FontSize(textStyle.fontSize!) : null;
518-
fontStyle = textStyle.fontStyle;
519-
fontWeight = textStyle.fontWeight;
520-
letterSpacing = textStyle.letterSpacing;
521-
textShadow = textStyle.shadows;
522-
wordSpacing = textStyle.wordSpacing;
523-
lineHeight = LineHeight(textStyle.height ?? 1.2);
524-
textTransform = TextTransform.none;
506+
factory Style.fromTextStyle(TextStyle textStyle) {
507+
return Style(
508+
backgroundColor: textStyle.backgroundColor,
509+
color: textStyle.color,
510+
textDecoration: textStyle.decoration,
511+
textDecorationColor: textStyle.decorationColor,
512+
textDecorationStyle: textStyle.decorationStyle,
513+
textDecorationThickness: textStyle.decorationThickness,
514+
fontFamily: textStyle.fontFamily,
515+
fontFamilyFallback: textStyle.fontFamilyFallback,
516+
fontFeatureSettings: textStyle.fontFeatures,
517+
fontSize:
518+
textStyle.fontSize != null ? FontSize(textStyle.fontSize!) : null,
519+
fontStyle: textStyle.fontStyle,
520+
fontWeight: textStyle.fontWeight,
521+
letterSpacing: textStyle.letterSpacing,
522+
textShadow: textStyle.shadows,
523+
wordSpacing: textStyle.wordSpacing,
524+
lineHeight: LineHeight(textStyle.height ?? 1.2),
525+
);
525526
}
526527

527528
/// Sets any dimensions set to rem or em to the computed size

packages/flutter_html_table/lib/flutter_html_table.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,6 @@ Alignment _getCellAlignment(TableCellElement cell, TextDirection alignment) {
290290
Alignment verticalAlignment;
291291

292292
switch (cell.style.verticalAlign) {
293-
case null:
294293
case VerticalAlign.baseline:
295294
case VerticalAlign.sub:
296295
case VerticalAlign.sup:

test/elements/a_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_html/flutter_html.dart';
33
import 'package:flutter_test/flutter_test.dart';
44

5-
import '../test_data.dart';
5+
import '../test_utils.dart';
66

77
void main() {
88
testWidgets('<a> test', (WidgetTester tester) async {

test/golden_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_html/flutter_html.dart';
33
import 'package:flutter_test/flutter_test.dart';
44

5-
import 'test_data.dart';
5+
import 'test_utils.dart';
66

77
class TestApp extends StatelessWidget {
88
final Widget body;
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import 'package:flutter_html/flutter_html.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
4+
import '../../test_utils.dart';
5+
6+
void main() {
7+
testWidgets(
8+
'Tag with vertical align set inline should receive that style',
9+
(tester) async {
10+
await tester.pumpWidget(
11+
TestApp(
12+
child: Html(
13+
data: """
14+
<span style="vertical-align: super;">Text</span>
15+
""",
16+
),
17+
),
18+
);
19+
expect(find.text("Text", findRichText: true), findsOneWidget);
20+
expect(
21+
findCssBox(find.text("Text", findRichText: true))!
22+
.style
23+
.verticalAlign,
24+
equals(VerticalAlign.sup));
25+
},
26+
);
27+
28+
testWidgets(
29+
'Tag with vertical align set in style tag should receive that style',
30+
(tester) async {
31+
await tester.pumpWidget(
32+
TestApp(
33+
child: Html(
34+
data: """
35+
<style>span {vertical-align: sub;}</style>
36+
<span>Text</span>
37+
""",
38+
),
39+
),
40+
);
41+
expect(find.text("Text", findRichText: true), findsOneWidget);
42+
expect(
43+
findCssBox(find.text("Text", findRichText: true))!
44+
.style
45+
.verticalAlign,
46+
equals(VerticalAlign.sub));
47+
},
48+
);
49+
50+
testWidgets(
51+
'Tag with no vertical align set should have default',
52+
(tester) async {
53+
await tester.pumpWidget(
54+
TestApp(
55+
child: Html(
56+
data: """
57+
<span>Text</span>
58+
""",
59+
),
60+
),
61+
);
62+
expect(find.text("Text", findRichText: true), findsOneWidget);
63+
expect(
64+
findCssBox(find.text("Text", findRichText: true))!
65+
.style
66+
.verticalAlign,
67+
equals(VerticalAlign.baseline));
68+
},
69+
);
70+
71+
testWidgets(
72+
'Tag with vertical align bottom set should have that value',
73+
(tester) async {
74+
await tester.pumpWidget(
75+
TestApp(
76+
child: Html(
77+
data: """
78+
<div style="vertical-align: bottom;">Text</div>
79+
""",
80+
),
81+
),
82+
);
83+
expect(find.text("Text", findRichText: true), findsOneWidget);
84+
expect(
85+
findCssBox(find.text("Text", findRichText: true))!
86+
.style
87+
.verticalAlign,
88+
equals(VerticalAlign.bottom));
89+
},
90+
);
91+
92+
testWidgets(
93+
'Tag with vertical align middle set should have that value',
94+
(tester) async {
95+
await tester.pumpWidget(
96+
TestApp(
97+
child: Html(
98+
data: """
99+
<div style="vertical-align: middle;">Text</div>
100+
""",
101+
),
102+
),
103+
);
104+
expect(find.text("Text", findRichText: true), findsOneWidget);
105+
expect(
106+
findCssBox(find.text("Text", findRichText: true))!
107+
.style
108+
.verticalAlign,
109+
equals(VerticalAlign.middle));
110+
},
111+
);
112+
113+
testWidgets(
114+
'Tag with vertical align top set should have that value',
115+
(tester) async {
116+
await tester.pumpWidget(
117+
TestApp(
118+
child: Html(
119+
data: """
120+
<div style="vertical-align: top;">Text</div>
121+
""",
122+
),
123+
),
124+
);
125+
expect(find.text("Text", findRichText: true), findsOneWidget);
126+
expect(
127+
findCssBox(find.text("Text", findRichText: true))!
128+
.style
129+
.verticalAlign,
130+
equals(VerticalAlign.top));
131+
},
132+
);
133+
}

test/test_data.dart renamed to test/test_utils.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter_html/src/css_box_widget.dart';
3+
import 'package:flutter_test/flutter_test.dart';
24

35
class TestApp extends StatelessWidget {
46
final Widget child;
@@ -124,3 +126,18 @@ const testData = <String, String>{
124126
'u': '<u>Hello, World!</u>',
125127
'var': '<var>Hello, World!</var>',
126128
};
129+
130+
CssBoxWidget? findCssBox(Finder finder) {
131+
final boxFinder = find.ancestor(
132+
of: finder,
133+
matching: find.byType(CssBoxWidget),
134+
);
135+
136+
final found = boxFinder.evaluate();
137+
138+
if (found.isEmpty) {
139+
return null;
140+
} else {
141+
return found.first.widget as CssBoxWidget;
142+
}
143+
}

0 commit comments

Comments
 (0)