npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vdt.js

v0.3.2

Published

A template engine based on virtual-dom

Downloads

64

Readme

Vdt.js

vdt is short for virtual-dom template

Vdt.js is a template engine based on virtual-dom technology. It is inspired by React/virtual-dom, and uses JSX as template syntax.

See TodoMVC implemented by Vdt.js

Features

  • Just the ui. Just the template further more. But more powerful than common template.
  • Virtual-dom. Diff update unlike Handlebars/mustache.js.
  • Lightweight. Rewrite a compiler instead of jstransform. Discard ES6 syntax sugar and JS analysis, so it's faster.
  • Template can be extended. <t:parent> <b:section>
  • Easy to use. You can use it with any other js library, such as jQuery. See vdt-todomvc

Install

npm install vdt.js --save

Example

demo

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>vdt template engine demo</title>
</head>
<body>
<script type="text/vdt" id="template">
    var a = 1, // this is a
        showInfo = function(index, name) {
            alert('Click ' + index + ' ' + name);
        }
    <div class="users">
        <input id="add" value={input} /> input: {input}
        <ul>
            {/* output users */}
            {users.map(function(user, index) {
                return <li class="user" id={user.id} ev-click={
                    // use es5's bind or underscore's bind to pass arguments
                    showInfo.bind(null, index, user.name)
                    // or closure
                    /*function() {
                        showInfo(index, user.name);
                    }*/
                }>{index}: {user.name}</li>
            })}
        </ul>
        {/* custom attributes */}
        <div attributes={{'data-a': a, input: input}} id={a} ev-dblclick={function() {console.log('Dblclick')}}>this is a({a})</div>
    </div>
</script>
<script type="text/javascript" src="../dist/vdt.js"></script>
<script type="text/javascript">
    var data = {
        users: [
            {name: 'John', id: '1'},
            {name: 'Javey', id: '2'},
            {name: 'Tom', id: '3'},
            {name: 'Sarah', id: '4'}
        ],
        input: ''
    };

    var str = document.getElementById('template').innerHTML,
        vdt = Vdt(str),
        dom = vdt.render(data);

    document.body.appendChild(dom);

    var input = document.getElementById('add');
    input.addEventListener('input', function(e) {
        data.input = e.target.value;
        vdt.update(data);
    });
    input.addEventListener('change', function(e) {
        data.users.push({name: e.target.value, id: data.users.length});
        data.input = '';
        vdt.update(data);
    });
</script>
</body>
</html>

Custom attributes

See vnode.md

You can write template like this to render custom attributes directly.

<div attributes={{'data-a': a, input: input}} id={a}>this is a({a})</div>

Notice

  1. ~~Use className instead of class in html.~~

  2. ~~All html tags must be closed. e.g. <input />.~~

  3. Use {/* comment */} instead of <!-- comment -->. It is just Javascript comment which is wrapped by {}.

  4. The last html element will be returned. You must wrap all html in a element. e.g.

    <div>
        <h1>title</h1>
        <div>body</div>
    </div>

    instead of

    <h1>title</h1>
    <div>body</div>

    The second one will return only one element <div>body</body>.

Express middleware

Take vdt as a express middleware.

app.use(require('vdt.js').middleware({
    src: 'vdt/src/path',
    amd: true, // and amd wrapper
    force: false, // force compile
    autoReturn: true // see api of `Vdt` below
}));

Escape & Unescape

Any output will be escaped. If you want prevent it, you can do it likes below:

var a = '<h1>title</h1>';
<div>{a}</div> // a will be escaped, -> <div>&lt;h1&gt;title&lt;/h1&gt;</div>
<div innerHTML={a}></div> // a will not be escaped -> <div><h1>title</h1></div>

Event

You can bind event in vdt template directly by adding ev-event property, likes below:

<ul>
    {/* output users */}
    {users.map(function(user, index) {
        return <li className="user" id={user.id} ev-click={
            // use es5's bind or underscore's bind to pass arguments
            showInfo.bind(null, index, user.name)
            // or closure
            /*function() {
                showInfo(index, user.name);
            }*/
        }>{index}: {user.name}</li>
    })}
</ul>

Template Extend

Vdt template can be extended. Use <t:templateFunction> and <b:block> directive.

Use <t:templateFunction> to extend the parent template function. templateFunction is a function of parent template.

Use <t:block> to set block which can be filled by child.

Use parent() to get parent content.

<script type="text/vdt" id="parent">
    <div className="card">
        <div className="head">{title}</div>
        <b:body>
            <div>parent body</div>
        </b:body>
        <b:footer>
            <div>parent footer</div>
        </b:footer>
    </div>
</script>
<script type="text/vdt" id="child">
    // You can also compile it in node, then require it by require.js
    var parent = Vdt.compile(document.getElementById('parent').innerHTML);
    <t:parent title="child card title">
        <b:body>
            <div>child body</div>
        </b:body>
        <b:footer>
            {parent()}
            <div>child footer</div>
        </b:footer>
    </t:parent>
</script>

Api

Vdt(source, [options])

Compile source then return a vdt object.

  • @param source {String|Function} JSX template source or a template function returned by Vdt.compile
  • @param options.autoReturn=true {Object|Boolean} If add return keyword at end or not. The last element of template have to be a html tag element if is true.
  • @return {Object} a vdt object

Vdt.compile(source, [options])

Compile JSX template source then return a template function which should pass to Vdt.

The returned function has a property named source. You can use it to pre-process JSX.

  • @param source {String} JSX template source
  • @param options.autoReturn=true {Object|Boolean} If add return keyword at end or not. The last element of template have to be a html tag element if is true.
  • @return {Function} a template function should pass to Vdt.

template.source

The source code of template function.

The vdt object

The object returned by Vdt.

vdt.render(data)

Handle data and return a dom.

  • @param data {Object} data passed to template
  • ~~@param thisArg {Object} the binding of this in template.~~ this is data in template.
  • @return {Dom} html dom

vdt.update([data])

Update the dom using the new data.

  • @param data {Object} the whole data passed to template. If it is not provided, vdt.data will be used.
  • @return {Dom} html dom which has updated

vdt.data

The data passed to vdt above. So you can modify it directly.

Vdt.parse(source)

Parse JSX template to an ast object

  • @param source {String} JSX template source
  • @return {Object} abstract syntax tree object

Vdt.stringify(ast)

Stringify the ast object to hscript string.

  • @param ast {Object} abstract syntax tree object
  • @return {String} hscript string with a return expression at end

Vdt.virtualDom

The object exported by virtual-dom module.

Benchmark

See Benchmark

Render(compile every time)

  • Vdt.js#render x 5,454 ops/sec ±2.40% (89 runs sampled)
  • Lodash#render x 2,390 ops/sec ±3.68% (81 runs sampled)
  • Underscore#render x 6,035 ops/sec ±5.86% (81 runs sampled)
  • Handlebars#render x 959 ops/sec ±6.16% (77 runs sampled)
  • Mustache#render x 4,899 ops/sec ±6.09% (84 runs sampled)

Fastest is Underscore#render

Update(cache compiled result)

  • Vdt.js#update x 14,724 ops/sec ±3.61% (87 runs sampled)
  • Lodash#update x 7,734 ops/sec ±2.70% (84 runs sampled)
  • Underscore#update x 7,989 ops/sec ±4.52% (89 runs sampled)
  • Handlebars#update x 7,200 ops/sec ±2.63% (86 runs sampled)
  • Mustache#update x 7,747 ops/sec ±2.40% (96 runs sampled)

Fastest is Vdt.js#update