wrapText static method

String wrapText(
  1. String text, {
  2. bool wrapAtWordBoundary = false,
})

Wraps the text so that it stays within email's 76 characters per line convention. text the text that should be wrapped. Set wrapAtWordBoundary to true in case the text should be wrapped at word boundaries / spaces.

Implementation

static String wrapText(String text, {bool wrapAtWordBoundary = false}) {
  if (text.length <= MailConventions.textLineMaxLength) {
    return text;
  }
  final buffer = StringBuffer();
  final runes = text.runes;
  int? lastRune;
  int? lastSpaceIndex;
  var currentLineLength = 0;
  var currentLineStartIndex = 0;
  for (var runeIndex = 0; runeIndex < runes.length; runeIndex++) {
    final rune = runes.elementAt(runeIndex);
    if (rune == AsciiRunes.runeLineFeed &&
        lastRune == AsciiRunes.runeCarriageReturn) {
      buffer.write(text.substring(currentLineStartIndex, runeIndex + 1));
      currentLineLength = 0;
      currentLineStartIndex = runeIndex + 1;
      lastSpaceIndex = null;
    } else {
      if (wrapAtWordBoundary &&
          (rune == AsciiRunes.runeSpace || rune == AsciiRunes.runeTab)) {
        lastSpaceIndex = runeIndex;
      }
      currentLineLength++;
      if (currentLineLength >= MailConventions.textLineMaxLength) {
        // edge case: this could be in the middle of a \r\n sequence:
        if (rune == AsciiRunes.runeCarriageReturn &&
            runeIndex < runes.length - 1 &&
            runes.elementAt(runeIndex + 1) == AsciiRunes.runeLineFeed) {
          lastRune = rune;
          continue; // the break will be handled in the next loop iteration
        }
        var endIndex = (wrapAtWordBoundary && lastSpaceIndex != null)
            ? lastSpaceIndex
            : runeIndex;
        if (endIndex < runes.length - 1) {
          endIndex++;
        }
        buffer.write(text.substring(currentLineStartIndex, endIndex));
        buffer.write('\r\n');
        currentLineLength = 0;
        currentLineStartIndex = endIndex;
        lastSpaceIndex = null;
      }
    }
    lastRune = rune;
  }
  // final currentIndex = 0;
  // while (currentIndex + MailConventions.textLineMaxLength < text.length) {
  //   final length = MailConventions.textLineMaxLength;
  //   if (wrapAtWordBoundary) {
  //     final endIndex = currentIndex + MailConventions.textLineMaxLength - 1;
  //     final runes = text.runes;
  //     final rune = runes.elementAt(endIndex);
  //     if (rune != AsciiRunes.runeSpace) {
  //       for (final runeIndex = endIndex; --runeIndex > currentIndex;) {
  //         rune = runes.elementAt(runeIndex);
  //         if (rune == AsciiRunes.runeSpace) {
  //           endIndex = runeIndex;
  //           break;
  //         }
  //       }
  //     }
  //     length = endIndex - currentIndex + 1;
  //   }
  //   buffer.write(text.substring(currentIndex, currentIndex + length));
  //   buffer.write('\r\n');
  //   currentIndex += length;
  // }
  if (currentLineStartIndex < text.length) {
    buffer.write(text.substring(currentLineStartIndex));
  }
  return buffer.toString();
}