Skip to content

Commit f52af25

Browse files
Merge pull request Sub6Resources#178 from dotneet/ruby
[new-parser]Support ruby element.
2 parents 2931bce + cb2c2bf commit f52af25

File tree

4 files changed

+84
-13
lines changed

4 files changed

+84
-13
lines changed

example/lib/main.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ const htmlData = """
4141
dog.<br />
4242
The quick brown fox jumped over the lazy dog.
4343
</p>
44+
<p>
45+
<ruby>
46+
漢<rt>かん</rt>
47+
字<rt>じ</rt>
48+
</ruby>
49+
&nbsp;is Japanese Kanji
50+
</p>
4451
<table>
4552
<colgroup>
4653
<col width="50%" />

lib/html_parser.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ class HtmlParser extends StatelessWidget {
246246
return TextSpan(text: tree.text);
247247
} else {
248248
return WidgetSpan(
249-
alignment: PlaceholderAlignment.aboveBaseline,
249+
alignment: tree.alignment,
250250
baseline: TextBaseline.alphabetic,
251251
child: tree.toWidget(context),
252252
);

lib/src/html_elements.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ const STYLED_ELEMENTS = [
2222
"kbd",
2323
"mark",
2424
"q",
25-
"rp",
26-
"rt",
27-
"ruby",
2825
"s",
2926
"samp",
3027
"small",
@@ -87,6 +84,9 @@ const REPLACED_ELEMENTS = [
8784
"svg",
8885
"template",
8986
"video",
87+
"rp",
88+
"rt",
89+
"ruby",
9090
];
9191

9292
const LAYOUT_ELEMENTS = [

lib/src/replaced_element.dart

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:convert';
2+
import 'dart:math';
23

34
import 'package:chewie/chewie.dart';
45
import 'package:chewie_audio/chewie_audio.dart';
@@ -19,14 +20,19 @@ import 'package:html/dom.dart' as dom;
1920
/// A [ReplacedElement] may use its children nodes to determine relevant information
2021
/// (e.g. <video>'s <source> tags), but the children nodes will not be saved as [children].
2122
abstract class ReplacedElement extends StyledElement {
22-
ReplacedElement({
23-
String name,
24-
Style style,
25-
dom.Element node,
26-
}) : super(name: name, children: null, style: style, node: node);
23+
PlaceholderAlignment alignment;
24+
25+
ReplacedElement(
26+
{String name,
27+
Style style,
28+
dom.Element node,
29+
this.alignment = PlaceholderAlignment.aboveBaseline})
30+
: super(name: name, children: null, style: style, node: node);
2731

2832
static List<String> parseMediaSources(List<dom.Element> elements) {
29-
return elements.where((element) => element.localName == 'source').map((element) {
33+
return elements
34+
.where((element) => element.localName == 'source')
35+
.map((element) {
3036
return element.attributes['src'];
3137
}).toList();
3238
}
@@ -68,7 +74,8 @@ class ImageContentElement extends ReplacedElement {
6874

6975
@override
7076
Widget toWidget(RenderContext context) {
71-
if (src == null) return Text(alt ?? "", style: context.style.generateTextStyle());
77+
if (src == null)
78+
return Text(alt ?? "", style: context.style.generateTextStyle());
7279
if (src.startsWith("data:image") && src.contains("base64,")) {
7380
return Image.memory(base64.decode(src.split("base64,")[1].trim()));
7481
} else {
@@ -110,7 +117,9 @@ class IframeContentElement extends ReplacedElement {
110117
child: WebView(
111118
initialUrl: src,
112119
javascriptMode: JavascriptMode.unrestricted,
113-
gestureRecognizers: {Factory(() => PlatformViewVerticalGestureRecognizer())},
120+
gestureRecognizers: {
121+
Factory(() => PlatformViewVerticalGestureRecognizer())
122+
},
114123
),
115124
);
116125
}
@@ -189,7 +198,9 @@ class VideoContentElement extends ReplacedElement {
189198
videoPlayerController: VideoPlayerController.network(
190199
src.first ?? "",
191200
),
192-
placeholder: poster != null ? Image.network(poster) : Container(color: Colors.black),
201+
placeholder: poster != null
202+
? Image.network(poster)
203+
: Container(color: Colors.black),
193204
autoPlay: autoplay,
194205
looping: loop,
195206
showControls: showControls,
@@ -229,6 +240,55 @@ class EmptyContentElement extends ReplacedElement {
229240
Widget toWidget(_) => null;
230241
}
231242

243+
class RubyElement extends ReplacedElement {
244+
dom.Element element;
245+
246+
RubyElement({@required this.element, String name = "ruby"})
247+
: super(name: name, alignment: PlaceholderAlignment.middle);
248+
249+
@override
250+
Widget toWidget(RenderContext context) {
251+
dom.Node textNode = null;
252+
List<Widget> widgets = List<Widget>();
253+
final rubySize = max(9.0, context.style.fontSize / 2);
254+
final rubyYPos = rubySize + 2;
255+
element.nodes.forEach((c) {
256+
if (c.nodeType == dom.Node.TEXT_NODE) {
257+
textNode = c;
258+
}
259+
if (c is dom.Element) {
260+
if (c.localName == "rt" && textNode != null) {
261+
final widget = Stack(
262+
alignment: Alignment.center,
263+
children: <Widget>[
264+
Container(
265+
alignment: Alignment.bottomCenter,
266+
child: Center(
267+
child: Transform(
268+
transform:
269+
Matrix4.translationValues(0, -(rubyYPos), 0),
270+
child: Text(c.innerHtml,
271+
style: context.style
272+
.generateTextStyle()
273+
.copyWith(fontSize: rubySize))))),
274+
Container(
275+
child: Text(textNode.text.trim(),
276+
style: context.style.generateTextStyle())),
277+
],
278+
);
279+
widgets.add(widget);
280+
}
281+
}
282+
});
283+
return Row(
284+
crossAxisAlignment: CrossAxisAlignment.end,
285+
textBaseline: TextBaseline.alphabetic,
286+
mainAxisSize: MainAxisSize.min,
287+
children: widgets,
288+
);
289+
}
290+
}
291+
232292
ReplacedElement parseReplacedElement(dom.Element element) {
233293
switch (element.localName) {
234294
case "audio":
@@ -287,6 +347,10 @@ ReplacedElement parseReplacedElement(dom.Element element) {
287347
width: double.tryParse(element.attributes['width'] ?? ""),
288348
height: double.tryParse(element.attributes['height'] ?? ""),
289349
);
350+
case "ruby":
351+
return RubyElement(
352+
element: element,
353+
);
290354
default:
291355
return EmptyContentElement(name: element.localName);
292356
}

0 commit comments

Comments
 (0)