pdf-tools/util/caseManagement.ts

167 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

function lowerToPascalCase(str: string) {
return str.replace(/(?:^|\s)\w/g, (match) => match.toUpperCase()).replaceAll(
" ",
"",
);
}
function lowerToTrainCase(str: string) {
return str.replace(/(?:^|\s)\w/g, (match) => match.toUpperCase()).replaceAll(
" ",
"-",
);
}
/**
* @param str
* @returns camelCased string (single letter words are lower cased, e.g. SSN -> ssn)
*/
function lowerToCamelCase(str: string): string {
const words = str.trim().split(/\s+/);
const result: string[] = [];
let i = 0;
while (i < words.length) {
if (words[i].length === 1) {
// Weve hit the start of a chain of single-letter words
let j = i;
while (j < words.length && words[j].length === 1) {
j++;
}
const chainIsAtStart = i === 0;
// Process that entire chain
for (let k = i; k < j; k++) {
result[k] = chainIsAtStart
? words[k].toLowerCase()
: words[k].toUpperCase();
}
i = j;
} else {
// Normal multi-letter word
if (i === 0) {
// first word: all lower
result[i] = words[i].toLowerCase();
} else {
// subsequent words: capitalize first letter
result[i] = words[i][0].toUpperCase() +
words[i].slice(1).toLowerCase();
}
i++;
}
}
return result.join("");
}
function lowerToSnakeCase(str: string) {
return str.replace(" ", "_");
}
function lowerToKebabCase(str: string) {
return str.replace(" ", "-");
}
function lowerToMacroCase(str: string) {
return str.replace(/\w\S*/g, (match) => match.toUpperCase()).replaceAll(
" ",
"_",
);
}
function lowerToTitleCase(str: string) {
return str.replace(/(?:^|\s)\w/g, (match) => match.toUpperCase());
}
type CaseType =
| "pascal"
| "camel"
| "snake"
| "kebab"
| "macro"
| "upper"
| "lower"
| "train"
| "title"
| "";
function parseCase(str: string) {
const isCaseMap = new Map<CaseType, (str: string) => boolean>([
["pascal", (str: string) => {
return /^[A-Z][a-zA-Z]*$/.test(str);
}],
["camel", (str: string) => {
return /^[a-z][a-zA-Z]*$/.test(str);
}],
["snake", (str: string) => {
return /^[a-z][a-z0-9_]*$/.test(str);
}],
["kebab", (str: string) => {
return /^[a-z][a-z0-9-]*$/.test(str);
}],
["macro", (str: string) => {
return /^[A-Z]*$/.test(str);
}],
["upper", (str: string) => {
return /^[A-Z]*$/.test(str);
}],
["lower", (str: string) => {
return /^[a-z]*$/.test(str);
}],
["train", (str: string) => {
return /([A-Z][a-z]*(?:-|$))+/.test(str);
}],
]);
for (const [key, value] of isCaseMap) {
if (value(str)) return key;
}
return "";
}
function coerceCaseToLower(str: string, caseType: CaseType) {
switch (caseType) {
case "pascal":
case "camel":
return str.replace(/[A-Z]/g, (match) => " " + match.toLowerCase().trim());
case "macro":
case "snake":
case "upper":
return str.replaceAll("_", " ").toLowerCase();
case "train":
case "kebab":
return str.replaceAll("-", " ").toLowerCase();
default:
return str.toLowerCase();
}
}
export function toCase(str: string, toCase: CaseType) {
const caseType = parseCase(str) || "";
if (caseType === toCase) return str;
const lowerStr = coerceCaseToLower(str, caseType);
switch (toCase) {
case "pascal":
return lowerToPascalCase(lowerStr);
case "camel":
return lowerToCamelCase(lowerStr);
case "snake":
return lowerToSnakeCase(lowerStr);
case "kebab":
return lowerToKebabCase(lowerStr);
case "macro":
return lowerToMacroCase(lowerStr);
case "upper":
return lowerStr.toUpperCase();
case "lower":
return lowerStr.toLowerCase();
case "train":
return lowerToTrainCase(lowerStr);
case "title":
return lowerToTitleCase(lowerStr);
default:
return str;
}
}
if (import.meta.main) {
console.log(toCase("SSN", "camel"));
}