Compare commits
2 commits
main
...
braid/html
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef2dbe8fbe | ||
|
|
defe39bc88 |
1 changed files with 39 additions and 24 deletions
|
|
@ -28,30 +28,36 @@ class HtmlMessage extends StatelessWidget {
|
||||||
});
|
});
|
||||||
|
|
||||||
dom.Node _linkifyHtml(dom.Node element) {
|
dom.Node _linkifyHtml(dom.Node element) {
|
||||||
for (final node in element.nodes) {
|
final nodes = element.nodes;
|
||||||
if (node is! dom.Text) {
|
if (!element.hasChildNodes()) {
|
||||||
node.replaceWith(_linkifyHtml(node));
|
return element;
|
||||||
continue;
|
}
|
||||||
|
for (final dom.Node node in nodes) {
|
||||||
|
if (node is Element) {
|
||||||
|
final newNode = _linkifyHtml(node);
|
||||||
|
node.replaceWith(newNode);
|
||||||
|
} else if (node is dom.Text) {
|
||||||
|
final linkified = linkify(
|
||||||
|
node.text,
|
||||||
|
options: const LinkifyOptions(
|
||||||
|
humanize: false,
|
||||||
|
looseUrl: true,
|
||||||
|
defaultToHttps: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final newNode = dom.Element.tag('span');
|
||||||
|
for (final element in linkified) {
|
||||||
|
if (element is TextElement) {
|
||||||
|
newNode.nodes.add(dom.Text(element.text));
|
||||||
|
} else if (element is LinkableElement) {
|
||||||
|
final anchor = dom.Element.tag('a');
|
||||||
|
anchor.attributes['href'] = element.url;
|
||||||
|
anchor.nodes.add(dom.Text(element.originText));
|
||||||
|
newNode.nodes.add(anchor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node.replaceWith(newNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
final parts = linkify(
|
|
||||||
node.text,
|
|
||||||
options: const LinkifyOptions(humanize: false),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!parts.any((part) => part is UrlElement)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final newHtml = parts
|
|
||||||
.map(
|
|
||||||
(linkifyElement) => linkifyElement is! UrlElement
|
|
||||||
? linkifyElement.text
|
|
||||||
: '<a href="${linkifyElement.text}">${linkifyElement.text}</a>',
|
|
||||||
)
|
|
||||||
.join(' ');
|
|
||||||
|
|
||||||
node.replaceWith(dom.Element.html('<p>$newHtml</p>'));
|
|
||||||
}
|
}
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +94,13 @@ class HtmlMessage extends StatelessWidget {
|
||||||
padding: HtmlPaddings.only(left: 6, bottom: 0),
|
padding: HtmlPaddings.only(left: 6, bottom: 0),
|
||||||
);
|
);
|
||||||
|
|
||||||
final element = _linkifyHtml(HtmlParser.parseHTML(renderHtml));
|
// I encountered messages containing only a String with several HTML elements - without a common parent containing
|
||||||
|
// them - in this case, we'd end up with *several* top level elements - and the HTML parser fails
|
||||||
|
//
|
||||||
|
// We hence add an inline-block `<div>` around the entire message in order to ensure we're dealing with a single
|
||||||
|
// top-level element.
|
||||||
|
final paddedHtml = '<div style="display: inline-block;">$renderHtml</div>';
|
||||||
|
final element = _linkifyHtml(HtmlParser.parseHTML(paddedHtml));
|
||||||
|
|
||||||
// there is no need to pre-validate the html, as we validate it while rendering
|
// there is no need to pre-validate the html, as we validate it while rendering
|
||||||
return Html.fromElement(
|
return Html.fromElement(
|
||||||
|
|
@ -344,6 +356,7 @@ class MatrixMathExtension extends HtmlExtension {
|
||||||
final TextStyle? style;
|
final TextStyle? style;
|
||||||
|
|
||||||
MatrixMathExtension({this.style});
|
MatrixMathExtension({this.style});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<String> get supportedTags => {'div'};
|
Set<String> get supportedTags => {'div'};
|
||||||
|
|
||||||
|
|
@ -377,6 +390,7 @@ class CodeExtension extends HtmlExtension {
|
||||||
final double fontSize;
|
final double fontSize;
|
||||||
|
|
||||||
CodeExtension({required this.fontSize});
|
CodeExtension({required this.fontSize});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<String> get supportedTags => {'code'};
|
Set<String> get supportedTags => {'code'};
|
||||||
|
|
||||||
|
|
@ -414,6 +428,7 @@ class RoomPillExtension extends HtmlExtension {
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
|
|
||||||
RoomPillExtension(this.context, this.room);
|
RoomPillExtension(this.context, this.room);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<String> get supportedTags => {'a'};
|
Set<String> get supportedTags => {'a'};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue