kopia lustrzana https://gitlab.com/mysocialportal/relatica
170 wiersze
4.5 KiB
Dart
170 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']);
|
|
}
|
|
}
|
|
for (var n in node.nodes) {
|
|
_updateSwapTagLinks(n, tags);
|
|
}
|
|
}
|
|
}
|
|
|
|
String htmlWithTagLinkSwap(String htmlContentFragment, List<String> tags) {
|
|
try {
|
|
final dom = parseFragment(htmlContentFragment);
|
|
for (var n in dom.nodes) {
|
|
_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('');
|
|
}
|