@heliosgraphics/utils 6.0.0-alpha.10 → 6.0.0-alpha.13
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/classnames.ts +35 -12
- package/clipboard.ts +7 -3
- package/colors.ts +14 -7
- package/debounce.ts +21 -7
- package/equals.ts +22 -42
- package/index.ts +1 -1
- package/package.json +22 -4
- package/sanitize.ts +1 -1
- package/strings.ts +1 -1
- package/throttle.ts +16 -5
- package/uuid.ts +6 -7
- package/validations.ts +1 -1
- package/classnames.spec.ts +0 -17
- package/clipboard.spec.ts +0 -40
- package/colors.spec.ts +0 -40
- package/debounce.spec.ts +0 -101
- package/equals.spec.ts +0 -168
- package/sanitize.spec.ts +0 -558
- package/sleep.spec.ts +0 -59
- package/slug.spec.ts +0 -15
- package/strings.spec.ts +0 -77
- package/throttle.spec.ts +0 -142
- package/tsconfig.json +0 -40
- package/uuid.spec.ts +0 -32
- package/validations.spec.ts +0 -26
package/strings.spec.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { it, describe, expect } from "vitest"
|
|
2
|
-
import { removeMarkdown, removeNewlines, ellipsis } from "./strings"
|
|
3
|
-
|
|
4
|
-
describe("strings", () => {
|
|
5
|
-
describe("removeMarkdown", () => {
|
|
6
|
-
it("removes a bold format", () => expect(removeMarkdown("a **bold** text")).toEqual("a bold text"))
|
|
7
|
-
it("removes a link but keeps the name", () =>
|
|
8
|
-
expect(removeMarkdown("a [link](https://x.com) hello")).toEqual("a link hello"))
|
|
9
|
-
it("removes a bold link", () =>
|
|
10
|
-
expect(removeMarkdown("a [bold **link**](https://x.com) hello")).toEqual("a bold link hello"))
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
describe("removeNewlines", () => {
|
|
14
|
-
it("removes no newline", () => expect(removeNewlines("first line same line")).toEqual("first line same line"))
|
|
15
|
-
it("removes newline", () =>
|
|
16
|
-
expect(removeNewlines("first line\n\n\nsecond line\n")).toEqual("first line second line"))
|
|
17
|
-
it("removes r newline", () =>
|
|
18
|
-
expect(removeNewlines("first line\r\n\nsecond line\n")).toEqual("first line second line"))
|
|
19
|
-
it("removes t newline", () => expect(removeNewlines("first line\tsecond line\n")).toEqual("first line second line"))
|
|
20
|
-
it("removes only a newline", () => expect(removeNewlines("\r")).toEqual(""))
|
|
21
|
-
it("removes nothing without newline", () => expect(removeNewlines("hey", undefined)).toEqual("hey"))
|
|
22
|
-
it("cuts string at the right position", () => expect(removeNewlines("ellipsis", 5)).toEqual("ellip"))
|
|
23
|
-
it("skips cutting if unnecessary", () => expect(removeNewlines("ellipsis", 20)).toEqual("ellipsis"))
|
|
24
|
-
it("returns empty string for null", () => expect(removeNewlines(null, 10)).toEqual(""))
|
|
25
|
-
it("returns empty string for undefined", () => expect(removeNewlines(undefined)).toEqual(""))
|
|
26
|
-
it("returns empty string for empty string", () => expect(removeNewlines("", 10)).toEqual(""))
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
describe("ellipsis", () => {
|
|
30
|
-
describe("end position (default)", () => {
|
|
31
|
-
it("truncates text at end with ellipsis", () => expect(ellipsis("Hello World", 8)).toEqual("Hello..."))
|
|
32
|
-
it("truncates longer text at end", () =>
|
|
33
|
-
expect(ellipsis("Lorem ipsum dolor sit amet", 15)).toEqual("Lorem ipsum ..."))
|
|
34
|
-
it("returns original text if shorter than max length", () => expect(ellipsis("Short", 10)).toEqual("Short"))
|
|
35
|
-
it("returns original text if equal to max length", () => expect(ellipsis("Exactly10!", 10)).toEqual("Exactly10!"))
|
|
36
|
-
it("handles single character with end position", () => expect(ellipsis("A", 5)).toEqual("A"))
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
describe("middle position", () => {
|
|
40
|
-
it("truncates text in middle with ellipsis", () =>
|
|
41
|
-
expect(ellipsis("Hello World", 8, "middle")).toEqual("He...rld"))
|
|
42
|
-
it("truncates longer text in middle", () =>
|
|
43
|
-
expect(ellipsis("Lorem ipsum dolor sit amet", 15, "middle")).toEqual("Lorem ...t amet"))
|
|
44
|
-
it("returns original text if shorter than max length", () =>
|
|
45
|
-
expect(ellipsis("Short", 10, "middle")).toEqual("Short"))
|
|
46
|
-
it("returns original text if equal to max length", () =>
|
|
47
|
-
expect(ellipsis("Exactly10!", 10, "middle")).toEqual("Exactly10!"))
|
|
48
|
-
it("handles odd length correctly", () => expect(ellipsis("Hello World", 7, "middle")).toEqual("He...ld"))
|
|
49
|
-
it("handles even length correctly", () => expect(ellipsis("Hello World", 8, "middle")).toEqual("He...rld"))
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
describe("edge cases", () => {
|
|
53
|
-
it("returns empty string for empty input", () => expect(ellipsis("", 5)).toEqual(""))
|
|
54
|
-
it("returns empty string for null input", () => expect(ellipsis(null as unknown as string, 5)).toEqual(""))
|
|
55
|
-
it("returns empty string for undefined input", () =>
|
|
56
|
-
expect(ellipsis(undefined as unknown as string, 5)).toEqual(""))
|
|
57
|
-
it("handles very small max length with end position", () => expect(ellipsis("Hello", 3)).toEqual(""))
|
|
58
|
-
it("handles very small max length with middle position", () => expect(ellipsis("Hello", 3, "middle")).toEqual(""))
|
|
59
|
-
it("handles max length of 4 with end position", () => expect(ellipsis("Hello", 4)).toEqual("H..."))
|
|
60
|
-
it("handles max length of 4 with middle position", () => expect(ellipsis("Hello", 4, "middle")).toEqual("...o"))
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
describe("emoji handling", () => {
|
|
64
|
-
it("truncates text with emojis at end", () => expect(ellipsis("Hello 👋 World 🌍", 12)).toEqual("Hello 👋 ..."))
|
|
65
|
-
it("truncates text with emojis in middle", () =>
|
|
66
|
-
expect(ellipsis("Hello 👋 World 🌍", 12, "middle")).toEqual("Hell...ld 🌍"))
|
|
67
|
-
it("preserves emojis when text is shorter than max length", () => expect(ellipsis("Hi 👋", 10)).toEqual("Hi 👋"))
|
|
68
|
-
it("handles text with basic emojis", () => expect(ellipsis("Hello world 😊", 10)).toEqual("Hello w..."))
|
|
69
|
-
it("demonstrates emoji splitting limitation", () => {
|
|
70
|
-
// Note: This function works with UTF-16 code units, not visual characters
|
|
71
|
-
// Complex emojis may be split incorrectly at boundaries
|
|
72
|
-
const result = ellipsis("👨💻 Work", 8)
|
|
73
|
-
expect(result.length).toBeLessThanOrEqual(8)
|
|
74
|
-
})
|
|
75
|
-
})
|
|
76
|
-
})
|
|
77
|
-
})
|
package/throttle.spec.ts
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from "vitest"
|
|
2
|
-
import { throttle } from "./throttle"
|
|
3
|
-
import { sleep } from "./sleep"
|
|
4
|
-
|
|
5
|
-
describe("throttle", () => {
|
|
6
|
-
it("executes callback once within throttle window", async () => {
|
|
7
|
-
const fn = vi.fn()
|
|
8
|
-
const throttled = throttle(fn, 50)
|
|
9
|
-
|
|
10
|
-
throttled()
|
|
11
|
-
expect(fn).toHaveBeenCalledTimes(1)
|
|
12
|
-
|
|
13
|
-
throttled()
|
|
14
|
-
throttled()
|
|
15
|
-
expect(fn).toHaveBeenCalledTimes(1)
|
|
16
|
-
|
|
17
|
-
await sleep(60)
|
|
18
|
-
throttled()
|
|
19
|
-
expect(fn).toHaveBeenCalledTimes(2)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
it("executes immediately on first call", () => {
|
|
23
|
-
const fn = vi.fn()
|
|
24
|
-
const throttled = throttle(fn, 50)
|
|
25
|
-
|
|
26
|
-
throttled()
|
|
27
|
-
expect(fn).toHaveBeenCalledTimes(1)
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it("preserves function arguments on first call", () => {
|
|
31
|
-
const fn = vi.fn()
|
|
32
|
-
const throttled = throttle(fn, 50)
|
|
33
|
-
|
|
34
|
-
throttled("arg1", "arg2", 123)
|
|
35
|
-
expect(fn).toHaveBeenCalledWith("arg1", "arg2", 123)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it("ignores subsequent calls within throttle window", () => {
|
|
39
|
-
const fn = vi.fn()
|
|
40
|
-
const throttled = throttle(fn, 50)
|
|
41
|
-
|
|
42
|
-
throttled("first")
|
|
43
|
-
expect(fn).toHaveBeenCalledWith("first")
|
|
44
|
-
|
|
45
|
-
throttled("second")
|
|
46
|
-
throttled("third")
|
|
47
|
-
expect(fn).toHaveBeenCalledTimes(1)
|
|
48
|
-
expect(fn).toHaveBeenCalledWith("first")
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it("allows execution after throttle window expires", async () => {
|
|
52
|
-
const fn = vi.fn()
|
|
53
|
-
const throttled = throttle(fn, 50)
|
|
54
|
-
|
|
55
|
-
throttled("first")
|
|
56
|
-
expect(fn).toHaveBeenCalledTimes(1)
|
|
57
|
-
|
|
58
|
-
await sleep(60)
|
|
59
|
-
|
|
60
|
-
throttled("second")
|
|
61
|
-
expect(fn).toHaveBeenCalledTimes(2)
|
|
62
|
-
expect(fn).toHaveBeenLastCalledWith("second")
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it("works with functions that have specific parameter types", () => {
|
|
66
|
-
const fn = vi.fn((str: string, num: number) => str + num)
|
|
67
|
-
const throttled = throttle(fn, 50)
|
|
68
|
-
|
|
69
|
-
throttled("test", 42)
|
|
70
|
-
expect(fn).toHaveBeenCalledWith("test", 42)
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
it("works with functions that return values", () => {
|
|
74
|
-
const fn = vi.fn((x: number) => x * 2)
|
|
75
|
-
const throttled = throttle(fn, 50)
|
|
76
|
-
|
|
77
|
-
throttled(5)
|
|
78
|
-
expect(fn).toHaveBeenCalledWith(5)
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
it("handles rapid successive calls correctly", () => {
|
|
82
|
-
const fn = vi.fn()
|
|
83
|
-
const throttled = throttle(fn, 50)
|
|
84
|
-
|
|
85
|
-
for (let i = 0; i < 10; i++) {
|
|
86
|
-
throttled(i)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
expect(fn).toHaveBeenCalledTimes(1)
|
|
90
|
-
expect(fn).toHaveBeenCalledWith(0)
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
it("works with zero delay", async () => {
|
|
94
|
-
const fn = vi.fn()
|
|
95
|
-
const throttled = throttle(fn, 0)
|
|
96
|
-
|
|
97
|
-
throttled()
|
|
98
|
-
expect(fn).toHaveBeenCalledTimes(1)
|
|
99
|
-
|
|
100
|
-
await sleep(1)
|
|
101
|
-
throttled()
|
|
102
|
-
expect(fn).toHaveBeenCalledTimes(2)
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it("maintains separate throttle windows for different throttled functions", () => {
|
|
106
|
-
const fn1 = vi.fn()
|
|
107
|
-
const fn2 = vi.fn()
|
|
108
|
-
const throttled1 = throttle(fn1, 50)
|
|
109
|
-
const throttled2 = throttle(fn2, 50)
|
|
110
|
-
|
|
111
|
-
throttled1()
|
|
112
|
-
throttled2()
|
|
113
|
-
|
|
114
|
-
expect(fn1).toHaveBeenCalledTimes(1)
|
|
115
|
-
expect(fn2).toHaveBeenCalledTimes(1)
|
|
116
|
-
|
|
117
|
-
throttled1()
|
|
118
|
-
throttled2()
|
|
119
|
-
|
|
120
|
-
expect(fn1).toHaveBeenCalledTimes(1)
|
|
121
|
-
expect(fn2).toHaveBeenCalledTimes(1)
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it("resets throttle window correctly", async () => {
|
|
125
|
-
const fn = vi.fn()
|
|
126
|
-
const throttled = throttle(fn, 50)
|
|
127
|
-
|
|
128
|
-
throttled()
|
|
129
|
-
expect(fn).toHaveBeenCalledTimes(1)
|
|
130
|
-
|
|
131
|
-
await sleep(25)
|
|
132
|
-
throttled()
|
|
133
|
-
expect(fn).toHaveBeenCalledTimes(1)
|
|
134
|
-
|
|
135
|
-
await sleep(30)
|
|
136
|
-
throttled()
|
|
137
|
-
expect(fn).toHaveBeenCalledTimes(2)
|
|
138
|
-
|
|
139
|
-
throttled()
|
|
140
|
-
expect(fn).toHaveBeenCalledTimes(2)
|
|
141
|
-
})
|
|
142
|
-
})
|
package/tsconfig.json
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"allowJs": false,
|
|
4
|
-
"baseUrl": ".",
|
|
5
|
-
"esModuleInterop": true,
|
|
6
|
-
"forceConsistentCasingInFileNames": true,
|
|
7
|
-
"incremental": true,
|
|
8
|
-
"isolatedModules": true,
|
|
9
|
-
"jsx": "preserve",
|
|
10
|
-
"lib": ["dom", "dom.iterable", "esnext"],
|
|
11
|
-
"module": "esnext",
|
|
12
|
-
"moduleResolution": "bundler",
|
|
13
|
-
"noEmit": true,
|
|
14
|
-
"noFallthroughCasesInSwitch": true,
|
|
15
|
-
"noImplicitAny": true,
|
|
16
|
-
"noImplicitOverride": true,
|
|
17
|
-
"noImplicitReturns": true,
|
|
18
|
-
"noImplicitThis": true,
|
|
19
|
-
"noPropertyAccessFromIndexSignature": true,
|
|
20
|
-
"noUncheckedIndexedAccess": true,
|
|
21
|
-
"noUnusedLocals": true,
|
|
22
|
-
"noUnusedParameters": true,
|
|
23
|
-
"exactOptionalPropertyTypes": true,
|
|
24
|
-
"resolveJsonModule": true,
|
|
25
|
-
"skipLibCheck": true,
|
|
26
|
-
"sourceMap": true,
|
|
27
|
-
"strict": true,
|
|
28
|
-
"strictBindCallApply": true,
|
|
29
|
-
"strictFunctionTypes": true,
|
|
30
|
-
"strictNullChecks": true,
|
|
31
|
-
"strictPropertyInitialization": true,
|
|
32
|
-
"target": "ES2022",
|
|
33
|
-
"useDefineForClassFields": true,
|
|
34
|
-
"verbatimModuleSyntax": false,
|
|
35
|
-
"types": ["node"]
|
|
36
|
-
},
|
|
37
|
-
"typeRoots": ["./node_modules/@types", "./types"],
|
|
38
|
-
"include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"],
|
|
39
|
-
"exclude": ["node_modules"]
|
|
40
|
-
}
|
package/uuid.spec.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { it, describe, expect } from "vitest"
|
|
2
|
-
import { getUUID, isUUID } from "./uuid"
|
|
3
|
-
|
|
4
|
-
describe("validations", () => {
|
|
5
|
-
describe("getUUID", () => {
|
|
6
|
-
const UUID_1 = getUUID()
|
|
7
|
-
const UUID_1_IS_VALID = isUUID(UUID_1)
|
|
8
|
-
const UUID_2_STRING = "any-string"
|
|
9
|
-
const UUID_2 = getUUID(UUID_2_STRING)
|
|
10
|
-
const UUID_3 = getUUID()
|
|
11
|
-
const UUID_4 = getUUID()
|
|
12
|
-
|
|
13
|
-
it("returns a valid uuid", () => expect(UUID_1_IS_VALID).toEqual(true))
|
|
14
|
-
it("returns passed through", () => expect(UUID_2).toEqual(UUID_2_STRING))
|
|
15
|
-
it("returns different uuids on separate calls", () => expect(UUID_3).not.toEqual(UUID_4))
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
describe("isUUID", () => {
|
|
19
|
-
const UUID_3 = getUUID()
|
|
20
|
-
const UUID_3_IS_VALID = isUUID(UUID_3)
|
|
21
|
-
const UUID_4_IS_VALID = isUUID("101bfe56-8c16-4f94-9b45-759ea5e67cea")
|
|
22
|
-
|
|
23
|
-
it("validates a random uuid", () => expect(UUID_3_IS_VALID).toEqual(true))
|
|
24
|
-
it("validates a static uuid", () => expect(UUID_4_IS_VALID).toEqual(true))
|
|
25
|
-
|
|
26
|
-
const UUID_5_IS_VALID = isUUID("")
|
|
27
|
-
const UUID_6_IS_VALID = isUUID(undefined)
|
|
28
|
-
|
|
29
|
-
it("catches empty string", () => expect(UUID_5_IS_VALID).toEqual(false))
|
|
30
|
-
it("catches undefined", () => expect(UUID_6_IS_VALID).toEqual(false))
|
|
31
|
-
})
|
|
32
|
-
})
|
package/validations.spec.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { validateUrl, validateEmail } from "./validations"
|
|
2
|
-
import { it, describe, expect } from "vitest"
|
|
3
|
-
|
|
4
|
-
describe("validations", () => {
|
|
5
|
-
describe("validateEmail", () => {
|
|
6
|
-
it("validates email", () => expect(validateEmail("x@x.com")).toEqual(true))
|
|
7
|
-
it("validates email with +", () => expect(validateEmail("x+x@x.com")).toEqual(true))
|
|
8
|
-
it("validates email with long tld", () => expect(validateEmail("0@helios.graphics")).toEqual(true))
|
|
9
|
-
it("catches long invalid string", () => expect(validateEmail("@space.city")).toEqual(false))
|
|
10
|
-
it("catches empty string", () => expect(validateEmail("")).toEqual(false))
|
|
11
|
-
it("catches undefined", () => expect(validateEmail(undefined)).toEqual(false))
|
|
12
|
-
it("catches multi @", () => expect(validateEmail("x@@x.com")).toEqual(false))
|
|
13
|
-
it("catches a weird one", () => expect(validateEmail("x@@@x.com@/@x.com")).toEqual(false))
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
describe("validateHttpUrl", () => {
|
|
17
|
-
it("validates url", () => expect(validateUrl("https://x.com")).toEqual(true))
|
|
18
|
-
it("validates url with long tld", () => expect(validateUrl("https://lorem-ipsum.graphics")).toEqual(true))
|
|
19
|
-
it("validates url with double subdomain", () => expect(validateUrl("https://0.x.x.com")).toEqual(true))
|
|
20
|
-
it("catches ftp", () => expect(validateUrl("ftp://x.com")).toEqual(false))
|
|
21
|
-
it("catches string containing url", () => expect(validateUrl("lorem ipsum https://x.com")).toEqual(false))
|
|
22
|
-
it("catches unsafe http", () => expect(validateUrl("http://x.com")).toEqual(false))
|
|
23
|
-
it("catches empty string", () => expect(validateUrl("")).toEqual(false))
|
|
24
|
-
it("catches undefined", () => expect(validateUrl(undefined)).toEqual(false))
|
|
25
|
-
})
|
|
26
|
-
})
|