scule
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -1,31 +0,46 @@ | ||
declare type Splitter = "-" | "_" | "/" | "."; | ||
declare type FirstOfString<S extends string> = S extends `${infer F}${string}` ? F : never; | ||
declare type RemoveFirstOfString<S extends string> = S extends `${string}${infer R}` ? R : never; | ||
declare type IsUpper<S extends string> = S extends Uppercase<S> ? true : false; | ||
declare type IsLower<S extends string> = S extends Lowercase<S> ? true : false; | ||
declare type SameLetterCase<X extends string, Y extends string> = IsUpper<X> extends IsUpper<Y> ? true : IsLower<X> extends IsLower<Y> ? true : false; | ||
declare type CapitalizedWords<T extends readonly string[], Accumulator extends string = ""> = T extends readonly [infer F extends string, ...infer R extends string[]] ? CapitalizedWords<R, `${Accumulator}${Capitalize<F>}`> : Accumulator; | ||
declare type JoinLowercaseWords<T extends readonly string[], Joiner extends string, Accumulator extends string = ""> = T extends readonly [infer F extends string, ...infer R extends string[]] ? Accumulator extends "" ? JoinLowercaseWords<R, Joiner, `${Accumulator}${Lowercase<F>}`> : JoinLowercaseWords<R, Joiner, `${Accumulator}${Joiner}${Lowercase<F>}`> : Accumulator; | ||
declare type LastOfArray<T extends any[]> = T extends [...any, infer R] ? R : never; | ||
declare type RemoveLastOfArray<T extends any[]> = T extends [...infer F, any] ? F : never; | ||
declare type SplitByCase<T, Separator extends string = Splitter, Accumulator extends unknown[] = []> = string extends Separator ? string[] : T extends `${infer F}${infer R}` ? [LastOfArray<Accumulator>] extends [never] ? SplitByCase<R, Separator, [F]> : LastOfArray<Accumulator> extends string ? R extends "" ? SplitByCase<R, Separator, [...RemoveLastOfArray<Accumulator>, `${LastOfArray<Accumulator>}${F}`]> : SameLetterCase<F, FirstOfString<R>> extends true ? F extends Separator ? FirstOfString<R> extends Separator ? SplitByCase<R, Separator, [...Accumulator, ""]> : IsUpper<FirstOfString<R>> extends true ? SplitByCase<RemoveFirstOfString<R>, Separator, [...Accumulator, FirstOfString<R>]> : SplitByCase<R, Separator, [...Accumulator, ""]> : SplitByCase<R, Separator, [...RemoveLastOfArray<Accumulator>, `${LastOfArray<Accumulator>}${F}`]> : IsLower<F> extends true ? SplitByCase<RemoveFirstOfString<R>, Separator, [...RemoveLastOfArray<Accumulator>, `${LastOfArray<Accumulator>}${F}`, FirstOfString<R>]> : SplitByCase<R, Separator, [...Accumulator, F]> : never : Accumulator extends [] ? T extends "" ? [] : string[] : Accumulator; | ||
declare type PascalCase<T> = string extends T ? string : string[] extends T ? string : T extends string ? SplitByCase<T> extends readonly string[] ? CapitalizedWords<SplitByCase<T>> : never : T extends readonly string[] ? CapitalizedWords<T> : never; | ||
declare type CamelCase<T> = string extends T ? string : string[] extends T ? string : Uncapitalize<PascalCase<T>>; | ||
declare type JoinByCase<T, Joiner extends string> = string extends T ? string : string[] extends T ? string : T extends string ? SplitByCase<T> extends readonly string[] ? JoinLowercaseWords<SplitByCase<T>, Joiner> : never : T extends readonly string[] ? JoinLowercaseWords<T, Joiner> : never; | ||
type Splitter = "-" | "_" | "/" | "."; | ||
type FirstOfString<S extends string> = S extends `${infer F}${string}` ? F : never; | ||
type RemoveFirstOfString<S extends string> = S extends `${string}${infer R}` ? R : never; | ||
type IsUpper<S extends string> = S extends Uppercase<S> ? true : false; | ||
type IsLower<S extends string> = S extends Lowercase<S> ? true : false; | ||
type SameLetterCase<X extends string, Y extends string> = IsUpper<X> extends IsUpper<Y> ? true : IsLower<X> extends IsLower<Y> ? true : false; | ||
type CapitalizedWords<T extends readonly string[], Accumulator extends string = ""> = T extends readonly [infer F extends string, ...infer R extends string[]] ? CapitalizedWords<R, `${Accumulator}${Capitalize<Lowercase<F>>}`> : Accumulator; | ||
type JoinLowercaseWords<T extends readonly string[], Joiner extends string, Accumulator extends string = ""> = T extends readonly [infer F extends string, ...infer R extends string[]] ? Accumulator extends "" ? JoinLowercaseWords<R, Joiner, `${Accumulator}${Lowercase<F>}`> : JoinLowercaseWords<R, Joiner, `${Accumulator}${Joiner}${Lowercase<F>}`> : Accumulator; | ||
type LastOfArray<T extends any[]> = T extends [...any, infer R] ? R : never; | ||
type RemoveLastOfArray<T extends any[]> = T extends [...infer F, any] ? F : never; | ||
type SplitByCase<T, Separator extends string = Splitter, Accumulator extends unknown[] = []> = string extends Separator ? string[] : T extends `${infer F}${infer R}` ? [LastOfArray<Accumulator>] extends [never] ? SplitByCase<R, Separator, [F]> : LastOfArray<Accumulator> extends string ? R extends "" ? SplitByCase<R, Separator, [ | ||
...RemoveLastOfArray<Accumulator>, | ||
`${LastOfArray<Accumulator>}${F}` | ||
]> : SameLetterCase<F, FirstOfString<R>> extends true ? F extends Separator ? FirstOfString<R> extends Separator ? SplitByCase<R, Separator, [...Accumulator, ""]> : IsUpper<FirstOfString<R>> extends true ? SplitByCase<RemoveFirstOfString<R>, Separator, [ | ||
...Accumulator, | ||
FirstOfString<R> | ||
]> : SplitByCase<R, Separator, [...Accumulator, ""]> : SplitByCase<R, Separator, [ | ||
...RemoveLastOfArray<Accumulator>, | ||
`${LastOfArray<Accumulator>}${F}` | ||
]> : IsLower<F> extends true ? SplitByCase<RemoveFirstOfString<R>, Separator, [ | ||
...RemoveLastOfArray<Accumulator>, | ||
`${LastOfArray<Accumulator>}${F}`, | ||
FirstOfString<R> | ||
]> : SplitByCase<R, Separator, [...Accumulator, F]> : never : Accumulator extends [] ? T extends "" ? [] : string[] : Accumulator; | ||
type JoinByCase<T, Joiner extends string> = string extends T ? string : string[] extends T ? string : T extends string ? SplitByCase<T> extends readonly string[] ? JoinLowercaseWords<SplitByCase<T>, Joiner> : never : T extends readonly string[] ? JoinLowercaseWords<T, Joiner> : never; | ||
type PascalCase<T> = string extends T ? string : string[] extends T ? string : T extends string ? SplitByCase<T> extends readonly string[] ? CapitalizedWords<SplitByCase<T>> : never : T extends readonly string[] ? CapitalizedWords<T> : never; | ||
type CamelCase<T> = string extends T ? string : string[] extends T ? string : Uncapitalize<PascalCase<T>>; | ||
type KebabCase<T extends string | readonly string[], Joiner extends string = "-"> = JoinByCase<T, Joiner>; | ||
type SnakeCase<T extends string | readonly string[]> = JoinByCase<T, "_">; | ||
declare function isUppercase(char?: string): boolean | undefined; | ||
declare function splitByCase<T extends string>(string_: T): SplitByCase<T>; | ||
declare function splitByCase<T extends string, Separator extends readonly string[]>(string_: T, separators: Separator): SplitByCase<T, Separator[number]>; | ||
declare function upperFirst<S extends string>(string_: S): Capitalize<S>; | ||
declare function lowerFirst<S extends string>(string_: S): Uncapitalize<S>; | ||
declare function splitByCase<T extends string>(str: T): SplitByCase<T>; | ||
declare function splitByCase<T extends string, Separator extends readonly string[]>(str: T, separators: Separator): SplitByCase<T, Separator[number]>; | ||
declare function upperFirst<S extends string>(str: S): Capitalize<S>; | ||
declare function lowerFirst<S extends string>(str: S): Uncapitalize<S>; | ||
declare function pascalCase(): ""; | ||
declare function pascalCase<T extends string | readonly string[]>(string_: T): PascalCase<T>; | ||
declare function pascalCase<T extends string | readonly string[]>(str: T): PascalCase<T>; | ||
declare function camelCase(): ""; | ||
declare function camelCase<T extends string | readonly string[]>(string_: T): CamelCase<T>; | ||
declare function camelCase<T extends string | readonly string[]>(str: T): CamelCase<T>; | ||
declare function kebabCase(): ""; | ||
declare function kebabCase<T extends string | readonly string[]>(string_: T): JoinByCase<T, "-">; | ||
declare function kebabCase<T extends string | readonly string[], Joiner extends string>(string_: T, joiner: Joiner): JoinByCase<T, Joiner>; | ||
declare function kebabCase<T extends string | readonly string[]>(str: T): KebabCase<T>; | ||
declare function kebabCase<T extends string | readonly string[], Joiner extends string>(str: T, joiner: Joiner): KebabCase<T, Joiner>; | ||
declare function snakeCase(): ""; | ||
declare function snakeCase<T extends string | readonly string[]>(string_: T): JoinByCase<T, "_">; | ||
declare function snakeCase<T extends string | readonly string[]>(str: T): SnakeCase<T>; | ||
export { camelCase, isUppercase, kebabCase, lowerFirst, pascalCase, snakeCase, splitByCase, upperFirst }; | ||
export { type CamelCase, type JoinByCase, type KebabCase, type PascalCase, type SnakeCase, type SplitByCase, camelCase, isUppercase, kebabCase, lowerFirst, pascalCase, snakeCase, splitByCase, upperFirst }; |
{ | ||
"name": "scule", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "String case utils", | ||
@@ -10,5 +10,5 @@ "repository": "unjs/scule", | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"require": "./dist/index.cjs", | ||
"import": "./dist/index.mjs", | ||
"types": "./dist/index.d.ts" | ||
"import": "./dist/index.mjs" | ||
}, | ||
@@ -25,19 +25,21 @@ "./*": "./*" | ||
"build": "unbuild", | ||
"dev": "vitest", | ||
"lint": "eslint --ext .ts .", | ||
"prepublishOnly": "pnpm build", | ||
"release": "pnpm test && standard-version && git push --follow-tags && pnpm publish", | ||
"test": "pnpm lint && vitest run --coverage" | ||
"dev": "vitest dev --typecheck", | ||
"lint": "eslint --cache --ext .ts,.js,.mjs,.cjs . && prettier -c src test", | ||
"lint:fix": "eslint --cache --ext .ts,.js,.mjs,.cjs . --fix && prettier -c src test -w", | ||
"prepack": "pnpm run build", | ||
"release": "pnpm test && changelogen --release --push && npm publish", | ||
"test": "pnpm lint && vitest run --typecheck --coverage" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^18.11.9", | ||
"@vitest/coverage-c8": "^0.25.2", | ||
"eslint": "^8.27.0", | ||
"eslint-config-unjs": "^0.0.2", | ||
"standard-version": "^9.5.0", | ||
"typescript": "^4.8.4", | ||
"unbuild": "^0.9.4", | ||
"vitest": "^0.25.2" | ||
"@types/node": "^20.9.0", | ||
"@vitest/coverage-v8": "^1.0.0-beta.4", | ||
"changelogen": "^0.5.5", | ||
"eslint": "^8.53.0", | ||
"eslint-config-unjs": "^0.2.1", | ||
"prettier": "^3.1.0", | ||
"typescript": "^5.2.2", | ||
"unbuild": "^2.0.0", | ||
"vitest": "^1.0.0-beta.4" | ||
}, | ||
"packageManager": "pnpm@7.16.0" | ||
} | ||
"packageManager": "pnpm@8.10.5" | ||
} |
@@ -5,5 +5,4 @@ # 🧵 Scule | ||
[![npm downloads][npm-downloads-src]][npm-downloads-href] | ||
[![Github Actions][github-actions-src]][github-actions-href] | ||
[![bundle][bundle-src]][bundle-href] | ||
[![Codecov][codecov-src]][codecov-href] | ||
[![bundle][bundle-src]][bundle-href] | ||
@@ -18,4 +17,2 @@ <!-- ![](.github/banner.svg) --> | ||
npm i scule | ||
# or | ||
yarn add scule | ||
``` | ||
@@ -27,9 +24,9 @@ | ||
// CommonJS | ||
const { pascalCase } = require('scule') | ||
const { pascalCase } = require("scule"); | ||
// ESM | ||
import { pascalCase } from 'scule' | ||
import { pascalCase } from "scule"; | ||
``` | ||
**Notice:** You may need to transpile package for legacy environments | ||
**Notice:** You may need to transpile package for legacy environments. | ||
@@ -40,35 +37,61 @@ ## Utils | ||
Splits string and joins by PascalCase convention (`foo-bar` => `FooBar`) | ||
Splits string and joins by PascalCase convention: | ||
**Remarks:** | ||
```ts | ||
pascalCase("foo-bar_baz"); | ||
// FooBarBaz | ||
``` | ||
- If an uppercase letter is followed by other uppercase letters (like `FooBAR`), they are preserved | ||
**Notice:** If an uppercase letter is followed by other uppercase letters (like `FooBAR`), they are preserved. | ||
### `camelCase` | ||
Splits string and joins by camelCase convention (`foo-bar` => `fooBar`) | ||
Splits string and joins by camelCase convention: | ||
```ts | ||
camelCase("foo-bar_baz"); | ||
// fooBarBaz | ||
``` | ||
### `kebabCase(str)` | ||
Splits string and joins by kebab-case convention (`fooBar` => `foo-bar`) | ||
Splits string and joins by kebab-case convention: | ||
**Remarks:** | ||
```ts | ||
kebabCase("fooBar_Baz"); | ||
// foo-bar-baz | ||
``` | ||
- It does **not** preserve case | ||
**Notice:** It does **not** preserve case. | ||
### `snakeCase` | ||
Splits string and joins by snake_case convention (`foo-bar` => `foo_bar`) | ||
Splits string and joins by snake_case convention: | ||
```ts | ||
snakeCase("foo-barBaz"); | ||
// foo_bar_baz | ||
``` | ||
### `upperFirst(str)` | ||
Converts first character to upper case | ||
Converts first character to upper case: | ||
```ts | ||
upperFirst("hello world!"); | ||
// Hello world! | ||
``` | ||
### `lowerFirst(str)` | ||
Converts first character to lower case | ||
Converts first character to lower case: | ||
```ts | ||
lowerFirst("Hello world!"); | ||
// hello world! | ||
``` | ||
### `splitByCase(str, splitters?)` | ||
- Splits string by the splitters provided (default: `['-', '_', '/', '.]`) | ||
- Splits string by the splitters provided (default: `['-', '_', '/', '.']`) | ||
- Splits when case changes from lower to upper or upper to lower | ||
@@ -79,2 +102,10 @@ - Ignores numbers for case changes | ||
## Development | ||
- Clone this repository | ||
- Install latest LTS version of [Node.js](https://nodejs.org/en/) | ||
- Enable [Corepack](https://github.com/nodejs/corepack) using corepack enable | ||
- Install dependencies using pnpm install | ||
- Run interactive tests using pnpm dev | ||
## License | ||
@@ -85,15 +116,10 @@ | ||
<!-- Badges --> | ||
[npm-version-src]: https://img.shields.io/npm/v/scule?style=flat-square | ||
[npm-version-src]: https://img.shields.io/npm/v/scule?style=flat&colorA=18181B&colorB=F0DB4F | ||
[npm-version-href]: https://npmjs.com/package/scule | ||
[npm-downloads-src]: https://img.shields.io/npm/dm/scule?style=flat-square | ||
[npm-downloads-src]: https://img.shields.io/npm/dm/scule?style=flat&colorA=18181B&colorB=F0DB4F | ||
[npm-downloads-href]: https://npmjs.com/package/scule | ||
[github-actions-src]: https://img.shields.io/github/workflow/status/unjs/scule/ci/main?style=flat-square | ||
[github-actions-href]: https://github.com/unjs/scule/actions?query=workflow%3Aci | ||
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/scule/main?style=flat-square | ||
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/scule/main?style=flat&colorA=18181B&colorB=F0DB4F | ||
[codecov-href]: https://codecov.io/gh/unjs/scule | ||
[bundle-src]: https://img.shields.io/bundlephobia/minzip/scule?style=flat-square | ||
[bundle-src]: https://img.shields.io/bundlephobia/minzip/scule?style=flat&colorA=18181B&colorB=F0DB4F | ||
[bundle-href]: https://bundlephobia.com/result?p=scule |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
22602
8
188
120
9