Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Combustion is a simple template engine abstaction built built upon code from underscore's template function. It's a micro-templating library, similar to John Resig's implementation, but it allows custom injection of helpers and the utility library of choice in a strict commonjs environment where globals are annihilated. It's dependency-free and tiny when it's main entry point is required, but for node it includes helpers for server-side compilation.
Require the library, and make a compiler with a custom helper object, and optionally inject utility library to make available inside template code. If no utility library is given, the $
variable inside a template function will now refer to an empty object and shadow whatever global value it may or may not have.
var compiler = require('combustion')();
var template = compiler("hello: <b><%= name %></b>");
template({name: 'clux'}); // "hello: <b>clux</b>"
The API is as follows:
When one instantiates combustion with a settings object and a utility library we get a compiler function.This compiles JavaScript templates into functions that can be evaluated for rendering. Template functions can both interpolate variables, using <%= … %>, as well as execute arbitrary JavaScript code, with <% … %>. If you wish to interpolate a value, and have it be HTML-escaped, use <%- … %> When you evaluate a template function, pass in a data object that has properties corresponding to the template's free variables.
var tStr = "<div id=\"winner\"><% if (name == 'clux') { %> \
<b><%=name + '!'%></b> \
<% } else { %> \
<i><%-'lucky ' + name%></i> \
<% } %> \
</div>";
var template = compiler(tStr);
template({name:clux});
// '<div id="winner"><b>clux!</b></div>'
template({name:'<injector>'});
// '<div id="winner"><i>lucky <injector></i></div>'
Note the multiline comment breaks are only needed if you wrote the templates inside javascript - which would be silly.
Combustion allows adding helpers into the scope of the template functions. This is done on a per compiler basis, to encourage the use of similar helpers in similar areas (typically per controller file if you are using mvc-style). An entire utility library can also be injected for own methods (like how _.template
injects _
into the template scope).
var helpers = {
print : function () {
return Array.prototype.join.call(arguments, '');
}
, pluralize : function (str, num) {
return num + ' ' + (num === 1 ? : '' : 's');
}
};
var settings = {
utility : require('interlude')
, helpers : helpers
, helperName : 'h'
}
var compiler = require('combustion')(settings);
var template = compiler("<%= h.pluralize('winner', $.gcd(number, 6)) %>");
template({number: 4}); // "2 winners"
template({number: 5}); // "1 winner"
Here the functional utility library interlude is made available inside the templates instead of underscore. Customize and use your own helper library if you want to.
If ERB-style delimiters aren't your cup of tea, you can change the template settings to use different symbols to set off interpolated code. Define an interpolate regex to match expressions that should be interpolated verbatim, an escape regex to match expressions that should be inserted after being HTML escaped, and an evaluate regex to match expressions that should be evaluated without insertion into the resulting string. You may define or omit any combination of the three. For example, to perform Mustache.js style templating:
var settings = {
interpolate : /\{\{(.+?)\}\}/g
};
var compiler = require('combustion')(settings);
var template = compiler("Hello {{ name }}!");
template("November clux"); // "Hello November clux!"
By default, template places the values from your data in the local scope via the with
statement. However, you can specify a single variable name with the variable setting. This can significantly improve the speed at which a template is able to render.
var compiler = require('combustion')({variable : 'data'})
var template = compiler("<%= data.name %>!");
template({name: "Hogan"}); // "Hogan!"
Precompiling your templates can be a big help when debugging errors you can't reproduce. This is because precompiled templates can provide line numbers and a stack trace, something that is not possible when compiling templates on the client. The source property is available on the compiled template function for easy precompilation.
compiler("hello <%=name%>!").source;
"function(obj){
with(obj||{}){
var __p='hello '+
(name)+
'!';
}
return __p;
}"
This allows basic pre-compilation, but it's not simply concatenating these sources as unescaping (i.e. <%- "<inject>" %>
)assumes a 10 line dependency inside combustion, and if you want helpers available, then the build step needs to promise the file you are compiling into, that these helpers will exist in the commonjs environment.
To obtain this functionality combustion should be installed globally to make the combust
executable available from anywhere. We use the executable to parse a template directory recursively:
$ combust -d ./templateDir > templates.js
Then require it from your commonjs environment:
var templates = require('./templates');
templates['user/profile']; // template function compiled from templateDir/user/profile.html
Place a .combustion
file inside the template directory (or in each if you require different settings per folder) and customize all the options. The file should look like lib/settings.js - but changing objects for file names (see below). If you want a more global config file, put it one or more levels above the templates directories.
Thus, say you have two .combustion
files, one in templateDir/user
and one in templateDir/entry
. Perhaps because a developer has done one with different delimiters, or one require a different helper object say, then:
$ combust -d ./templateDir/user > userTmpls.js
$ combust -d ./templateDir/entry > entryTmpls.js
then from your cjs environment:
var userTmpls = require('./userTmpls');
userTmpls['profile']; // template function compiled from templateDir/user/profile.html
Since each file now contains the templates from this folder this namespaces the templates by file rather than adding slashes in between directories when templates were found recursively.
A combustion config file looks almost exactly like the default settings object passed to combustion
on the client, with one distinct difference:
Thus, a sensible default .combustion
file can look like this:
/**
* @file templateDir/.combustion
*/
module.exports = {
evaluate : /<%([\s\S]+?)%>/g
, interpolate : /<%=([\s\S]+?)%>/g
, escape : /<%-([\s\S]+?)%>/g
, helpers : './helpers'
, helperName : 'h'
, utility : 'interlude'
, variable : null
};
Note that if helpers or utility takes the form of a relative path, note that the path must be relative to where you place the output of combust
, otherwise your build tool will complain.
Install it locally if you want client side compilation, otherwise globally (with the -g flag) for precompilation
$ npm install -g combustion
Install development dependencies
$ npm install
Run the tests
$ npm test
MIT-Licensed. See LICENSE file for details.
FAQs
A primitive, but efficient micro-templating engine
We found that combustion demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.