-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmod.ts
79 lines (62 loc) · 1.75 KB
/
mod.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
import { parse } from "npm:[email protected]";
interface Config<T> {
querySelector?: string;
params?: T;
}
async function tseval(code: string): Promise<(params: unknown) => Promise<unknown>> {
const b64 = btoa(code);
const module = (
await import(`data:application/typescript;base64,${b64}`)
);
return module.default;
}
async function evaluateValue(item: unknown): Promise<string> {
if (!item) {
return "";
}
if (typeof item === "function") {
return evaluateValue(await item());
}
if (typeof item === "object") {
const evaluatedObject: Record<string, unknown> = {};
await Promise.all(
Object.entries(item).map(async ([key, val]) => {
evaluatedObject[key] = await evaluateValue(val);
})
);
return Object
.values(evaluatedObject)
.join('');
}
return String(item);
}
async function render<T>(code: string, config: Config<T> = {}): Promise<string> {
if (!config.querySelector) {
config.querySelector = 'deno, script[type="application/typescript"]';
}
const dom = parse(code);
const scripts = dom
.querySelectorAll(config.querySelector);
for (const script of scripts) {
try {
const init = await tseval(`
export default async function(params) {
${script.text}
}
`);
const result = await evaluateValue(
await init(config.params)
);
script.replaceWith(result);
} catch (error) {
script.replaceWith(`<!-- ${error} -->`);
}
}
return dom.toString();
}
export {
render,
}
export type {
Config
}