Skip to content

Commit 3a7e53b

Browse files
committed
Revamp ruby rendering to support text-based and container-based styling
1 parent 68033b6 commit 3a7e53b

File tree

5 files changed

+37
-18
lines changed

5 files changed

+37
-18
lines changed

lib/html_parser.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ class HtmlParser extends StatelessWidget {
214214
} else if (INTERACTABLE_ELEMENTS.contains(node.localName)) {
215215
return parseInteractableElement(node, children);
216216
} else if (REPLACED_ELEMENTS.contains(node.localName)) {
217-
return parseReplacedElement(node, navigationDelegateForIframe);
217+
return parseReplacedElement(node, children, navigationDelegateForIframe);
218218
} else if (LAYOUT_ELEMENTS.contains(node.localName)) {
219219
return parseLayoutElement(node, children);
220220
} else if (TABLE_CELL_ELEMENTS.contains(node.localName)) {

lib/src/html_elements.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const STYLED_ELEMENTS = [
2222
"kbd",
2323
"mark",
2424
"q",
25+
"rt",
2526
"s",
2627
"samp",
2728
"small",

lib/src/replaced_element.dart

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ abstract class ReplacedElement extends StyledElement {
2929
required String name,
3030
required Style style,
3131
required String elementId,
32+
List<StyledElement>? children,
3233
dom.Element? node,
3334
this.alignment = PlaceholderAlignment.aboveBaseline,
34-
}) : super(name: name, children: [], style: style, node: node, elementId: elementId);
35+
}) : super(name: name, children: children ?? [], style: style, node: node, elementId: elementId);
3536

3637
static List<String?> parseMediaSources(List<dom.Element> elements) {
3738
return elements
@@ -230,22 +231,24 @@ class EmptyContentElement extends ReplacedElement {
230231
class RubyElement extends ReplacedElement {
231232
dom.Element element;
232233

233-
RubyElement({required this.element, String name = "ruby"})
234-
: super(name: name, alignment: PlaceholderAlignment.middle, style: Style(), elementId: element.id);
234+
RubyElement({
235+
required this.element,
236+
required List<StyledElement> children,
237+
String name = "ruby"
238+
}) : super(name: name, alignment: PlaceholderAlignment.middle, style: Style(), elementId: element.id, children: children);
235239

236240
@override
237241
Widget toWidget(RenderContext context) {
238-
dom.Node? textNode;
242+
String? textNode;
239243
List<Widget> widgets = <Widget>[];
240-
//TODO calculate based off of parent font size.
241244
final rubySize = max(9.0, context.style.fontSize!.size! / 2);
242245
final rubyYPos = rubySize + rubySize / 2;
243-
element.nodes.forEach((c) {
244-
if (c.nodeType == dom.Node.TEXT_NODE) {
245-
textNode = c;
246+
context.tree.children.forEach((c) {
247+
if (c is TextContentElement) {
248+
textNode = c.text;
246249
}
247-
if (c is dom.Element) {
248-
if (c.localName == "rt" && textNode != null) {
250+
if (!(c is TextContentElement)) {
251+
if (c.name == "rt" && textNode != null) {
249252
final widget = Stack(
250253
alignment: Alignment.center,
251254
children: <Widget>[
@@ -255,12 +258,23 @@ class RubyElement extends ReplacedElement {
255258
child: Transform(
256259
transform:
257260
Matrix4.translationValues(0, -(rubyYPos), 0),
258-
child: Text(c.innerHtml,
259-
style: context.style
260-
.generateTextStyle()
261-
.copyWith(fontSize: rubySize))))),
262-
Container(
263-
child: Text(textNode!.text!.trim(),
261+
child: ContainerSpan(
262+
newContext: RenderContext(
263+
buildContext: context.buildContext,
264+
parser: context.parser,
265+
style: c.style,
266+
tree: c,
267+
),
268+
style: c.style,
269+
child: Text(c.element!.innerHtml,
270+
style: c.style
271+
.generateTextStyle()
272+
.copyWith(fontSize: rubySize)),
273+
)))),
274+
ContainerSpan(
275+
newContext: context,
276+
style: context.style,
277+
child: Text(textNode!.trim(),
264278
style: context.style.generateTextStyle())),
265279
],
266280
);
@@ -361,6 +375,7 @@ class MathElement extends ReplacedElement {
361375

362376
ReplacedElement parseReplacedElement(
363377
dom.Element element,
378+
List<StyledElement> children,
364379
NavigationDelegate? navigationDelegateForIframe,
365380
) {
366381
switch (element.localName) {
@@ -435,6 +450,7 @@ ReplacedElement parseReplacedElement(
435450
case "ruby":
436451
return RubyElement(
437452
element: element,
453+
children: children,
438454
);
439455
case "math":
440456
return MathElement(

lib/src/styled_element.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class StyledElement {
2424
}) : this._node = node;
2525

2626
bool matchesSelector(String selector) =>
27-
_node != null && matches(_node as dom.Element, selector);
27+
(_node != null && matches(_node as dom.Element, selector)) || name == selector;
2828

2929
Map<String, String> get attributes =>
3030
_node?.attributes.map((key, value) {

test/html_parser_test.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ void testNewParser(BuildContext context) {
8282
Your browser does not support the video tag.
8383
</video>
8484
""").getElementsByTagName("video")[0],
85+
[],
8586
null,
8687
);
8788

@@ -101,6 +102,7 @@ void testNewParser(BuildContext context) {
101102
Your browser does not support the audio tag.
102103
</audio>
103104
""").getElementsByTagName("audio")[0],
105+
[],
104106
null,
105107
);
106108
expect(audioContentElement, isA<AudioContentElement>());

0 commit comments

Comments
 (0)