@pcg/text-kit 1.0.0-alpha.0

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/src/cases.ts ADDED
@@ -0,0 +1,317 @@
1
+ import * as cc from 'change-case';
2
+ import { default as cyrillicToTranslit } from 'cyrillic-to-translit-js';
3
+ import { createRandomAbbreviationString } from './generators.js';
4
+
5
+ /**
6
+ * Convert a string to string with the first character in uppercase.
7
+ * @example
8
+ * ucfirst('hello world'); // Hello world
9
+ **/
10
+ export const ucfirst = (input: string) => {
11
+ return input.charAt(0).toUpperCase() + input.substring(1);
12
+ };
13
+
14
+ /**
15
+ * Convert a string to string with the first character in lower case.
16
+ * @example
17
+ * lcfirst('Hello world'); // hello world
18
+ **/
19
+ export const lcfirst = (input: string) => {
20
+ return input.charAt(0).toLowerCase() + input.substring(1);
21
+ };
22
+
23
+ /**
24
+ * Convert a string to PascalCase.
25
+ * @example
26
+ * pascalCase('foo bar'); //=> 'FooBar'
27
+ * pascalCase('foo_bar'); //=> 'FooBar'
28
+ * pascalCase('foo-bar'); //=> 'FooBar'
29
+ * pascalCase('foo.bar'); //=> 'FooBar'
30
+ * pascalCase('fooBar'); //=> 'FooBar'
31
+ **/
32
+ export const pascalCase = (input: string) => {
33
+ return cc.pascalCase(input, {
34
+ mergeAmbiguousCharacters: true,
35
+ });
36
+ };
37
+
38
+ /**
39
+ * Convert a string to camelCase.
40
+ * @example
41
+ * camelCase('foo bar'); //=> 'fooBar'
42
+ * camelCase('foo_bar'); //=> 'fooBar'
43
+ * camelCase('foo-bar'); //=> 'fooBar'
44
+ * camelCase('foo.bar'); //=> 'fooBar'
45
+ * camelCase('fooBar'); //=> 'fooBar'
46
+ * camelCase('FooBar'); //=> 'fooBar'
47
+ **/
48
+ export const camelCase = (input: string) => {
49
+ return cc.camelCase(input);
50
+ };
51
+
52
+ /**
53
+ * Convert a string to param-case.
54
+ * @example
55
+ * paramCase('foo bar'); //=> 'foo-bar'
56
+ * paramCase('foo_bar'); //=> 'foo-bar'
57
+ * paramCase('foo-bar'); //=> 'foo-bar'
58
+ * paramCase('foo.bar'); //=> 'foo-bar'
59
+ * paramCase('fooBar'); //=> 'foo-bar'
60
+ * paramCase('FooBar'); //=> 'foo-bar'
61
+ **/
62
+ export const paramCase = (input: string) => {
63
+ return cc.kebabCase(input);
64
+ };
65
+
66
+ /**
67
+ * Convert a string to "dot.case".
68
+ * @example
69
+ * dotCase('foo bar'); //=> 'foo.bar'
70
+ * dotCase('foo_bar'); //=> 'foo.bar'
71
+ * dotCase('foo-bar'); //=> 'foo.bar'
72
+ * dotCase('foo.bar'); //=> 'foo.bar'
73
+ * dotCase('fooBar'); //=> 'foo.bar'
74
+ * dotCase('FooBar'); //=> 'foo.bar'
75
+ **/
76
+ export const dotCase = (input: string) => {
77
+ return cc.dotCase(input);
78
+ };
79
+
80
+ /**
81
+ * Convert a string to snake_case.
82
+ * @example
83
+ * snakeCase('foo bar'); //=> 'foo_bar'
84
+ * snakeCase('foo_bar'); //=> 'foo_bar'
85
+ * snakeCase('foo-bar'); //=> 'foo_bar'
86
+ * snakeCase('foo.bar'); //=> 'foo_bar'
87
+ * snakeCase('fooBar'); //=> 'foo_bar'
88
+ * snakeCase('FooBar'); //=> 'foo_bar'
89
+ **/
90
+ export const snakeCase = (input: string) => {
91
+ return cc.snakeCase(input);
92
+ };
93
+
94
+ /**
95
+ * Convert a string to CONSTANT_CASE.
96
+ * @example
97
+ * constantCase('foo bar'); //=> 'FOO_BAR'
98
+ * constantCase('foo_bar'); //=> 'FOO_BAR'
99
+ * constantCase('foo-bar'); //=> 'FOO_BAR'
100
+ * constantCase('foo.bar'); //=> 'FOO_BAR'
101
+ * constantCase('fooBar'); //=> 'FOO_BAR'
102
+ * constantCase('FooBar'); //=> 'FOO_BAR'
103
+ **/
104
+ export const constantCase = (input: string) => {
105
+ return cc.constantCase(input);
106
+ };
107
+
108
+ /**
109
+ * Convert a string to sentence.
110
+ * @deprecated use sentenceCase instead
111
+ * @example
112
+ * toSentence('foo bar'); //=> 'Foo bar'
113
+ * toSentence('foo_bar'); //=> 'Foo bar'
114
+ * toSentence('foo-bar'); //=> 'Foo bar'
115
+ * toSentence('foo.bar'); //=> 'Foo bar'
116
+ * toSentence('fooBar'); //=> 'Foo bar'
117
+ * toSentence('FooBar'); //=> 'Foo bar'
118
+ * toSentence('foo bar baz'); //=> 'Foo bar baz'
119
+ **/
120
+ export const toSentence = (input: string) => {
121
+ return ucfirst(cc.noCase(input, {
122
+ delimiter: ' ',
123
+ }));
124
+ };
125
+
126
+ /**
127
+ * Convert a string to sentence.
128
+ * @example
129
+ * sentenceCase('foo bar'); //=> 'Foo bar'
130
+ * sentenceCase('foo_bar'); //=> 'Foo bar'
131
+ * sentenceCase('foo-bar'); //=> 'Foo bar'
132
+ * sentenceCase('foo.bar'); //=> 'Foo bar'
133
+ * sentenceCase('fooBar'); //=> 'Foo bar'
134
+ * sentenceCase('FooBar'); //=> 'Foo bar'
135
+ * sentenceCase('foo bar baz'); //=> 'Foo bar baz'
136
+ **/
137
+ export const sentenceCase = (input: string) => {
138
+ return cc.sentenceCase(input);
139
+ };
140
+
141
+ /**
142
+ * Convert a string to upper cased sentence.
143
+ * @deprecated use capitalCase instead
144
+ * @example
145
+ * toUcSentence('foo bar'); //=> 'Foo Bar'
146
+ * toUcSentence('foo_bar'); //=> 'Foo Bar'
147
+ * toUcSentence('foo-bar'); //=> 'Foo Bar'
148
+ * toUcSentence('foo.bar'); //=> 'Foo Bar'
149
+ * toUcSentence('fooBar'); //=> 'Foo Bar'
150
+ * toUcSentence('FooBar'); //=> 'Foo Bar'
151
+ * toUcSentence('foo bar baz'); //=> 'Foo Bar Baz'
152
+ **/
153
+ export const toUcSentence = (input: string) => {
154
+ return cc.capitalCase(input);
155
+ };
156
+
157
+ /**
158
+ * Convert a string to upper cased sentence.
159
+ * @example
160
+ * capitalCase('foo bar'); //=> 'Foo Bar'
161
+ * capitalCase('foo_bar'); //=> 'Foo Bar'
162
+ * capitalCase('foo-bar'); //=> 'Foo Bar'
163
+ * capitalCase('foo.bar'); //=> 'Foo Bar'
164
+ * capitalCase('fooBar'); //=> 'Foo Bar'
165
+ * capitalCase('FooBar'); //=> 'Foo Bar'
166
+ * capitalCase('foo bar baz'); //=> 'Foo Bar Baz'
167
+ **/
168
+ export const capitalCase = (input: string) => {
169
+ return cc.capitalCase(input);
170
+ };
171
+
172
+ /**
173
+ * Alias to "toUcSentence"
174
+ * @deprecated use capitalCase instead
175
+ **/
176
+ export const capitalize = (input: string) => toUcSentence(input);
177
+
178
+ /**
179
+ * Convert a string to lower cased sentence.
180
+ * @deprecated use lowerSentenceCase instead
181
+ * @example
182
+ * toLcSentence('foo bar'); //=> 'foo bar'
183
+ * toLcSentence('foo_bar'); //=> 'foo bar'
184
+ * toLcSentence('foo-bar'); //=> 'foo bar'
185
+ * toLcSentence('foo.bar'); //=> 'foo bar'
186
+ * toLcSentence('fooBar'); //=> 'foo bar'
187
+ * toLcSentence('FooBar'); //=> 'foo bar'
188
+ * toLcSentence('Foo bar baz'); //=> 'foo bar baz'
189
+ **/
190
+ export const toLcSentence = (input: string) => {
191
+ return sentenceCase(input).toLowerCase();
192
+ };
193
+
194
+ /**
195
+ * Convert a string to lower cased sentence.
196
+ * @example
197
+ * lowerSentenceCase('foo bar'); //=> 'foo bar'
198
+ * lowerSentenceCase('foo_bar'); //=> 'foo bar'
199
+ * lowerSentenceCase('foo-bar'); //=> 'foo bar'
200
+ * lowerSentenceCase('foo.bar'); //=> 'foo bar'
201
+ * lowerSentenceCase('fooBar'); //=> 'foo bar'
202
+ * lowerSentenceCase('FooBar'); //=> 'foo bar'
203
+ * lowerSentenceCase('Foo bar baz'); //=> 'foo bar baz'
204
+ **/
205
+ export const lowerSentenceCase = (input: string) => {
206
+ return sentenceCase(input).toLowerCase();
207
+ };
208
+
209
+ /**
210
+ * Convert a table name to sql alias.
211
+ * @example
212
+ * toSqlAlias('foo bar'); //=> 'fb'
213
+ * toSqlAlias('book'); //=> 'b'
214
+ * toSqlAlias('article-category'); //=> 'ac'
215
+ **/
216
+ export const toSqlAlias = (input: string): string => {
217
+ return snakeCase(input)
218
+ .split('_')
219
+ .reduce((acc, word) => acc.concat(word[0]), '');
220
+ };
221
+
222
+ export interface ToAbbreviationOptions {
223
+ maxLength?: number;
224
+ minLength?: number;
225
+ lang?: 'uk' | 'ru' | 'mn';
226
+ iteration?: number;
227
+ }
228
+
229
+ /**
230
+ * Remove vowels from a word.
231
+ * @param word - word to remove vowels from
232
+ * @returns word without vowels
233
+ * @example
234
+ * removeVowels('foo'); //=> 'f'
235
+ */
236
+ export const removeVowels = (word: string) => {
237
+ return word.replace(/[aeiou]/gi, '');
238
+ };
239
+
240
+ /**
241
+ * Convert a string to abbreviation.
242
+ * @example
243
+ * toAbbreviation('Sabbath Schook'); //=> 'SB'
244
+ * toAbbreviation('Рожеві окуляри', {
245
+ * lang: 'uk',
246
+ * }); //=> 'RO'
247
+ * toAbbreviation('Удивительные факты', {
248
+ * lang: 'ru',
249
+ * }); //=> 'UF'
250
+ */
251
+ export const toAbbreviation = (input: string, opts?: ToAbbreviationOptions): string => {
252
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
253
+ const transliterator = (cyrillicToTranslit as any)(opts?.lang ? {
254
+ preset: opts.lang,
255
+ } : undefined);
256
+
257
+ const words = transliterator
258
+ .transform(input)
259
+ .toUpperCase()
260
+ .replace(/[^A-Z ]/g, '')
261
+ .split(' ')
262
+ .filter((word: string) => word.length > 0);
263
+
264
+ // .map((word) =>).toUpperCase());
265
+
266
+ let abbreviation = '';
267
+
268
+ // Sabbath School => SS
269
+ if (words.length > 1) {
270
+ abbreviation = words.reduce((acc: string, word: string) => {
271
+ if (word.length >= 1) {
272
+ acc += word[0];
273
+ }
274
+
275
+ return acc;
276
+ }, '');
277
+ } else if (words.length === 1) {
278
+ const word = words[0];
279
+
280
+ // Sabbath => SBBTH
281
+ if (word.length > 1) {
282
+ abbreviation = word.slice(0, 1) + removeVowels(word.slice(1));
283
+ } else {
284
+ abbreviation = word;
285
+ }
286
+ }
287
+
288
+ // If the maxLength option is set, trim the abbreviation before adding random characters and appending digits
289
+ if (opts?.maxLength && !opts?.iteration) {
290
+ abbreviation = abbreviation.slice(0, opts.maxLength);
291
+ }
292
+
293
+ // If the minLength option is set, ensure the abbreviation meets the minimum length by appending random characters before appending digits
294
+ if (opts?.minLength && abbreviation.length < opts.minLength) {
295
+ let charsNeeded = opts.minLength - abbreviation.length;
296
+ if (opts?.iteration && opts?.iteration > 0) {
297
+ charsNeeded -= 1;
298
+ }
299
+
300
+ if (charsNeeded > 0) {
301
+ abbreviation += createRandomAbbreviationString(charsNeeded).toUpperCase();
302
+ }
303
+ }
304
+
305
+ // Append a number based on the iteration option
306
+ if (opts?.iteration) {
307
+ if (opts?.maxLength) {
308
+ // Calculate the maximum length the abbreviation can be, considering the digits and random characters
309
+ const maxAbbrLength = opts.maxLength - 1;
310
+ abbreviation = abbreviation.slice(0, maxAbbrLength);
311
+ }
312
+
313
+ abbreviation += opts.iteration;
314
+ }
315
+
316
+ return abbreviation;
317
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Decline a noun based on a number.
3
+ * @example
4
+ * const words = ['элемент', 'элемента', 'элементов'];
5
+ *
6
+ * decline(0, words, false) // => 'элементов'
7
+ * decline(24, words, false) // => 'элемента'
8
+ * decline(21, words, false) // => 'элемент'
9
+ *
10
+ * decline(0, words) // => '0 элементов'
11
+ * decline(24, words) // => '24 элемента'
12
+ * decline(21, words) // => '21 элемент'
13
+ */
14
+ export const decline = (n: number, words: string[], concat = true) => {
15
+ const word =
16
+ words[
17
+ n % 100 > 4 && n % 100 < 20
18
+ ? 2
19
+ : [2, 0, 1, 1, 1, 2][n % 10 < 5 ? n % 10 : 5]
20
+ ];
21
+
22
+ return concat ? `${n} ${word}` : word;
23
+ };
@@ -0,0 +1,41 @@
1
+ import { camelCase, pascalCase } from './cases.js';
2
+ import { singularToPlural } from './pluralize.js';
3
+
4
+ /**
5
+ Returns variations of entity type names
6
+
7
+ @example
8
+ | entityType | 'CodePuzzle' |
9
+ |----------------------------|-----------------------|
10
+ | pascalCaseEntityType | 'CodePuzzle' |
11
+ | camelCaseEntityType | 'CodePuzzle' |
12
+ | pluralEntityType | 'CodePuzzles' |
13
+ | pluralCamelCaseEntityType | 'codePuzzles' |
14
+ | pluralPascalCaseEntityType | 'CodePuzzles' |
15
+ | createMutationName | 'createCodePuzzle' |
16
+ | updateMutationName | 'updateCodePuzzle' |
17
+ | deleteMutationName | 'deleteCodePuzzle' |
18
+ | dublicateMutationName | 'dublicateCodePuzzle' |
19
+ | publishMutationName | 'publishCodePuzzle' |
20
+ */
21
+ export const createEntityTypeNames = (entityType: string) => {
22
+ const pluralEntityType = singularToPlural(entityType); // codepuzzles
23
+ const camelCaseEntityType = camelCase(entityType); // codepuzzle
24
+ const pascalCaseEntityType = pascalCase(entityType); // CodePuzzle
25
+
26
+ const pluralPascalCaseEntityType = pascalCase(pluralEntityType); // CodePuzzles
27
+
28
+ return {
29
+ pluralEntityType,
30
+ camelCaseEntityType,
31
+ pascalCaseEntityType,
32
+ pluralCamelCaseEntityType: camelCase(pluralEntityType),
33
+ pluralPascalCaseEntityType,
34
+ createMutationName: `create${pascalCaseEntityType}`,
35
+ updateMutationName: `update${pascalCaseEntityType}`,
36
+ deleteMutationName: `delete${pascalCaseEntityType}`,
37
+ dublicateMutationName: `dublicate${pascalCaseEntityType}`,
38
+ publishMutationName: `publish${pascalCaseEntityType}`,
39
+ unpublishMutationName: `unpublish${pascalCaseEntityType}`,
40
+ };
41
+ };
@@ -0,0 +1,16 @@
1
+ import { customAlphabet } from 'nanoid/non-secure';
2
+
3
+ export const createRandomString = (size = 8) => {
4
+ return customAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', size)();
5
+ };
6
+
7
+ export const createRandomAbbreviationString = (size = 8) => {
8
+ return customAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ', size)();
9
+ };
10
+
11
+ export const createNumericCode = (num: number, length: number): string => {
12
+ // Add leading zeros if necessary using padStart
13
+ const numberStr = num.toString().padStart(length, '0');
14
+
15
+ return numberStr;
16
+ };
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from './cases.js';
2
+ export * from './declination.js';
3
+ export * from './generators.js';
4
+ export * from './pluralize.js';
5
+
@@ -0,0 +1,35 @@
1
+ import * as pluralize from 'pluralize';
2
+
3
+ /**
4
+ * Change the plural form of a word to its singular form.
5
+ * @example
6
+ * pluralToSingular('books'); //=> 'book'
7
+ */
8
+ export const singularToPlural = (input: string): string => {
9
+ return pluralize.plural(input);
10
+ };
11
+
12
+ /**
13
+ * Change the singular form of a word to its plural form.
14
+ * @example
15
+ * singularToPlural('book'); //=> 'books'
16
+ */
17
+ export const pluralToSingular = (input: string): string => {
18
+ return pluralize.singular(input);
19
+ };
20
+
21
+ /**
22
+ * Checks if a given word is in its plural form.
23
+ *
24
+ * @param word - The word to check for plural form
25
+ * @returns `true` if the word is plural, `false` if it's singular
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * isPlural("cats"); // true
30
+ * isPlural("cat"); // false
31
+ * ```
32
+ */
33
+ export const isPlural = (word: string): boolean =>
34
+ singularToPlural(word) === word;
35
+
@@ -0,0 +1,196 @@
1
+ import {
2
+ describe, expect, test,
3
+ } from 'vitest';
4
+
5
+ import {
6
+ camelCase,
7
+ capitalCase,
8
+ constantCase,
9
+ dotCase,
10
+ lcfirst,
11
+ lowerSentenceCase,
12
+ paramCase,
13
+ pascalCase,
14
+ sentenceCase,
15
+ snakeCase,
16
+ toAbbreviation,
17
+ ToAbbreviationOptions,
18
+ toSqlAlias,
19
+ ucfirst,
20
+ } from '../src/cases.js';
21
+
22
+ describe('Cases', () => {
23
+ test('ucfirst', () => {
24
+ expect(ucfirst('simple')).toBe('Simple');
25
+ expect(ucfirst('S')).toBe('S');
26
+ });
27
+
28
+ test('lcfirst', () => {
29
+ expect(lcfirst('Simple')).toBe('simple');
30
+ });
31
+
32
+ test('camelCase', () => {
33
+ expect(camelCase('simple')).toBe('simple');
34
+ expect(camelCase('some.dot.case')).toBe('someDotCase');
35
+ expect(camelCase('some-param-case')).toBe('someParamCase');
36
+ expect(camelCase('some_param_case')).toBe('someParamCase');
37
+ expect(camelCase('SOME_PARAM_CASE')).toBe('someParamCase');
38
+ expect(camelCase('some spaced case')).toBe('someSpacedCase');
39
+ expect(camelCase('someCamelCase')).toBe('someCamelCase');
40
+ expect(camelCase('SomePascalCase')).toBe('somePascalCase');
41
+ });
42
+
43
+ test('pascalCase', () => {
44
+ expect(pascalCase('simple')).toBe('Simple');
45
+ expect(pascalCase('some.dot.case')).toBe('SomeDotCase');
46
+ expect(pascalCase('some-param-case')).toBe('SomeParamCase');
47
+ expect(pascalCase('some spaced case')).toBe('SomeSpacedCase');
48
+ expect(pascalCase('someCamelCase')).toBe('SomeCamelCase');
49
+ expect(pascalCase('SomePascalCase')).toBe('SomePascalCase');
50
+ expect(pascalCase('upload-2')).toBe('Upload2');
51
+ });
52
+
53
+ test('paramCase', () => {
54
+ expect(paramCase('simple')).toBe('simple');
55
+ expect(paramCase('some.dot.case')).toBe('some-dot-case');
56
+ expect(paramCase('some-param-case')).toBe('some-param-case');
57
+ expect(paramCase('some spaced case')).toBe('some-spaced-case');
58
+ expect(paramCase('someCamelCase')).toBe('some-camel-case');
59
+ expect(paramCase('SomePascalCase')).toBe('some-pascal-case');
60
+ });
61
+
62
+ test('dotCase', () => {
63
+ expect(dotCase('simple')).toBe('simple');
64
+ expect(dotCase('some.dot.case')).toBe('some.dot.case');
65
+ expect(dotCase('some-param-case')).toBe('some.param.case');
66
+ expect(dotCase('some spaced case')).toBe('some.spaced.case');
67
+ expect(dotCase('someCamelCase')).toBe('some.camel.case');
68
+ expect(dotCase('SomePascalCase')).toBe('some.pascal.case');
69
+ });
70
+
71
+ test('snakeCase', () => {
72
+ expect(snakeCase('simple')).toBe('simple');
73
+ expect(snakeCase('some.dot.case')).toBe('some_dot_case');
74
+ expect(snakeCase('some-param-case')).toBe('some_param_case');
75
+ expect(snakeCase('some spaced case')).toBe('some_spaced_case');
76
+ expect(snakeCase('someCamelCase')).toBe('some_camel_case');
77
+ expect(snakeCase('SomePascalCase')).toBe('some_pascal_case');
78
+ });
79
+
80
+ test('constantCase', () => {
81
+ expect(constantCase('maxValue')).toBe('MAX_VALUE');
82
+ expect(constantCase('mp4-720')).toBe('MP4_720');
83
+ expect(constantCase('QUALITY_4K')).toBe('QUALITY_4_K');
84
+ });
85
+
86
+ test('sentenceCase', () => {
87
+ expect(sentenceCase('simple')).toBe('Simple');
88
+ expect(sentenceCase('some.dot.case')).toBe('Some dot case');
89
+ expect(sentenceCase('some-param-case')).toBe('Some param case');
90
+ expect(sentenceCase('some spaced case')).toBe('Some spaced case');
91
+ expect(sentenceCase('someCamelCase')).toBe('Some camel case');
92
+ expect(sentenceCase('SomePascalCase')).toBe('Some pascal case');
93
+ });
94
+
95
+ test('capitalCase', () => {
96
+ expect(capitalCase('simple')).toBe('Simple');
97
+ expect(capitalCase('some.dot.case')).toBe('Some Dot Case');
98
+ expect(capitalCase('some-param-case')).toBe('Some Param Case');
99
+ expect(capitalCase('some spaced case')).toBe('Some Spaced Case');
100
+ expect(capitalCase('someCamelCase')).toBe('Some Camel Case');
101
+ expect(capitalCase('SomePascalCase')).toBe('Some Pascal Case');
102
+ });
103
+
104
+ test('lowerSentenceCase', () => {
105
+ expect(lowerSentenceCase('simple')).toBe('simple');
106
+ expect(lowerSentenceCase('some.dot.case')).toBe('some dot case');
107
+ expect(lowerSentenceCase('some-param-case')).toBe('some param case');
108
+ expect(lowerSentenceCase('some spaced case')).toBe('some spaced case');
109
+ expect(lowerSentenceCase('someCamelCase')).toBe('some camel case');
110
+ expect(lowerSentenceCase('SomePascalCase')).toBe('some pascal case');
111
+ });
112
+
113
+ test('toSqlAlias', () => {
114
+ expect(toSqlAlias('foo bar')).toBe('fb');
115
+ expect(toSqlAlias('book')).toBe('b');
116
+ expect(toSqlAlias('article-category')).toBe('ac');
117
+ });
118
+
119
+ test.each<[string, string, ToAbbreviationOptions]>([
120
+ ['Sabbath', 'SBBTH', {
121
+ }],
122
+ ['Sabbath', 'SB', {
123
+ maxLength: 2,
124
+ }],
125
+ ['Sabbath School', 'SS', {
126
+ }],
127
+ ['Sabbath && (School)', 'SS', {
128
+ }],
129
+ ['Рожеві окуляри', 'RO', {
130
+ lang: 'uk',
131
+ }],
132
+ ['Удивительные факты', 'UF', {
133
+ lang: 'ru',
134
+ }],
135
+ [`Very long title but i dont know why, maybe because i can't stop write this title`, 'VLTBI', {
136
+ maxLength: 5,
137
+ }],
138
+ ['Sabbath School', 'SS', {
139
+ maxLength: 5,
140
+ iteration: 0,
141
+ }],
142
+ ['Sabbath School', 'SS1', {
143
+ maxLength: 5,
144
+ iteration: 1,
145
+ }],
146
+ ['Sabbath', 'SBBTH', {
147
+ maxLength: 5,
148
+ iteration: 0,
149
+ }],
150
+ ['Sabbath', 'SBBT1', {
151
+ maxLength: 5,
152
+ iteration: 1,
153
+ }],
154
+ ])('toAbbreviation(%s) = %s (%j)', (
155
+ abbreviation: string,
156
+ expected: string,
157
+ opts: ToAbbreviationOptions,
158
+ ) => {
159
+ expect(toAbbreviation(abbreviation, opts)).toBe(expected);
160
+ });
161
+
162
+ test.each<[string, number, ToAbbreviationOptions]>([
163
+ ['Some text', 3, {
164
+ maxLength: 5,
165
+ minLength: 3,
166
+ }],
167
+ ['Sabbath School', 6, {
168
+ maxLength: 6,
169
+ minLength: 6,
170
+ }],
171
+ ['0_o', 3, {
172
+ maxLength: 5,
173
+ minLength: 3,
174
+ iteration: 1,
175
+ }],
176
+ ['S4', 3, {
177
+ maxLength: 5,
178
+ minLength: 3,
179
+ iteration: 1,
180
+ }],
181
+ ['333', 3, {
182
+ maxLength: 5,
183
+ minLength: 3,
184
+ iteration: 1,
185
+ }],
186
+ ])('toAbbreviation with random strings: toAbbreviation(%s).length => %s (%j)', (
187
+ abbreviation,
188
+ expectedLenght,
189
+ opts,
190
+ ) => {
191
+ const result = toAbbreviation(abbreviation, opts);
192
+ // console.log(abbreviation, result);
193
+
194
+ expect(result.length).toBe(expectedLenght);
195
+ });
196
+ });
@@ -0,0 +1,14 @@
1
+ import { expect, test } from 'vitest';
2
+
3
+ import { decline } from '../src/declination.js';
4
+ const words = ['элемент', 'элемента', 'элементов'];
5
+
6
+ test('must decline word', () => {
7
+ expect(decline(0, words, false)).toBe('элементов');
8
+ expect(decline(24, words, false)).toBe('элемента');
9
+ expect(decline(21, words, false)).toBe('элемент');
10
+
11
+ expect(decline(0, words)).toBe('0 элементов');
12
+ expect(decline(24, words)).toBe('24 элемента');
13
+ expect(decline(21, words)).toBe('21 элемент');
14
+ });