Skip to content
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
12 changes: 9 additions & 3 deletions lib/html_parser.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:collection';
import 'dart:math';

import 'package:collection/collection.dart';
import 'package:csslib/parser.dart' as cssparser;
import 'package:csslib/visitor.dart' as css;
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -438,7 +439,7 @@ class HtmlParser extends StatelessWidget {
&& tree.text!.startsWith(' ')
&& tree.element?.localName != "br"
&& (!keepLeadingSpace.data
|| BLOCK_ELEMENTS.contains(tree.element?.localName ?? ""))
|| tree.style.display == Display.BLOCK)
&& (elementIndex < 1
|| (elementIndex >= 1
&& parentNodes?[elementIndex - 1] is dom.Text
Expand Down Expand Up @@ -747,11 +748,16 @@ class HtmlParser extends StatelessWidget {
static StyledElement _removeEmptyElements(StyledElement tree) {
List<StyledElement> toRemove = <StyledElement>[];
bool lastChildBlock = true;
tree.children.forEach((child) {
tree.children.forEachIndexed((index, child) {
if (child is EmptyContentElement || child is EmptyLayoutElement) {
toRemove.add(child);
} else if (child is TextContentElement
&& (tree.name == "body" || tree.name == "ul")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is getting s complex... I am sure at one point we need to rewrite this 'node cleanup' altogether.

&& ((tree.name == "body"
&& (index == 0
|| index + 1 == tree.children.length
|| tree.children[index - 1].style.display == Display.BLOCK
|| tree.children[index + 1].style.display == Display.BLOCK))
|| tree.name == "ul")
&& child.text!.replaceAll(' ', '').isEmpty) {
toRemove.add(child);
} else if (child is TextContentElement
Expand Down
2 changes: 1 addition & 1 deletion lib/src/css_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ class ExpressionMapping {
if (value is css.NumberTerm) {
return FontSize(double.tryParse(value.text));
} else if (value is css.PercentageTerm) {
return FontSize.percent(int.tryParse(value.text)!);
return FontSize.percent(double.tryParse(value.text)!);
} else if (value is css.EmTerm) {
return FontSize.em(double.tryParse(value.text));
} else if (value is css.RemTerm) {
Expand Down
102 changes: 59 additions & 43 deletions lib/src/replaced_element.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:math';

import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_html/html_parser.dart';
Expand Down Expand Up @@ -74,55 +75,70 @@ class RubyElement extends ReplacedElement {

@override
Widget toWidget(RenderContext context) {
String? textNode;
StyledElement? node;
List<Widget> widgets = <Widget>[];
final rubySize = max(9.0, context.style.fontSize!.size! / 2);
final rubySize = context.parser.style['rt']?.fontSize?.size ?? max(9.0, context.style.fontSize!.size! / 2);
final rubyYPos = rubySize + rubySize / 2;
context.tree.children.forEach((c) {
if (c is TextContentElement) {
textNode = c.text;
List<StyledElement> children = [];
context.tree.children.forEachIndexed((index, element) {
if (!((element is TextContentElement)
&& (element.text ?? "").trim().isEmpty
&& index > 0
&& index + 1 < context.tree.children.length
&& !(context.tree.children[index - 1] is TextContentElement)
&& !(context.tree.children[index + 1] is TextContentElement))) {
children.add(element);
}
if (!(c is TextContentElement)) {
if (c.name == "rt" && textNode != null) {
final widget = Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
alignment: Alignment.bottomCenter,
child: Center(
child: Transform(
transform:
Matrix4.translationValues(0, -(rubyYPos), 0),
child: ContainerSpan(
newContext: RenderContext(
buildContext: context.buildContext,
parser: context.parser,
style: c.style,
tree: c,
),
});
children.forEach((c) {
if (c.name == "rt" && node != null) {
final widget = Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
alignment: Alignment.bottomCenter,
child: Center(
child: Transform(
transform:
Matrix4.translationValues(0, -(rubyYPos), 0),
child: ContainerSpan(
newContext: RenderContext(
buildContext: context.buildContext,
parser: context.parser,
style: c.style,
child: Text(c.element!.innerHtml,
style: c.style
.generateTextStyle()
.copyWith(fontSize: rubySize)),
)))),
ContainerSpan(
newContext: context,
style: context.style,
child: Text(textNode!.trim(),
style: context.style.generateTextStyle())),
],
);
widgets.add(widget);
}
tree: c,
),
style: c.style,
child: Text(c.element!.innerHtml,
style: c.style
.generateTextStyle()
.copyWith(fontSize: rubySize)),
)))),
ContainerSpan(
newContext: context,
style: context.style,
child: node is TextContentElement ? Text((node as TextContentElement).text?.trim() ?? "",
style: context.style.generateTextStyle()) : null,
children: node is TextContentElement ? null : [context.parser.parseTree(context, node!)]),
],
);
widgets.add(widget);
} else {
node = c;
}
});
return Row(
key: AnchorKey.of(context.parser.key, this),
crossAxisAlignment: CrossAxisAlignment.end,
textBaseline: TextBaseline.alphabetic,
mainAxisSize: MainAxisSize.min,
children: widgets,
return Padding(
padding: EdgeInsets.only(top: rubySize),
child: Wrap(
key: AnchorKey.of(context.parser.key, this),
runSpacing: rubySize,
children: widgets.map((e) => Row(
crossAxisAlignment: CrossAxisAlignment.end,
textBaseline: TextBaseline.alphabetic,
mainAxisSize: MainAxisSize.min,
children: [e],
)).toList(),
),
);
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/style.dart
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,8 @@ class FontSize {
const FontSize(this.size, {this.units = ""});

/// A percentage of the parent style's font size.
factory FontSize.percent(int percent) {
return FontSize(percent.toDouble() / -100.0, units: "%");
factory FontSize.percent(double percent) {
return FontSize(percent / -100.0, units: "%");
}

factory FontSize.em(double? em) {
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter_html_audio/lib/flutter_html_audio.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class _AudioWidgetState extends State<AudioWidget> {

@override
void initState() {
final sources = <String?>[
sources = <String?>[
if (widget.context.tree.element?.attributes['src'] != null)
widget.context.tree.element!.attributes['src'],
...ReplacedElement.parseMediaSources(widget.context.tree.element!.children),
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter_html_video/lib/flutter_html_video.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class _VideoWidgetState extends State<VideoWidget> {
@override
void initState() {
final attributes = widget.context.tree.element?.attributes ?? {};
final sources = <String?>[
sources = <String?>[
if (attributes['src'] != null)
attributes['src'],
...ReplacedElement.parseMediaSources(widget.context.tree.element!.children),
Expand Down