splitFrontMatter function
Splits leading --- YAML front matter from the markdown body.
Only the flat key: value pairs docs actually use are read; anything
more structured (nested maps, lists) is skipped rather than mis-parsed.
Implementation
({Map<String, String> frontMatter, String body}) splitFrontMatter(String raw) {
final normalized = raw.replaceAll('\r\n', '\n');
if (!normalized.startsWith('---\n')) {
return (frontMatter: const {}, body: normalized);
}
final end = normalized.indexOf('\n---', 3);
if (end < 0) return (frontMatter: const {}, body: normalized);
final block = normalized.substring(4, end);
final body = normalized.substring(normalized.indexOf('\n', end + 1) + 1);
final frontMatter = <String, String>{};
String? key;
final folded = StringBuffer();
void flush() {
final pending = key;
if (pending != null && folded.isNotEmpty) {
frontMatter[pending] = folded.toString().trim();
}
folded.clear();
}
for (final line in block.split('\n')) {
final match = RegExp(r'^([A-Za-z_][\w-]*):\s*(.*)$').firstMatch(line);
if (match != null) {
flush();
key = match.group(1);
final value = match.group(2)!.trim();
// `>-` / `|` introduce a folded block; its lines follow indented.
folded.write(
value == '>-' || value == '>' || value == '|' ? '' : _unquote(value),
);
} else if (key != null && line.startsWith(RegExp(r'\s'))) {
folded.write(' ${line.trim()}');
}
}
flush();
return (frontMatter: frontMatter, body: body);
}