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

express-dot-engine

v1.0.8

Published

Node.js engine using the ultra fast doT templating with support for layouts, partials and friendly for front-end web libraries (Angular, Ember, Backbone...)

Downloads

2,331

Readme

express-dot-engine

GitHub release (latest SemVer) node Build Status

Node.js engine using the ultra fast doT templating with support for layouts, partials. It's friendly for front-end web libraries (Angular, Ember, Backbone...)

Important

The default settings of doT has been change to use [[ ]] instead of {{ }}. This is to support client side templates (Angular, Ember, ...). You can change it back by changing the Settings (see below).

Features

  • extremely fast (see jsperf)
  • all the advantage of doT
  • layout and partial support
  • uses [[ ]] by default, not clashing with {{ }} (Angular, Ember...)
  • custom helpers to your views
  • conditional, array iterators, custom delimiters...
  • use it as logic-less or with logic, it is up to you
  • use it also for your email (or anything) templates
  • automatic caching in production

Great for

  • √ Purists that wants html as their templates but with full access to javascript
  • √ Minimum server-side logic, passing server models to client-side frameworks like Angular, Ember, Backbone...
  • √ Clean and fast templating with support for layouts and partials
  • √ Email templating

Not so much for

  • Jade style lovers (http://jade-lang.com/)
  • Full blown templating with everything already coded for you (you can however provide any custom functions to your views)

Installation

Install with npm

$ npm install express-dot-engine --save

Then set the engine in express

var engine = require('express-dot-engine');
...

app.engine('dot', engine.__express);
app.set('views', path.join(__dirname, './views'));
app.set('view engine', 'dot');

To use a different extension for your templates, for example to get better syntax highlighting in your IDE, replace 'dot' with your extension of choice. See express' documentation

app.engine('html', engine.__express);
app.set('views', path.join(__dirname, './views'));
app.set('view engine', 'html');

Settings

By default, the engine uses [[ ]] instead of {{ }} on the backend. This allows the use of front-end templating libraries that already use {{ }}.

[[ ]]     for evaluation
[[= ]]    for interpolation
[[! ]]    for interpolation with encoding
[[# ]]    for compile-time evaluation/includes and partials
[[## #]]  for compile-time defines
[[? ]]    for conditionals
[[~ ]]    for array iteration

If you want to configure this you can change the exposed doT settings.

// doT settings
engine.settings.dot = {
  evaluate:    /\[\[([\s\S]+?)\]\]/g,
  interpolate: /\[\[=([\s\S]+?)\]\]/g,
  encode:      /\[\[!([\s\S]+?)\]\]/g,
  use:         /\[\[#([\s\S]+?)\]\]/g,
  define:      /\[\[##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\]\]/g,
  conditional: /\[\[\?(\?)?\s*([\s\S]*?)\s*\]\]/g,
  iterate:     /\[\[~\s*(?:\]\]|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\]\])/g,
  varname: 'layout, partial, locals, model',
  strip: false,
  append: true,
  selfcontained: false,
};

Layout

You can specify the layout using yaml and refer to the section as you would from a model.

You can also define any extra configurations (like a page title) that are inherited to the master.

Multiple section support

master.dot

<!doctype html>
<html lang="en">
  <head>
    <title>[[= layout.title ]]</title>
  </head>
  <body>
    Hello from master.dot <br />
    [[= layout.section1 ]] <br />
    [[= layout.section2 ]]
  </body>
</html>

index.dot

---
layout: master.dot
title: Index page
---

[[##section1:
  Hello from index.dot
#]]

[[##section2:
  Hello from index.dot again
#]]

Result

<!doctype html>
<html lang="en">
  <head>
    <title>Index page</title>
  </head>
  <body>
    Hello from master.dot <br />
    Hello from index.dot <br />
    Hello from index.dot again
  </body>
</html>

Cascading layout support

CEO.dot

<!doctype html>
<html lang="en">
  <head>
    <title>[[= layout.title ]]</title>
  </head>
  <body>
    Hello from CEO.dot <br />
    [[= layout.section ]]
  </body>
</html>

Boss.dot

---
layout: ceo.dot
---

[[##section:
  Hello from Boss.dot <br />
  [[= layout.section ]]
#]]

me.dot

---
layout: boss.dot
title: Page title
---

[[##section:
  Hello from me.dot
#]]

Result

<!doctype html>
<html lang="en">
  <head>
    <title>Boss page</title>
  </head>
  <body>
    Hello from CEO.dot <br />
    Hello from Boss.dot <br />
    Hello from me.dot
  </body>
</html>

Partials

Partials are supported. The path is relative to the path of the current file.

index.dot

<div>
  Message from partial: [[= partial('partials/hello.dot') ]]
</div>

partials/hello.dot

<span>Hello from partial</span>

Result

<div>
  My partial says: <span>Hello from partial</span>
</div>

Server model

In your node application, the model passed to the engine will be available through [[= model. ]] in your template. Layouts and Partials also has access to the server models.

server.js

app.get('/', function(req, res){
  res.render('index', { fromServer: 'Hello from server', });
});

view.dot

<div>
  Server says: [[= model.fromServer ]]
</div>

Result

<div>
  Server says: Hello from server
</div>

Pro tip

If you want to make the whole model available in the client (to use in angular for example), you can render the model as JSON in a variable on the view.

<script>
  var model = [[= JSON.stringify(model) ]];
</script>

Helper

You can provide custom helper properties or methods to your views.

server

var engine = require('express-dot-engine');

engine.helper.myHelperProperty = 'Hello from server property helper';

engine.helper.myHelperMethod = function(param) {

  // you have access to the server model
  var message = this.model.fromServer;

  // .. any logic you want
  return 'Server model: ' + message;
}

...

app.get('/', function(req, res) {
  res.render('helper/index', { fromServer: 'Hello from server', });
});

view

<!doctype html>
<html lang="en">
  <head>
    <title>Helper example</title>
  </head>
  <body>

    model: [[= model.fromServer ]] <br />
    helper property: [[# def.myHelperProperty ]] <br />
    helper method: [[# def.myHelperMethod('Hello as a parameter') ]] <br />
    helper in view: [[# def.helperInView ]]

  </body>
</html>

[[##def.helperInView:
  Hello from view helper ([[= model.fromServer ]])
#]]

Templating for email (or anything)

  • render(filename, model, [callback])
  • renderString(templateStr, model, [callback])

The callback is optional. The callback is in node style function(err, result) {}

Example

var engine = require('express-dot-engine');
var model = { message: 'Hello', };

// render from a file
var rendered = engine.render('path/to/file', model);
email.send('Subject', rendered);

// async render from template string
engine.renderString(
  '<div>[[= model.message ]]</div>',
  model,
  function(err, rendered) {
    email.send('Subject', rendered);
  }
);

...

Custom template provider

You can provide a custom template provider

server


function getTemplate(name, options, callback) {
    var isAsync = callback && typeof callback === 'function',
        template = '<div>custom template, you can store templates in the database</div>';
    if(!isAsync){
      return template;
    }
    callback(null, template);
};

app.get('/', function(req, res) {
  res.render('helper/index', { getTemplate: getTemplate, });
});

Caching

Caching is enabled when express is running in production via the 'view cache' variable in express. This is done automatically. If you want to enable cache in development, you can add this

app.set('view cache', true);

How to run the examples

1. Install express-dot-engine

$ npm install express-dot-engine

2. Install express

$ npm install express

3. Run the example

$ node examples

Open your browser to http://localhost:2015

Roadmap

  • Html minification in prod
  • Automatically remove server-side comments

License

MIT