All files color.ts

95.78% Statements 91/95
88.88% Branches 16/18
100% Functions 6/6
95.78% Lines 91/95

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 94 95 961x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 16x 16x 16x 16x 16x 16x 16x 16x 1x 1x 1x 1x 1x 1x 16x 16x 16x 16x 1x 3x 3x 3x 3x 3x 3x 3x 3x 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x         4x 3x 3x 4x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 1x 1x 1x 1x 1x 1x  
import {
  Parsed,
  ColorCoded,
  Char,
  Parsable,
  ensureParsed,
  getColor,
  Line,
  Tokenized,
  Token,
} from './code';
 
export enum Undertone {
  Grey = '#212121',
  Plum = '#3c2126',
  Purple = '#2a2133',
  Blue = '#011c39',
  Teal = '#043132',
  Green = '#172808',
  Brown = '#2c1608',
}
 
function getBackground(
  char: Char,
  highlight: Record<string, string>,
): string | undefined {
  const relevantSection = char.sections.find((s) => s in highlight);
  return relevantSection !== undefined ? highlight[relevantSection] : undefined;
}
 
export function color(
  code: Parsed<Char> | Parsable,
  highlight: Record<string, string> = {},
): Parsed<Char & ColorCoded, Line & ColorCoded> {
  const parsed = ensureParsed(code);
  const chars = parsed.chars.map((char) => ({
    ...char,
    color: getColor(char.classList),
    background: getBackground(char, highlight),
  }));
  const lines = parsed.lines.map((line, i) => {
    const { tags } = line;
    const relevantTag = tags.find((tag) => tag in highlight);
    const background = relevantTag ? highlight[relevantTag] : undefined;
    return {
      ...line,
      number: i + 1,
      background,
    };
  });
  return {
    ...parsed,
    chars,
    lines,
  };
}
 
export function tokenize<L extends Line>(
  code: Parsed<Char & ColorCoded, L>,
): Tokenized<Token & ColorCoded, L> {
  const chars = code.chars;
  let lastFgColor: string | undefined | symbol = Symbol();
  let lastBgColor: string | undefined | symbol = Symbol();
  let [ln, at] = [0, 0];
  const tokens: (Token & ColorCoded)[] = [];
  for (let i = 0; i < chars.length; i++) {
    const char = chars[i];
    const color = char.color;
    const background = char.background;
    if (char.char === '\n') {
      lastFgColor = Symbol();
      lastBgColor = Symbol();
      ln++;
      at = 0;
    } else if (color === lastFgColor && background === lastBgColor) {
      tokens[tokens.length - 1].token += char.char;
      at++;
    } else {
      tokens.push({
        token: char.char,
        location: [ln, at],
        color,
        background,
      });
      at++;
    }
    lastFgColor = color;
    lastBgColor = background;
  }
  return {
    language: code.language,
    lines: code.lines,
    tokens,
  };
}