diff --git a/text/_util.ts b/text/_util.ts new file mode 100644 index 000000000000..61e98b0f7002 --- /dev/null +++ b/text/_util.ts @@ -0,0 +1,13 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +export function splitToWords(input: string) { + input = input.replaceAll(/[^a-zA-Z0-9\s-_]/g, ""); + if (/[\s-_]+/.test(input)) return input.split(/[\s-_]+/); + return input.split(/(?=[A-Z])+/); +} + +export function capitalizeWord(word: string): string { + return word + ? word[0].toLocaleUpperCase() + word.slice(1).toLocaleLowerCase() + : word; +} diff --git a/text/_util_test.ts b/text/_util_test.ts new file mode 100644 index 000000000000..d0854e243af4 --- /dev/null +++ b/text/_util_test.ts @@ -0,0 +1,58 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +import { assertEquals } from "../assert/assert_equals.ts"; +import { splitToWords } from "./_util.ts"; + +Deno.test({ + name: "split() handles whitespace", + fn() { + const result = splitToWords("deno Is AWESOME"); + const expected = ["deno", "Is", "AWESOME"]; + assertEquals(result, expected); + }, +}); + +Deno.test({ + name: "split() handles mixed delimiters", + fn() { + const result = splitToWords("I am up-to-date!"); + const expected = ["I", "am", "up", "to", "date"]; + assertEquals(result, expected); + }, +}); + +Deno.test({ + name: "split() handles upper case delimiter", + fn() { + const result = splitToWords("denoIsAwesome"); + const expected = ["deno", "Is", "Awesome"]; + assertEquals(result, expected); + }, +}); + +Deno.test({ + name: "split() handles hyphen delimiter", + fn() { + const result = splitToWords("deno-is-awesome"); + const expected = ["deno", "is", "awesome"]; + assertEquals(result, expected); + }, +}); + +Deno.test({ + name: "split() handles screaming snake case", + fn() { + const result = splitToWords("DENO_IS_AWESOME"); + const expected = ["DENO", "IS", "AWESOME"]; + assertEquals(result, expected); + }, +}); + +Deno.test({ + name: "split() handles underscore delimiter", + fn() { + const result = splitToWords("deno_is_awesome"); + const expected = ["deno", "is", "awesome"]; + assertEquals(result, expected); + }, +}); diff --git a/text/case.ts b/text/case.ts new file mode 100644 index 000000000000..0d5ec523442c --- /dev/null +++ b/text/case.ts @@ -0,0 +1,75 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +import { capitalizeWord, splitToWords } from "./_util.ts"; + +/** + * Converts a string into camelCase. + * + * @example + * ```ts + * import { toCamelCase } from "https://deno.land/std@$STD_VERSION/text/case.ts"; + * + * toCamelCase("deno is awesome"); // "denoIsAwesome" + * ``` + * + * @param input The string that is going to be converted into camelCase + * @returns The string as camelCase + */ +export function toCamelCase(input: string): string { + input = input.trim(); + const [first = "", ...rest] = splitToWords(input); + return [first.toLocaleLowerCase(), ...rest.map(capitalizeWord)].join(""); +} + +/** + * Converts a string into kebab-case. + * + * @example + * ```ts + * import { toKebabCase } from "https://deno.land/std@$STD_VERSION/text/case.ts"; + * + * toKebabCase("deno is awesome"); // "deno-is-awesome" + * ``` + * + * @param input The string that is going to be converted into kebab-case + * @returns The string as kebab-case + */ +export function toKebabCase(input: string): string { + input = input.trim(); + return splitToWords(input).join("-").toLocaleLowerCase(); +} + +/** + * Converts a string into PascalCase. + * + * @example + * ```ts + * import { toPascalCase } from "https://deno.land/std@$STD_VERSION/text/case.ts"; + * + * toPascalCase("deno is awesome"); // "DenoIsAwesome" + * ``` + * + * @param input The string that is going to be converted into PascalCase + * @returns The string as PascalCase + */ +export function toPascalCase(input: string): string { + input = input.trim(); + return splitToWords(input).map(capitalizeWord).join(""); +} + +/** + * Converts a string into snake_case. + * + * @example + * ```ts + * import { toSnakeCase } from "https://deno.land/std@$STD_VERSION/text/case.ts"; + * toSnakeCase("deno is awesome"); // "deno_is_awesome" + * ``` + * + * @param input The string that is going to be converted into snake_case + * @returns The string as snake_case + */ +export function toSnakeCase(input: string): string { + input = input.trim(); + return splitToWords(input).join("_").toLocaleLowerCase(); +} diff --git a/text/case_test.ts b/text/case_test.ts new file mode 100644 index 000000000000..2574c9ce9f2a --- /dev/null +++ b/text/case_test.ts @@ -0,0 +1,116 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +import { assertEquals } from "../assert/assert_equals.ts"; +import { toCamelCase, toKebabCase, toPascalCase, toSnakeCase } from "./case.ts"; + +Deno.test("toCamelCase() handles an empty string", () => { + assertEquals(toCamelCase(""), ""); +}); + +Deno.test("toCamelCase() converts a single word", () => { + const input = "shruberry"; + const expected = "shruberry"; + assertEquals(toCamelCase(input), expected); +}); + +Deno.test("toCamelCase() converts a sentence", () => { + const input = "she turned me into a newt"; + const expected = "sheTurnedMeIntoANewt"; + assertEquals(toCamelCase(input), expected); +}); + +Deno.test("toCamelCase() converts multiple delimiters", () => { + const result = toCamelCase("I am up-to-date!"); + const expected = "iAmUpToDate"; + assertEquals(result, expected); +}); + +Deno.test("toCamelCase() trims whitespace", () => { + const result = toCamelCase(" deno Is AWESOME "); + const expected = "denoIsAwesome"; + assertEquals(result, expected); +}); + +Deno.test("toKebabCase() handles an empty string", () => { + assertEquals(toKebabCase(""), ""); +}); + +Deno.test("toKebabCase() converts a single word", () => { + const input = "shruberry"; + const expected = "shruberry"; + assertEquals(toKebabCase(input), expected); +}); + +Deno.test("toKebabCase() converts a sentence", () => { + const input = "she turned me into a newt"; + const expected = "she-turned-me-into-a-newt"; + assertEquals(toKebabCase(input), expected); +}); + +Deno.test("toKebabCase() converts multiple delimiters", () => { + const result = toKebabCase("I am up-to-date!"); + const expected = "i-am-up-to-date"; + assertEquals(result, expected); +}); + +Deno.test("toKebabCase() trims whitespace", () => { + const result = toKebabCase(" deno Is AWESOME "); + const expected = "deno-is-awesome"; + assertEquals(result, expected); +}); + +Deno.test("toPascalCase() handles empty string", () => { + assertEquals(toPascalCase(""), ""); +}); + +Deno.test("toPascalCase() converts a single word", () => { + const input = "shruberry"; + const expected = "Shruberry"; + assertEquals(toPascalCase(input), expected); +}); + +Deno.test("toPascalCase() converts a sentence", () => { + const input = "she turned me into a newt"; + const expected = "SheTurnedMeIntoANewt"; + assertEquals(toPascalCase(input), expected); +}); + +Deno.test("toPascalCase() converts multiple delimiters", () => { + const result = toPascalCase("I am up-to-date!"); + const expected = "IAmUpToDate"; + assertEquals(result, expected); +}); + +Deno.test("toPascalCase() trims whitespace", () => { + const result = toPascalCase(" deno Is AWESOME "); + const expected = "DenoIsAwesome"; + assertEquals(result, expected); +}); + +Deno.test("toSnakeCase() handles an empty string", () => { + assertEquals(toSnakeCase(""), ""); +}); + +Deno.test("toSnakeCase() converts a single word", () => { + const input = "shruberry"; + const expected = "shruberry"; + assertEquals(toSnakeCase(input), expected); +}); + +Deno.test("toSnakeCase() converts a sentence", () => { + const input = "she turned me into a newt"; + const expected = "she_turned_me_into_a_newt"; + assertEquals(toSnakeCase(input), expected); +}); + +Deno.test("toSnakeCase() converts multiple delimiters", () => { + const result = toSnakeCase("I am up-to-date!"); + const expected = "i_am_up_to_date"; + assertEquals(result, expected); +}); + +Deno.test("toSnakeCase() trims whitespace", () => { + const result = toSnakeCase(" deno Is AWESOME "); + const expected = "deno_is_awesome"; + assertEquals(result, expected); +}); diff --git a/text/mod.ts b/text/mod.ts index e7acec4090b1..f1a8adbf6041 100644 --- a/text/mod.ts +++ b/text/mod.ts @@ -4,3 +4,4 @@ export * from "./levenshtein_distance.ts"; export * from "./closest_string.ts"; export * from "./compare_similarity.ts"; export * from "./word_similarity_sort.ts"; +export * from "./case.ts";