-
Notifications
You must be signed in to change notification settings - Fork 0
/
javascript.ts
58 lines (48 loc) · 1.53 KB
/
javascript.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
import { isArray, isObject, isFunction, isString, isBigInt } from '@blackglory/prelude'
import { map } from '@src/map.js'
import { dedent } from '@src/dedent.js'
export type JavaScriptValue =
| string
| number
| bigint
| boolean
| null
| undefined
| { [property: string | number]: JavaScriptValue }
| JavaScriptValue[]
| ((...args: unknown[]) => unknown)
export function javascript(
strings: TemplateStringsArray
, ...values: JavaScriptValue[]
): string {
return dedent(...map(stringifyJavaScriptValue, strings, ...values))
}
function stringifyJavaScriptValue(val: JavaScriptValue): string {
if (isString(val)) return stringifyString(val)
if (isBigInt(val)) return stringifyBigInt(val)
if (isArray(val)) return stringifyArray(val)
if (isFunction(val)) return stringifyFunction(val)
if (isObject(val)) return stringifyObject(val)
return `${val}`
}
function stringifyFunction(fn: (...args: unknown[]) => unknown): string {
return fn.toString()
}
function stringifyString(text: string): string {
return JSON.stringify(text)
}
function stringifyObject(obj: object): string {
const body = Object.entries(obj)
.map(([key, value]) => {
return `${stringifyJavaScriptValue(key)}: ${stringifyJavaScriptValue(value)}`
})
.join(',')
return '{' + body + '}'
}
function stringifyArray(arr: JavaScriptValue[]): string {
const body = arr.map(x => stringifyJavaScriptValue(x)).join(',')
return '[' + body + ']'
}
function stringifyBigInt(val: bigint): string {
return `BigInt(${stringifyJavaScriptValue(val.toString())})`
}