ITADN
mcollina/fastify-html
mcollina/fastify-html · 文件 下载 ZIP
文件最后提交记录最后更新时间
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

fastify-html

以最自然的 Fastify 方式生成 html,使用模板标签、 布局和插件系统。

模板表达式默认会被转义,除非它们以 ! 作为前缀。

安装

npm i fastify fastify-html

用法

import fastify from 'fastify'
import fastifyHtml from 'fastify-html'

const app = fastify()
await app.register(fastifyHtml)

app.addLayout(function (inner, reply) {
  return app.html`
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <script src="https://unpkg.com/htmx.org@1.9.5"></script>
      </head>
      <body>
        <!-- Prefix expressions with ! if they contain safe HTML or other html tags -->
        !${inner}
      </body>
    </html>
  `
}, { skipOnHeader: 'hx-request' })

app.get('/', async (req, reply) => {
  const name = req.query.name || 'World'
  return reply.html`<h1>Hello ${name}</h1>`
})

app.get('/complex-response/:page', async (req, reply) => {
  const name = req.query.name || 'World'
  const userInfo = await getUserInfo(name) || {}
  const demand = req.query.demand
  
  return reply.html`
      <div>
        Welcome, ${name}.
        <br /><br />

        User information:
        <br />

        !${Object.keys(userInfo).map(
          (key) => app.html`
            ${key}: <b>${userInfo[key]}</b>
            <br />
          `
        )}
        <br />

        !${
          demand
            ? app.html`
              <p>Your demand: ${demand}</p>
            `
            : ""
        }
      </div>
  `
})

await app.listen({ port: 3000 })

async function getUserInfo(name) {
  return { age: 25, location: "Earth" };
}

异步模式用法

import fastify from 'fastify'
import fastifyHtml from 'fastify-html'
import { createReadStream } from 'node:fs'

const app = fastify()
await app.register(fastifyHtml, { async: true })

app.addLayout(function (inner, reply) {
  return app.html`
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <script src="https://unpkg.com/htmx.org@1.9.5"></script>
      </head>
      <body>
        !${inner}
      </body>
    </html>
  `
}, { skipOnHeader: 'hx-request' })

app.get('/:name', async (req, reply) => {
  return reply.html`
      <div>
        Welcome, ${req.params.name}.
        <br /><br />

        User information:
        <br />

        <!-- Promises are supported and resolved automatically in async mode -->
        !${getUserInfoPromise(req.params.name)}
        <br />

        <!-- Streams and (a)sync generators are supported too -->
        <div>
          File content:
          <br />
          !${createReadStream('./path/to/file.txt')}
        </div>
      </div>
  `
})

await app.listen({ port: 3000 })

async function getUserInfoPromise(name) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ age: 25, location: "Earth" });
    }, 1000);
  });
}

插件

布局支持并遵循封装,这意味着 addLayout 调用不会暴露给父级插件,如下所示:

import fastify from 'fastify'
import fastifyHtml from 'fastify-html'

const app = fastify()
await app.register(fastifyHtml)

app.addLayout(function (inner, reply) {
  return app.html`
    <!DOCTYPE html>
    <html lang="en">
      <body>
        !${inner}
      </body>
    </html>
  `
})

app.get('/', async (req, reply) => {
  const name = req.query.name || 'World'
  strictEqual(reply.html`<h1>Hello ${name}</h1>`, reply)
  return reply
})

app.register(async function (app) {
  app.addLayout(function (inner) {
    return app.html`
      <i>
        !${inner}
      </i>
    `
  })

  app.get('/nested', async (req, reply) => {
    const name = req.query.name || 'World'
    return reply.html`<h1>Nested ${name}</h1>`
  })
})

await app.listen({ port: 3000 })

选项

  • async: 启用异步模式以处理异步模板表达式。在注册 fastify-html 插件时,将此选项设置为 true,以利用诸如 Promise 解析、流处理和异步生成器支持等功能。

许可证

MIT