Compile your jade templates into Virtual DOM functions. Works with multiple Virtual DOM libraries, including:
For people who like declarative reactive templating, but don't like writing HTML or JSX.
Create a template:
.items
each item in items
.item(
class={active: item.active}
data-id=item.id
)
.item-title= item.title
.item-description= item.description
require()
your template as a function
and use a rendering system like main-loop:
const mainLoop = require('main-loop');
const template = require('./items.jade');
const initState = {
items: [],
};
const loop = mainLoop(initState, template, {
create: require("virtual-dom/create-element"),
diff: require("virtual-dom/diff"),
patch: require("virtual-dom/patch"),
});
document.body.appendChild(loop.target);
Then update whenever you'd like!
loop.update({
items: [
{
id: 'asdf',
title: 'some title',
description: 'some description',
active: false,
},
],
});
- For easy configuration with Webpack, use virtual-jade-loader.
- To translate with Babel, use babel-plugin-virtual-jade.
- Can be used with any CommonJS environment with client-side
require()
s. - All templates must return a single root element.
- Requires you to install the appropriate virtual-dom library in your top-level app.
str
is the jade source as a string.
fnStr
is output JS that you should include as a CommonJS module.
Options are:
filename
: path and name of Jade source file forstr
. Required if you useinclude
orextends
in templates.marshalDataset=true
: whether to convertdata-
attributes todataset
members. Set to false to treat as props with the same name as the attributes (if your target Virtual DOM renderer does not support thedataset
API).pretty=false
: whether to beautify the resulting JS. Requires you to installjs-beautify
yourself.propsWrapper
: optional object to wrap Jade attributes in; for example, withpropsWrapper = 'props'
, the templatediv(foo="bar")
will translate to something likeh('div', {props: {foo: 'bar'}})
rather thanh('div', {foo: 'bar'})
rawProps
: whether to skip Jade attribute -> HTML property conversion; this is set to true in the default Snabbdom configurationserializeAttrsObjects
: special behavior for the Snabbdom-styleattrs
attribute object. If true, object values within anattrs
attribute will be automatically stringified (since HTML element attributes are always strings); for example, indiv(attrs={foo: {hello: 'world'}})
thefoo
attr will end up in HTML as"{"hello":"world"}"
(rather than"[object Object]"
).runtime
: optional override to include any arbitrary Virtual DOM library that defines theh()
hyperscript function. E.g.var h = require('my-special-lib/h');
vdom
: name of the Virtual DOM library configuration to load (currently eithervirtual-dom
orsnabbdom
).
Returns a string that looks like:
function render(locals) {
var result_of_with = /* stuff */
if (result_of_with) return result_of_with.value;;
}
You are expected to eval()
the string if you want the source as a function.
Otherwise, just create a module in the following format:
const js = `module.exports = ${fnStr}`;
Within code blocks in your template code, you can access Jade mixin functions via the $mixins
variable.
In virtual-jade, mixins boil down to functions that take arguments and return a tree of h(name, attrs, children)
.
They are like React stateless components.
Accessing them via $mixins
is useful for special cases where you want to pass around handles to blocks of Jade code as callback functions (see example below).
mixin item(x)
.item
.more-tree= x + 1
list-virtual-scroll(props={itemRenderer: $mixins.item})
// in list-virtual-scroll.jade
each val in allItems.slice(startIdx, endIdx)
= props.itemRenderer(val)
- Install deps:
npm install
- Run tests:
npm test
- Run linter:
npm run lint
- Generate coverage report:
npm run test-cov
- Run all the verifications together:
npm run test-ci
- Run tests with verbose debugging output (compiled functions as well as rendered HTML):
DEBUG=test npm test