new linkify handling

Should fix mentions in non-HTML messages
This commit is contained in:
Henry Hiles 2026-11-01 16:42:23 -05:00
commit 40f5d0f459
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs

View file

@ -0,0 +1,45 @@
import "package:html/dom.dart";
import "package:html/parser.dart";
import "package:linkify/linkify.dart";
import "package:nexus/helpers/matrix_linkifier.dart";
extension LinkifyHtml on String {
/// Wraps bare links in this HTML's text in `<a>` tags.
///
/// Only text nodes are touched, so attribute values are left alone, and
/// text already inside a link or code is skipped.
String get linkifiedHtml {
final fragment = parseFragment(this);
_linkifyNode(fragment);
return fragment.outerHtml;
}
}
void _linkifyNode(Node node) {
if (node is Element && const {"a", "code", "pre"}.contains(node.localName)) {
return;
}
for (final child in node.nodes.toList()) {
if (child is! Text) {
_linkifyNode(child);
continue;
}
final elements = linkifyText(child.data);
if (!elements.any((element) => element is LinkableElement)) continue;
elements
.map(
(element) => switch (element) {
LinkableElement(:final text, :final url) =>
Element.tag("a")
..attributes["href"] = url
..append(Text(text)),
_ => Text(element.text),
},
)
.forEach((replacement) => node.insertBefore(replacement, child));
child.remove();
}
}