parseMarkdown function

List<MarkdownToken> parseMarkdown(
  1. String text
)

Parse markdown text into tokens.

Implementation

List<MarkdownToken> parseMarkdown(String text) {
  if (!hasMarkdownSyntax(text)) {
    return [TextToken(text)];
  }

  final tokens = <MarkdownToken>[];
  final lines = text.split('\n');
  var i = 0;

  while (i < lines.length) {
    final line = lines[i];

    // Code block (fenced)
    if (line.startsWith('```')) {
      final lang = line.substring(3).trim().isEmpty
          ? null
          : line.substring(3).trim();
      final codeLines = <String>[];
      i++;
      while (i < lines.length && !lines[i].startsWith('```')) {
        codeLines.add(lines[i]);
        i++;
      }
      tokens.add(CodeBlockToken(codeLines.join('\n'), lang));
      i++; // Skip closing ```
      continue;
    }

    // Heading
    final headingMatch = RegExp(r'^(#{1,6})\s+(.*)').firstMatch(line);
    if (headingMatch != null) {
      tokens.add(
        HeadingToken(headingMatch.group(2)!, headingMatch.group(1)!.length),
      );
      i++;
      continue;
    }

    // Horizontal rule
    if (RegExp(r'^(\*{3,}|-{3,}|_{3,})\s*$').hasMatch(line)) {
      tokens.add(const HorizontalRuleToken());
      i++;
      continue;
    }

    // Blockquote
    if (line.startsWith('> ')) {
      final quoteLines = <String>[];
      while (i < lines.length && lines[i].startsWith('> ')) {
        quoteLines.add(lines[i].substring(2));
        i++;
      }
      tokens.add(BlockquoteToken(quoteLines.join('\n')));
      continue;
    }

    // Ordered list
    final olMatch = RegExp(r'^(\d+)\.\s+(.*)').firstMatch(line);
    if (olMatch != null) {
      tokens.add(
        ListItemToken(
          olMatch.group(2)!,
          ordered: true,
          index: int.tryParse(olMatch.group(1)!) ?? 1,
        ),
      );
      i++;
      continue;
    }

    // Unordered list
    if (RegExp(r'^[\-*+]\s+').hasMatch(line)) {
      tokens.add(ListItemToken(line.replaceFirst(RegExp(r'^[\-*+]\s+'), '')));
      i++;
      continue;
    }

    // Regular text — parse inline elements
    if (line.trim().isNotEmpty) {
      _parseInlineTokens(line, tokens);
      tokens.add(const TextToken('\n'));
    } else {
      tokens.add(const TextToken('\n'));
    }
    i++;
  }

  return tokens;
}