Skip to content

Commit

Permalink
feat: add string formatter utils
Browse files Browse the repository at this point in the history
  • Loading branch information
trevor-anderson committed Feb 20, 2024
1 parent 298a94c commit 3ab68f2
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/utils/formatters/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { intToCurrencyStr, intToCurrencyRoundedStr } from "./currency";
import { getTimeStr, getDateStr, getDateAndTimeStr } from "./dateTime";
import { capitalize, prettifyPhoneNum } from "./strings";

/**
* A utility object with helper methods for formatting data as "pretty" strings for display.
*/
export const fmt = {
// currency
intToCurrencyStr,
intToCurrencyRoundedStr,
// dateTime
getTimeStr,
getDateStr,
getDateAndTimeStr,
// strings
capitalize,
prettifyPhoneNum,
};
38 changes: 38 additions & 0 deletions src/utils/formatters/strings.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { prettifyPhoneNum, prettifyBizName } from "./strings";

describe("formatters/strings", () => {
describe("prettifyPhoneNum()", () => {
test(`formats a valid phone number string into a "pretty" format`, () => {
expect(prettifyPhoneNum("1234567890")).toBe("(123) 456-7890");
expect(prettifyPhoneNum(" 1234567890 ")).toBe("(123) 456-7890");
expect(prettifyPhoneNum(" +(123)4567890 ")).toBe("(123) 456-7890");
});

test("throws an error if shouldValidate is true and the input is an empty string", () => {
expect(() => {
prettifyPhoneNum("");
}).toThrowError('Phone number formatter received an invalid value: ""');
});
});

describe("prettifyBizName()", () => {
test("capitalizes the first letter of each word in the provided string arg", () => {
expect(prettifyBizName("foo bar baz")).toBe("Foo Bar Baz");
expect(prettifyBizName("FOO BAR BAZ")).toBe("Foo Bar Baz");
expect(prettifyBizName("foo BAR baz")).toBe("Foo Bar Baz");
});

test("uppercases common business name acronyms", () => {
expect(prettifyBizName("foo bar llc baz")).toBe("Foo Bar LLC Baz");
expect(prettifyBizName("foo bar inc baz")).toBe("Foo Bar INC Baz");
expect(prettifyBizName("foo bar co baz")).toBe("Foo Bar CO Baz");
expect(prettifyBizName("foo bar corp baz")).toBe("Foo Bar CORP Baz");
expect(prettifyBizName("foo bar ltd baz")).toBe("Foo Bar LTD Baz");
expect(prettifyBizName("foo bar lp baz")).toBe("Foo Bar LP Baz");
});

test("does not throw when provided an empty string", () => {
expect(prettifyBizName("")).toBe("");
});
});
});
54 changes: 54 additions & 0 deletions src/utils/formatters/strings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { isValidPhone } from "@nerdware/ts-string-helpers";
import { safeJsonStringify } from "@nerdware/ts-type-safety-utils";

/**
* Formats a phone number string into a "pretty" format.
*
* @param phoneNum The phone number string to format.
* @param shouldValidate Whether or not to validate the input before formatting it (defaults to `true`).
* @returns The formatted phone number string.
* @throws If `shouldValidate` is `true` and the input is invalid.
*/
export const prettifyPhoneNum = (phoneNum: string, shouldValidate: boolean = true) => {
phoneNum = phoneNum.replace(/\D/g, "");

if (shouldValidate && !isValidPhone(phoneNum)) {
throw new Error(
`Phone number formatter received an invalid value: ${safeJsonStringify(phoneNum)}`
);
}

return `(${phoneNum.substring(0, 3)}) ${phoneNum.substring(3, 6)}-${phoneNum.substring(6, 11)}`;
};

/**
* Capitalizes the first letter of `str`, and makes all other letters lowercase.
*
* @param str The string to capitalize.
* @returns The capitalized string.
*/
export const capitalize = <S extends string>(str: S) => {
return `${str.charAt(0).toUpperCase()}${str.slice(1).toLowerCase()}` as Capitalize<S>;
};

/**
* For each word in the provided string arg, unless the word is included in the
* list below, the first letter is capitalized and the rest are lowercased. The
* common acronyms listed below are entirely uppercased.
*
* Common business name acronyms which are uppercased:
* - LLC
* - INC
* - CO
* - CORP
* - LTD
* - LP
*/
export const prettifyBizName = (rawBizName: string) => {
return rawBizName
.split(" ")
.map((word) =>
/^(llc|inc|co|corp|ltd|lp)\.?$/i.test(word) ? word.toUpperCase() : capitalize(word)
)
.join(" ");
};

0 comments on commit 3ab68f2

Please sign in to comment.