Skip to content

Commit 60ed09e

Browse files
committed
inflekt
1 parent 50809e5 commit 60ed09e

4 files changed

Lines changed: 92 additions & 28 deletions

File tree

packages/inflection/README.md

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
1-
# @interweb/inflection
2-
3-
Inflection utilities for pluralization and singularization with PostGraphile-compatible Latin suffix handling.
1+
# inflekt
2+
3+
<p align="center">
4+
<img src="https://raw.githubusercontent.com/constructive-io/constructive/refs/heads/main/assets/outline-logo.svg" height="250">
5+
<br />
6+
<strong>smart pluralization and inflection for the modern web</strong>
7+
<br />
8+
<br />
9+
Inflection utilities for pluralization and singularization with PostGraphile-compatible Latin suffix handling
10+
<br />
11+
<br />
12+
<a href="https://github.com/constructive-io/dev-utils/actions/workflows/ci.yml">
13+
<img height="20" src="https://github.com/constructive-io/dev-utils/actions/workflows/ci.yml/badge.svg" />
14+
</a>
15+
<a href="https://github.com/constructive-io/dev-utils/blob/main/LICENSE">
16+
<img height="20" src="https://img.shields.io/badge/license-MIT-blue.svg"/>
17+
</a>
18+
</p>
419

520
## Installation
621

722
```bash
8-
npm install @interweb/inflection
23+
npm install inflekt
924
```
1025

1126
## Usage
@@ -19,9 +34,16 @@ import {
1934
distinctPluralize,
2035
lcFirst,
2136
ucFirst,
37+
camelize,
38+
underscore,
39+
toPascalCase,
40+
toCamelCase,
41+
toSnakeCase,
42+
toKebabCase,
43+
toConstantCase,
2244
toFieldName,
2345
toQueryName,
24-
} from '@interweb/inflection';
46+
} from 'inflekt';
2547

2648
// Basic singularization/pluralization
2749
singularize('Users'); // 'User'
@@ -36,10 +58,22 @@ singularize('Media'); // 'Medium'
3658
singularizeLast('UserProfiles'); // 'UserProfile'
3759
pluralizeLast('UserProfile'); // 'UserProfiles'
3860

39-
// Case transformations
61+
// First character case transformations
4062
lcFirst('UserProfile'); // 'userProfile'
4163
ucFirst('userProfile'); // 'UserProfile'
4264

65+
// Snake case / camel case conversions
66+
camelize('user_profile'); // 'UserProfile'
67+
camelize('user_profile', true); // 'userProfile'
68+
underscore('UserProfile'); // 'user_profile'
69+
70+
// Full case transformations (re-exported from komoji)
71+
toPascalCase('hello-world'); // 'HelloWorld'
72+
toCamelCase('hello-world'); // 'helloWorld'
73+
toSnakeCase('helloWorld'); // 'hello_world'
74+
toKebabCase('HelloWorld'); // 'hello-world'
75+
toConstantCase('helloWorld'); // 'HELLO_WORLD'
76+
4377
// GraphQL naming helpers
4478
toFieldName('Users'); // 'user'
4579
toQueryName('User'); // 'users'
@@ -60,7 +94,14 @@ toQueryName('User'); // 'users'
6094

6195
- `lcFirst(str)` - Convert first character to lowercase (PascalCase to camelCase)
6296
- `ucFirst(str)` - Convert first character to uppercase (camelCase to PascalCase)
97+
- `camelize(str, lowFirstLetter?)` - Convert snake_case to PascalCase (or camelCase if lowFirstLetter is true)
98+
- `underscore(str)` - Convert PascalCase/camelCase to snake_case
6399
- `fixCapitalisedPlural(str)` - Fix capitalized S after numbers (e.g., `Table1S` -> `Table1s`)
100+
- `toPascalCase(str)` - Convert to PascalCase (re-exported from komoji)
101+
- `toCamelCase(str)` - Convert to camelCase (re-exported from komoji)
102+
- `toSnakeCase(str)` - Convert to snake_case (re-exported from komoji)
103+
- `toKebabCase(str)` - Convert to kebab-case (re-exported from komoji)
104+
- `toConstantCase(str)` - Convert to CONSTANT_CASE (re-exported from komoji)
64105

65106
### Naming Helpers
66107

packages/inflection/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "@interweb/inflection",
2+
"name": "inflekt",
33
"version": "0.0.1",
44
"description": "Inflection utilities for pluralization and singularization with PostGraphile-compatible Latin suffix handling",
55
"author": "Constructive <developers@constructive.io>",
@@ -26,6 +26,7 @@
2626
"url": "https://github.com/constructive-io/dev-utils"
2727
},
2828
"keywords": [
29+
"inflekt",
2930
"inflection",
3031
"pluralize",
3132
"singularize",
@@ -40,6 +41,7 @@
4041
"makage": "0.1.8"
4142
},
4243
"dependencies": {
43-
"inflection": "^3.0.0"
44+
"inflection": "^3.0.0",
45+
"komoji": "workspace:^"
4446
}
4547
}

packages/inflection/src/case.ts

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
/**
22
* Case transformation utilities
33
*/
4-
import * as inflection from 'inflection';
4+
export {
5+
toPascalCase,
6+
toCamelCase,
7+
toSnakeCase,
8+
toKebabCase,
9+
toConstantCase,
10+
} from 'komoji';
511

612
/**
713
* Convert PascalCase to camelCase (lowercase first character)
@@ -11,25 +17,6 @@ export function lcFirst(str: string): string {
1117
return str.charAt(0).toLowerCase() + str.slice(1);
1218
}
1319

14-
/**
15-
* Convert a string to camelCase
16-
* @param str - The string to convert
17-
* @param lowFirstLetter - If true, the first letter will be lowercase (default: false)
18-
* @example camelize("user_profile") -> "UserProfile"
19-
* @example camelize("user_profile", true) -> "userProfile"
20-
*/
21-
export function camelize(str: string, lowFirstLetter?: boolean): string {
22-
return inflection.camelize(str, lowFirstLetter);
23-
}
24-
25-
/**
26-
* Convert a camelCase or PascalCase string to snake_case
27-
* @example underscore("UserProfile") -> "user_profile"
28-
*/
29-
export function underscore(str: string): string {
30-
return inflection.underscore(str);
31-
}
32-
3320
/**
3421
* Convert camelCase to PascalCase (uppercase first character)
3522
* @example "userProfile" -> "UserProfile"
@@ -46,3 +33,34 @@ export function ucFirst(str: string): string {
4633
export function fixCapitalisedPlural(str: string): string {
4734
return str.replace(/[0-9]S(?=[A-Z]|$)/g, (match) => match.toLowerCase());
4835
}
36+
37+
/**
38+
* Convert snake_case to PascalCase (or camelCase if lowFirstLetter is true)
39+
* @param str - The snake_case string to convert
40+
* @param lowFirstLetter - If true, returns camelCase instead of PascalCase
41+
* @example camelize('user_profile') -> 'UserProfile'
42+
* @example camelize('user_profile', true) -> 'userProfile'
43+
*/
44+
export function camelize(str: string, lowFirstLetter?: boolean): string {
45+
const result = str
46+
.split('_')
47+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
48+
.join('');
49+
50+
if (lowFirstLetter) {
51+
return lcFirst(result);
52+
}
53+
return result;
54+
}
55+
56+
/**
57+
* Convert PascalCase or camelCase to snake_case
58+
* @example underscore('UserProfile') -> 'user_profile'
59+
* @example underscore('userProfile') -> 'user_profile'
60+
*/
61+
export function underscore(str: string): string {
62+
return str
63+
.replace(/([A-Z])/g, '_$1')
64+
.replace(/^_/, '')
65+
.toLowerCase();
66+
}

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)