The fastest + concise javascript template engine for nodejs and browsers. Partials, custom delimiters and more.

Overview

doT

Created in search of the fastest and concise JavaScript templating function with emphasis on performance under V8 and nodejs. It shows great performance for both nodejs and browsers.

doT.js is fast, small and has no dependencies.

Build Status npm version Coverage Status

v2 !!!

v2.0.0-beta.1 is released - switching recommended!

See release notes.

To install:

npm install dot@beta

Note from the maintainer

doT is a really solid piece of software engineering (I didn’t create it) that is rarely updated exactly for this reason.

It took me years to grasp how it works even though it’s only 140 lines of code - it looks like magic.

I used it in my other projects (e.g. ajv) as the smallest, the fastest and the most functional (all three!) templating engine ever made, that is particularly useful in all code generation scenarios where manipulating AST is an overkill.

It’s a race car of templating engines - doT lacks bells and whistles that other templating engines have, but it allows to achive more than any other, if you use it right (YMMV).

Features

custom delimiters
runtime evaluation
runtime interpolation
compile-time evaluation
partials support
conditionals support
array iterators
encoding
control whitespace - strip or preserve
streaming friendly
use it as logic-less or with logic, it is up to you

Docs, live playground and samples

http://olado.github.com/doT (todo: update docs with new features added in version 1.0.0)

New in version 1.0.0

Added parameters support in partials

{{##def.macro:param:
	<div>{{=param.foo}}</div>
#}}

{{#def.macro:myvariable}}

Node module now supports auto-compilation of dot templates from specified path

var dots = require("dot").process({ path: "./views"});

This will compile .def, .dot, .jst files found under the specified path. Details

  • It ignores sub-directories.
  • Template files can have multiple extensions at the same time.
  • Files with .def extension can be included in other files via {{#def.name}}
  • Files with .dot extension are compiled into functions with the same name and can be accessed as renderer.filename
  • Files with .jst extension are compiled into .js files. Produced .js file can be loaded as a commonJS, AMD module, or just installed into a global variable (default is set to window.render)
  • All inline defines defined in the .jst file are compiled into separate functions and are available via _render.filename.definename

Basic usage:

       var dots = require("dot").process({path: "./views"});
       dots.mytemplate({foo:"hello world"});

The above snippet will:

  • Compile all templates in views folder (.dot, .def, .jst)
  • Place .js files compiled from .jst templates into the same folder These files can be used with require, i.e. require("./views/mytemplate")
  • Return an object with functions compiled from .dot templates as its properties
  • Render mytemplate template

CLI tool to compile dot templates into js files

./bin/dot-packer -s examples/views -d out/views

Example for express

Many people are using doT with express. I added an example of the best way of doing it examples/express:

doT with express

Notes

doU.js is here only so that legacy external tests do not break. Use doT.js.
doT.js with doT.templateSettings.append=false provides the same performance as doU.js.

Security considerations

doT allows arbitrary JavaScript code in templates, making it one of the most flexible and powerful templating engines. It means that doT security model assumes that you only use trusted templates and you don't use any user input as any part of the template, as otherwise it can lead to code injection.

It is strongly recommended to compile all templates to JS code as early as possible. Possible options:

  • using doT as dev-dependency only and compiling templates to JS files, for example, as described above or using a custom script, during the build. This is the most performant and secure approach and it is strongly recommended.
  • if the above approach is not possible for some reason (e.g. templates are dynamically generated using some run-time data), it is recommended to compile templates to in-memory functions during application start phase, before any external input is processed.
  • compiling templates lazily, on demand, is less safe. Even though the possibility of the code injection via prototype pollution was patched (#291), there may be some other unknown vulnerabilities that could lead to code injection.

Please report any found vulnerabilities to npm, not via issue tracker.

Author

Laura Doktorova @olado

License

doT is licensed under the MIT License. (See LICENSE-DOT)

logo by Kevin Kirchner

Thank you @KevinKirchner for the logo.

Comments
  • Object iterators added.

    Object iterators added.

    Added support of object property iterators, e.g. for (key in obj) {...}

    Notation is similar to array iterators, '@' char is used instead of '~':

    {{@ {one: 1, two: 2, three: 3} :val :key}}
        {{=key}} = {{=val}}
    {{@}}
    

    Also, this can iterate only own properties – with additional '@':

    {{ obj = (function() {
        function O() {
            this.four = 4;
        }
        O.prototype = { one: 1, two: 2, three: 3 };
        return new O;
    })(); }}
    
    {{@@ obj :val :key}}
        {{=key}} = {{=val}}
    {{@@}}
    
    discussion 
    opened by milichev 16
  • Code execution after prototype pollution

    Code execution after prototype pollution

    Suggested continuation from https://github.com/olado/doT/issues/281 and as was originally described in "Part B" of https://hackerone.com/reports/390929

    If you agree, I can submit the suggested fix as a PR

    Description

    First, note that with the addition of default function parameters in ES2015, it is easy to evaluate arbitrary JS expressions if you have access to arg in new Function(arg, body), for example new Function("x=alert(2+2)","return x")

    Next, note that calling doT.process({}) without specifying templateSettings (which is the intended way of using the function when not attempting to override defaults) will allow a templateSettings property to be taken from o's prototype: image

    So, with a previously exploited prototype pollution vulnerability, doT can be caused to run arbitrary code stored as a string in that prototype:

    /*elsewhere*/
    Object.prototype.templateSettings = {varname:"x=alert(1+1)"};
    /* in app code */
    const templates = require("dot").process({path: "./my_trusted_templates_that_I_wrote"});
    templates.mytemplate(data); // Executes code specified by prototype
    
    ### Suggested fix
    
    On line 45, highlighted above, replace `... o.templateSettings ? ...` with `... Object.prototype.hasOwnProperty.call(o,"templateSettings") ? ...`
    
    
    ### Aside - similar but unaffected property
    ![image](https://user-images.githubusercontent.com/5790026/69501734-c68a5980-0ed5-11ea-81ab-ea70d264cb1a.png)
    ^ Here, a similar issue could be present with `Object.prototype.varname` but upon closer inspection, I don't think it's a significant issue since doT users are prevented from omitting the varname property in normal doT usage
    opened by fabiocbinbutter 15
  • Always install dottojs dependencies

    Always install dottojs dependencies

    doT installed as dependency provides dottojs binary, but it doesn't work:

    $ ./node_modules/.bin/dottojs --help
    
    module.js:340
        throw err;
              ^
    Error: Cannot find module 'commander'
    
    discussion 
    opened by dmage 14
  • Is this project still maintained?

    Is this project still maintained?

    I love doT, but there has been no commit for over a year now. There are 35 interesting pull request out there. I myself would like to have some Object iterator built in.

    Please @olado consider those pull request. Merge or close. If you have no time for this project ... why not assign it to somebody else?

    opened by zevero 11
  • ejs way using javascript translated to .doT engine

    ejs way using javascript translated to .doT engine

    it is possible to do this way I used to use this javascript functions or regex in ejs in .dot? . I explain in this question

    <%= blog.created_at.getFullYear() %> <%= blog.short_name.replace(new RegExp(" ", "g"), "-") %> <%= blog.content.match(/<img[^>]+src="([^">]+)/)[1] %>

    but I have trouble making this work in .dot engine. I know my problem are javascript function, regex and match I'm using. meaning bold part, is not correct here ( getFullYear() , replace(new RegExp(" ", "g"), "-") , match(/]+src="([^">]+)/)[1] )

    {{= blog.created_at.getFullYear() }} {{= blog.short_name.replace(new RegExp(" ", "g"), "-") }} {{= blog.content.match(/<img[^>]+src="([^">]+)/)[1] }}

    thanks in advance

    opened by mikzuit 9
  • Do not let interpret doT numbers as integer, but as string

    Do not let interpret doT numbers as integer, but as string

    {{=it.number1}}{{=it.number2}}

    evaluates to var += (it.number1)+(it.number2); which results in var += (it.number1 + it.number2);. It then concatenates the resulting number to var, which is bad.

    Please evaluate it as var += String(it.number1)+String(it.number2); — this is what users really want, I think.

    Quick fix: change the lines 46 - 49 from:

        var startend = {
            append: { start: "'+(", end: ")+'", endencode: "||'').toString().encodeHTML()+'" },
            split: { start: "';out+=(", end: ");out+='", endencode: "||'').toString().encodeHTML();out+='"}
        }, skip = /$^/;
    

    to:

        var startend = {
            append: { start: "'+String(", end: ")+'", endencode: "||'').toString().encodeHTML()+'" },
            split: { start: "';out+=String(", end: ");out+='", endencode: "||'').toString().encodeHTML();out+='"}
        }, skip = /$^/;
    
    needs review 
    opened by bwoebi 9
  • Using templates with Require.js and r.js

    Using templates with Require.js and r.js

    Is possible to use doT template with requirejs?? I mean, put the templates in a folder and dynamically pull this templates.. When build process run (r.js), precompile this templates?

    opened by matiasfha 9
  • Add basic support for the Express framework

    Add basic support for the Express framework

    I added a single function to the node module (index.js) to support the Express framework.

    No dependencies. The main doT.js remains untouched.

    I guess there's reasons for this to be in its own module/repo, as in https://github.com/cstigler/express-dot and also reasons for this to be included in doT.

    You could also have an express.js file in the repo with some more functionality (like cache support) and require it in index.js

    I think it's useful to just include the doT module in for project and use it right away with Express, which seems to be widely adopted (I don't know statistically). I've been using it like that for a while.

    Usage in an Express app is simple, as expected:

    app.set('view engine', 'dot');
    

    if you're using .dot files. Or:

    app.engine('html', require('dot').__express);
    app.use('view engine', 'html');
    

    if you want to use any other extension.

    I hope this is useful if it makes sense to you.

    Happy new year.

    needs review 
    opened by acstll 9
  • Adds an engine attribute for easy identification

    Adds an engine attribute for easy identification

    I am working on an application server and the ability to identify and handle various templating engines is important. Right now we are handling detection of doT by looking at the shape of the template engine. Would be nice to have a single field to check like handlebars has, for instance.

    This adds an engine attribute so that it will be easy to detect in the future.

    opened by designfrontier 8
  • please leave native prototypes alone

    please leave native prototypes alone

    a dev on my team just added some doT templates to our app. we've had a lengthy discussion regarding it, and my final "please don't use this" landed here:

    • https://github.com/olado/doT/blob/master/doT.js#L45

    there is absolutely no reason you need to inject your own methods onto native prototypes. especially methods that don't even work correctly.

    needs review 
    opened by stephenmathieson 8
  • Feature request: Context delimeter for prefix free output

    Feature request: Context delimeter for prefix free output

    Hi, It would be nice if there was a context delimeter. Instead of needing to add "it" as a prefix for every data reference.

    <div>Hi {{=it.name}}!</div>
    <div>{{=it.age || ''}}</div>
    

    becomes

    {{$ it}}
    <div>Hi {{=name}}!</div>
    <div>{{=age || ''}}</div>
    {{$}}
    

    Or in a more complex scenario with nesting

    var data = {
      "name": "Jake",
      "age":31,
      "mother":"Kate",
      "father":"John",
      "interests": ["basketball","hockey","photography"],
      "contact": {
        "email":"[email protected]",
        "phone":"999999999"
      }
    }
    

    Could be used like this:

    {{$ it}}
      <div>I'm {{=name}} and I love..</div>
      <ul>
        {{~interests :value}}
          <li>{{=value}}!</li>
        {{~}}
      </ul>
      <div>Please contact me</div>
      {{$ contact}}
        Phone: {{=phone}}
        Email: {{=email}}
      {{$}}
    {{$}}
    

    I roughly tried something along these lines in my fork some time back but never really tested or used it. This give a few big advantages. 1) Easier to read the templates without "it" everywhere. 2) If the data structure ever changes- (i.e. something gets nested inside another object when previously it had not) fixing the template is simply a matter of adding a new context delimiter.

    Thoughts? Thanks!

    opened by dannyc 8
  • Using single curly braces as delimiters doesn't work

    Using single curly braces as delimiters doesn't work

    I was messing around with the new delimiters option released in 2.0.0-beta.1 and found out that setting { and } as start and end delimiters respectively, breaks in some cases.

    const dot = require('dot')
    
    const tmpl = dot.template('{?merchant}/{=merchant}{?}/{=version}/{=product}', {
      argName: ['merchant', 'version', 'product'],
      delimiters: { start: '{', end: '}' },
    })
    
    tmpl({ product: 'cookie', version: '1.0.0', merchant: '243' }) 🐛 
    
    // Could not create a template function: let out='';if(merchant)';out+='/'+(merchant);out+='out+='/'+(version)+'/'+(product);return out;
    Uncaught SyntaxError: Unexpected identifier
    

    If I don't use conditionals in my template string, the rendering works fine.

    const tmpl = dot.template('/{=merchant}/{=version}/{=product}', {
      argName: ['merchant', 'version', 'product'],
      delimiters: { start: '{', end: '}' },
    })
    
    tmpl({ product: 'cookie', version: '1.0.0', merchant: '243' }) ✅ 
    // '/243/1.0.0/cookie'
    

    Other delimiters that I've tried, such as [ and ], seem to work fine in all scenarios, though.

    opened by nfantone 1
  • No lock file found in the dot project on Tag: v2.0.0-beta.1

    No lock file found in the dot project on Tag: v2.0.0-beta.1

    Issue: There is no package-lock.json or npm-shrinkwrap.json file uploaded to the GitHub repository https://github.com/olado/doT

    Questions: We are conducting a research study on the lock files used in JS projects. We were curious:

    1. Will you upload any lock files to GitHub as recommended above? (Yes/No), and why?:
    2. Do you have any additional comments? (If so, please write it down):

    For any publication or research report based on this study, we will share all responses from developers in an anonymous way. Both your projects and personal information will be kept confidential.

    Rationale: NPM introduced package-lock.json and npm-shrimpwrap.json files to capture the exact dependency tree installed at any point in time. When package.json defines the required dependencies and their respective versions using semantic versioning (e.g., “express”: “^4.16.4”), npm always downloads the latest version of packages to satisfy the specified version ranges (e.g., 4.17.1)[1]. If the latest version of any package keeps changing and has backward incompatibility issues with previous versions, the project may have an inconsistent running environment and get intermittent failures. In such scenarios, it can be very difficult for developers to debug programs and settle down the software environment [2].

    List of Risks:

    • Nondeterministic package downloads and installations across different environments [3]
    • Produce irreproducible builds [4]
    • Inconsistent results of program execution [5]

    Suggested Solution: Please fixate the dependencies by either specifying the exact library version in the package.json file or by uploading the package-lock.json or npm-shrinkwrap.json file to GitHub.

    References: https://docs.npmjs.com/cli/v7/configuring-npm/package-lock-json https://blog.logrocket.com/why-you-should-use-package-lock-json/ 2019. 10 npm Security Best Practices. https://snyk.io/blog/ten-npm-security-best-practices/. Pronnoy Goswami, Saksham Gupta, Zhiyuan Li, Na Meng, and Daphne Yao. 2020. Investigating The Reproducibility of NPM Packages. In2020 IEEE International 2021. Npm Security Best Practices. https://bytesafe.dev/posts/npm-security-best-practices/#no9-deterministic-results.

    opened by mahirkabir 0
  • Added VS code Extension in the READme.md

    Added VS code Extension in the READme.md

    Hi Folks, I came across some simple yet efficient Template engine 'Dot-js'. Created a VS - Code Extension. Feel free to explore that.

    https://github.com/Deepthi1496/doT-template-snippet

    If you like this extension, provide comments and Stars - which makes me understand you appreciate the work and help the community for the better :)

    opened by Deepthi1496 0
  • control instructions should not be counted as white space

    control instructions should not be counted as white space

    Given this template, it should render a CSV output with no empty lines

    host,pin,subject
    {{~ it :e }}
    {{=e.host}},{{=e.hash}},{{=e.subject.CN}}
    {{~}}
    

    However, the output contains an empty line after the header and after each of the arrays items. Currently this template has to be used to get a proper formatted CSV output:

    host,pin,subject{{~ it :e }}
    {{=e.host}},{{=e.hash}},{{=e.subject.CN}}{{~}}
    

    which is rather ugly. Will this be fixed in V2?

    opened by pke 2
  • V2 types not resolving?

    V2 types not resolving?

    I am using V2 doT like so:

    import * as doT from 'doT';
    
    const tmpl = doT.template("{{=foo}}{{=bar}}", {argName: ["foo", "bar"]})
    tmpl({foo: 1, bar: 2}) // "12"
    

    And it works just dandy. However, I am not seeing any types. In vscode I get the following message on my import:

    Could not find a declaration file for module 'doT'. 'node_modules/dot/doT.js' implicitly has an 'any' type.ts(7016)

    Am I missing something? It would be helpful to see an example with working types.

    opened by jmac-slash0 1
Releases(v2.0.0-beta.1)
  • v2.0.0-beta.1(Jul 26, 2020)

    Changes/additions:

    • ES6 code generated
    • types: https://github.com/olado/doT/blob/v2/doT.d.ts
    • varname option renamed to argName
    • support templates without explicit context "it" - the list of properties should be passed as array to argName option, template function will expect an object and will destructure it into multiple arguments - so it is nearly zero-cost:
    const tmpl = doT.template("{{=foo}}{{=bar}}", {argName: ["foo", "bar"]})
    tmpl({foo: 1, bar: 2}) // "12"
    
    • partial options can be passed, global options object will not be available in the next release.
    • custom encoders:
      • syntax {{<encoder name>! it.foo}}, encoders passed to encoders option object ( is any valid JS identifier) as functions (or as code strings in selfContained: true mode).
      • HTML encoding with syntax {{! it.foo }} requires passing {encoders: {"": require("dot/encodeHTML")}} options
    • type safe interpolation (maybe % should be dropped...):
      • {{%n= it.foo}} - it.foo must be number (or exception will be thrown)
      • {{%s= it.foo}} - string
      • {{%b= it.foo}} - boolean
    • support iterables for {{~iter:x}} and {{~iter:x:i}} syntaxes (now uses for-of loop).
    • syntax is no longer in options
    • configurable delimiters:
      • e.g. {delimiters: {start: "<%", end: "%>"}} via options to change for one template
      • or setDelimiters({start: "<%", end: "%>"}) to change globally
    • reduces internal variables names usage, two configurable name prefixes are used, can be changed via options (internalPrefix: "_val", encodersPrefix: "_enc").
    • optional iterator index variable is now local (with let)

    Removed:

    • doT.process (possibly will be added if there is an interest)
    • browser bundle (possibly will be added if there is a substantial interest)
    • dot-packer - can be added as a separate module to dot-template org
    • legacy doU engine
    • append: false option (only append: true now, that is faster and that was default anyway)
    • no HTML interpolation by default (see custom encoders above)
    Source code(tar.gz)
    Source code(zip)
  • v1.1.3(Jul 25, 2020)

  • 2.0.0-beta.0(Feb 16, 2017)

  • 1.1.0(Feb 16, 2017)

Owner
Laura Doktorova
Laura Doktorova
1KB lightweight, fast & powerful JavaScript templating engine with zero dependencies. Compatible with server-side environments like node.js, module loaders like RequireJS and all web browsers.

JavaScript Templates Contents Demo Description Usage Client-side Server-side Requirements API tmpl() function Templates cache Output encoding Local he

Sebastian Tschan 1.7k Jan 3, 2023
Variation-template - Variation is a PSD template that is covered into a web template using HTML5, CSS3, Bootstrapv4.6, JavaScript.

Variation Template Design Variation is a PSD website template. In this project this template is designed with HTML. Deployment This site is deployed a

Bipronath Saha 1 Jan 1, 2022
Take a swig of the best template engine for JavaScript.

NOT MAINTAINED Fork and use at your own risk. Swig Swig is an awesome, Django/Jinja-like template engine for node.js. Features Available for node.js a

Paul Armstrong 3.1k Jan 4, 2023
A powerful templating engine with inheritance, asynchronous control, and more (jinja2 inspired)

Nunjucks Nunjucks is a full featured templating engine for javascript. It is heavily inspired by jinja2. View the docs here. Installation npm install

Mozilla 8k Dec 30, 2022
Embedded JS template engine for Node, Deno, and the browser. Lighweight, fast, and pluggable. Written in TypeScript

eta (η) Documentation - Chat - RunKit Demo - Playground Summary Eta is a lightweight and blazing fast embedded JS templating engine that works inside

Eta 682 Dec 29, 2022
eXtensible Template Engine lib for node and the browser

xtemplate High Speed, eXtensible Template Engine lib on browser and nodejs. support async control, inheritance, include, logic expression, custom func

xtemplate 553 Nov 21, 2022
Pug – robust, elegant, feature rich template engine for Node.js

Pug Full documentation is at pugjs.org Pug is a high-performance template engine heavily influenced by Haml and implemented with JavaScript for Node.j

Pug 21.1k Dec 30, 2022
Highly opinionated project template for Serverless Framework that follows and applies hexagonal architecture principle to serverless world. Prepared with easy testing in mind.

serverless-hexagonal-template Highly opinionated project template for Serverless Framework that applies hexagonal architecture principles to the serve

Paweł Zubkiewicz 126 Dec 26, 2022
Examples of how to re-create the WordPress Template Hierarchy using headless clients and WPGraphQL

WPGraphQL Template Hierarchy Debugger This is a project to demonstrate how to re-create the WordPress template hierarchy with Headless WordPress using

Jason Bahl 17 Oct 29, 2022
A template to be used for creating js/scss projects and deploy them to github pages

A template to be used for creating js/scss projects and deploy them to github pages

Cariera în IT 15 Oct 30, 2022
Script Template Fivem in Type Script

fivem-ts ?? A Typescript Template for FiveM ?? This is a basic template for creating a FiveM resource using Typescript. It includes webpack config fil

Vinícius Pereira 3 Jun 11, 2021
A K6 Multi Scenario template applying some best practices along some examples

K6-Multi-Scenario-Template It is a performance testing template that shows how to use K6 to implement a Multi Scenario template applying some best pra

Swiss Life OSS 33 Nov 27, 2022
Tailwind & Next Mentorship Template

This is a Next.js project bootstrapped with create-next-app. Getting Started First, run the development server: npm run dev # or yarn dev Open http://

Nauval 21 May 22, 2022
Template to create reactjs component library which will help you to create your dream library.

reactjs-library-template Template to create reactjs component library which will help you to create your dream library. How to use Commands to setup e

Nishant Tomar 1 Dec 25, 2021
Low tech template for a reduced carbon impact :seedling:

Enverse minimalist front-end template ?? ?? For all else, use Astro.build ?? Recomended package manager: pnpm Preact + Typescript + Vite How to use: F

null 2 Jan 10, 2022
Obsidian To HTML, A template for building obsidian style notes to a static site

oth (Obsidian To HTML) This is a template for publishing obsidian notes as a static site. The goal of the project is to stay minimal, since this is a

Ulisse mini 11 Nov 4, 2022
My discord.js bot template

My discord.js Bot Template This repository is an ongoing project to extract core pieces of the discord.js bots and ecosystems I run into a reusable te

Ian Mitchell 8 Mar 3, 2022
Asynchronous Javascript templating for the browser and server

Dust.js Asynchronous Javascript templating for the browser and server. This fork is maintained by LinkedIn. Install NPM Important: We recommend that y

LinkedIn 2.9k Dec 31, 2022
Asynchronous Javascript templating for the browser and server

Dust.js Asynchronous Javascript templating for the browser and server. This fork is maintained by LinkedIn. Install NPM Important: We recommend that y

LinkedIn 2.9k Dec 31, 2022