All files / json-ot/types/ot-string-irreversible util.ts

100% Statements 53/53
100% Branches 28/28
100% Functions 6/6
100% Lines 39/39

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    3x 27571x 27569x 5510x 5510x   22059x 22059x 22059x   15438x 8928x 7860x 4482x 6510x 15438x     6621x 4727x 6621x         3x 13218x   9728x   3490x       3x 5530x     3x 3367x 3362x 3362x 3362x     3x 2151x 2151x 8199x 2151x 2151x                     3x 6219x   4362x     1857x 1857x        
import type {StringOp, StringOpComponent} from './types';
 
export const append = (op: StringOp, component: StringOpComponent): void => {
  if (!component) return;
  if (!op.length) {
    op.push(component);
    return;
  }
  const lastIndex = op.length - 1;
  const last = op[lastIndex];
  switch (typeof component) {
    case 'number': {
      if (typeof last === 'number') {
        if (component > 0 && last > 0) op[lastIndex] = last + component;
        else if (component < 0 && last < 0) op[lastIndex] = last + component;
        else op.push(component);
      } else op.push(component);
      break;
    }
    case 'string': {
      if (typeof last === 'string') op[lastIndex] = last + component;
      else op.push(component);
      break;
    }
  }
};
 
export const componentLength = (component: StringOpComponent): number => {
  switch (typeof component) {
    case 'number':
      return Math.abs(component);
    case 'string':
      return component.length;
  }
};
 
export const isDeleteComponent = (component: StringOpComponent): boolean => {
  return typeof component === 'number' && component < 0;
};
 
export const trim = (op: StringOp): void => {
  if (!op.length) return;
  const last = op[op.length - 1];
  const isLastRetain = typeof last === 'number' && last > 0;
  if (isLastRetain) op.pop();
};
 
export const normalize = (op: StringOp): StringOp => {
  const op2: StringOp = [];
  const length = op.length;
  for (let i = 0; i < length; i++) append(op2, op[i]);
  trim(op2);
  return op2;
};
 
/**
 * Extracts a full or a part of a component from an operation.
 *
 * @param component Component from which to extract a chunk.
 * @param offset Position within the component to start from.
 * @param maxLength Maximum length of the component to extract.
 * @returns Full or partial component at index `index` of operation `op`.
 */
export const chunk = (component: StringOpComponent, offset: number, maxLength: number): StringOpComponent => {
  switch (typeof component) {
    case 'number': {
      return component > 0 ? Math.min(component - offset, maxLength) : -Math.min(-component - offset, maxLength);
    }
    case 'string': {
      const end = Math.min(offset + maxLength, component.length);
      return component.substring(offset, end);
    }
  }
};