parseMarkdown function
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;
}