-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathRenderer.ts
More file actions
34 lines (33 loc) · 1.1 KB
/
Renderer.ts
File metadata and controls
34 lines (33 loc) · 1.1 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
import { dom } from "@typeup/dom"
export type RenderFunction<N extends dom.Node = dom.Node> = (renderer: Renderer, node: N) => Promise<string>
export class Renderer {
private constructor(private variables: { [name: string]: string } = {}) {}
get(name: string): string | undefined {
return this.variables[name]
}
set(name: string, value: string) {
this.variables[name] = value
}
async render(node: dom.Node | dom.Node[]): Promise<string> {
let result: string
if (Array.isArray(node))
result = (await Promise.all(node.map(n => this.render(n))))
.reduce<string[]>((r, e) => (Array.isArray(e) ? [...r, ...e] : [...r, e]), [])
.join("")
else {
const render = renderers[node.class]
result = render ? await render(this, node) : ""
}
return result
}
scope(): Renderer {
return new Renderer({ ...this.variables })
}
static create(): Renderer {
return new Renderer({})
}
}
const renderers: { [className: string]: RenderFunction } = {}
export function register<N extends dom.Node = dom.Node>(className: string, render: RenderFunction<N>) {
renderers[className] = render as RenderFunction
}