From 845377844ac0de1f6da0c17ae435b0437c9744bc Mon Sep 17 00:00:00 2001 From: abhi-byte62 Date: Tue, 6 Oct 2026 22:54:28 +0530 Subject: [PATCH 1/2] fix: capitalize first word in titleCase even if it is an exception word --- src/index.ts | 4 ++-- test/scule.test.ts | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index f1983fd..5e51bbe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -186,8 +186,8 @@ export function titleCase< >(str?: T, opts?: UserCaseOptions) { return (Array.isArray(str) ? str : splitByCase(str as string)) .filter(Boolean) - .map((p) => - titleCaseExceptions.test(p) + .map((p, i) => + i > 0 && titleCaseExceptions.test(p) ? p.toLowerCase() : upperFirst(opts?.normalize ? p.toLowerCase() : p), ) diff --git a/test/scule.test.ts b/test/scule.test.ts index bd5ec3b..67f76ef 100644 --- a/test/scule.test.ts +++ b/test/scule.test.ts @@ -140,6 +140,14 @@ describe("titleCase", () => { ["foo", "Foo"], ["foo-bar", "Foo Bar"], ["this-IS-aTitle", "This is a Title"], + ["in-world", "In World"], + ["inWorld", "In World"], + ["and-then", "And Then"], + ["andThen", "And Then"], + [["in", "world"], "In World"], + [["and", "then"], "And Then"], + ["the-quick-brown-fox-and-the-dog", "The Quick Brown Fox and the Dog"], + ["a-tale-of-two-cities", "A Tale of Two Cities"], ])("%s => %s", (input, expected) => { expect(titleCase(input)).toMatchObject(expected); }); From 6be606b28adfb33cd3095a12bd9f06480a4f5120 Mon Sep 17 00:00:00 2001 From: abhi-byte62 Date: Thu, 8 Oct 2026 19:22:14 +0530 Subject: [PATCH 2/2] fix(titleCase): support space delimiter when splitting string input --- src/index.ts | 6 +++++- test/scule.test.ts | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 5e51bbe..2fec97a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -184,7 +184,11 @@ export function titleCase< T extends string | readonly string[], UserCaseOptions extends CaseOptions = CaseOptions, >(str?: T, opts?: UserCaseOptions) { - return (Array.isArray(str) ? str : splitByCase(str as string)) + return ( + Array.isArray(str) + ? str + : splitByCase(str as string, [...STR_SPLITTERS, " "]) + ) .filter(Boolean) .map((p, i) => i > 0 && titleCaseExceptions.test(p) diff --git a/test/scule.test.ts b/test/scule.test.ts index 67f76ef..910143d 100644 --- a/test/scule.test.ts +++ b/test/scule.test.ts @@ -141,13 +141,17 @@ describe("titleCase", () => { ["foo-bar", "Foo Bar"], ["this-IS-aTitle", "This is a Title"], ["in-world", "In World"], + ["in world", "In World"], ["inWorld", "In World"], ["and-then", "And Then"], + ["and then", "And Then"], ["andThen", "And Then"], [["in", "world"], "In World"], [["and", "then"], "And Then"], ["the-quick-brown-fox-and-the-dog", "The Quick Brown Fox and the Dog"], + ["the quick brown fox and the dog", "The Quick Brown Fox and the Dog"], ["a-tale-of-two-cities", "A Tale of Two Cities"], + ["a tale of two cities", "A Tale of Two Cities"], ])("%s => %s", (input, expected) => { expect(titleCase(input)).toMatchObject(expected); });