@ditojs/utils 3.0.0 → 3.1.1

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 (44) hide show
  1. package/package.json +5 -3
  2. package/src/__snapshots__/index.test.js.snap +0 -90
  3. package/src/array/flattten.test.js +0 -29
  4. package/src/array/shuffle.test.js +0 -25
  5. package/src/base/base.test.js +0 -590
  6. package/src/class/mixin.test.js +0 -70
  7. package/src/dataPath/getEntriesAtDataPath.test.js +0 -204
  8. package/src/dataPath/getValueAtDataPath.test.js +0 -140
  9. package/src/dataPath/normalizeDataPath.test.js +0 -36
  10. package/src/dataPath/parseDataPath.test.js +0 -67
  11. package/src/dataPath/setDataPathEntries.test.js +0 -36
  12. package/src/dataPath/setValueAtDataPath.test.js +0 -34
  13. package/src/function/toAsync.test.js +0 -31
  14. package/src/function/toCallback.test.js +0 -29
  15. package/src/function/toPromiseCallback.test.js +0 -24
  16. package/src/html/escapeHtml.test.js +0 -19
  17. package/src/html/stripHtml.test.js +0 -37
  18. package/src/index.test.js +0 -7
  19. package/src/object/clone.test.js +0 -131
  20. package/src/object/equals.test.js +0 -278
  21. package/src/object/groupBy.test.js +0 -70
  22. package/src/object/mapKeys.test.js +0 -16
  23. package/src/object/mapValues.test.js +0 -38
  24. package/src/object/mergeDeeply.test.js +0 -152
  25. package/src/object/pick.test.js +0 -23
  26. package/src/object/pickBy.test.js +0 -48
  27. package/src/string/camelize.test.js +0 -37
  28. package/src/string/capitalize.test.js +0 -33
  29. package/src/string/decamelize.test.js +0 -83
  30. package/src/string/deindent.test.js +0 -181
  31. package/src/string/format.test.js +0 -196
  32. package/src/string/formatDate.test.js +0 -28
  33. package/src/string/formatPlainDate.test.js +0 -13
  34. package/src/string/getCommonPrefix.test.js +0 -23
  35. package/src/string/isAbsoluteUrl.test.js +0 -15
  36. package/src/string/isCreditCard.test.js +0 -50
  37. package/src/string/isDomain.test.js +0 -24
  38. package/src/string/isEmail.test.js +0 -37
  39. package/src/string/isHostname.test.js +0 -12
  40. package/src/string/isUrl.test.js +0 -1595
  41. package/src/string/labelize.test.js +0 -39
  42. package/src/string/parsePlainDate.test.js +0 -20
  43. package/src/timer/debounce.test.js +0 -101
  44. package/src/timer/debounceAsync.test.js +0 -143
@@ -1,48 +0,0 @@
1
- import { pickBy } from './pickBy.js'
2
-
3
- describe('pickBy()', () => {
4
- it('should work with a callback argument', () => {
5
- const object = { a: 1, b: 2, c: 3, d: 4 }
6
- const actual = pickBy(object, n => n === 1 || n === 3)
7
- expect(actual).toStrictEqual({ a: 1, c: 3 })
8
- })
9
-
10
- it('should support string property accessor for truthy values', () => {
11
- const users = {
12
- user1: { name: 'Alice', active: true },
13
- user2: { name: 'Bob', active: false },
14
- user3: { name: 'Charlie', active: true }
15
- }
16
- const actual = pickBy(users, 'active')
17
- expect(actual).toStrictEqual({
18
- user1: { name: 'Alice', active: true },
19
- user3: { name: 'Charlie', active: true }
20
- })
21
- })
22
-
23
- it('should filter by numeric property with string accessor', () => {
24
- const items = {
25
- a: { score: 0 },
26
- b: { score: 5 },
27
- c: { score: 10 }
28
- }
29
- const actual = pickBy(items, 'score')
30
- expect(actual).toStrictEqual({
31
- b: { score: 5 },
32
- c: { score: 10 }
33
- })
34
- })
35
-
36
- it('should filter by string property with string accessor', () => {
37
- const data = {
38
- a: { label: '' },
39
- b: { label: 'test' },
40
- c: { label: 'value' }
41
- }
42
- const actual = pickBy(data, 'label')
43
- expect(actual).toStrictEqual({
44
- b: { label: 'test' },
45
- c: { label: 'value' }
46
- })
47
- })
48
- })
@@ -1,37 +0,0 @@
1
- import { camelize } from './camelize.js'
2
-
3
- const strings = [
4
- 'foo bar', 'Foo bar', 'foo Bar', 'Foo Bar', 'FOO BAR', 'FooBar', 'fooBar'
5
- ]
6
-
7
- describe('camelize()', () => {
8
- describe.each([
9
- [undefined, 'fooBar'],
10
- [false, 'fooBar'],
11
- [true, 'FooBar']
12
- ])(
13
- 'camelize(value, %o)',
14
- (pascalCase, expected) => {
15
- describe.each([
16
- ...strings,
17
- 'foo-bar',
18
- 'foo_bar',
19
- '--foo-bar--',
20
- '__foo_bar__'
21
- ])(
22
- `camelize(%o, ${pascalCase})`,
23
- value => {
24
- it(`returns ${expected}`, () => {
25
- expect(camelize(value, pascalCase)).toBe(expected)
26
- })
27
- }
28
- )
29
- }
30
- )
31
-
32
- it('should return an empty string if nothing can be processed', () => {
33
- expect(camelize()).toBe('')
34
- expect(camelize(null)).toBe('')
35
- expect(camelize('')).toBe('')
36
- })
37
- })
@@ -1,33 +0,0 @@
1
- import { capitalize } from './capitalize.js'
2
-
3
- describe('capitalize()', () => {
4
- it('should capitalize hyphenated text', () => {
5
- expect(capitalize('some-hyphenated-text')).toBe('Some-Hyphenated-Text')
6
- })
7
-
8
- it('should capitalize underscored text', () => {
9
- expect(capitalize('some_underscored_text')).toBe('Some_Underscored_Text')
10
- })
11
-
12
- it('should capitalize a camel-cased text', () => {
13
- expect(capitalize('someCamelCasedText')).toBe('SomeCamelCasedText')
14
- })
15
-
16
- it('should capitalize normal text', () => {
17
- expect(capitalize('some normal text')).toBe('Some Normal Text')
18
- })
19
-
20
- it('should consider numbers as word-breaks', () => {
21
- expect(capitalize('one234five')).toBe('One234Five')
22
- })
23
-
24
- it('should support umlauts', () => {
25
- expect(capitalize('mäuse häuschen')).toBe('Mäuse Häuschen')
26
- })
27
-
28
- it('should return an empty string if nothing can be processed', () => {
29
- expect(capitalize()).toBe('')
30
- expect(capitalize(null)).toBe('')
31
- expect(capitalize('')).toBe('')
32
- })
33
- })
@@ -1,83 +0,0 @@
1
- import { decamelize, hyphenate, underscore } from './decamelize.js'
2
-
3
- const strings = [
4
- 'foo bar', 'Foo bar', 'foo Bar', 'Foo Bar', 'FOO BAR', 'FooBar', 'fooBar'
5
- ]
6
-
7
- describe('decamelize()', () => {
8
- const expected = 'foo bar'
9
- describe.each(strings)(
10
- 'decamelize(%o)',
11
- value => {
12
- it(`returns ${expected}`, () => {
13
- expect(decamelize(value)).toBe(expected)
14
- })
15
- }
16
- )
17
-
18
- it('should return an empty string if nothing can be processed', () => {
19
- expect(decamelize()).toBe('')
20
- expect(decamelize(null)).toBe('')
21
- expect(decamelize('')).toBe('')
22
- })
23
- })
24
-
25
- describe('hyphenate()', () => {
26
- const expected = 'foo-bar'
27
- describe.each(strings)(
28
- 'hyphenate(%o)',
29
- value => {
30
- it(`returns ${expected}`, () => {
31
- expect(hyphenate(value)).toBe(expected)
32
- })
33
- }
34
- )
35
-
36
- it('should hyphenate single space between words', () => {
37
- expect(hyphenate('Foo Bar')).toBe('foo-bar')
38
- })
39
-
40
- it('should hyphenate multiple spaces', () => {
41
- expect(hyphenate('Foo Bar')).toBe('foo-bar')
42
- })
43
-
44
- it('should trim leading whitespace', () => {
45
- expect(hyphenate(' Foo Bar')).toBe('foo-bar')
46
- })
47
-
48
- it('should trim trailing whitespace', () => {
49
- expect(hyphenate('Foo Bar ')).toBe('foo-bar')
50
- })
51
-
52
- it('should hyphenate special characters correctly', () => {
53
- expect(hyphenate('Foo & Bar')).toBe('foo-&-bar')
54
- })
55
- })
56
-
57
- describe('underscore()', () => {
58
- const expected = 'foo_bar'
59
- describe.each(strings)(
60
- 'underscore(%o)',
61
- value => {
62
- it(`returns ${expected}`, () => {
63
- expect(underscore(value)).toBe(expected)
64
- })
65
- }
66
- )
67
-
68
- it('should underscore multiple spaces', () => {
69
- expect(underscore('Foo Bar')).toBe('foo_bar')
70
- })
71
-
72
- it('should trim leading whitespace', () => {
73
- expect(underscore(' Foo Bar')).toBe('foo_bar')
74
- })
75
-
76
- it('should trim trailing whitespace', () => {
77
- expect(underscore('Foo Bar ')).toBe('foo_bar')
78
- })
79
-
80
- it('should underscore special characters correctly', () => {
81
- expect(underscore('Foo & Bar')).toBe('foo_&_bar')
82
- })
83
- })
@@ -1,181 +0,0 @@
1
- import { deindent } from './deindent.js'
2
-
3
- describe('deindent()', () => {
4
- it('should deindent indented multi-line strings', () => {
5
- expect(
6
- deindent`
7
- some
8
- indented
9
- text`
10
- ).toBe(
11
- `some
12
- indented
13
- text`
14
- )
15
- })
16
-
17
- it('should preserve the last line-break', () => {
18
- expect(
19
- deindent`
20
- some
21
- indented
22
- text
23
- `
24
- ).toBe(
25
- `some
26
- indented
27
- text
28
- `
29
- )
30
- })
31
-
32
- it('should only swallow the first line-break, not those following', () => {
33
- expect(
34
- deindent`
35
-
36
-
37
- some
38
- indented
39
- text
40
- `
41
- ).toBe(
42
- `
43
-
44
- some
45
- indented
46
- text
47
- `
48
- )
49
- })
50
-
51
- it('should not swallow the empty line-breaks at the end', () => {
52
- expect(
53
- deindent`
54
- some
55
- indented
56
- text
57
-
58
-
59
- `
60
- ).toBe(
61
- `some
62
- indented
63
- text
64
-
65
-
66
- `
67
- )
68
- })
69
-
70
- it('should handle multi-line strings without first or last line', () => {
71
- expect(
72
- deindent`some
73
- indented
74
- text
75
- some
76
- indented
77
- text`
78
- ).toBe(
79
- `some
80
- indented
81
- text
82
- some
83
- indented
84
- text`
85
- )
86
- })
87
-
88
- it('should handle multi-line strings without first or last line', () => {
89
- expect(
90
- deindent` some
91
- indented
92
- text`
93
- ).toBe(
94
- `some
95
- indented
96
- text`
97
- )
98
- })
99
-
100
- it('should correctly indent nested single-line string values', () => {
101
- const singleLineText = 'single-line text'
102
- expect(
103
- deindent`
104
- some
105
- indented
106
- ${singleLineText}
107
- `
108
- ).toBe(
109
- `some
110
- indented
111
- single-line text
112
- `
113
- )
114
- })
115
-
116
- it('should correctly indent unnested multi-line string values', () => {
117
- const multiLineText = 'multi-\nline\ntext'
118
- expect(
119
- deindent`
120
- some
121
- indented
122
- ${multiLineText}
123
- `
124
- ).toBe(
125
- `some
126
- indented
127
- multi-
128
- line
129
- text
130
- `
131
- )
132
- })
133
-
134
- it('should correctly indent nested multi-line string values', () => {
135
- const multiLineText = 'multi-\nline\ntext'
136
- expect(
137
- deindent`
138
- some
139
- indented
140
- ${multiLineText}
141
- `
142
- ).toBe(
143
- `some
144
- indented
145
- multi-
146
- line
147
- text
148
- `
149
- )
150
- })
151
-
152
- it('should maintain the indent of prefixed multi-line string values', () => {
153
- const multiLineText = 'multi-\nline\ntext'
154
- expect(
155
- deindent`
156
- some
157
- indented
158
- content: ${multiLineText}
159
- `
160
- ).toBe(
161
- `some
162
- indented
163
- content: multi-
164
- line
165
- text
166
- `
167
- )
168
- })
169
-
170
- it('should not deindent if the first line starts with text', () => {
171
- expect(
172
- deindent`some
173
- indented
174
- text`
175
- ).toBe(
176
- `some
177
- indented
178
- text`
179
- )
180
- })
181
- })
@@ -1,196 +0,0 @@
1
- import { format } from './format.js'
2
-
3
- describe('format()', () => {
4
- const integer = 123456789
5
- const float = 123456.789
6
- const date = new Date(2012, 5, 9, 22, 45, 30)
7
-
8
- it('should return undefined when no value is given', () => {
9
- expect(format()).toBe(undefined)
10
- })
11
-
12
- it('should return null when value is null', () => {
13
- expect(format(null)).toBe(null)
14
- expect(format(null, { number: true })).toBe(null)
15
- expect(format(null, { date: true })).toBe(null)
16
- expect(format(null, { time: true })).toBe(null)
17
- })
18
-
19
- it('should use the en-US locale by default', () => {
20
- expect(format(integer)).toBe('123,456,789')
21
- expect(format(float)).toBe('123,456.789')
22
- expect(format(date)).toMatch(/^June 9, 2012 at 10:45:30\sPM$/)
23
- })
24
-
25
- it('should format numbers with different locale and default options', () => {
26
- expect(format(integer, { locale: 'de-DE' })).toBe('123.456.789')
27
- expect(format(float, { locale: 'de-DE' })).toBe('123.456,789')
28
- })
29
-
30
- it('should format dates with different locale and default options', () => {
31
- expect(format(date, { locale: 'de-DE' })).toBe('9. Juni 2012 um 22:45:30')
32
- })
33
-
34
- it('should format string as numbers if told so', () => {
35
- expect(
36
- format('123456789', { locale: 'de-DE', number: true })
37
- ).toBe('123.456.789')
38
- })
39
-
40
- it('should format numbers as dates if told so', () => {
41
- expect(
42
- format(integer, { locale: 'de-DE', date: false, time: true })
43
- ).toBe('11:17:36')
44
- expect(
45
- format(integer, { locale: 'de-DE', date: true, time: false })
46
- ).toBe('2. Januar 1970')
47
- expect(
48
- format(integer, { locale: 'de-DE', date: true, time: true })
49
- ).toBe('2. Januar 1970 um 11:17:36')
50
- })
51
-
52
- it('should omit time when `options.date = true`', () => {
53
- expect(
54
- format(date, { locale: 'de-DE', date: true })
55
- ).toBe('9. Juni 2012')
56
- })
57
-
58
- it('should omit date when `options.time = true`', () => {
59
- expect(
60
- format(date, { locale: 'de-DE', time: true })
61
- ).toBe('22:45:30')
62
- })
63
-
64
- it('should omit time when `options.time = false`', () => {
65
- expect(
66
- format(date, { locale: 'de-DE', time: false })
67
- ).toBe('9. Juni 2012')
68
- })
69
-
70
- it('should omit date when `options.date = false`', () => {
71
- expect(
72
- format(date, { locale: 'de-DE', date: false })
73
- ).toBe('22:45:30')
74
- })
75
-
76
- it(`should return an empty string when \`options.date = false\` and \`options.time = false\``, () => {
77
- expect(
78
- format(date, { locale: 'de-DE', date: false, time: false })
79
- ).toBe('')
80
- })
81
-
82
- it('should support fine-grained control of `options.number`', () => {
83
- expect(
84
- format(integer, {
85
- locale: 'de-DE',
86
- number: {
87
- style: 'currency',
88
- currency: 'EUR'
89
- }
90
- })
91
- ).toMatch(/^123\.456\.789,00\s€$/)
92
- expect(
93
- format(integer, {
94
- locale: 'de-CH',
95
- number: {
96
- style: 'currency',
97
- currency: 'CHF'
98
- }
99
- })
100
- ).toMatch(/^CHF\s123['\u2019]456['\u2019]789\.00$/)
101
- expect(
102
- format(float, {
103
- locale: 'de-DE',
104
- number: {
105
- style: 'currency',
106
- currency: 'EUR'
107
- }
108
- })
109
- ).toMatch(/^123\.456,79\s€$/)
110
- expect(
111
- format(float, {
112
- locale: 'de-CH',
113
- number: {
114
- style: 'currency',
115
- currency: 'CHF'
116
- }
117
- })
118
- ).toMatch(/^CHF\s123['\u2019]456\.79$/)
119
- })
120
-
121
- it('should support fine-grained control of `options.date`', () => {
122
- expect(
123
- format(date, {
124
- locale: 'de-DE',
125
- date: {
126
- month: 'short',
127
- day: false
128
- },
129
- time: false
130
- })
131
- ).toBe('Juni 2012')
132
- expect(
133
- format(date, {
134
- locale: 'de-DE',
135
- date: {
136
- year: false,
137
- day: '2-digit'
138
- },
139
- time: false
140
- })
141
- ).toBe('09. Juni')
142
- })
143
-
144
- it('should support custom `options.number.format()` overrides', () => {
145
- expect(
146
- format(integer, {
147
- locale: 'en-GB',
148
- number: {
149
- style: 'currency',
150
- currency: 'GBP',
151
- format: (value, type) =>
152
- type === 'group'
153
- ? `’`
154
- : type === 'decimal'
155
- ? ','
156
- : undefined
157
- }
158
- })
159
- ).toBe(`£123’456’789,00`)
160
- })
161
-
162
- it(`should support custom \`options.date.format()\` and \`options.time.format()\` overrides`, () => {
163
- expect(
164
- format(date, {
165
- locale: 'en-GB',
166
- date: {
167
- day: 'numeric',
168
- month: 'numeric',
169
- year: 'numeric',
170
- format: (value, type, options) =>
171
- type === 'literal' && options.month === 'numeric'
172
- ? value.replace(/\//, '.').replace(/,/, '')
173
- : undefined
174
- },
175
- time: {
176
- hour: '2-digit',
177
- minute: '2-digit',
178
- second: '2-digit',
179
- format: value => value.replace(/:/, '_')
180
- }
181
- })
182
- ).toBe('09.06.2012 22_45_30')
183
- })
184
-
185
- it('should handle string values', () => {
186
- expect(
187
- format('2016-05-24T15:54:14.876Z', { date: true })
188
- ).toBe('May 24, 2016')
189
- expect(
190
- format('2016-05-24T15:54:14.876Z', { date: true, time: true })
191
- ).toMatch(/^May 24, 2016 at 05:54:14\sPM$/)
192
- expect(format('123456789', { number: true })).toBe('123,456,789')
193
- expect(format('123456.789', { number: true })).toBe('123,456.789')
194
- expect(format('Hello World')).toBe('Hello World')
195
- })
196
- })
@@ -1,28 +0,0 @@
1
- import { formatDate } from './formatDate.js'
2
-
3
- describe('formatDate()', () => {
4
- const date = new Date(2012, 5, 9, 22, 45, 30)
5
-
6
- it('should not format null', () => {
7
- expect(formatDate(null, { locale: 'de-DE' })).toBe(null)
8
- })
9
-
10
- it('should use the en-US locale by default', () => {
11
- expect(formatDate(date)).toMatch(/^June 9, 2012 at 10:45:30\sPM$/)
12
- expect(formatDate(date, {})).toMatch(/^June 9, 2012 at 10:45:30\sPM$/)
13
- })
14
-
15
- it('should format dates with different locale and default options', () => {
16
- expect(formatDate(date, { locale: 'de-DE' }))
17
- .toBe('9. Juni 2012 um 22:45:30')
18
- })
19
-
20
- it('should format numbers or strings as dates', () => {
21
- expect(formatDate(0, { locale: 'de-DE' }))
22
- .toBe('1. Januar 1970 um 01:00:00')
23
- expect(formatDate(1000000000000, { locale: 'de-DE' }))
24
- .toBe('9. September 2001 um 03:46:40')
25
- expect(formatDate('04 Dec 1995 00:12:00 GMT', { locale: 'de-DE' }))
26
- .toBe('4. Dezember 1995 um 01:12:00')
27
- })
28
- })
@@ -1,13 +0,0 @@
1
- import { formatPlainDate } from './formatPlainDate.js'
2
-
3
- describe('formatPlainDate()', () => {
4
- it('should format the local plain date', () => {
5
- expect(formatPlainDate(new Date(2026, 4, 14))).toBe('2026-05-14')
6
- expect(formatPlainDate(new Date(2026, 4, 14, 23, 59))).toBe(
7
- '2026-05-14'
8
- )
9
- expect(formatPlainDate(new Date(987, 0, 1))).toBe('0987-01-01')
10
- // Local mean time, with an offset in seconds in some timezones:
11
- expect(formatPlainDate(new Date(1850, 6, 1))).toBe('1850-07-01')
12
- })
13
- })
@@ -1,23 +0,0 @@
1
- import { getCommonPrefix, getCommonOffset } from './getCommonPrefix.js'
2
-
3
- describe('getCommonPrefix()', () => {
4
- it('should return the longest common prefix', () => {
5
- expect(getCommonPrefix('interstate', 'intersection')).toBe('inters')
6
- expect(getCommonPrefix('intersection', 'interstate')).toBe('inters')
7
- })
8
- it('should compare case-sensitively', () => {
9
- expect(getCommonPrefix('interstate', 'Intersection')).toBe('')
10
- expect(getCommonPrefix('InterState', 'Intersection')).toBe('Inter')
11
- })
12
- })
13
-
14
- describe('getCommonOffset()', () => {
15
- it('should return the longest common prefix', () => {
16
- expect(getCommonOffset('interstate', 'intersection')).toBe(6)
17
- expect(getCommonOffset('intersection', 'interstate')).toBe(6)
18
- })
19
- it('should compare case-sensitively', () => {
20
- expect(getCommonOffset('interstate', 'Intersection')).toBe(0)
21
- expect(getCommonOffset('InterState', 'Intersection')).toBe(5)
22
- })
23
- })
@@ -1,15 +0,0 @@
1
- import { isAbsoluteUrl } from './isAbsoluteUrl.js'
2
-
3
- describe('isAbsoluteUrl()', () => {
4
- it('should return true for absolute URLs starting with schemas', () => {
5
- expect(isAbsoluteUrl('http://lineto.com')).toBe(true)
6
- expect(isAbsoluteUrl('https://lineto.com')).toBe(true)
7
- expect(isAbsoluteUrl('ftp://lineto.com')).toBe(true)
8
- expect(isAbsoluteUrl('file:///Users/lineto')).toBe(true)
9
- expect(isAbsoluteUrl('mailto:user@lineto.com')).toBe(true)
10
- expect(isAbsoluteUrl('//lineto.com')).toBe(true)
11
- expect(isAbsoluteUrl('/static/index.html')).toBe(false)
12
- expect(isAbsoluteUrl('../index.html')).toBe(false)
13
- expect(isAbsoluteUrl('../static//index.html')).toBe(false)
14
- })
15
- })