-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutils.ts
More file actions
99 lines (91 loc) · 2.9 KB
/
utils.ts
File metadata and controls
99 lines (91 loc) · 2.9 KB
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
import { AsyncBuffer, asyncBufferFromUrl, cachedAsyncBuffer } from 'hyparquet'
import { AsyncBufferFrom } from './workers/types.js'
/**
* Helper function to join class names
*/
export function cn(...names: (string | undefined | false)[]): string {
return names.filter((n) => n).join(' ')
}
/**
* Convert AsyncBufferFromUrl to AsyncBuffer.
*/
export function asyncBufferFrom(from: AsyncBufferFrom): Promise<AsyncBuffer> {
if ('url' in from) {
// Cached asyncBuffer for urls only
const key = JSON.stringify(from)
const cached = cache.get(key)
if (cached) return cached
const asyncBuffer = asyncBufferFromUrl(from).then(cachedAsyncBuffer)
cache.set(key, asyncBuffer)
return asyncBuffer
} else {
return from.file.arrayBuffer()
}
}
const cache = new Map<string, Promise<AsyncBuffer>>()
// TODO(SL): do we really want a singleton?
export function getFileDateShort(file?: { lastModified?: string }): string {
if (!file?.lastModified) return ''
const date = new Date(file.lastModified)
// time if within last 24 hours, date otherwise
const time = date.getTime()
const now = Date.now()
if (now - time < 86400000) {
return date.toLocaleTimeString()
}
return date.toLocaleDateString()
}
/**
* Parse date from lastModified field and format as locale string
*
* @param file file-like object with lastModified
* @param file.lastModified last modified date string
* @returns formatted date string
*/
export function getFileDate(file?: { lastModified?: string }): string {
if (!file?.lastModified) return ''
const date = new Date(file.lastModified)
return isFinite(date.getTime()) ? date.toLocaleString() : ''
}
/**
* Returns the file size in human readable format
*
* @param bytes file size in bytes
* @returns formatted file size string
*/
export function formatFileSize(bytes: number): string {
const sizes = ['b', 'kb', 'mb', 'gb', 'tb']
if (bytes === 0) return '0 b'
const i = Math.floor(Math.log2(bytes) / 10)
if (i === 0) return bytes.toLocaleString('en-US') + ' b'
const size = sizes[i]
if (size === undefined) {
throw new Error(`Size not found at index ${i}`)
}
const base = bytes / Math.pow(1024, i)
return (
(base < 10 ? base.toFixed(1) : Math.round(base)).toLocaleString('en-US') +
' ' +
size
)
}
/**
* Parse the content-length header from a fetch response.
*
* @param headers fetch response headers
* @returns content length in bytes or undefined if not found
*/
export function parseFileSize(headers: Headers): number | undefined {
const contentLength = headers.get('content-length')
return contentLength ? Number(contentLength) : undefined
}
export const contentTypes: Record<string, string> = {
png: 'image/png',
jpg: 'image/jpeg',
jpeg: 'image/jpeg',
gif: 'image/gif',
svg: 'image/svg+xml',
tiff: 'image/tiff',
webp: 'image/webp',
}
export const imageTypes = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.tiff', '.webp']