footnoteDefinitionAt function
A footnote definition starting at line start, or null.
[^label]: text, then its continuation: following lines up to a blank
line, unless they start another definition or a block of their own; and
after a blank line, further paragraphs indented by four or more spaces.
lines is its body with the marker and the continuation indent removed.
Implementation
({String label, List<String> lines, int next})? footnoteDefinitionAt(
List<String> lines,
int start,
) {
final line = lines[start];
if (!startsAfterIndent(line, 0x5B /* [ */)) {
return null;
}
final t = line.trimLeft();
if (!t.startsWith('[^')) {
return null;
}
final close = t.indexOf(']');
if (close < 3 || close + 1 >= t.length || t[close + 1] != ':') {
return null;
}
final label = t.substring(2, close);
if (label.contains(RegExp(r'[\s\[]'))) {
return null;
}
var first = t.substring(close + 2);
if (first.startsWith(' ') || first.startsWith('\t')) {
first = first.substring(1);
}
final body = <String>[first];
var k = start + 1;
while (k < lines.length) {
final next = lines[k];
if (isBlank(next)) {
var j = k + 1;
while (j < lines.length && isBlank(lines[j])) {
j += 1;
}
if (j < lines.length && indentWidth(lines[j]) >= 4) {
for (var b = k; b < j; b++) {
body.add('');
}
k = j;
continue;
}
break;
}
if (indentWidth(next) < 4 &&
(startsDefinition(next) || _interruptsParagraph(next.trimLeft()))) {
break;
}
body.add(stripIndent(next, 4));
k += 1;
}
while (body.isNotEmpty && body.last.trim().isEmpty) {
body.removeLast();
}
return (label: label, lines: body, next: k);
}