I can't figure out how to use the dustjs-linkedin templates for express 3.x
#app.js
var dust = require('dustjs-linkedin');
app.set('view engine', 'dust');
app.get('/test1', routes.test1);
#./routes/test.js
exports.test1 = function(req, res){
res.locals.session = req.session;
res.render('test1', { title: 'Test 1' } );
};
#./views/test1.dust
{+base.dust/}
{<main}
Child Content
{/main}
#./views/base.dust
{+main}
Base Content
{/main}
I get the following error when going to /test1
500 Error: Cannot find module 'dust'
I had the same problems as you. And to ease the use of dustjs-linkedin together with express 3.x i put together the small library klei-dust. The library is simple to setup and you can set the root folder for views, which applies to base-templates and partials.
So if you have a views folder at views/ with home.dust and base.dust templates, the home.dust can look like this:
{>base/}
{<main}
Hello world
{/main}
So there's no need to write views/base.dust for it to work.
I've managed to get a working version of dustjs-linkedin with consolidate module.
https://github.com/chovy/express-template-demo
FYI, the layout has to be double quoted...that was a major gotcha for me, and its relative to app.js file, and it needs a trailing /
{+"views/base.dust"/}
<p>Page content here</p>
I will explain u how you should use express 3.x with dustjs-linkedin.
1) express has 2 config to set. 'view engine' and app.engine
"view engine" just sets the default and that app.engine just maps what engine to use for a given file extension.
so you should do something like this:
app.set('view engine', 'dustjs-linkedin');
app.set('views', __dirname + '/views');
app.engine('dust', dust.compileFromPath);
There is only one problem with this is that the method compileFromPath doesn't exist in dust :p.
You should add a method in the dust object with this signature that Express expects: (path, options, callback)
you can read more about this here: http://expressjs.com/api.html#app.engine.
Another option would be to use consolidate (http://spalatnik.com/blog/?p=54) but unfortunately Consolidate doesn't support the dustjs-linkedin version it only support the old dust version.
Related
I and the team got a task to implement multiple themes for our project (keeping in mind that we have a single-theme project right now).
By theme I don't mean just CSS, I mean different markup files, certain features for certain things, etc. (If you don't like the word 'theme' in this context don't use it, I hope you get the idea: some things need to be reused across the codebase, some things need to be specific to a theme). Overall, we have no problem of structuring it in a maintainable way and implementing the most of it, but we don't know how to make multiple express-handlebars configs, which we can switch based on certain factors.
Right now we have a pretty standard express-handlebars project structure like such:
views/
index
layouts/
main.hbs
content.hbs
whatever.hbs
What we want is something like this:
views/
themes
theme1
layouts/
main.hbs
index.hbs
content.hbs
theme2
layouts/
main.hbs
index
We use a pretty standard way to initialize express-handlebars in our app startup file like this:
var handlebars = exphbs.create({
defaultLayout: 'main',
extname: '.hbs',
helpers: require('./server/hbsHelpers')
});
app.engine('.hbs', handlebars.engine);
app.set('view engine', '.hbs');
app.set('views', __dirname + '/views');
I was thinking to initialize several exphbs objects and switch them at runtime (request time) but this is not going to work since app.set would be an app-wide setting (long story short we host multiple websites with one app and can't afford change anything on app level, only on the express request level).
Desired behaviour is something like this:
res.render(‘/theme1/file.hbs’);
looks like there's no problem just to render directly without a configuration, but then we also need to specify that handlebars needs to grab layouts and partials for a specific theme from a specific source
or
res.render(‘file.hbs’, { theme: ‘theme1’ });
We're using this variant of express handlebars – https://github.com/ericf/express-handlebars
(May be you can advice an alternative that allows what I described above that we can interchange and not break a lot of things - our code base is pretty huge)?
Any of your help, ideas or advice would be highly appreciated.
You didn't mention how you would determine which theme each request would be rendered with but I think the simplest approach is to override the res.render() method.
app.use(function(req, res, next) {
// cache original render
var _render = res.render;
res.render = function(view, options, done) {
// custom logic to determine which theme to render
var theme = getThemeFromRequest(req);
// ends up rendering /themes/theme1/index.hbs
_render.call(this, 'themes/' + theme + '/' + view, options, done);
};
next();
});
function getThemeFromRequest(req) {
// in your case you probably would get this from req.hostname or something
// but this example will render the file from theme2 if you add ?theme=2 to the url
if(req.query && req.query.theme) {
return 'theme' + req.query.theme;
}
// default to theme1
return 'theme1';
}
The nice thing about this is your calls in your controller will still be clean - res.render('feature/index.hbs') as long as you have that file in each theme folder you should be good.
You could make getThemeFromRequest a lot smarter and it could check to see if the template exists for that theme and if not render the file from the default theme which may help prevent a bunch of duplicate html.
I have converted static html and converted it into strings and emailed it. Now want to pass dynamic value to the html and convert it into string and email it. I'm using cons.underscore as view engine for rendering html pages.
DON'T USE readFileSync! It will lock your program!
If you need pass dynamic variables into template render, you need use the .render in your express server.
Maybe you will need install the extensions:
npm install underscore --save
npm install consolidate --save
For this, set your template engine in express:
app.set('view engine', 'html');
app.engine('html', require('consolidate').underscore);
And get the page like this on your listener:
var options = { email : 'test#op.com'};
res.render('index', options);
I'm getting an Error: cannot find module 'hogan' when I send a request to the node.js server implemented in Coffeescript here:
https://gist.github.com/wmayner/306c89d7f8fbeed3f098
I've installed the dependencies hogan.js, consolidate, and express.
I've reproduced the example code from consolidate's documentation (reproduced below) almost exactly, so I'm having trouble seeing where this error is coming from. It looks like it should work.
From the consolidate docs:
var express = require('express')
, cons = require('consolidate')
, app = express();
// assign the swig engine to .html files
app.engine('html', cons.swig);
// set .html as the default extension
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
I've also tried declaring `hogan = require('hogan.js')' as a dependency.
Anyone have an idea why this is happening?
Note: The gist above differs from the consolidate docs in that I'm setting the view engine to hogan rather than html. This is because I'd rather use .hogan than .html for my template file extensions (I've tried .html and I get the same error).
Your gist sets hogan as view engine, but that should be html like in the Consolidate docs:
// tell Express to use Consolidates 'hogan' renderer for .html templates
engines = require 'consolidate'
engine = 'hogan'
app.engine 'html', engines[engine]
// tell Express to use '.html' as extension to find views with .render()
app.set 'view engine', 'html'
EDIT: realizing that perhaps you want to use .hogan as extension for your template files, you could use this instead:
app.engine 'hogan', engines[engine]
app.set 'view engine', 'hogan'
I'm trying to get Mustache working properly with Express, and as one can guess, I'm having troubles.
The following line initializes Mustache nice and clean. Variables render as expected.
app.register('html', require(__dirname+'/public/js/libs/mustache.js'));
However, the problems start to rise when partials are thrown in the mix. With Mustache, this here partial should invoke header view/partial.
{{> header}}
But alas, nothing happens. :/ Even when I offer the partial directly, Mustache fails to render it.
app.get('/', function(req, res) {
res.render('welcome', {
partials: {
header: '<h1>Header</h1>'
}
});
});
So, it seems that the partials aren't working at all. I've found one hack that get's the partials somewhat working:
http://bitdrift.com/post/2376383378/using-mustache-templates-in-express
After that the partials render when offered directly at render call (see above), but it still fails on rendering the partials directly to views/layouts:
Layout looks something like this:
Behold, the header
{{> header}}
<p>Let's move to more important stuff...</p>
Header view looks something like this:
<h1>Header</h1>
Express can load the views by themselves just ok, but it doesn't know how to handle the Mustache partials...
Using express (at least version 3) and mustache-express, You can load partials as usual using double mustaches that begin with a greater than sign.
First consider the following is appended within our app.js file:
/** import the module */
import mustache from 'mustache-express';
/** view engine setup */
app.engine('mst', mustache());
app.set('view engine', 'mst');
app.set('views', path.join(__dirname, 'mvc/views'));
/** the route where we will display the partials */
app.get('/', (req, res) => {
let view = {
title: 'Homepage',
// ...
};
/** we are going to use a file called template.mst for rendering */
res.render('template', view);
});
Any double mustaches that begin with a greater than sign (i.e. {{> file}}) will be considered a partial. The file within the partial will be rendered at runtime. Consider this file to be a partial we want to insert:
mvc/views/partial.mst
<h2>418 | I'm a teapot</h2>
And here is our template:
mvc/views/template.mst
<h1>template.mst file</h1>
<!-- output: <h2>418 | I'm a teapot</h2> -->
{{> partial}}
Managed to get this working with the latest version of hogan-express.
https://github.com/vol4ok/hogan-express
All that is needed is to install hogan-express and use it as template engine on express. No hacking or tuning required.
I'm not sure what's exactly in your ./public/js/libs/mustache.js ... I use the mustache module from npm + a variation of the templating object you linked to.
In any case, the object you pass to app.register needs to call mustache.to_html(template, locals, partials) at some point.
You need to pass the partials object as the third argument to mustache's to_html.
Is there a template engine for Express (node.js) which is based on Mustache or uses a similar syntax?
All I could find is haml, jade, ejs, jquery templates and one based on CoffeeScript (I write plain JS).
I want to write "normal" html, so only ejs and jqtpl would fit. I already use mustache with backbone so it would be best to also use it on the server side with Node.js
Just stumbled on this ancient thread but no one has mentioned consolidate.js, which seems to be the "right" way under Express 3 (refer to http://expressjs.com/faq.html). It also provides an easy way to switch/experiment with templating systems.
Here's a simple example - http://invitingthebell.com/2012/12/24/mustache-templates-in-express-3-0/.
Code, in case it disappears is:
var express = require('express')
, cons = require('consolidate')
, app = express();
// assign the mustache engine to .html files
app.engine('html', cons.mustache);
// set .html as the default extension
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
// test mustache
app.get('/', function(req, res){
var viewdata = { 'test' : 'Hey now.'};
res.render('index', viewdata);
});
app.listen(3000);
The index.html file in the views directory:
<html>
<head><title>Some CMS</title></head>
<body>
<h1>Mustache</h1>
<p>What do you say?</p>
<p>{{test}}</p>
</body>
</html>
You could probably add Mustache as a rendering engine by following the Express manual:
View filenames take the form “.”, where is the name of the module >that will be required. For example the view layout.ejs will tell the view system to >require(‘ejs’), the module being loaded must export the method exports.compile(str, >options), and return a Function to comply with Express.
Edit:
From the Mustache manual under Usage:
Below is quick example how to use mustache.js:
var view = {
title: "Joe",
calc: function () {
return 2 + 4;
}
};
var output = Mustache.render("{{title}} spends {{calc}}", view);
In this example, the Mustache.render function takes two parameters: 1) the mustache >template and 2) a view object that contains the data and code needed to render the >template.
From the above I suspect you could just export Mustache.render, but I haven't tested it. The object literals used as data look the same, but if they do happen to be different, you could probably just wrap Mustache.render in a function that formats it correctly.
Edit: Xomby's wrapper link contains an example of how to wrap handlebars for express, Mustache should be similar.
Try Hogan.js http://twitter.github.com/hogan.js/
I think it's what Twitter and LinkedIn uses in production.
Here's a working example/tutorial on using NodeJS, ExpressJS and MustacheJS Template Engine:
http://devcrapshoot.com/javascript/nodejs-expressjs-and-mustachejs-template-engine
You can build out a complete web page like you normally would, placing the mustacheJS fields where you like. Use express to route to the page, use node fs.readFileSync(); to get the html file, use mustache to update the data on the page then spit it out to the client.
It's kinda neat. I hope it helps!
-A-
Have you already tried stache ? It is no longer maintained but you can follow some links and get more recent stuff ..
I found Handlebars.js which is an extension of the Mustache template system/language.
And there is a really simple wrapper to use it with Express.
Sure, the best way to do this is the post here:
http://iamtherockstar.com/blog/2011/11/21/using-mustache-templates-express-apps/
So far, this has worked great for me. The only problem I have found is not using partials at the root path for views. For example partials in view/partials - the engine by default only finds partials as view. Let me know if you figure that out!
Check out Handlerbars. " Handlebars provides the power necessary to let you build semantic templates effectively with no frustration.
Handlebars is largely compatible with Mustache templates. In most cases it is possible to swap out Mustache with Handlebars and continue using your current templates. Complete details can be found here " - Handlebars