import 'package:html/dom.dart'; import 'package:html/parser.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; } } 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(''); }