Server side templating engine written in JavaScript
boxwood was created to achieve the following design goals:
- templates can be split into components
- css is hashed per component
- css is automatically minified
- critical css is inlined
- templates can import other dependencies
- inline images or svgs
- i18n support
- server side
- good for seo
- small (1 file, 700 LOC~)
- easy to start, familiar syntax
- easy to test
The template starts with a standard js file, which builds a tree of nodes, that get rendered to html.
npm install boxwood
const { compile } = require("boxwood")
const { join } = require("path")
// ...
const path = join(__dirname, "index.js")
const { template } = compile(path)
// ...
const html = template({ foo: "bar" })
console.log(html)
You can use express-boxwood for express.
// example/index.js
const layout = require("./layout")
const banner = require("./banner")
module.exports = () => {
return layout({ language: "en" }, [
banner({
title: "Hello, world!",
description: "Lorem ipsum dolor sit amet",
}),
])
}
// example/layout/index.js
const { component, css, doctype, html, body } = require("boxwood")
const head = require("./head")
const styles = css.load(__dirname)
module.exports = component(
({ language }, children) => {
return [
doctype(),
html({ lang: language }, [
head(),
body({ className: styles.layout }, children),
]),
]
},
{ styles }
)
// example/layout/head/index.js
const { head, title } = require("boxwood")
module.exports = () => {
return head([title("example")])
}
// example/banner/index.js
const { component, css, h1, p, section } = require("boxwood")
const styles = css.load(__dirname)
module.exports = component(
({ title, description }) => {
return section({ className: styles.banner }, [
h1(title),
description && p(description),
])
},
{ styles }
)
// example/banner/index.test.js
const test = require("node:test")
const assert = require("node:assert")
const { compile } = require("boxwood")
test("banner renders a title", async () => {
const { template } = compile(__dirname)
const html = template({ title: "foo" })
assert(html.includes("<h1>foo</h1>"))
})
test("banner renders an optional description", async () => {
const { template } = compile(__dirname)
const html = template({ title: "foo", description: "bar" })
assert(html.includes("<h1>foo</h1>"))
assert(html.includes("<p>bar</p>"))
})
You can check the test
dir for more examples.
All contributions are highly appreciated. Please feel free to open new issues and send PRs.
MIT