Mirror of https://github.com/roostorg/coop github.com/roostorg/coop
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 96 lines 2.8 kB view raw
1import { JsonValue, type Opaque } from 'type-fest'; 2 3// Split by newline and by commas, see https://stackoverflow.com/a/34316181 4export function splitByWhitespaceAndCommas(input: string): string[] { 5 return input.trim().split(/[\s,]+/); 6} 7 8function ucFirst(s: string): string { 9 return (s[0] ?? '').toUpperCase() + s.slice(1); 10} 11 12/** 13 * If the string s is formatted like an 'ENUM_VALUE', 14 * then change it to 'Enum Value'. 15 */ 16export function titleCaseEnumString(s: string): string { 17 return s 18 .split('_') 19 .map((word) => word.toLowerCase()) 20 .map(ucFirst) 21 .join(' '); 22} 23 24export function titleCaseEnumStringWithArticle(s: string): string { 25 const titleCased = titleCaseEnumString(s); 26 return ['A', 'a', 'E', 'e', 'I', 'i', 'O', 'o', 'U', 'u'].includes( 27 titleCased[0], 28 ) 29 ? `an ${titleCased}` 30 : `a ${titleCased}`; 31} 32 33export function prettyPrintJson(it: string) { 34 return prettyPrintJsonValue(JSON.parse(it)); 35} 36 37export function prettyPrintJsonValue(it: JsonValue) { 38 return JSON.stringify(it, undefined, 4); 39} 40 41export function isValidJson(it: string) { 42 try { 43 JSON.parse(it); 44 return true; 45 } catch (e) { 46 return false; 47 } 48} 49 50/** 51 * Converts a string to a human readable label with a 'best effort' approach, 52 * specifically looking for snake case, camel case, and spaces. Full disclosure, 53 * this was written by ChatGPT. 54 */ 55export function toHumanReadableLabel(input: string): string { 56 // Define regular expressions for different cases 57 const camelCase = /([a-z])([A-Z])/g; 58 const snakeCase = /_/g; 59 const spaceCase = / /g; 60 const kebabCase = /^[a-z]+(-[a-z]+)*$/; 61 const pascalCase = /^[A-Z][a-zA-Z]*$/; 62 63 if (camelCase.test(input)) { 64 return input 65 .replace(camelCase, '$1 $2') 66 .split(' ') 67 .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 68 .join(' '); 69 } else if (snakeCase.test(input) || spaceCase.test(input)) { 70 return input 71 .replace(snakeCase, ' ') 72 .split(' ') 73 .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 74 .join(' '); 75 } else if (kebabCase.test(input)) { 76 return input 77 .split('-') 78 .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 79 .join(' '); 80 } else if (pascalCase.test(input)) { 81 return input.charAt(0).toUpperCase() + input.slice(1); 82 } 83 84 // If not any of the above cases, just return the original string with first character capitalized 85 return input.charAt(0).toUpperCase() + input.slice(1); 86} 87 88export function truncateIdIfNeeded(id: string | undefined, maxLength: number) { 89 return id && id.length > maxLength ? id.substring(0, maxLength) + '...' : id; 90} 91 92export type NonEmptyString = Opaque<string, 'NonEmptyString'>; 93 94export function isNonEmptyString(it: unknown): it is NonEmptyString { 95 return typeof it === 'string' && it !== ''; 96}