collectLines static method

MarkdownDefinitions collectLines(
  1. List<String> lines, {
  2. MarkdownBlockRegistry? blockRegistry,
})

collect over a document already split into lines.

Implementation

static MarkdownDefinitions collectLines(
  List<String> lines, {
  MarkdownBlockRegistry? blockRegistry,
}) {
  // A definition opens its line with `[`. Checking each line's first
  // character is far cheaper than reading every character of the document,
  // and most documents have no such line.
  if (!lines.any((line) => startsAfterIndent(line, _openBracket))) {
    return empty;
  }
  final links = <String, MdLinkDefinition>{};
  final footnotes = <String, int>{};
  var mayStart = true;
  var i = 0;
  while (i < lines.length) {
    final line = lines[i];
    final first = firstNonSpace(line);
    if (first == -1) {
      mayStart = true;
      i += 1;
      continue;
    }
    final custom = blockRegistry?.match(lines, i);
    if (custom != null) {
      i = custom.endLine;
      mayStart = false;
      continue;
    }
    final unit = line.codeUnitAt(first);
    if (unit == 0x60 /* ` */ || unit == 0x7E /* ~ */ ) {
      final fence = fenceOpen(line.substring(first));
      if (fence != null) {
        i += 1;
        while (i < lines.length && !isFenceClose(lines[i], fence)) {
          i += 1;
        }
        i += 1;
        mayStart = false;
        continue;
      }
    }
    if (unit == 0x5C /* \ */ && line.startsWith(r'\[', first)) {
      var rest = line.substring(first);
      while (rest.startsWith(r'\[')) {
        rest = rest.substring(2);
      }
      if (!rest.contains(r'\]')) {
        i += 1;
        while (i < lines.length && !lines[i].contains(r'\]')) {
          i += 1;
        }
      }
      i += 1;
      mayStart = false;
      continue;
    }
    if (unit == 0x3C /* < */ && line.startsWith('<!--', first)) {
      final end = htmlCommentEnd(lines, i);
      i = end.next;
      mayStart = end.trailing.trim().isEmpty;
      continue;
    }
    if (mayStart && unit == _openBracket && first <= 3) {
      final footnote = footnoteDefinitionAt(lines, i);
      if (footnote != null) {
        footnotes.putIfAbsent(
          normalizeLabel(footnote.label),
          () => footnotes.length + 1,
        );
        i = footnote.next;
        continue;
      }
      final link = linkDefinitionAt(line);
      if (link != null) {
        links.putIfAbsent(normalizeLabel(link.label), () => link.definition);
        i += 1;
        continue;
      }
    }
    mayStart = false;
    i += 1;
  }
  if (links.isEmpty && footnotes.isEmpty) {
    return empty;
  }
  return MarkdownDefinitions._(links, footnotes, null);
}