All files / fuse-ui-shared stringCases.ts

88.54% Statements 85/96
87.93% Branches 51/58
84% Functions 21/25
90.54% Lines 67/74
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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 1301x   1x 1x 1x 1x 1x 1x 1x 1x     1x 19x 19x   36x 36x 11x   21x 4x   23x 17x       26x 14x 39x 18x 10x 11x 5x 8x   1x 19x   19x 18x 4x     14x 1x     13x 2x     11x 6x     5x       5x 1x     4x 4x       1x     1x 12x 12x 4x     8x     1x 12x 12x   12x 2x     10x   3x 3x           4x 4x   3x     10x           8x   6x       2x             4x   4x   1x  
import { asArray, first } from './iterator';
 
export enum StringCases {
  unknown,
  lowerCase,
  upperCase,
  camelCase,
  pascalCase,
  snakeCase,
  kebabCase
}
 
export function* breakWords(text: string): IterableIterator<string> {
  const capitalWord = /([A-Z][a-z0-9]*)/g;
  let cur = 0;
  for (; ;) {
    const match = capitalWord.exec(text);
    if (!match) {
      break;
    }
    if (match.index > cur) {
      yield text.substr(cur, match.index - cur);
    }
    yield match[1];
    cur = match.index + match[1].length;
  }
}
 
const isLowerCase = (text: string) => text && text.match(/^[a-z0-9]+$/);
const isUpperCase = (text: string) => text && text.match(/^[A-Z0-9]+$/);
const isWord = (text: string) => text && text.match(/^[a-zA-Z0-9]+$/);
const isCamelCase = (text: string) => text && isWord(text) && isLowerCase(first(breakWords(text)));
const isCapitalWord = (text: string) => text.match(/^[A-Z][a-z0-9]*$/);
const isPascalCase = (text: string) => text && isWord(text) && asArray(breakWords(text)).filter(x => !isCapitalWord(x)).length === 0;
const isSnakeCase = (text: string) => text && text.indexOf('_') >= 0 && text.split('_').filter(x => !isWord(x)).length === 0;
const isKebabCase = (text: string) => text && text.indexOf('-') >= 0 && text.split('-').filter(x => !isWord(x)).length === 0;
 
export function detectCase(name: string): StringCases {
  let result = StringCases.unknown;
 
  if (name) {
    if (isLowerCase(name)) {
      return StringCases.lowerCase;
    }
 
    if (isUpperCase(name)) {
      return StringCases.upperCase;
    }
 
    if (isCamelCase(name)) {
      return StringCases.camelCase;
    }
 
    if (isPascalCase(name)) {
      return StringCases.pascalCase;
    }
 
    Iif (isCamelCase(name)) {
      return StringCases.camelCase;
    }
 
    if (isSnakeCase(name)) {
      return StringCases.snakeCase;
    }
 
    Eif (isKebabCase(name)) {
      return StringCases.kebabCase;
    }
  }
 
  return result;
}
 
export function capitalize(word: string): string {
  const match = word.match(/^([a-z])[a-z0-9A-Z]*$/);
  if (!match) {
    return word;
  }
 
  return `${match[1].toUpperCase()}${word.substr(1)}`;
}
 
export function toCase(targetCase: StringCases, text): string {
  const source = detectCase(text);
  let words: string[] = [];
 
  if (source === targetCase) {
    return text;
  }
 
  switch (source) {
    case StringCases.kebabCase:
      words = text.split('-');
      break;
    case StringCases.snakeCase:
      words = text.split('_');
      break;
    case StringCases.camelCase:
    case StringCases.pascalCase:
      words = asArray(breakWords(text));
      break;
    default:
      words = [text];
  }
 
  switch (targetCase) {
    case StringCases.lowerCase:
      return words.map(x => x.toLowerCase()).join('');
    case StringCases.upperCase:
      return words.map(x => x.toUpperCase()).join('');
    case StringCases.camelCase:
      return words.map((x, i) => i === 0 ? x.toLowerCase() : capitalize(x)).join('');
    case StringCases.pascalCase:
      return words.map((x, i) => i === 0 ? capitalize(x) : capitalize(x)).join('');
    case StringCases.kebabCase:
      return words.map(x => x.toLowerCase()).join('-');
    case StringCases.snakeCase:
      return words.map(x => x.toLowerCase()).join('_');
    default:
  }
 
  return text;
}
 
export const camelCase = (word: string) => toCase(StringCases.camelCase, word);
 
export const pascalCase = (word: string) => toCase(StringCases.pascalCase, word);
 
export const kebabCase = (word: string) => toCase(StringCases.kebabCase, word);