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 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().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 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 = ''; } 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(''); }