import { IIdentifierStyleDTO } from '../model/types' ; import { words , isUpperCase , isLowerCase , isTitleCase , trim , toTitleCase , toUpperCase as stringToUpperCase , toLowerCase as stringToLowerCase , toLowerCaseIfNotUpperCase , toTitleCaseIfNotUpperCase , } from './string' ; import { pipe , flipCurry } from './function' ; export const LOWER_CASE = 'LOWERCASE' ; export const UPPER_CASE = 'UPPERCASE' ; export const CAMEL_CASE = 'CAMELCASE' ; export const PASCAL_CASE = 'PASCALCASE' ; export const SNAKE_CASE = 'SNAKECASE' ; export const KEBAB_CASE = 'KEBABCASE' ; export const SNAKE_UPPER_CASE = 'SNAKEUPPERCASE' ; export const SNAKE_PASCAL_CASE = 'SNAKEPASCALCASE' ; export const UPPER_SNAKE_CASE = 'UPPERSNAKECASE' ; export const PASCAL_SNAKE_CASE = 'PASCALSNAKECASE' ; export const KEBAB_UPPER_CASE = 'KEBABUPPERCASE' ; export const KEBAB_PASCAL_CASE = 'KEBABPASCALCASE' ; export const UPPER_KEBAB_CASE = 'UPPERKEBABCASE' ; export const PASCAL_KEBAB_CASE = 'PASCALKEBABCASE' ; export const HYPHEN_CASE = 'HYPHENCASE' ; export const AUTO = 'AUTO' ; export const UNKNOWN = 'UNKNOWN' ; type TSep = '_' | '-' | '' ; type TMapCbl = ( ( value : string , index : number ) => string ) | ( ( value : string ) => string ) ; const snakeSep = '_' ; const kebabSep = '-' ; const emptySep = '' ; function convertCase ( value , sep , wordConverter ) { return words ( value ) . map ( wordConverter ) . join ( sep ) ; } function getToLowerCaseConverter ( keepUpperCase ? ) { return keepUpperCase ? toLowerCaseIfNotUpperCase : stringToLowerCase ; } function getToTitleCaseConverter ( keepUpperCase ? ) { return keepUpperCase ? toTitleCaseIfNotUpperCase : toTitleCase ; } export function toLowerCase ( value , keepUpperCase ? ) { return convertCase ( value , emptySep , getToLowerCaseConverter ( keepUpperCase ) ) ; } export function toUpperCase ( value ) { return convertCase ( value , emptySep , stringToUpperCase ) ; } export function toPascalCase ( value , keepUpperCase ? ) { return convertCase ( value , emptySep , getToTitleCaseConverter ( keepUpperCase ) ) ; } function getToCamelCaseMapCbl ( keepUpperCase ? ) { return function cbl ( value , index ) : string { const fistWordConverter = getToLowerCaseConverter ( keepUpperCase ) ; const restWordsConverter = getToTitleCaseConverter ( keepUpperCase ) ; const converter = index === 0 ? fistWordConverter : restWordsConverter ; return converter ( value ) ; } ; } export function toCamelCase ( value , keepUpperCase ? ) { return convertCase ( value , emptySep , getToCamelCaseMapCbl ( keepUpperCase ) ) ; } export function toSnakeCase ( value , keepUpperCase ? ) { return convertCase ( value , snakeSep , getToLowerCaseConverter ( keepUpperCase ) ) ; } export function toKebabCase ( value , keepUpperCase ? ) { return convertCase ( value , kebabSep , getToLowerCaseConverter ( keepUpperCase ) ) ; } export function toSnakeUpperCase ( value ) { return convertCase ( value , snakeSep , stringToUpperCase ) ; } export function toSnakePascalCase ( value , keepUpperCase ? ) { return convertCase ( value , snakeSep , getToTitleCaseConverter ( keepUpperCase ) ) ; } export function toKebabUpperCase ( value ) { return convertCase ( value , kebabSep , stringToUpperCase ) ; } export function toKebabPascalCase ( value , keepUpperCase ? ) { return convertCase ( value , kebabSep , getToTitleCaseConverter ( keepUpperCase ) ) ; } export function normalizeCase ( caseStr ) { return pipe ( flipCurry ( toPascalCase ) ( false ) , stringToUpperCase ) ( caseStr ) ; } function isUpperCaseList ( wordList ) { return wordList . every ( ( word ) => isUpperCase ( word ) ) ; } function isLowerCaseList ( wordList ) { return wordList . every ( ( word ) => isLowerCase ( word ) ) ; } function isCamelCaseList ( wordList ) { return ( isLowerCase ( wordList [ 0 ] ) && wordList . slice ( 1 ) . every ( ( word ) => isTitleCase ( word ) || isUpperCase ( word ) ) ) ; } function isPascalCaseList ( wordList ) { return ( ! isUpperCaseList ( wordList ) && wordList . every ( ( word ) => isTitleCase ( word ) || isUpperCase ( word ) ) ) ; } /**
 * If identifier containers any characters that are not in the character set { a-z, A-Z, -, _ },
 * UNKNOWN will be returned.
 */ export function checkIdentifierCase ( identifier ) { if ( /[^a-zA-Z\-_]/ . test ( identifier ) ) { return UNKNOWN ; } const trimmedIdentifier = pipe < string > ( flipCurry ( trim ) ( snakeSep ) , flipCurry ( trim ) ( kebabSep ) ) ( identifier ) ; const wordList = words ( trimmedIdentifier ) ; const isSnakeJoined = trimmedIdentifier . includes ( snakeSep ) ; const isKebabJoined = trimmedIdentifier . includes ( kebabSep ) ; if ( isSnakeJoined && isKebabJoined ) { return UNKNOWN ; } switch ( true ) { case isCamelCaseList ( wordList ) : if ( isSnakeJoined || isKebabJoined ) { return UNKNOWN ; } if ( wordList . length === 1 ) { return LOWER_CASE ; } return CAMEL_CASE ; case isLowerCaseList ( wordList ) : if ( isSnakeJoined ) { return SNAKE_CASE ; } if ( isKebabJoined ) { return KEBAB_CASE ; } return LOWER_CASE ; case isPascalCaseList ( wordList ) : if ( isSnakeJoined ) { return SNAKE_PASCAL_CASE ; } if ( isKebabJoined ) { return KEBAB_PASCAL_CASE ; } return PASCAL_CASE ; case isUpperCaseList ( wordList ) : if ( isSnakeJoined ) { return SNAKE_UPPER_CASE ; } if ( isKebabJoined ) { return KEBAB_UPPER_CASE ; } return UPPER_CASE ; default : return UNKNOWN ; } } const identifierConverterTable = { [ LOWER_CASE ] : toLowerCase , [ UPPER_CASE ] : toUpperCase , [ CAMEL_CASE ] : toCamelCase , [ PASCAL_CASE ] : toPascalCase , [ SNAKE_CASE ] : toSnakeCase , [ KEBAB_CASE ] : toKebabCase , [ HYPHEN_CASE ] : toKebabCase , [ SNAKE_UPPER_CASE ] : toSnakeUpperCase , [ UPPER_SNAKE_CASE ] : toSnakeUpperCase , [ SNAKE_PASCAL_CASE ] : toSnakePascalCase , [ PASCAL_SNAKE_CASE ] : toSnakePascalCase , [ KEBAB_UPPER_CASE ] : toKebabUpperCase , [ UPPER_KEBAB_CASE ] : toKebabUpperCase , [ KEBAB_PASCAL_CASE ] : toKebabPascalCase , [ PASCAL_KEBAB_CASE ] : toKebabPascalCase , [ UNKNOWN ] : ( arg ) => arg , } ; export function convertIdentifierCase ( identifier , identifierCase , keepUpperCase ? ) { return identifierConverterTable [ identifierCase ] ( identifier , keepUpperCase ) ; } export function convertIdentifierStyle ( identifier , style , placeholder ) { if ( style . noTransformation ) { return identifier ; } let identifierCase = normalizeCase ( style . case ) ; if ( identifierCase === AUTO ) { identifierCase = checkIdentifierCase ( placeholder ) ; } const { keepUpperCase , prefix , suffix } = style ; const convertedIdentifier = convertIdentifierCase ( identifier , identifierCase , keepUpperCase ) ; return `${ prefix }${ convertedIdentifier }${ suffix }` ; }