All files / src/shared/lib/helpers trimlines.ts

95.23% Statements 40/42
47.36% Branches 9/19
71.42% Functions 5/7
95% Lines 38/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93  9x 9x 9x 9x   9x 9x 9x   9x 213x           9x 33x 33x 15x   18x 18x 18x     9x           40x   40x         80x 60x     20x   20x   13x 5x 12x 12x 12x 5x                     15x         88x 88x 3x 3x   85x                 9x     9x         9x  
/* eslint-disable no-control-regex */
const LINE_MAX = 4;
const LINE_MIN = 2;
const CHARS_PER_LINE = 18;
const CHARS_MAX_TOTAL = 18 + 18 + 16;
 
const varRegex = new RegExp("\\$[VLT]?[0-9]+\\$", "g");
const varCharRegex = new RegExp("#[VLT]?[0-9]+#", "g");
const commandRegex = new RegExp("\\!S[0-5]\\!", "g");
 
const lineLength = (line: string) => {
  return line
    .replace(varRegex, "255")
    .replace(varCharRegex, "C")
    .replace(commandRegex, "").length;
};
 
const cropLine = (line: string, maxLength: number): string => {
  const len = lineLength(line);
  if (len <= maxLength) {
    return line;
  }
  const lenDiff = len - maxLength;
  const cropped = line.substring(0, line.length - lenDiff);
  return cropLine(cropped, maxLength);
};
 
const trimlines = (
  string: string,
  maxCharsPerLine = CHARS_PER_LINE,
  maxLines = LINE_MAX,
  maxTotal = CHARS_MAX_TOTAL,
): string => {
  let lengthCount = 0;
 
  return (
    string
      .split("\n")
      .map((line, lineIndex) => {
        // Include whole line if under limits
        if (lineLength(line) <= maxCharsPerLine) {
          return line;
        }
 
        let cropped = line;
        // If not last line
        if (lineIndex < maxLines - 1) {
          // Crop to last space if possible
          if (cropped.indexOf(" ") > -1) {
            while (cropped.indexOf(" ") > -1) {
              const lastBreakSymbol = cropped.lastIndexOf(" ");
              cropped = cropped.substring(0, lastBreakSymbol);
              if (lineLength(cropped) <= maxCharsPerLine) {
                return `${cropped}\n${trimlines(
                  line.substring(cropped.length + 1, line.length),
                  maxCharsPerLine,
                  maxLines,
                )}`;
              }
            }
          }
        }
 
        // Fallback to just cropping the line to fit mid word
        return cropLine(line, maxCharsPerLine);
      })
      .join("\n")
      .split("\n")
      .map((line) => {
        lengthCount += lineLength(line);
        if (lengthCount > maxTotal) {
          const amountOver = lengthCount - maxTotal;
          return line.substring(0, line.length - amountOver);
        }
        return line;
      })
      .slice(0, maxLines)
      .join("\n")
      // Crop to max 80 characters used in C string buffer
      .substring(0, 80)
  );
};
 
export const textNumLines = (string: string) =>
  Math.max(LINE_MIN, (string || "").split("\n").length);
 
export const textNumNewlines = (input: string): number => {
  // eslint-disable-next-line no-control-regex
  return (input.match(/(\n|\r|\x0a|\x0d|\\012|\\015)/g)?.length ?? 0) + 1;
};
 
export default trimlines;