Templating Engine for Node that's NOT Jade - javascript

Jade is indeed very neat, but I personally dislike the syntax and look of it. Yeah, being able to write just :
body
h1 Hello
p This is
b bold
Thats cool and all, but I prefer the look and feel of HTML/XML still. It was made to be human and machine readable and overall I think it's easier to glance at and understand.
Are there any templating engines that work more like:
<body>
<h1>{title}</h1>
<p>{content}</p>
</body>
Using the same Jade like concept of:
res.render('index', {
title:pageTitle,
content:pageContent
});

Take a look at EJS. Allows you to use regular HTML and embed Javascript code.
For example:
<div>
<% if (foo) { %>
foo
<% }else { %>
bar
<% } %>
</div>
Also, what you're looking for is an "Express-compatible" templating engine, and EJS is Express-compatible. It's made by one of the main guys behind Express.

You can use straight HTML in Jade, give this a try:
<body>
<h1>#{title}</h1>
<p>#{content}</p>
</body>

Something that specifically looks like that would probably be Mustache for Node.js. Check the demo.

Consider jQuery templates. You can provide your data in JSON and apply it to a template.

If you're already using underscore.js
var compiled = _.template("hello: <%= name %>");
compiled({name : 'moe'});
=> "hello: moe"

Templates can be only a matter of taste. I don't like Jade either and favouring HTML is a better option.
Most of times, webdesign layouts cannot be easily converted to those templates.
the sample provided moustache:
<h1>{{header}}</h1>
{{#bug}}
{{/bug}}
{{#items}}
{{#first}}
<li><strong>{{name}}</strong></li>
{{/first}}
{{#link}}
<li>{{name}}</li>
{{/link}}
{{/items}}
{{#empty}}
<p>The list is empty.</p>
{{/empty}}
It can be mixed with Angular.js syntax... could be a problem for people using it.

I recommend a new template engine: Saker, it enables fluid coding workflow, unlike most template syntaxes, you do not need to interrupt your coding to explicitly denote server blocks within your HTML.
Github: https://github.com/eshengsky/saker
The code looks like:
<body>
<h1>#title</h1>
<p>#content</p>
</body>

I personally use Nunjucks with all of my Node JS projects for a few years now and still loving it. I switched from Swig because Swig was lacking in some of extensibility when a project became more complex.
I, too, am not a fan of Jade / Pug. I prefer normal HTML syntax and inject some custom templating schemes.

Related

jQuery - simple way to bind json content to element?

Ever since Knockout and Angularjs presented a simpler way to otput content from JSON files, I find myself resorting to using them in instances when I would much rather use jQuery for simple tasks.
What would be the simplest way to display some content on the page using jQuery that would be equivalent to {{ model }} in angularjs?
For example, if I have a json file:
{
"something-1": "A",
"something-2": "B",
"something-3": "C"
}
this allows me to output content from data.json in a template by simply using curly brackets...
$http.get("data.json").success(function(data)
{
$scope.content = data;
});
Then in HTML:
{{ content['something-1'] }} <br/>
{{ content['something-2'] }} <br/>
{{ content['something-3'] }}
In jQuery using a simple ajax call to a json file allows me to read the file contents but I am unaware of any way that would allow me a simple and practical data output such as angularjs does.
Can someone suggest a practical way?
I think the simplest way is to use something like mustache.js (https://github.com/janl/mustache.js), jquery has some plugin but nothing inside the core library.
underscore.js also provides this option.
var compiled = _.template("hello: <%= name %>");
compiled({name: 'moe'});
=> "hello: moe"

How do I use helpers with Dust.js on a local environment?

I'm programming using dust-full.js from the linkedIn fork (2.5.1). I'm trying to use helpers for conditionals, but I can't seem to get it to work. Right now, I'm using my local machine (I have no intention at the moment to include a server backend, but it may be where this project goes). I currently test my code on my Dropbox public folder. All non-helper code has worked.
The code in question:
{?quote temp="4"}
Once you have chosen the best answer{#if cond="{temp} > 1"}s{/if}, please select the "Submit" button.
{:else}
Choose the best answer{#if cond="{temp} > 1"}s{/if}, then select the "Submit" button.
{/quote}
I have previously added the dust-full.js distribution and helpers like so:
<script src="script/dust-full.js" type="text/javascript"></script>
<script src="script/dust-helpers.min.js" type="text/javascript"></script>
I saw in other threads and on the dust.js tutorial that one needed to "require" the helpers. Using code like this:
var dust = require('dustjs-linkedin');
dust.helper = require('dustjs-helpers');
However, when I include this, I get the console error: "ReferenceError: require is not defined." I assume that this is because "require" is usually used/included in node.js, but I honestly don't know. I would prefer not to include node.js, as I don't know it and I'm not interested in learning additional libraries. However, I do not know how to evaluate helpers.
I have four questions:
Are there any obvious bugs in the code I've provided?
Are dust.js helpers only available using when using server-side scripting?
(Assuming the answer to 2 is "No") Can helpers be used only with dust-full.js and dust-helpers.js?
(Assuming the answer to 3 is "No") How does one use helpers only using client-side scripting?
Using require to load the helpers is for a server environment like Node. You should be able to do exactly what you've done to load the helpers-- just include them after the main dust script and they'll be automatically added to the dust object.
What you've done looks correct, so is it possible that you've used the wrong path to your dust-helpers Javascript file?
Here is a snippet showing the {#gt} helper working. (The {#if} helper is deprecated, so you'll get warnings in the console when you use it-- but {#gt} does exactly what you want.)
<div id="output"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dustjs-linkedin/2.5.1/dust-full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dustjs-helpers/1.5.0/dust-helpers.min.js"></script>
<script>
var tmpl = dust.compile('Hello World! Choose the best answer{#gt key=temp value=1}s{/gt}', "test"),
context = { "temp": 4 };
dust.loadSource(tmpl);
dust.render("test", context, function(err, out) {
document.getElementById("output").textContent = out;
});
</script>

HoganJs and AngularJs with NodeJs

We are trying to use NodeJs with HoganJs for server side templating. However we are also wanting to use AngularJs for our client side needs.
The problem is that both HoganJs and AngularJs use "{{" and "}}" to full fill their compiler needs. Because of this Hogan strips out if at all there is a angular's "{{", because of the way hogan works.
My question is is there a out of the box solution that allows me to use both Angular and Hogan together, without clashing with each other.
If not, does anyone knows what/where/how to tweak one of these to make them love each other and work gracefully.
Thanks in advance...
If you're using express, you can change hogan's delimiters like so:
var app = express();
app.locals.delimiters = '<% %>';
Place the above before :
app.set('view engine', 'hjs');
Now in your page.hjs file, for the data { template : "Template test" }, you can do :
<p>This is a <% template %></p>
Try with
Hogan.compile(text, {delimiters: '<% %>'});
so you can change the delimeters Hogan
uses by passing the compile method an option overriding them.
http://comments.gmane.org/gmane.comp.lang.javascript.express/1426
NB
imo using a template system is useless using angularjs because
of https://stackoverflow.com/a/20270422/356380
Alternative to changing Hogan delimeters as other answer shows... change Angular's! I did this while using doT (which also uses {{ and }}) and it works fine:
say you have this in your layout HTML:
<html ng-app="cooApp">
Add this script to call up Angular with custom delims (I'm also including reference to Angular just for clarification):
<script src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.2/angular.min.js'></script>
<script>
var cooApp = angular.module('cooApp', [], function($interpolateProvider) {
$interpolateProvider.startSymbol('{%');
$interpolateProvider.endSymbol('%}');
});
</script>
Now just use {% and %} for Angular stuff.
Without changing delimiters, on Angular 1.x you can use the ng-non-bindable directive for in the elements that uses HoganJS, Mustache or any other code of this kind:
Example:
<div>
{{angularjs_variable}}
<div ng-non-bindable>{{hogan_variable}}</div>
</div>
This is useful if the element contains what appears to be AngularJS directives and bindings but which should be ignored by AngularJS. [...]

Escape double braces {{ ... }} in Mustache template. (templating a template in NodeJS)

I'm trying to template a template, like below:
{{{
{
"name" : "{{name}}",
"description" : "{{description}}"
}
}}}
{{{debug this}}}
<h1>{{name}}</h1>
Where I want to triple brackets to stay, but double brackets to be replaced with the JSON passed in. Anyone know the best way to do this without writing post-process JS code, and if not, is there a good nodeJS template engine for this type of scenario?
As described in this Question handlebars doesn't support changing the delimiters. But you can escape the double braces with a backslash like this:
HTML:
... \{{ myHandlbarsVar }} ...
You can switch delimiters to something that won't conflict with the triple mustaches, like erb-style tags:
{{=<% %>=}}
{{{
{
"name": "<% name %>",
"description": "<% description %>"
}
}}}
{{{debug this}}}
<%={{ }}=%>
Note that you can do this as many times as you like throughout your template. Any time you run into something that conflicts, pick a new set of delimiters :)
You can also assign Mustache.tags = ["[[", "]]"]; before your template compilation.
http://jsfiddle.net/fhwe4o8k/1/
e.g.
$(function () {
Mustache.tags = ["[[", "]]"];
var template = $('#test').html();
Mustache.parse(template);
var rendered = Mustache.render(template, {test: "Chris"});
$('#content-placeholder').html(rendered);
});
another option is create a helper for outputing curly brackets.
Handlebars.registerHelper('curly', function(object, open) {
return open ? '{' : '}';
});
and then use it in the template like this:
<script id="template" type="text/x-handlebars-template">
{{curly true}}{{name}}{{curly}}
</script>
which then outputs:
{Stack Over Flow Rocks}
The template contains HTML, so you could use HTML-Entities, for example the ASCII-codes 123 and 125 for braces:
{{{myValue}}}
I just wanted slightly different approach. I have tried few other other ways and here are few things which I didn't like about them:
Changing Angular default {{obj.property}} brackets to something else is a bad idea. Mainly beacause as soon as you start using third party components which are not aware of you non standard angular configuration, bindings in those third part components will stop working. Also worth mentioning that AngularJS team doesn't seem to want to go the route of allowing multiple binding notations, check this issue
I quite like Mustache templates and don't want to switch the whole project to something else because of this small issue.
Quite a few people recommend not to mix client and server side rendering. I don't fully agree, I believe if you are building a multipage website which has few pages with angular and some other which are static (something like about us or Terms and Conditions pages) it is perfectly fine to use server side templating to make maintaining those pages easier. But that said, for parts which are Angular you shouldn't mixing server side rendering.
Ok no my answer:
If you are using NodeJS and Express you should be to the following:
Replace bindings {{}} in your angular part with something like {[{}]} (or something completely unique)
Now in you route add a callback to you render method:
app.get('/', function(req, res){
res.render('home', {
title: 'Awesome Website',
description: 'Uber Awesome Website'
}, function(err, html){
var htmlWithReplacedLeftBracket = html.replace(/{\[{/g, '{{');
var finalHtml = htmlWithReplacedLeftBracket.replace(/}\]}/g, '}}');
res.send(finalHtml);
});
});
This should allow you to use Mustache together with AngularJS. One improvement you could do is extract that method into a separate module to reuse across all routes.
This is a good solution I have found for this type of problem where you can easily switch delimiters in the template settings in runtime:
http://olado.github.com/doT/
You can do the RegEx settings like this:
doT.templateSettings = {
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: 'it',
strip: true,
append: true,
selfcontained: false
};

JavaScript template library that doesn't use eval/new Function

Google Chrome extensions using manifest_version: 2 are restricted from using eval or new Function. All of the JavaScript templating libraries I checked (mustachejs, underscorejs, jQuery template, hoganjs, etc) use new Function. Are there any that are fairly mature and supported that don't use either?
Info about the security restrictions.
It turns out that mustachejs added new Function recently and using tag 0.4.2 doesn't have it. It the API is slightly different with Mustache.to_html instead of Mustache.render and there are likely some performance reduction.
I opened an issue to potentially get new Function removed in a future release.
It doesn't appear that Pure uses either eval or new Function.
The answers here are outdated so I post an update.
Since September, Google changed their policy and allowed unsafe-eval in manifest 2 extensions. See this thread and this page.
So libraries using eval(), new Function() etc. can be used if unsafe-eval is turned on for your extensions.
Closure Templates is a templating library that does not use eval. Templates are compiled to JavaScript ahead of time, so that what gets included in your app is a plain .js file that should not run into CSP issues.
Distal template doesn't use eval.
It really depends on what you mean by "template library". If you just want string interpolation, there's no need for eval or new Function, when you start needing embedded looping structures, things get more complicated.
A few months ago I wrote a String.prototype.tmpl.js script that I've used a couple times here and there in places where I don't mind overriding String.prototype. As a static function, you can use:
tmpl.js:
function tmpl(tmpl, o) {
return tmpl.replace(/<%=(?:"([^"]*)"|(.*?))%>/g, function (item, qparam, param) {
return o[qparam] || o[param];
});
}
An example template:
<div id="bar"></div>
<script type="text/x-tmpl" id="foo">
<h1><%=title%></h1>
<p><%=body%></p>
</script>
<script>
(function () {
var foo,
bar;
foo = document.getElementById('foo');
bar = document.getElementById('bar');
bar.innerHTML = tmpl(foo.innerHTML, {
title: 'foo bar baz',
body: 'lorem ipsum dolor sit amet'
});
}());
</script>
The base tmpl script can of course be modified to take advantage of document fragments to actually build out DOM elements, but as-is I'm not sure whether it counts as a "template library".
The best solution to this problem is to pre-compile your templates before you deploy your extension. Both handlebarsjs and eco offer pre-compilation as a feature. I actually wrote a blog post that goes into more depth.
Maybe you can write a function eval1:
function eval1(blah) {
var s = document.createElement("script");
s.src = blah;
document.head.appendChild(s);
document.head.removeChild(s);
}
and do a find/replace in the library you want, but that'd be cheating, right?
I recently run into the same problem. After updating manifest version my extension stopped working. I tried Mustache but it unable to render index of the array and names of the object properties. So I had to create my own simple but effective templating library Ashe which is free of eval and new Function. Hope it will help someone.
https://developer.chrome.com/extensions/sandboxingEval
Not sure when it was added, but you can do Firefox style sandboxing in Chrome now. I'm porting my Firefox extension, so I need this (since I don't have evalInSandbox :P)

Categories

Resources