fastify-html
Version:
Generate html in the most natural Fastify way, using template tags, layouts and the plugin system.
46 lines (38 loc) • 1.35 kB
JavaScript
import fp from 'fastify-plugin'
import { html, htmlAsyncGenerator } from 'ghtml'
import { Readable } from 'node:stream'
const kLayout = Symbol('fastifyHtmlLayout')
export default fp(async (fastify, opts) => {
fastify.decorate('html', opts.async ? htmlAsyncGenerator : html)
fastify.decorate(kLayout, null)
fastify.decorate('addLayout', function (render, { skipOnHeader } = {}) {
// Using a symbol attached to `this` and a stack allows us to
// support nested layouts with encapsulated plugins.
const layout = {
render,
parent: this[kLayout],
skipOnHeader
}
this[kLayout] = layout
})
fastify.decorateReply('html', function (strings, ...values) {
let htmlString = fastify.html(strings, ...values)
let layout = this.server[kLayout]
// render each layout in the stack
// using a while loop instead of recursion
// to avoid stack overflows and reduce memory usage
while (layout) {
if (layout.skipOnHeader && this.request.headers[layout.skipOnHeader]) {
layout = layout.parent
continue
}
htmlString = layout.render(htmlString, this)
layout = layout.parent
}
this.header('Content-Type', 'text/html; charset=utf-8')
this.send(opts.async ? Readable.from(htmlString) : htmlString)
return this
})
}, {
name: 'fastify-html'
})