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 27846x 27844x 5507x 5507x   22337x 22337x 22337x   15679x 9166x 8117x 4581x 6513x 15679x     6658x 4664x 6658x         3x 13876x   10192x   3684x       3x 5686x     3x 3364x 3362x 3362x 3362x     3x 2148x 2148x 8216x 2148x 2148x                     3x 6522x   4583x     1939x 1939x        
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);
    }
  }
};