relatica/lib/utils/html_to_edit_text_helper.dart

166 wiersze
4.5 KiB
Dart

import 'package:html/dom.dart';
import 'package:html/parser.dart';
import 'package:path/path.dart' as p;
import '../globals.dart';
import '../services/auth_service.dart';
import 'network_utils.dart';
String htmlToSimpleText(String htmlContentFragment) {
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;
}
}
void _updateSwapTagLinks(Node node, List<String> tags) {
if (node is Element) {
if (node.attributes.containsKey('href') &&
(node.attributes['class']?.contains('hashtag') ?? false) &&
node.attributes['rel'] == 'tag') {
final url = Uri.parse(node.attributes['href'] ?? '');
late final String tag;
final pathEnd = p.split(url.path).last;
if (pathEnd == 'search' && url.queryParameters.containsKey('tag')) {
tag = url.queryParameters['search']!;
} else {
tag = pathEnd;
}
final tagLowercase = tag.toLowerCase();
final hasExpectedTag = tags
.firstWhere((t) => t.toLowerCase() == tagLowercase, orElse: () => '')
.isNotEmpty;
if (hasExpectedTag) {
final profile = getIt<AccountsService>().currentProfile;
final newTagUrl = generateTagUrlFromProfile(profile, tag);
print(node.attributes['href']);
node.attributes['href'] = newTagUrl.toString();
print(node.attributes['href']);
}
}
node.nodes.forEach((n) => _updateSwapTagLinks(n, tags));
}
}
String htmlWithTagLinkSwap(String htmlContentFragment, List<String> tags) {
try {
final dom = parseFragment(htmlContentFragment);
dom.nodes.forEach((n) => _updateSwapTagLinks(n, tags));
final result = dom.outerHtml;
return result;
} catch (e) {
return htmlContentFragment;
}
}
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('');
}