parse static method

List<SpanText> parse(
  1. String paragraph
)

Implementation

static List<SpanText> parse(String paragraph) {
  if (paragraph.isEmpty) return [];
  if (!paragraph.startsWith("<p>")) {
    paragraph = "<p>$paragraph";
  }
  if (!paragraph.endsWith("</p>")) {
    paragraph = "$paragraph</p>";
  }
  List<SpanText> texts = [];

  // Regex to extract everything inside <p> and spans within <p>
  RegExp pTagExp = RegExp(r'<p[^>]*>(.*?)</p>', dotAll: true);
  RegExp spanTagExp = RegExp(r'<(\w+)[^>]*>(.*?)</\1>', dotAll: true);

  // Helper function to recursively extract nested spans
  List<SpanText> parseSpans(String text, List<String> tags) {
    List<SpanText> texts = [];

    Iterable<RegExpMatch> spanMatches = spanTagExp.allMatches(text);

    int lastIndex = 0;

    for (var spanMatch in spanMatches) {
      String spanText = spanMatch.group(2)!;
      String spanType = spanMatch.group(1)!;
      int spanStart = spanMatch.start;
      int spanEnd = spanMatch.end;

      // Add any normal text between last index and span start
      if (spanStart > lastIndex) {
        String normalText = text.substring(lastIndex, spanStart);
        if (normalText.isNotEmpty) {
          texts.add(NormalText(text: normalText));
        }
      }

      // Parse nested spans recursively
      List<String> nestedTags = [...tags, spanType];
      var nestedElements = parseSpans(spanText, nestedTags);
      if (nestedElements.isEmpty) {
        texts.add(SpannedText(text: spanText, types: nestedTags));
      } else {
        texts.addAll(nestedElements);
      }

      lastIndex = spanEnd;
    }

    // Add any remaining normal text after the last span
    if (lastIndex < text.length) {
      String remainingText = text.substring(lastIndex);
      if (remainingText.isNotEmpty) {
        if (tags.isNotEmpty) {
          texts.add(SpannedText(
            text: remainingText,
            types: tags,
          ));
        } else {
          texts.add(NormalText(text: remainingText));
        }
      }
    }

    return texts;
  }

  // Find the content inside <p> tags
  Iterable<RegExpMatch> pMatches = pTagExp.allMatches(paragraph);

  for (var pMatch in pMatches) {
    String pContent = pMatch.group(1)!; // Get the inner content of <p>

    // Parse content, starting with no parent tags
    texts.addAll(parseSpans(pContent, []));
  }

  return texts;
}