-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
rend.js
149 lines (127 loc) · 4.49 KB
/
rend.js
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import { html } from './src/html.js'
import { stringify } from './src/stringify.js'
import { slot } from './src/slots.js'
import { renderBody } from './src/render.js'
export class Rend {
// options:
// - header, footer: template functions that will wrap around the content
// - prod (boolean): enable for performance enhancements such as cached templates
constructor(options = {}) {
this.options = options
// production cache of templates. default disabled. Set options.prod = true to enable.
this.templates = {}
}
// render returns a string of the rendered content
async render(bodyFunc, d) {
// console.log("render", bodyFunc)
// if single param, then it's new slotted way, so just single input
// console.log("typeof d", typeof d,d)
let d2 = d
let o = this.options
if (!d) d = {}
if (!d.__rend__) d.__rend__ = {}
if (this.options.data) {
d = { ...o.data, ...d }
}
if (o.layout) {
// new slotted style
d.__rend__.slotted = true
if (typeof d2 === 'undefined') {
// console.log("d is undefined")
d = { ...d, ...bodyFunc } // the single param is the data map
} else {
d.__default__ = bodyFunc
}
if (d.rend?.nowrap) {
return await renderBody(async () => `${await slot('', d)}`, d)
}
let b = await renderBody(o.layout, d)
return b
} else {
let b = await renderBody(bodyFunc, d)
if (d.rend?.nowrap) {
return b
}
let s = `${o.header ? o.header(d) : ''}
${b}
${o.footer ? o.footer(d) : ''}
`
return s
}
}
// these are used in your HTTP handlers to return a rend rendered response
async html(bodyFunc, d) {
return new Response(await this.render(bodyFunc, d), {
status: this.options.layout ? d?.status || bodyFunc.status || 200 : d?.status || 200,
headers: {
'Content-Type': 'text/html',
},
})
}
nowrap(d) {
d = d || {}
d.rend = d.rend ?? {}
d.rend.nowrap = true
return d
}
async text(bodyFunc, d) {
return new Response(await this.render(bodyFunc, this.nowrap(d)), {
status: this.options.layout ? d?.status || bodyFunc.status || 200 : d?.status || 200,
headers: {
'Content-Type': 'text/plain',
},
})
}
async json(bodyFunc, d) {
return new Response(await this.render(bodyFunc, this.nowrap(d)), {
status: this.options.layout ? d?.status || bodyFunc.status || 200 : d?.status || 200,
headers: {
'Content-Type': 'application/json',
},
})
}
async css(bodyFunc, d) {
return new Response(await this.render(bodyFunc, this.nowrap(d)), {
status: this.options.layout ? d?.status || bodyFunc.status || 200 : d?.status || 200,
headers: {
'Content-Type': 'text/css',
},
})
}
async js(bodyFunc, d) {
return new Response(await this.render(bodyFunc, this.nowrap(d)), {
status: this.options.layout ? d?.status || bodyFunc.status || 200 : d?.status || 200,
headers: {
'Content-Type': 'text/javascript',
},
})
}
// send
// TODO: move these into fastify folder or repo
// reply is a fastify reply object
// bodyFunc can be a function or a string path to a module that exports a render function
async send(reply, bodyFunc, d = {}, opts = {}) {
reply.header('Content-Type', 'text/html')
this.addHeaders(reply, opts)
return reply.send(await this.render(bodyFunc, d))
}
async sendCSS(reply, styles, opts = {}) {
reply.header('Content-Type', 'text/css')
this.addHeaders(reply, opts)
return reply.send(styles)
}
async sendCSSLit(reply, styles, opts = {}) {
reply.header('Content-Type', 'application/javascript')
this.addHeaders(reply, opts)
return reply.send(`import { css } from 'lit'
export const styles = css\`${styles}\``)
}
addHeaders(reply, opts) {
if (opts.headers) {
for (const h in opts.headers) {
reply.header(h, opts.headers[h])
}
}
}
}
export { html, stringify, slot }