moderndash 0.0.6 → 0.0.8

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.
Files changed (39) hide show
  1. package/README.md +92 -0
  2. package/package.json +3 -2
  3. package/.ctiignore +0 -3
  4. package/test/.eslintrc.cjs +0 -5
  5. package/test/array/chunk.test.ts +0 -19
  6. package/test/array/differenceMethods.test.ts +0 -49
  7. package/test/array/dropMethods.test.ts +0 -30
  8. package/test/array/intersectionMethods.test.ts +0 -36
  9. package/test/array/shuffle.test.ts +0 -17
  10. package/test/array/takeMethods.test.ts +0 -41
  11. package/test/array/unionMethods.test.ts +0 -41
  12. package/test/array/uniqMethods.test.ts +0 -18
  13. package/test/array/unzipMethods.test.ts +0 -13
  14. package/test/array/zipMethods.test.ts +0 -48
  15. package/test/collection/countBy.test.ts +0 -13
  16. package/test/collection/groupBy.test.ts +0 -35
  17. package/test/collection/sample.test.ts +0 -17
  18. package/test/collection/sampleSize.test.ts +0 -33
  19. package/test/collection/sortBy.test.ts +0 -31
  20. package/test/function/after.test.ts +0 -19
  21. package/test/function/before.test.ts +0 -19
  22. package/test/function/debounce.test.ts +0 -47
  23. package/test/function/memoize.test.ts +0 -33
  24. package/test/function/once.test.ts +0 -29
  25. package/test/function/throttle.test.ts +0 -24
  26. package/test/lang/isEqualMethods.test.ts +0 -98
  27. package/test/string/camelCase.test.ts +0 -13
  28. package/test/string/capitalize.test.ts +0 -17
  29. package/test/string/deburr.test.ts +0 -16
  30. package/test/string/escape.test.ts +0 -17
  31. package/test/string/escapeRegExp.test.ts +0 -18
  32. package/test/string/kebabCase.test.ts +0 -18
  33. package/test/string/pascalCase.test.ts +0 -16
  34. package/test/string/snakeCase.test.ts +0 -23
  35. package/test/string/startCase.test.ts +0 -14
  36. package/test/string/stripSpecialChars.test.ts +0 -15
  37. package/test/string/unescape.test.ts +0 -17
  38. package/tsup.config.js +0 -10
  39. package/vitest.config.ts +0 -27
package/README.md ADDED
@@ -0,0 +1,92 @@
1
+ ![ModernDash Logo](/website/src/assets/moderndashLogo.svg)
2
+
3
+ <p align=center>
4
+ A Typescript-First utility library inspired by Lodash.
5
+ Optimized for modern browsers.
6
+ </p>
7
+ <p align=center>
8
+ ✅ ESM
9
+ ✅ Tree-shakable
10
+ ✅ Typescript Strict Mode (no any types)
11
+ ✅ Zero dependencies
12
+ </p>
13
+
14
+ -------
15
+
16
+ > **Warning**
17
+ > This library is still in development and is not ready for production use.
18
+
19
+ ## Documentation
20
+ The documentation is WIP.
21
+
22
+ ## Removed Functions because of trivial native alternatives
23
+ Look at [You-Dont-Need-Lodash](https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore) for native replacements.
24
+
25
+ ### Array Functions
26
+ - compact
27
+ - concat
28
+ - differenceBy property shorthand
29
+ - drop
30
+ - dropRight
31
+ - fill
32
+ - findIndex
33
+ - findLastIndex
34
+ - first/head
35
+ - flatten
36
+ - flattenDeep
37
+ - flattenDepth
38
+ - fromPairs
39
+ - initial
40
+ - join
41
+ - last
42
+ - lastIndexOf
43
+ - nth
44
+ - without
45
+ - reverse
46
+ - slice
47
+ - sortedIndexOf
48
+ - tail
49
+ - take
50
+ - takeRight
51
+ - without
52
+
53
+ ### Collection Functions
54
+ - each/forEach
55
+ - every
56
+ - filter
57
+ - find
58
+ - flatMap
59
+ - includes
60
+
61
+ ### String Functions
62
+ - lowerCase
63
+ - trim
64
+ - trimEnd
65
+ - trimStart
66
+ - pad
67
+ - padEnd
68
+ - padStart
69
+
70
+ Functions are not considered trivial if they:
71
+ - include reduce methods
72
+ - include multiple nested function calls
73
+
74
+ ## TODO
75
+ - More unzip tests
76
+ - Check if flatmapdeep, flatmapDepth is included in native flatmap
77
+ - GroupBy Property Shorthand
78
+
79
+ ## Might be added later (open for discussion)
80
+ - pull functions (pull, pullAll, pullAllBy, pullAllWith, pullAt)
81
+ - remove
82
+ - sorted functions (sortedIndex, sortedIndexBy, sortedIndexOf, sortedLastIndex, sortedLastIndexBy, sortedLastIndexOf, sortedUniq, sortedUniqBy)
83
+ - if performance is better than native alternatives (testing needed)
84
+ - xor functions (xor, xorBy, xorWith)
85
+ - zipObject, zipObjectDeep
86
+ - forEachRight
87
+ - findLast
88
+ - lowerFirst
89
+ - keyBy
90
+
91
+ ## Continue at
92
+ - invokeMap
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "moderndash",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "type": "module",
5
5
  "description": "A lodash inspired utility framework for ESM/Typescript/ES2020",
6
6
  "scripts": {
7
7
  "build": "ctix create ----startAt src --overwrite --noBackup & tsup",
8
- "prepublishOnly": "npm run build && @powershell cp '../README.md' './dist/README.md'",
8
+ "prepublishOnly": "npm run build && @powershell cp '../README.md' './README.md'",
9
+ "postpublish": "@powershell rm './README.md'",
9
10
  "test": "vitest",
10
11
  "test-ui": "vitest --ui"
11
12
  },
package/.ctiignore DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "src/helpers": "*",
3
- }
@@ -1,5 +0,0 @@
1
- module.exports = {
2
- rules: {
3
- "unicorn/consistent-function-scoping": "off"
4
- }
5
- }
@@ -1,19 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
-
3
- import { chunk } from '@array/chunk';
4
-
5
- describe('Chunk', () => {
6
- const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
7
-
8
- it('should chunk an array', () => {
9
- expect(chunk(2, array)).toEqual([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]);
10
- });
11
-
12
- it('should return the last chunk as remaining elements', () => {
13
- expect(chunk(3, array)).toEqual([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]);
14
- });
15
-
16
- it('should coerce `size` to an integer', () => {
17
- expect(chunk(array.length / 4, array)).toEqual([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]);
18
- });
19
- });
@@ -1,49 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
-
3
- import { difference } from '@array/difference';
4
- import { differenceBy } from '@array/differenceBy';
5
- import { differenceWith } from '@array/differenceWith';
6
-
7
- describe('difference', () => {
8
- it('should return the difference between two arrays', () => {
9
- const array1 = [1, undefined, null, NaN, 3, 4, 5];
10
- const array2 = [2, 4, undefined, NaN, null, 8];
11
- const result = difference(array1, array2);
12
- expect(result).toEqual([1, NaN, 3, 5]);
13
- });
14
- });
15
-
16
- describe('differenceBy', () => {
17
- it('should return match based on input function', () => {
18
- expect(differenceBy(Math.floor, [2.1, 1.2], [2.3, 3.4], [99])).toEqual([1.2]);
19
- });
20
- });
21
-
22
-
23
- describe('differenceWith', () => {
24
- it('should return an array containing the elements that are present in the first array but not in the other arrays', () => {
25
- const array1 = [1, 2, 3, 4];
26
- const array2 = [2, 3, 5, 6];
27
- const array3 = [3, 4, 5, 6];
28
-
29
- const difference = differenceWith((a, b) => a === b, array1, array2, array3);
30
- expect(difference).toEqual([1]);
31
- });
32
-
33
- it('should return an empty array if no elements are present in the first array but not in the other arrays', () => {
34
- const array1 = [1, 2, 3, 4];
35
- const array2 = [1, 2];
36
- const array3 = [3, 4];
37
-
38
- const difference = differenceWith((a, b) => a === b, array1, array2, array3);
39
- expect(difference).toEqual([]);
40
- });
41
-
42
- it('should return the first array if no elements are present in the other arrays', () => {
43
- const array1 = [1, 2, 3, 4];
44
- const array2: number[] = [];
45
-
46
- const difference = differenceWith((a, b) => a === b, array1, array2);
47
- expect(difference).toEqual(array1);
48
- });
49
- });
@@ -1,30 +0,0 @@
1
- import { it, expect, describe } from 'vitest';
2
-
3
- import { dropRightWhile } from '@array/dropRightWhile';
4
- import { dropWhile } from '@array/dropWhile';
5
-
6
- const array = [2, 4, 5, 6];
7
-
8
- describe('dropWhile', () => {
9
- it('removes elements from the start of the array until the predicate returns false', () => {
10
- expect(dropWhile(x => x % 2 === 0, array)).toEqual([5, 6]);
11
- });
12
-
13
- it('returns an empty array if the predicate always returns true', () => {
14
- expect(dropWhile(() => true, array)).toEqual([]);
15
- });
16
-
17
- it('returns the original array if the predicate always returns false', () => {
18
- expect(dropWhile(() => false, array)).toEqual(array);
19
- });
20
-
21
- it('returns an empty array if the input array is empty', () => {
22
- expect(dropWhile(() => true, [])).toEqual([]);
23
- });
24
- });
25
-
26
- describe('dropRightWhile', () => {
27
- it('should drop elements while `predicate` returns truthy', () => {
28
- expect(dropRightWhile(n => n > 4, array)).toEqual([2, 4]);
29
- });
30
- });
@@ -1,36 +0,0 @@
1
- import { expect, it, describe } from 'vitest';
2
-
3
- import { intersection } from '@array/intersection';
4
- import { intersectionBy } from '@array/intersectionBy';
5
- import { intersectionWith } from '@array/intersectionWith';
6
-
7
- describe('intersection', () => {
8
- it('returns the correct intersections', () => {
9
- const arr1 = [1, 2, 3, 4, 5];
10
- const arr2 = [3, 4, 5, 6, 7];
11
-
12
- const result = intersection(arr1, arr2);
13
- expect(result).toEqual([3, 4, 5]);
14
- });
15
- });
16
-
17
- describe('intersectionBy', () => {
18
- it('returns the correct intersections', () => {
19
- const arr1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }];
20
- const arr2 = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }];
21
-
22
- const result = intersectionBy(value => value.id, arr1, arr2);
23
- expect(result).toEqual([{ id: 3 }, { id: 4 }, { id: 5 }]);
24
- });
25
- });
26
-
27
-
28
- describe('intersectionWith', () => {
29
- it('returns the correct intersections', () => {
30
- const arr1 = [1, 2, 3, 4, 5];
31
- const arr2 = [3, 4, 5, 6, 7];
32
-
33
- const result = intersectionWith((a, b) => a % 2 === 0 && a === b, arr1, arr2);
34
- expect(result).toEqual([4]);
35
- });
36
- });
@@ -1,17 +0,0 @@
1
- import { test, describe, expect } from 'vitest';
2
-
3
- import { shuffle } from '@array/shuffle';
4
-
5
- describe('shuffle', () => {
6
- test('should shuffle the elements of the array', () => {
7
- const array = [1, 2, 3, 4, 5];
8
- const shuffledArray = shuffle(array);
9
- expect(shuffledArray).not.toEqual(array);
10
- });
11
-
12
- test('should not modify the original array', () => {
13
- const array = [1, 2, 3, 4, 5];
14
- shuffle(array);
15
- expect(array).toEqual([1, 2, 3, 4, 5]);
16
- });
17
- });
@@ -1,41 +0,0 @@
1
- import { it, expect, describe } from 'vitest';
2
-
3
- import { takeRightWhile } from '@array/takeRightWhile';
4
- import { takeWhile } from '@array/takeWhile';
5
-
6
- describe('takeWhile', () => {
7
- const numbers = [2, 4, 5, 6, 7, 8, 9, 10];
8
- it('should return the elements from the input array until the predicate returns false', () => {
9
- const evenNumbers = takeWhile((n) => n % 2 === 0, numbers);
10
- expect(evenNumbers).toEqual([2, 4]);
11
- });
12
-
13
- it('should return an empty array if the predicate always returns false', () => {
14
- const evenNumbers = takeWhile((n) => n > 10, numbers);
15
- expect(evenNumbers).toEqual([]);
16
- });
17
-
18
- it('should deal with different types', () => {
19
- const mixed = [1, 2, 3, '4', 5, '6', 7, '8', 9, '10', [], {}, undefined];
20
- const evenNumbers = takeWhile((n) => typeof n === 'number', mixed);
21
- expect(evenNumbers).toEqual([1, 2, 3]);
22
- });
23
- });
24
-
25
- describe('takeRightWhile', () => {
26
- const numbers = [2, 3, 5, 7, 11, 14, 17, 19, 23, 29];
27
- it('should return a new array with the last elements that satisfy the condition specified by the predicate function', () => {
28
- const result = takeRightWhile(n => n % 2 === 1, numbers);
29
- expect(result).toEqual([17, 19, 23, 29]);
30
- });
31
-
32
- it('should return an empty array if no elements satisfy the condition', () => {
33
- const result = takeRightWhile((n: number) => n % 100 === 1, numbers);
34
- expect(result).toEqual([]);
35
- });
36
-
37
- it('should return the original array if all elements satisfy the condition', () => {
38
- const result = takeRightWhile(() => true, numbers);
39
- expect(result).toEqual(numbers);
40
- });
41
- });
@@ -1,41 +0,0 @@
1
- import { it, expect, describe } from 'vitest';
2
-
3
- import { union } from '@array/union';
4
- import { unionBy } from '@array/unionBy';
5
- import { unionWith } from '@array/unionWith';
6
-
7
-
8
- describe('union', () => {
9
- const array1 = [1, 2, 3];
10
- const array2 = [2, 3, 4];
11
- const array3 = [3, 4, [5]];
12
-
13
- it('should return a new array with the unique elements from all of the provided arrays', () => {
14
- const result = union(array1, array2, array3);
15
- expect(result).toEqual([1, 2, 3, 4, [5]]);
16
- });
17
- });
18
-
19
-
20
- describe('unionWith', () => {
21
- it('returns a new array containing the unique values from the input arrays', () => {
22
- const result = unionWith((a, b) => a === b, [1, 2, 3], [2, 3, 4], [3, 4, 5]);
23
- expect(result).toEqual([1, 2, 3, 4, 5]);
24
- });
25
-
26
- it('uses the comparator function to determine uniqueness', () => {
27
- const result = unionWith((a, b) => a.id === b.id, [{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }]);
28
- expect(result).toEqual([{ id: 1 }, { id: 2 }, { id: 3 }]);
29
- });
30
- });
31
-
32
- describe('unionBy', () => {
33
- it('should return the union of the arrays, using the iteratee to determine uniqueness', () => {
34
- const objects = [{ x: 1 }, { x: 2 }, { x: 3 }];
35
- const moreObjects = [{ x: 2 }, { x: 3 }, { x: 4 }];
36
- expect(unionBy(o => o.x, objects, moreObjects)).toEqual([{ x: 1 }, { x: 2 }, { x: 3 }, { x: 4 }]);
37
-
38
- // The `property` iteratee shorthand.
39
- expect(unionBy('x', objects, moreObjects)).toEqual([{ x: 1 }, { x: 2 }, { x: 3 }, { x: 4 }]);
40
- });
41
- });
@@ -1,18 +0,0 @@
1
- import { it, expect, describe } from 'vitest';
2
-
3
- import { uniq } from '@array/uniq';
4
-
5
- describe('uniq', () => {
6
- it('should return an array with only unique values', () => {
7
- const input = [1, 2, 3, 3, 4, 5, 5, 6];
8
- const expectedOutput = [1, 2, 3, 4, 5, 6];
9
- expect(uniq(input)).toEqual(expectedOutput);
10
- });
11
-
12
- it('should handle objects and arrays correctly', () => {
13
- const input = [{ a: 1 }, { a: 2 }, { a: 1 }, [1, 2], [1, 2], [1, 2, 3]
14
- ];
15
- const expectedOutput = [{ a: 1 }, { a: 2 }, [1, 2], [1, 2, 3]];
16
- expect(uniq(input)).toEqual(expectedOutput);
17
- });
18
- });
@@ -1,13 +0,0 @@
1
- import { describe, test, expect } from 'vitest';
2
-
3
- import { unzipWith } from '@array/unzipWith';
4
-
5
- describe('unzipWith', () => {
6
- test('should unzip an arrays with a function', () => {
7
- const array: [number, string, boolean?][] = [[1, 'a', true], [2, 'b', false], [3, 'c']];
8
- const iteratee = (x: number, y: string, z?: boolean) => x.toString() + y + (z ? '!' : '');
9
-
10
- const result = unzipWith(iteratee, array);
11
- expect(result).toEqual(['1a!', '2b', '3c']);
12
- });
13
- });
@@ -1,48 +0,0 @@
1
- import { describe, test, expect } from 'vitest';
2
-
3
- import { zipWith } from '@array/zipWith';
4
-
5
- describe('zipWith function', () => {
6
- test('returns the expected result for three arrays of the same length', () => {
7
- const array1 = [1, 2, 3];
8
- const array2 = [10, 20, 30];
9
- const array3 = [100, 200, 300];
10
-
11
- const result = zipWith((a, b, c) => a + b + c, array1, array2, array3);
12
-
13
- expect(result).toEqual([111, 222, 333]);
14
- });
15
-
16
- test('returns the expected result for arrays of different lengths', () => {
17
- const array1 = [1, 2, 3, 4];
18
- const array2 = [10, 20, 30];
19
- const array3 = [100, 200];
20
-
21
- const result = zipWith((a, b, c) => a + b + c, array1, array2, array3);
22
-
23
- expect(result).toEqual([111, 222]);
24
- });
25
-
26
- test('returns an empty array for empty input arrays', () => {
27
- const array1: number[] = [];
28
- const array2: number[] = [];
29
- const array3: number[] = [];
30
-
31
- const result = zipWith((a, b, c) => a + b + c, array1, array2, array3);
32
-
33
- expect(result).toEqual([]);
34
- });
35
-
36
- test('works with arrays of different types', () => {
37
- const array1 = ['a', 'b', 'c'];
38
- const array2 = [1, 2, 3];
39
- const array3 = [true, false, true];
40
- // Todo fix type error
41
-
42
- const iteratee = (a: string, b: number, c: boolean) => a + b.toString() + c.toString();
43
- //
44
- const result = zipWith(iteratee, array1, array2, array3);
45
-
46
- expect(result).toEqual(['a1true', 'b2false', 'c3true']);
47
- });
48
- });
@@ -1,13 +0,0 @@
1
- import { describe, test, expect } from 'vitest';
2
-
3
- import { countBy } from '@collection/countBy';
4
- import { sample } from '@array/sample';
5
-
6
- describe('countBy function', () => {
7
- test('countBy', () => {
8
- const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
9
- const even = (value: number) => (value % 2 === 0).toString();
10
- const result = countBy(even, array);
11
- expect(result).toEqual({ 'true': 5, 'false': 5 });
12
- });
13
- });
@@ -1,35 +0,0 @@
1
- import { describe, test, expect } from 'vitest';
2
-
3
- import { groupBy } from '@collection/groupBy';
4
-
5
- describe('groupBy', () => {
6
- test('groups elements by evenness', () => {
7
- const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
8
- const even = (value: number) => (value % 2 === 0).toString();
9
- const result = groupBy(even, array);
10
- expect(result).toEqual({ 'true': [2, 4, 6, 8, 10], 'false': [1, 3, 5, 7, 9] });
11
- });
12
-
13
- test('should group an array by a property', () => {
14
- const array = [
15
- { name: 'Alice', age: 30 },
16
- { name: 'Bob', age: 35 },
17
- { name: 'Charlie', age: 30 },
18
- { name: 'Dave', age: 40 },
19
- { name: 'Eve', age: 35 }
20
- ];
21
-
22
- const result = groupBy(element => element.age, array);
23
-
24
- expect(result).toEqual({
25
- 30: [{ name: 'Alice', age: 30 }, { name: 'Charlie', age: 30 }],
26
- 35: [{ name: 'Bob', age: 35 }, { name: 'Eve', age: 35 }],
27
- 40: [{ name: 'Dave', age: 40 }]
28
- });
29
- });
30
-
31
- test('should work with an object for `collection`', function () {
32
- const actual = groupBy(Math.floor, { 'a': 6.1, 'b': 4.2, 'c': 6.3 } );
33
- expect(actual).toEqual({ '4': [4.2], '6': [6.1, 6.3] });
34
- });
35
- });
@@ -1,17 +0,0 @@
1
- import { test, describe, expect } from 'vitest';
2
-
3
- import { sample } from '@array/sample';
4
-
5
- describe('sample', () => {
6
- test('sample function returns a random value from an array', () => {
7
- const collection = [1, 2, 3, 4, 5];
8
- const result = sample(collection);
9
- expect(collection).toContain(result);
10
- });
11
-
12
- test('sample function returns undefined for an empty collection', () => {
13
- const collection = [] as unknown[];
14
- const result = sample(collection);
15
- expect(result).toBeUndefined();
16
- });
17
- });
@@ -1,33 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
-
3
- import { sampleSize } from '@array/sampleSize';
4
-
5
- describe('sampleSize', () => {
6
- test('should return an array of the specified size', () => {
7
- const array = [1, 2, 3, 4, 5];
8
- const size = 3;
9
- const result = sampleSize(size, array);
10
- expect(result).toHaveLength(size);
11
- });
12
-
13
- test('should return an empty array if size is 0 or less', () => {
14
- const array = [1, 2, 3, 4, 5];
15
- const size = 0;
16
- const result = sampleSize(size, array);
17
- expect(result).toHaveLength(0);
18
- });
19
-
20
- test('should return an empty array if the input array is empty', () => {
21
- const array: number[] = [];
22
- const size = 3;
23
- const result = sampleSize(size, array);
24
- expect(result).toHaveLength(0);
25
- });
26
-
27
- test('should return a random subset of the input array', () => {
28
- const array = [1, 2, 3, 4, 5];
29
- const size = 3;
30
- const result = sampleSize(size, array);
31
- expect(expect.arrayContaining(result)).toEqual(array);
32
- });
33
- });
@@ -1,31 +0,0 @@
1
- import { test, describe, expect } from 'vitest';
2
-
3
- import { sortBy } from '@collection/sortBy';
4
-
5
- describe('sortBy', () => {
6
- test('should sort the array in ascending order based on the iteratee function', () => {
7
- const numbers = [3, 1, 2];
8
- const sortedNumbers = sortBy(number => number, numbers);
9
- expect(sortedNumbers).toEqual([1, 2, 3]);
10
- });
11
-
12
- test('should return the original array if it is already sorted', () => {
13
- const numbers = [1, 2, 3];
14
- const sortedNumbers = sortBy(number => number, numbers);
15
- expect(sortedNumbers).toEqual(numbers);
16
- });
17
-
18
- test('should work with arrays of objects', () => {
19
- const users = [
20
- { name: 'Alice', age: 30 },
21
- { name: 'Bob', age: 25 },
22
- { name: 'Eve', age: 35 }
23
- ];
24
- const sortedUsers = sortBy(user => user.age, users);
25
- expect(sortedUsers).toEqual([
26
- { name: 'Bob', age: 25 },
27
- { name: 'Alice', age: 30 },
28
- { name: 'Eve', age: 35 }
29
- ]);
30
- });
31
- });
@@ -1,19 +0,0 @@
1
- import { describe, test, vi, expect } from 'vitest';
2
-
3
- import { after } from '@function/after';
4
-
5
- describe('after', () => {
6
- test('after function works correctly', () => {
7
- const testFn = vi.fn();
8
- const afterFn = after(3, testFn);
9
-
10
- afterFn(1);
11
- afterFn(1);
12
- expect(testFn).toHaveBeenCalledTimes(0);
13
-
14
- afterFn(1);
15
- afterFn(1);
16
-
17
- expect(testFn).toHaveBeenCalledTimes(2);
18
- });
19
- });
@@ -1,19 +0,0 @@
1
- import { describe, expect, test, vi } from 'vitest';
2
-
3
- import { before } from '@function/before';
4
-
5
- describe('before', () => {
6
- test('only calls 3 times', () => {
7
- const testFn = vi.fn();
8
- const beforeFn = before(3, testFn);
9
-
10
- beforeFn();
11
- beforeFn();
12
- expect(testFn).toHaveBeenCalledTimes(2);
13
-
14
- beforeFn();
15
- beforeFn();
16
-
17
- expect(testFn).toHaveBeenCalledTimes(3);
18
- });
19
- });
@@ -1,47 +0,0 @@
1
- import { afterEach, beforeAll, describe, expect, test, vi } from 'vitest';
2
-
3
- import { debounce } from '@function/debounce';
4
-
5
- describe('debounce', () => {
6
- const testFn = vi.fn((x: number) => x * 2);
7
-
8
- beforeAll(() => {
9
- vi.useFakeTimers();
10
- });
11
-
12
- afterEach(() => {
13
- testFn.mockClear();
14
- });
15
-
16
- test('only calls the function once', () => {
17
- const debounced = debounce(testFn, 100);
18
-
19
- debounced(1);
20
- debounced(1);
21
- debounced(1);
22
-
23
- expect(testFn).not.toHaveBeenCalled();
24
-
25
- vi.advanceTimersByTime(99);
26
- expect(testFn).not.toHaveBeenCalled();
27
-
28
- vi.advanceTimersByTime(1);
29
- expect(testFn).toHaveBeenCalledTimes(1);
30
- });
31
-
32
- test('calls the function again after the wait period', () => {
33
- const debounced = debounce(testFn, 100);
34
-
35
- debounced(1);
36
- vi.advanceTimersByTime(50);
37
- debounced(1);
38
- vi.advanceTimersByTime(50);
39
- debounced(1);
40
-
41
- vi.advanceTimersByTime(50);
42
- expect(testFn).not.toHaveBeenCalled();
43
-
44
- vi.advanceTimersByTime(50);
45
- expect(testFn).toHaveBeenCalledTimes(1);
46
- });
47
- });
@@ -1,33 +0,0 @@
1
- import { test, describe, expect, vi, beforeEach } from 'vitest';
2
-
3
- import { memoize } from '@function/memoize';
4
-
5
- describe('memoize', () => {
6
- const testFn = vi.fn((a: number, b: number) => a + b);
7
-
8
- beforeEach(() => {
9
- testFn.mockClear();
10
- });
11
-
12
-
13
- test('should memoize a function', () => {
14
- const memoizedFunc = memoize(testFn);
15
-
16
- expect(memoizedFunc(1, 2)).to.equal(3);
17
- expect(memoizedFunc(1, 2)).to.equal(3);
18
- expect(testFn).toHaveBeenCalledOnce();
19
- });
20
-
21
- test('should return different results for different arguments', () => {
22
- const memoizedFunc = memoize(testFn);
23
-
24
- expect(memoizedFunc(1, 2)).to.equal(3);
25
- expect(memoizedFunc(2, 3)).to.equal(5);
26
- expect(testFn).toHaveBeenCalledTimes(2);
27
- });
28
-
29
- test('should expose a cache property', () => {
30
- const memoizedFunc = memoize(testFn);
31
- expect(memoizedFunc.cache).to.be.an.instanceof(Map);
32
- });
33
- });
@@ -1,29 +0,0 @@
1
- import { test, describe, expect, vi, afterEach } from 'vitest';
2
-
3
- import { once } from '@function/once';
4
-
5
- describe('once', () => {
6
- const testFn = vi.fn((x: number) => x * 2);
7
-
8
- afterEach(() => {
9
- testFn.mockClear();
10
- });
11
-
12
- test('only calls the function once', () => {
13
- const onceFn = once(testFn);
14
-
15
- onceFn(1);
16
- expect(testFn).toHaveBeenCalledTimes(1);
17
- onceFn(1);
18
- expect(testFn).toHaveBeenCalledTimes(1);
19
- onceFn(1);
20
- expect(testFn).toHaveBeenCalledTimes(1);
21
- });
22
-
23
- test('preserves the return value of the function', () => {
24
- const onceFn = once(testFn);
25
-
26
- expect(onceFn(2)).toBe(4);
27
- expect(onceFn(3)).toBe(4);
28
- });
29
- });
@@ -1,24 +0,0 @@
1
- import { describe, expect, test, vi } from 'vitest';
2
-
3
- import { throttle } from '@function/throttle';
4
-
5
- describe('throttle', () => {
6
- test('only calls the function once', () => {
7
- vi.useFakeTimers();
8
-
9
- const callback = vi.fn();
10
- const throttled = throttle(callback, 100);
11
-
12
- throttled();
13
- throttled();
14
- throttled();
15
-
16
- expect(callback).toHaveBeenCalledTimes(1);
17
-
18
- vi.advanceTimersByTime(99);
19
- expect(callback).toHaveBeenCalledTimes(1);
20
-
21
- vi.advanceTimersByTime(1);
22
- expect(callback).toHaveBeenCalledTimes(2);
23
- });
24
- });
@@ -1,98 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
-
3
- import { isEqual } from '@lang/isEqual';
4
- import { isEqualWith } from '@lang/isEqualWith';
5
-
6
- describe('isEqual', () => {
7
- test('numbers', () => {
8
- expect(isEqual(1, 1)).toBe(true);
9
- expect(isEqual(1, 2)).toBe(false);
10
- });
11
-
12
- test('strings', () => {
13
- expect(isEqual('a', 'a')).toBe(true);
14
- expect(isEqual('a', 'b')).toBe(false);
15
- });
16
-
17
- test('booleans', () => {
18
- expect(isEqual(true, true)).toBe(true);
19
- expect(isEqual(true, false)).toBe(false);
20
- });
21
-
22
- test('null', () => {
23
- expect(isEqual(null, null)).toBe(true);
24
- expect(isEqual(null, undefined)).toBe(false);
25
- });
26
-
27
- test('undefined', () => {
28
- expect(isEqual(undefined, undefined)).toBe(true);
29
- expect(isEqual(undefined, null)).toBe(false);
30
- });
31
-
32
- test('objects', () => {
33
- expect(isEqual({ a: 1 }, { a: 1 })).toBe(true);
34
- expect(isEqual({ a: 1 }, { a: 2 })).toBe(false);
35
- });
36
-
37
- test('arrays', () => {
38
- expect(isEqual([1, 2, 3], [1, 2, 3])).toBe(true);
39
- expect(isEqual([1, 2, 3], [1, 2, 4])).toBe(false);
40
- });
41
-
42
- test('nested objects', () => {
43
- expect(isEqual({ a: { b: 1 } }, { a: { b: 1 } })).toBe(true);
44
- expect(isEqual({ a: { b: 1 } }, { a: { b: 2 } })).toBe(false);
45
- });
46
-
47
- test('nested arrays', () => {
48
- expect(isEqual([[1], [2], [3]], [[1], [2], [3]])).toBe(true);
49
- expect(isEqual([[1], [2], [3]], [[1], [2], [4]])).toBe(false);
50
- });
51
-
52
- test('nested objects and arrays', () => {
53
- expect(isEqual({ a: { b: [1] } }, { a: { b: [1] } })).toBe(true);
54
- expect(isEqual({ a: { b: [1] } }, { a: { b: [2] } })).toBe(false);
55
- });
56
-
57
- test('objects with different keys', () => {
58
- expect(isEqual({ a: 1 }, { b: 1 })).toBe(false);
59
- });
60
-
61
- test('arrays with different lengths', () => {
62
- expect(isEqual([1, 2, 3], [1, 2])).toBe(false);
63
- });
64
-
65
- // eslint-disable-next-line unicorn/consistent-function-scoping
66
- const testFunction = () => { return 1 };
67
- test('functions', () => {
68
- expect(isEqual(() => { return 1 }, () => { return 2 })).toBe(false);
69
- expect(isEqual(testFunction, testFunction)).toBe(true);
70
- });
71
-
72
- test('objects with functions', () => {
73
- expect(isEqual({ a: () => { return 1 } }, { a: () => { return 1 } })).toBe(false);
74
- expect(isEqual({ a: testFunction }, { a: testFunction })).toBe(true);
75
- });
76
-
77
- test('regExp', () => {
78
- expect(isEqual(/a(.*)/, /a(.*)/)).toBe(true);
79
- expect(isEqual(/a/, /b.*/)).toBe(false);
80
- });
81
- });
82
-
83
-
84
- describe('isEqualWith', () => {
85
- test('should return true if the customizer function returns equal values for both inputs', () => {
86
- expect(isEqualWith(Math.floor, 1.3, 1.8)).toBe(true);
87
- });
88
-
89
- test('should return false if the customizer function returns different values for both inputs', () => {
90
- const customizer = (value: number) => value * 2;
91
- expect(isEqualWith(customizer, 2, 5)).toBe(false);
92
- });
93
-
94
- test('should work with objects as input', () => {
95
- const customizer = (value: { a: number, b: number }) => value.a + value.b;
96
- expect(isEqualWith(customizer, { a: 2, b: 3 }, { a: 1, b: 4 })).toBe(true);
97
- });
98
- });
@@ -1,13 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
-
3
- import { camelCase } from '@string/camelCase';
4
-
5
- describe('camelCase', () => {
6
- test('should convert a string to camel case', () => {
7
- expect(camelCase('Foo Bar')).toBe('fooBar');
8
- expect(camelCase('fooBar')).toBe('fooBar');
9
- expect(camelCase('FooBar')).toBe('fooBar');
10
- expect(camelCase('--foo-bar--')).toBe('fooBar');
11
- expect(camelCase('__FOO_BAR__')).toBe('fooBar');
12
- });
13
- });
@@ -1,17 +0,0 @@
1
- import { expect, test, describe } from 'vitest';
2
-
3
- import { capitalize } from '@string/capitalize';
4
-
5
- describe('capitalize', () => {
6
- test('capitalizes the first letter of a string', () => {
7
- expect(capitalize('hello world')).toBe('Hello world');
8
- });
9
-
10
- test('returns an empty string for an empty input', () => {
11
- expect(capitalize('')).toBe('');
12
- });
13
-
14
- test('returns the original string for a single-character string', () => {
15
- expect(capitalize('a')).toBe('A');
16
- });
17
- });
@@ -1,16 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
-
3
- import { deburr } from '@string/deburr';
4
-
5
- describe('deburr', () => {
6
- test('removes diacritics from a string', () => {
7
- expect(deburr('Mëtàl Hëàd')).toEqual('Metal Head');
8
- expect(deburr('Pokémón')).toEqual('Pokemon');
9
- expect(deburr('résumé')).toEqual('resume');
10
- });
11
-
12
- test('returns the input string if it has no diacritics', () => {
13
- expect(deburr('hello')).toEqual('hello');
14
- expect(deburr('world')).toEqual('world');
15
- });
16
- });
@@ -1,17 +0,0 @@
1
- import { expect, test, describe } from 'vitest';
2
-
3
- import { escape } from '@string/escape';
4
-
5
- describe('escapeToHTML', () => {
6
- test('should escape special characters to HTML entities', () => {
7
- const str = '<p>Hello, World!</p>';
8
- const html = escape(str);
9
- expect(html).toBe('&lt;p&gt;Hello, World!&lt;/p&gt;');
10
- });
11
-
12
- test('should return the original string if it does not contain special characters', () => {
13
- const str = 'Hello, World!';
14
- const html = escape(str);
15
- expect(html).toBe(str);
16
- });
17
- });
@@ -1,18 +0,0 @@
1
- import { expect, test, describe } from 'vitest';
2
-
3
- import { escapeRegExp } from '@string/escapeRegExp';
4
-
5
- describe('escapeRegExp', () => {
6
- test('escapes special characters in a string', () => {
7
- expect(escapeRegExp('hello.world*')).toBe('hello\\.world\\*');
8
- expect(escapeRegExp('[lodash](https://lodash.com/)')).toBe('\\[lodash\\]\\(https://lodash\\.com/\\)');
9
- });
10
-
11
- test('returns an empty string for an empty input', () => {
12
- expect(escapeRegExp('')).toBe('');
13
- });
14
-
15
- test('returns the original string for a string without special characters', () => {
16
- expect(escapeRegExp('hello world')).toBe('hello world');
17
- });
18
- });
@@ -1,18 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
-
3
- import { kebabCase } from '@string/kebabCase';
4
-
5
- describe('kebabCase', () => {
6
- test('converts a string to kebab case', () => {
7
- expect(kebabCase('helloWorld')).toBe('hello-world');
8
- expect(kebabCase('helloCRUELWorld')).toBe('hello-cruel-world');
9
- });
10
-
11
- test('returns an empty string for an empty input', () => {
12
- expect(kebabCase('')).toBe('');
13
- });
14
-
15
- test('returns the original string for a single-word string', () => {
16
- expect(kebabCase('hello')).toBe('hello');
17
- });
18
- });
@@ -1,16 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
-
3
- import { pascalCase } from '@string/pascalCase';
4
-
5
- describe('toPascalCase', () => {
6
- test('converts a string to PascalCase', () => {
7
- expect(pascalCase('hello world')).toEqual('HelloWorld');
8
- expect(pascalCase('this is a.test')).toEqual('ThisIsATest');
9
- expect(pascalCase('CamelCase')).toEqual('CamelCase');
10
- });
11
-
12
- test('handles empty strings and single words correctly', () => {
13
- expect(pascalCase('')).toEqual('');
14
- expect(pascalCase('hello')).toEqual('Hello');
15
- });
16
- });
@@ -1,23 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
-
3
- import { snakeCase } from '@string/snakeCase';
4
-
5
- describe('snakeCase', () => {
6
- test('converts a string to snake_case', () => {
7
- expect(snakeCase('someString')).toBe('some_string');
8
- expect(snakeCase('someOtherString')).toBe('some_other_string');
9
- expect(snakeCase('someStringWithCamelCase')).toBe('some_string_with_camel_case');
10
- });
11
-
12
- test('converts a string with multiple uppercase letters to snake_case', () => {
13
- expect(snakeCase('someStringWithMultipleUppercaseLetters')).toBe('some_string_with_multiple_uppercase_letters');
14
- });
15
-
16
- test('handles strings that are already in snake_case', () => {
17
- expect(snakeCase('some_string')).toBe('some_string');
18
- });
19
-
20
- test('handles empty strings', () => {
21
- expect(snakeCase('')).toBe('');
22
- });
23
- });
@@ -1,14 +0,0 @@
1
- import { expect, test, describe } from 'vitest';
2
-
3
- import { startCase } from '@string/startCase';
4
-
5
- describe('startCase', () => {
6
- test('should convert a string to start case', () => {
7
- expect(startCase('hello world')).toBe('Hello World');
8
- expect(startCase('HELLO WORLD')).toBe('Hello World');
9
- expect(startCase('Hello World')).toBe('Hello World');
10
- expect(startCase('hello-world')).toBe('Hello World');
11
- expect(startCase('hello_world')).toBe('Hello World');
12
- expect(startCase('hello world')).toBe('Hello World');
13
- });
14
- });
@@ -1,15 +0,0 @@
1
- import { describe, test, expect } from 'vitest';
2
-
3
- import { stripSpecialChars } from '@string/stripSpecialChars';
4
-
5
- describe('stripSpecialChars', () => {
6
- test('removes special characters from a string', () => {
7
- expect(stripSpecialChars('Héllo, world!')).toEqual('Hello world');
8
- expect(stripSpecialChars('This string has #$%&*!')).toEqual('This string has ');
9
- expect(stripSpecialChars('Testing 123')).toEqual('Testing 123');
10
- });
11
-
12
- test('returns an empty string if given an empty string', () => {
13
- expect(stripSpecialChars('')).toEqual('');
14
- });
15
- });
@@ -1,17 +0,0 @@
1
- import { test, expect, describe } from 'vitest';
2
-
3
- import { unescapeHTML } from '@string/unescape';
4
-
5
- describe('unescapeHTML', () => {
6
- test('should unescape HTML entities', () => {
7
- const html = '&lt;p&gt;Hello, World!&lt;/p&gt;';
8
- const str = unescapeHTML(html);
9
- expect(str).toBe('<p>Hello, World!</p>');
10
- });
11
-
12
- test('should return the original string if it does not contain HTML entities', () => {
13
- const html = 'Hello, World!';
14
- const str = unescapeHTML(html);
15
- expect(str).toBe(html);
16
- });
17
- });
package/tsup.config.js DELETED
@@ -1,10 +0,0 @@
1
- import { defineConfig } from 'tsup';
2
-
3
- export default defineConfig({
4
- entry: ['src/index.ts'],
5
- format: ['esm'],
6
- sourcemap: true,
7
- clean: true,
8
- outDir: 'dist',
9
- dts: true
10
- });
package/vitest.config.ts DELETED
@@ -1,27 +0,0 @@
1
- /// <reference types="vitest" />
2
- // Configure Vitest (https://vitest.dev/config/)
3
-
4
- import { fileURLToPath, URL } from 'url';
5
-
6
- import { defineConfig } from 'vite';
7
-
8
- const getPath = (path: string) => fileURLToPath(new URL(path, import.meta.url));
9
-
10
- export default defineConfig({
11
- test: {
12
- /* for example, use global to avoid globals imports (describe, test, expect): */
13
- // globals: true,
14
- },
15
- resolve: {
16
- alias: {
17
- '@array': getPath('src/array'),
18
- '@lang': getPath('src/lang'),
19
- '@object': getPath('src/object'),
20
- '@function': getPath('src/function'),
21
- '@collection': getPath('src/collection'),
22
- '@string': getPath('src/string'),
23
- '@number': getPath('src/number'),
24
- '@helpers': getPath('src/helpers')
25
- }
26
- }
27
- });