fixMarkdownNewLines static method

String fixMarkdownNewLines(
  1. String data
)

Implementation

static String fixMarkdownNewLines(String data) {
  final codeBlockPattern =
      RegExp(r'```.*?```', dotAll: true); // Matches code blocks
  final nonCodeBlocks = <String>[];
  final codeBlocks = <String>[];

  // Split data into segments of code blocks and non-code blocks
  final matches = codeBlockPattern.allMatches(data);
  int lastMatchEnd = 0;

  for (final match in matches) {
    // Add text before the code block as a non-code block
    if (match.start > lastMatchEnd) {
      nonCodeBlocks.add(data.substring(lastMatchEnd, match.start));
    }
    // Add the code block itself
    codeBlocks.add(data.substring(match.start, match.end));
    lastMatchEnd = match.end;
  }

  // Add any remaining non-code block text
  if (lastMatchEnd < data.length) {
    nonCodeBlocks.add(data.substring(lastMatchEnd));
  }

  // Process non-code blocks (using \u200B as a temporary hack to show new lines):
  final processedNonCodeBlocks = nonCodeBlocks.map((block) {
    return block
        .replaceAll(
            '\n\n\n\n', '\n\n\n\u200B\n') // First replace quadruple newlines
        .replaceAll('\n\n\n', '\n\n\u200B\n') // Then replace triple newlines
        .replaceAll('\n', '  \n'); // Then replace single newlines
  }).toList();

  // Combine processed non-code blocks and code blocks back together
  final buffer = StringBuffer();
  int codeIndex = 0, nonCodeIndex = 0;

  for (final _ in matches) {
    if (nonCodeIndex < processedNonCodeBlocks.length) {
      buffer.write(processedNonCodeBlocks[nonCodeIndex++]);
    }
    if (codeIndex < codeBlocks.length) {
      buffer.write(codeBlocks[codeIndex++]);
    }
  }

  // Add any remaining non-code block
  if (nonCodeIndex < processedNonCodeBlocks.length) {
    buffer.write(processedNonCodeBlocks[nonCodeIndex]);
  }

  return buffer.toString();
}