@stacksjs/strings 0.58.48 → 0.58.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/case.ts +27 -0
- package/src/helpers.ts +3 -0
- package/src/index.ts +2 -0
- package/src/is.ts +170 -0
- package/src/macro.ts +131 -0
- package/src/pluralize.ts +26 -0
- package/src/string.ts +5 -0
- package/src/types.ts +4 -0
- package/src/utils.ts +117 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/strings",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.58.
|
|
4
|
+
"version": "0.58.50",
|
|
5
5
|
"description": "The Stacks string utilities.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
7
|
"license": "MIT",
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
],
|
|
51
51
|
"files": [
|
|
52
52
|
"README.md",
|
|
53
|
-
"dist"
|
|
53
|
+
"dist",
|
|
54
|
+
"src"
|
|
54
55
|
],
|
|
55
56
|
"scripts": {
|
|
56
57
|
"build": "bun --bun build.ts",
|
package/src/case.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* First letter uppercase, other lowercase
|
|
3
|
+
* @category string
|
|
4
|
+
* @example
|
|
5
|
+
* ```
|
|
6
|
+
* capitalize('hello world') => 'Hello world'
|
|
7
|
+
* ```
|
|
8
|
+
*/
|
|
9
|
+
export function capitalize(str: string): string {
|
|
10
|
+
return str[0] ? str[0].toUpperCase() + str.slice(1).toLowerCase() : ''
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
camelCase,
|
|
15
|
+
capitalCase,
|
|
16
|
+
constantCase,
|
|
17
|
+
dotCase,
|
|
18
|
+
noCase,
|
|
19
|
+
kebabCase,
|
|
20
|
+
kebabCase as paramCase,
|
|
21
|
+
pascalCase,
|
|
22
|
+
pathCase,
|
|
23
|
+
sentenceCase,
|
|
24
|
+
snakeCase,
|
|
25
|
+
split,
|
|
26
|
+
} from 'change-case'
|
|
27
|
+
export { titleCase } from 'title-case'
|
package/src/helpers.ts
ADDED
package/src/index.ts
ADDED
package/src/is.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type { HashAlgorithm } from '@stacksjs/types'
|
|
2
|
+
import v from 'validator'
|
|
3
|
+
|
|
4
|
+
export function isEmail(email: string) {
|
|
5
|
+
return v.isEmail(email)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function isStrongPassword(password: string) {
|
|
9
|
+
return v.isStrongPassword(password)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function isAlphanumeric(username: string) {
|
|
13
|
+
return v.isAlphanumeric(username)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function validateUsername(username: string) {
|
|
17
|
+
return isAlphanumeric(username)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function isURL(url: string) {
|
|
21
|
+
return v.isURL(url)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function isMobilePhone(phoneNumber: string) {
|
|
25
|
+
return v.isMobilePhone(phoneNumber)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function isAlpha(name: string) {
|
|
29
|
+
return v.isAlpha(name)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function isPostalCode(zipCode: string) {
|
|
33
|
+
return v.isPostalCode(zipCode, 'any')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function isNumeric(number: string) {
|
|
37
|
+
return v.isNumeric(number)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isHexColor(color: string) {
|
|
41
|
+
return v.isHexColor(color)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function isHexadecimal(hex: string) {
|
|
45
|
+
return v.isHexadecimal(hex)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function isBase64(base64: string) {
|
|
49
|
+
return v.isBase64(base64)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function isUUID(uuid: string) {
|
|
53
|
+
return v.isUUID(uuid)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function isJSON(json: string) {
|
|
57
|
+
return v.isJSON(json)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function isCreditCard(creditCard: string) {
|
|
61
|
+
return v.isCreditCard(creditCard)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function isISBN(isbn: string) {
|
|
65
|
+
return v.isISBN(isbn)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function isIP(ip: string) {
|
|
69
|
+
return v.isIP(ip)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function isIPRange(ip: string) {
|
|
73
|
+
return v.isIPRange(ip)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function isMACAddress(macAddress: string) {
|
|
77
|
+
return v.isMACAddress(macAddress)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function isLatLong(latitude: string) {
|
|
81
|
+
return v.isLatLong(latitude)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function isLatitude(longitude: string) {
|
|
85
|
+
return v.isLatLong(longitude)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function isLongitude(longitude: string) {
|
|
89
|
+
return v.isLatLong(longitude)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function isCurrency(currency: string) {
|
|
93
|
+
return v.isCurrency(currency)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function isDataURI(dataURI: string) {
|
|
97
|
+
return v.isDataURI(dataURI)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function isMimeType(mimeType: string) {
|
|
101
|
+
return v.isMimeType(mimeType)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function isJWT(jwt: string) {
|
|
105
|
+
return v.isJWT(jwt)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function isAscii(ascii: string) {
|
|
109
|
+
return v.isAscii(ascii)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function isBase32(base32: string) {
|
|
113
|
+
return v.isBase32(base32)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function isByteLength(byteLength: string) {
|
|
117
|
+
return v.isByteLength(byteLength)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function isFQDN(fqdn: string) {
|
|
121
|
+
return v.isFQDN(fqdn)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function isFullWidth(fullWidth: string) {
|
|
125
|
+
return v.isFullWidth(fullWidth)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function isHalfWidth(halfWidth: string) {
|
|
129
|
+
return v.isHalfWidth(halfWidth)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function isHash(hash: string, algorithm: HashAlgorithm) {
|
|
133
|
+
return v.isHash(hash, algorithm)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function isHSL(hsl: string) {
|
|
137
|
+
return v.isHSL(hsl)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function isIBAN(iban: string) {
|
|
141
|
+
return v.isIBAN(iban)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function isIdentityCard(identityCard: string) {
|
|
145
|
+
return v.isIdentityCard(identityCard)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function isISIN(isin: string) {
|
|
149
|
+
return v.isISIN(isin)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function isISO8601(iso8601: string) {
|
|
153
|
+
return v.isISO8601(iso8601)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function isISRC(isrc: string) {
|
|
157
|
+
return v.isISRC(isrc)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function isISSN(issn: string) {
|
|
161
|
+
return v.isISSN(issn)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function isISO31661Alpha2(iso31661Alpha2: string) {
|
|
165
|
+
return v.isISO31661Alpha2(iso31661Alpha2)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function isISO31661Alpha3(iso31661Alpha3: string) {
|
|
169
|
+
return v.isISO31661Alpha3(iso31661Alpha3)
|
|
170
|
+
}
|
package/src/macro.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import * as c from './case'
|
|
2
|
+
import * as p from './pluralize'
|
|
3
|
+
import * as u from './utils'
|
|
4
|
+
|
|
5
|
+
export const Str = {
|
|
6
|
+
slash(str: string) {
|
|
7
|
+
return u.slash(str)
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
ensurePrefix(prefix: string, str: string) {
|
|
11
|
+
return u.ensurePrefix(prefix, str)
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
ensureSuffix(suffix: string, str: string) {
|
|
15
|
+
return u.ensureSuffix(suffix, str)
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
template(str: string, ...args: any[]): string {
|
|
19
|
+
return u.template(str, ...args)
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Truncate a string
|
|
24
|
+
*/
|
|
25
|
+
truncate(str: string, length: number, end = '...') {
|
|
26
|
+
return u.truncate(str, length, end)
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
random(length = 16) {
|
|
30
|
+
return u.random(length)
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
capitalize(str: string) {
|
|
34
|
+
return c.capitalize(str)
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
slug(str: string) {
|
|
38
|
+
return u.slug(str)
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
detectIndent(str: string) {
|
|
42
|
+
return u.detectIndent(str)
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
detectNewline(str: string) {
|
|
46
|
+
return u.detectNewline(str)
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
camelCase(str: string) {
|
|
50
|
+
return c.camelCase(str)
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
capitalCase(str: string) {
|
|
54
|
+
return c.capitalCase(str)
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
constantCase(str: string) {
|
|
58
|
+
return c.constantCase(str)
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
dotCase(str: string) {
|
|
62
|
+
return c.dotCase(str)
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
noCase(str: string) {
|
|
66
|
+
return c.noCase(str)
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
paramCase(str: string) {
|
|
70
|
+
return c.paramCase(str)
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
pascalCase(str: string) {
|
|
74
|
+
return c.pascalCase(str)
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
pathCase(str: string) {
|
|
78
|
+
return c.pathCase(str)
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
sentenceCase(str: string) {
|
|
82
|
+
return c.sentenceCase(str)
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
snakeCase(str: string) {
|
|
86
|
+
return c.snakeCase(str)
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
titleCase(str: string) {
|
|
90
|
+
return c.titleCase(str)
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
kebabCase(str: string) {
|
|
94
|
+
return c.kebabCase(str)
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
plural(str: string) {
|
|
98
|
+
// plural, singular, isPlural, isSingular, addPluralRule, addSingularRule, addIrregularRule, addUncountableRule
|
|
99
|
+
return p.plural(str)
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
singular(str: string) {
|
|
103
|
+
return p.singular(str)
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
isPlural(str: string) {
|
|
107
|
+
return p.isPlural(str)
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
isSingular(str: string) {
|
|
111
|
+
return p.isSingular(str)
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
addPluralRule(rule: string | RegExp, repl: string) {
|
|
115
|
+
return p.addPluralRule(rule, repl)
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
addSingularRule(rule: string | RegExp, repl: string) {
|
|
119
|
+
return p.addSingularRule(rule, repl)
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
addIrregularRule(single: string, plural: string) {
|
|
123
|
+
return p.addIrregularRule(single, plural)
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
addUncountableRule(word: string | RegExp) {
|
|
127
|
+
return p.addUncountableRule(word)
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export const str = Str
|
package/src/pluralize.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as pluralize from 'pluralize'
|
|
2
|
+
|
|
3
|
+
type Rule = string | RegExp
|
|
4
|
+
type Replacement = string
|
|
5
|
+
type Word = string
|
|
6
|
+
export type PluralizeTest = (word: Word) => boolean
|
|
7
|
+
|
|
8
|
+
export interface Pluralize {
|
|
9
|
+
plural: (word: Word, count?: number, inclusive?: boolean) => Word
|
|
10
|
+
singular: (word: Word) => Word
|
|
11
|
+
isPlural: (word: Word) => boolean
|
|
12
|
+
isSingular: (word: Word) => boolean
|
|
13
|
+
addPluralRule: (rule: Rule, replacement: Replacement) => void
|
|
14
|
+
addSingularRule: (rule: Rule, replacement: Replacement) => void
|
|
15
|
+
addIrregularRule: (single: Word, plural: Word) => void
|
|
16
|
+
addUncountableRule: (word: Word | RegExp) => void
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const plural: Pluralize['plural'] = (...args) => pluralize.plural(...args)
|
|
20
|
+
export const singular: Pluralize['singular'] = (...args) => pluralize.singular(...args)
|
|
21
|
+
export const isPlural: Pluralize['isPlural'] = (...args) => pluralize.isPlural(...args)
|
|
22
|
+
export const isSingular: Pluralize['isSingular'] = (...args) => pluralize.isSingular(...args)
|
|
23
|
+
export const addPluralRule: Pluralize['addPluralRule'] = (...args) => pluralize.addPluralRule(...args)
|
|
24
|
+
export const addSingularRule: Pluralize['addSingularRule'] = (...args) => pluralize.addSingularRule(...args)
|
|
25
|
+
export const addIrregularRule: Pluralize['addIrregularRule'] = (...args) => pluralize.addIrregularRule(...args)
|
|
26
|
+
export const addUncountableRule: Pluralize['addUncountableRule'] = (...args) => pluralize.addUncountableRule(...args)
|
package/src/string.ts
ADDED
package/src/types.ts
ADDED
package/src/utils.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import slugify from 'slugify'
|
|
2
|
+
|
|
3
|
+
interface SlugOptions {
|
|
4
|
+
replacement?: string
|
|
5
|
+
remove?: RegExp
|
|
6
|
+
lower?: boolean
|
|
7
|
+
strict?: boolean
|
|
8
|
+
locale?: string
|
|
9
|
+
trim?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// port from nanoid
|
|
13
|
+
// https://github.com/ai/nanoid
|
|
14
|
+
const urlAlphabet = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Replace backslash to slash
|
|
18
|
+
*
|
|
19
|
+
* @category String
|
|
20
|
+
* @example
|
|
21
|
+
* ```
|
|
22
|
+
* slash('C:\\Users\\Chris') => 'C:/Users/Chris'
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function slash(str: string) {
|
|
26
|
+
return str.replace(/\\/g, '/')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Ensure prefix of a string
|
|
31
|
+
*
|
|
32
|
+
* @category String
|
|
33
|
+
* @example
|
|
34
|
+
* ```
|
|
35
|
+
* ensurePrefix('https://', 'google.com') => 'https://google.com'
|
|
36
|
+
* ensurePrefix('https://', 'http://google.com') => 'https://google.com'
|
|
37
|
+
*/
|
|
38
|
+
export function ensurePrefix(prefix: string, str: string) {
|
|
39
|
+
if (!str.startsWith(prefix))
|
|
40
|
+
return prefix + str
|
|
41
|
+
return str
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Ensure suffix of a string
|
|
46
|
+
*
|
|
47
|
+
* @category String
|
|
48
|
+
* @example
|
|
49
|
+
* ```
|
|
50
|
+
* ensureSuffix('.js', 'index') => 'index.js'
|
|
51
|
+
* ensureSuffix('.js', 'index.js') => 'index.js'
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export function ensureSuffix(suffix: string, str: string) {
|
|
55
|
+
return str.endsWith(suffix) ? str : str + suffix
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Dead simple template engine, just like Python's `.format()`
|
|
60
|
+
*
|
|
61
|
+
* @category String
|
|
62
|
+
* @example
|
|
63
|
+
* ```
|
|
64
|
+
* const result = template('Hello {0}! My name is {1}.',
|
|
65
|
+
* 'Buddy',
|
|
66
|
+
* 'Chris'
|
|
67
|
+
* ) // Hello Buddy! My name is Chris.
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export function template(str: string, ...args: any[]): string {
|
|
71
|
+
return str.replace(/{(\d+)}/g, (match, key) => {
|
|
72
|
+
const index = Number(key)
|
|
73
|
+
|
|
74
|
+
return Number.isNaN(index) ? match : args[index]
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function truncate(str: string, length: number, end = '...') {
|
|
79
|
+
if (str.length <= length)
|
|
80
|
+
return str
|
|
81
|
+
|
|
82
|
+
return str.slice(0, length - end.length) + end
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Generate a random string
|
|
87
|
+
* @category String
|
|
88
|
+
*/
|
|
89
|
+
export function random(size = 16, dict = urlAlphabet) {
|
|
90
|
+
let id = ''
|
|
91
|
+
let i = size
|
|
92
|
+
const len = dict.length
|
|
93
|
+
while (i--)
|
|
94
|
+
id += dict[(Math.random() * len) | 0]
|
|
95
|
+
return id
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Slugify a string
|
|
100
|
+
* @category string
|
|
101
|
+
* @example
|
|
102
|
+
* ```
|
|
103
|
+
* slug('Hello World') => 'hello-world'
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export function slug(str: string, options?: SlugOptions): string {
|
|
107
|
+
if (options)
|
|
108
|
+
return slugify(str, options)
|
|
109
|
+
|
|
110
|
+
return slugify(str, {
|
|
111
|
+
lower: true,
|
|
112
|
+
strict: true,
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export { default as detectIndent } from 'detect-indent'
|
|
117
|
+
export { detectNewline } from 'detect-newline'
|