/
util.ts
123 lines (122 loc) · 3.36 KB
/
util.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { moduleExts } from './constants.ts'
export default {
inDeno(): boolean {
return typeof Deno !== 'undefined' && this.isNEString(Deno.version?.deno)
},
isString(a: any): a is string {
return typeof a === 'string'
},
isNEString(a: any): a is string {
return typeof a === 'string' && a.length > 0
},
isArray(a: any): a is Array<any> {
return Array.isArray(a)
},
isNEArray(a: any): a is Array<any> {
return Array.isArray(a) && a.length > 0
},
isPlainObject(a: any): a is Record<string, any> {
return typeof a === 'object' && a !== null && !this.isArray(a) && Object.getPrototypeOf(a) == Object.prototype
},
isFunction(a: any): a is Function {
return typeof a === 'function'
},
isLikelyHttpURL(s: string): boolean {
const p = s.slice(0, 8).toLowerCase()
return p === 'https://' || p.slice(0, 7) === 'http://'
},
shortHash(hash: string): string {
return hash.slice(0, 9)
},
trimPrefix(s: string, prefix: string): string {
if (prefix !== '' && s.startsWith(prefix)) {
return s.slice(prefix.length)
}
return s
},
trimSuffix(s: string, suffix: string): string {
if (suffix !== '' && s.endsWith(suffix)) {
return s.slice(0, -suffix.length)
}
return s
},
trimModuleExt(url: string) {
for (const ext of moduleExts) {
if (url.endsWith('.' + ext)) {
return url.slice(0, -(ext.length + 1))
}
}
return url
},
ensureExt(s: string, ext: string): string {
if (s.endsWith(ext)) {
return s
}
return s + ext
},
splitBy(s: string, searchString: string): [string, string] {
const i = s.indexOf(searchString)
if (i >= 0) {
return [s.slice(0, i), s.slice(i + 1)]
}
return [s, '']
},
formatBytes(bytes: number) {
if (bytes < 1 << 10) {
return bytes.toString() + 'B'
}
if (bytes < 1 << 20) {
return Math.ceil(bytes / (1 << 10)) + 'KB'
}
if (bytes < 1 << 30) {
return this.trimSuffix((bytes / (1 << 20)).toFixed(1), '.0') + 'MB'
}
if (bytes < 1 << 40) {
return this.trimSuffix((bytes / (1 << 30)).toFixed(1), '.0') + 'GB'
}
if (bytes < 1 << 50) {
return this.trimSuffix((bytes / (1 << 40)).toFixed(1), '.0') + 'TB'
}
return this.trimSuffix((bytes / (1 << 50)).toFixed(1), '.0') + 'PB'
},
splitPath(path: string): string[] {
return path
.split(/[\/\\]+/g)
.map(p => p.trim())
.filter(p => p !== '' && p !== '.')
.reduce((path, p) => {
if (p === '..') {
path.pop()
} else {
path.push(p)
}
return path
}, [] as Array<string>)
},
cleanPath(path: string): string {
return '/' + this.splitPath(path).join('/')
},
debounce<T extends Function>(callback: T, delay: number): T {
let timer: number | null = null
return ((...args: any[]) => {
if (timer != null) {
clearTimeout(timer)
}
timer = setTimeout(() => {
timer = null
callback(...args)
}, delay)
}) as any
},
debounceX(id: string, callback: () => void, delay: number) {
const self = this as any
const timers: Map<string, number> = self.__debounce_timers || (self.__debounce_timers = new Map())
if (timers.has(id)) {
clearTimeout(timers.get(id)!)
}
timers.set(id, setTimeout(() => {
timers.delete(id)
callback()
}, delay))
}
}