2023-03-18 18:49:20 +00:00
|
|
|
import 'package:html/dom.dart';
|
|
|
|
import 'package:html/parser.dart';
|
|
|
|
|
2023-03-21 18:27:38 +00:00
|
|
|
String htmlToSimpleText(String htmlContentFragment) {
|
2023-05-08 11:18:09 +00:00
|
|
|
try {
|
|
|
|
final dom = parseFragment(htmlContentFragment);
|
|
|
|
final segments = dom.nodes
|
|
|
|
.map((n) => n is Element ? n.elementToEditText() : n.nodeToEditText())
|
|
|
|
.toList();
|
|
|
|
return segments.join('');
|
|
|
|
} catch (e) {
|
|
|
|
return htmlContentFragment;
|
|
|
|
}
|
2023-03-18 18:49:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extension NodeTextConverter on Node {
|
|
|
|
String nodeToEditText() {
|
|
|
|
if (nodes.isEmpty) {
|
|
|
|
final stringWithQuotes = toString();
|
|
|
|
final start = stringWithQuotes.startsWith('"') ? 1 : 0;
|
|
|
|
final end = stringWithQuotes.endsWith('"')
|
|
|
|
? stringWithQuotes.length - 1
|
|
|
|
: stringWithQuotes.length;
|
|
|
|
return stringWithQuotes.substring(start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
final convertedNodes = nodes
|
|
|
|
.map((n) => n is Element ? n.elementToEditText() : n.nodeToEditText())
|
|
|
|
.toList();
|
|
|
|
return convertedNodes.join('');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension ElementTextConverter on Element {
|
|
|
|
String elementToEditText({int depth = 0}) {
|
|
|
|
late final String innerText;
|
|
|
|
late final String startText;
|
|
|
|
late final String endText;
|
|
|
|
switch (localName) {
|
|
|
|
case 'a':
|
|
|
|
startText = '';
|
|
|
|
innerText = htmlLinkToString();
|
|
|
|
endText = '';
|
|
|
|
break;
|
|
|
|
case 'br':
|
|
|
|
startText = '';
|
|
|
|
innerText = '';
|
|
|
|
endText = '\n';
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
startText = '';
|
|
|
|
innerText = buildInnerText(depth);
|
|
|
|
endText = '\n';
|
|
|
|
break;
|
|
|
|
case 'em':
|
|
|
|
startText = '*';
|
|
|
|
innerText = buildInnerText(depth);
|
|
|
|
endText = '*';
|
|
|
|
break;
|
|
|
|
case 'strong':
|
|
|
|
startText = '**';
|
|
|
|
innerText = buildInnerText(depth);
|
|
|
|
endText = '**';
|
|
|
|
break;
|
|
|
|
case 'li':
|
|
|
|
startText = '\n${buildTabs(depth)}- ';
|
|
|
|
innerText = buildInnerText(depth);
|
|
|
|
endText = '';
|
|
|
|
break;
|
|
|
|
case 'ul':
|
|
|
|
startText = '';
|
|
|
|
innerText = buildInnerText(depth + 1);
|
|
|
|
endText = '';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
startText = '<$localName>';
|
|
|
|
innerText = buildInnerText(depth);
|
|
|
|
endText = '</$localName>';
|
|
|
|
}
|
|
|
|
|
|
|
|
return '$startText$innerText$endText';
|
|
|
|
}
|
|
|
|
|
|
|
|
String htmlLinkToString() {
|
|
|
|
final attrs = attributes['class'] ?? '';
|
|
|
|
if (attrs.contains('hashtag')) {
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (attrs.contains('mention')) {
|
|
|
|
final uri = Uri.parse(attributes['href'] ?? '');
|
|
|
|
final host = uri.host;
|
|
|
|
final username = text;
|
|
|
|
return '$username@$host';
|
|
|
|
}
|
|
|
|
|
|
|
|
return attributes['href'] ?? 'No link found';
|
|
|
|
}
|
|
|
|
|
|
|
|
String buildInnerText(int depth) {
|
|
|
|
if (nodes.isEmpty) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
final convertedNodes = nodes
|
|
|
|
.map((n) => n is Element
|
|
|
|
? n.elementToEditText(depth: depth)
|
|
|
|
: n.nodeToEditText())
|
|
|
|
.toList();
|
|
|
|
return convertedNodes.join('');
|
|
|
|
}
|
|
|
|
|
|
|
|
String buildTabs(int depth) => depth == 0
|
|
|
|
? ''
|
|
|
|
: List.generate(
|
|
|
|
depth,
|
|
|
|
(index) => ' ',
|
|
|
|
).join('');
|
|
|
|
}
|