pillarjs / hbs Goto Github PK
View Code? Open in Web Editor NEWExpress view engine wrapper for Handlebars
License: MIT License
Express view engine wrapper for Handlebars
License: MIT License
Express templating wrappers are being moved here:
I am trying to use i18n with hbs and express.
I tried to register a i18n helper for the translation, but I don't seem to manage to have both the request (to get the locale of the request) and the text to be translated in the same place.
I have tried two different ways to do that:
the first (have the request but not the text, from the i18n-node project examples):
// binding template helpers to request (Credits to https://github.com/enyo #12)
app.use(function(req, res, next) {
res.locals.__ = function() {
return i18n.__.apply(req, arguments);
};
res.locals.__n = function() {
return i18n.__n.apply(req, arguments);
};
// do not forget this, otherwise your app will hang
next();
});
The second (have the text but no the request):
hbs.registerHelper '__i', (options)->
if i18n?
return i18n.__.apply this, [options.fn this]
return options.fn this
hbs.registerHelper '__n', (options)->
if i18n?
return i18n.__n.apply this, [options.fn this]
return options.fn this
What I am currently doing, is defining a middleware that sets the locale of the i18n object on every request, and using the second way for registering the partial:
app.use (req, res, next) ->
i18n.setLocale i18n.getLocale req
do next
It works, but I am worried from concurrency issues.
Am I doing it wrong or is this the intended way of doing it?
Is there really a concurrency issue?
Should the hbs module be adjusted so that registering the partials work like other templating engines (the first example)
Thanks.
In 'layout.hbs' I'd like to place expression say {{{js_script}}} and register another template say 'script.hbs' to be included in the place. Is it possible?
Regards
Darek
There is warning that hbs.SafeString
is deprecated in the source code, but it seems to still be supported by Handlebars. Do you mean we should use handlebars.SafeString directly? Using the handlebars constructor gives a Object xxx has no method 'replace'
error:
hbs.registerHelper('help', function(){
return new handlebars.SafeString('hello')
})
hbs.localsAsTemplateData(app); doesnt seem to work for me.
app.locals.XY are directly accessible via {{ XY }} but properties are not accessible via {{@xy}}
Using latest version of express (4) and your latest lib
Inside a view, in express, you can access the application settings via settings.foo
, but once a partial is included, that partial doesn't get the settings object.
Simple test with:
hbs.registerHelper('log', function (context) {
console.log(context);
});
Then in the index.hbs:
{{#log settings}}{{/log}}
{{> subpage}}
And subpage.hbs:
{{#log settings}}{{/log}}
I would expect the same express internals regardless of whether I'm at the top level or not.
I'm getting a bug with that helper:
hbs.registerHelper('fromnow', function(val) {
return 'test';
});
and in my view:
{{fromnow user}}
The error is:
/node_modules/hbs/node_modules/handlebars/lib/handlebars/base.js:22
throw new Error("Could not find property '" + arg + "'");
^
Error: Could not find property 'fromnow'
Handlebars has the concept of lexical data which persists even as context changes. This is provided as the second parameter to the template:
var template = Handlebars.compile( source );
var html = template( context, { data: lexicalData } );
Although Express doesn't have this concept itself, it'd be useful to provide this functionality within hbs. Since Express merges app.locals
, response.locals
and the template data before passing it to the view, this would require proxying app.render()
. Unfortunately this isn't very clean, so I'd like to get a discussion going about whether or not you're open to exploring this idea.
I'm using hbs with express, and find that I have to restart my node server every time I make a change to a partial in order for that change to be picked up. It makes development a bit more complicated to have to perform that extra step.
With proper templates, one can disable caching in development mode so this isn't an issue. Is there any way to do the same for partials?
I currently use the registerPartials
helper; I could see modifying it (in development mode, or based on a config flag) to use the fs.watch API to monitor that directory, and then just reload the partials if something changes.
If I took a stab at this, is it something you'd consider pulling into the master branch?
It appears there is no way to escape front-end handlebars templates. When I try to push my <script type="x-handlebars-templates"> to the front end, all of the {{variables}} are consumed. I'm a noob to both node and express, so I might be missing something fundamental, but is there a way to do this?
Hello Don,
Thanks for your work on this!
Could you add a LICENSE file to the root directory or add licenses to the end of the readme? Given that express itself is only MIT licensed (https://github.com/visionmedia/express/blob/master/LICENSE ) that would probably make the most sense.
Thanks!
Used with this patch:
http://stackoverflow.com/questions/11315351/multiple-view-paths-on-node-js-express
I'm getting the ID/hash (__af2oij3__
) rendering for async helpers when I put my app on Heroku, but not locally. Just wondering if anyone else has run into this and has some ideas... Sorry I don't have more details to explain why it's happening. Is there a timeout that it gives on trying to replace the IDs after?
Hello,
I've upgraded to express 3.0 and using hbs version 1.0.3.
I get an error now that it can't find property 'partial' in node_modules/handlebars/lib/handlebars/base.js:22:11)
It occurs when I add the additional object to pass to the view in res.render()
res.render('account/index', {user: req.session.user, page_part: page_part});
Is there a workaround for this or a new way to pass variables?
Thank you!
I am using an html view engine:
app.set('view engine', 'html');
app.engine('html', require('./hbs')(app, config));
And specifying my layout (layout_simple.html
) like this:
res.render('signup', {
layout: 'layout_simple'
});
Up until version 2.8.0 this was working fine. After upgrading to hbs
2.9.0 I'm getting an error on load:
Error: ENOENT, open '/.../layout_simple.hbs'
(where /.../
is the correct view path.)
Specifying the layout explicitly as layout: 'layout_simple.html'
works correctly. Seems like a bug to me.
This change may be the culprit:
donpark:18c1823...donpark:5e44774#diff-0646323334941cee08c9e424acbee543R120
Hello,
I'm new to using template rendering in express. I was curious why hbs gives an error if I haven't defined a layout.hbs file. I discovered through a bit of source code browsing that I can disable the error using layout: false in the locals object, but why is that necessary?
Thanks!
Ben
Hello everyone ๐, I hope you have had a good 2014 year :)
to start 2015 in good condition I have a tricky question for you ๐
javascript code
var hbs = require('express-hbs');
app.engine('hbs', hbs.express3());
app.set('view engine', 'hbs'); // to lauche render when .hbs
app.set('views', __dirname + '/views');
...
hbs.registerHelper('log', function() {
console.log('log');
console.log('arguments:', arguments);
});
hbs.registerAsyncHelper('asynclog', function() {
console.log('asynclog');
console.log('arguments:', arguments);
});
...
handlebars code
log file
log
arguments: {
'0': 'tariffDatetimeLb',
'1': { name: 'log', hash: {}, data: { root: [Object] } }
}
asynclog
arguments: {
'0': 'tariffDatetimeLb',
'1': [Function]
}
I expected something like
log
arguments: {
'0': 'tariffDatetimeLb',
'1': { name: 'log', hash: {}, data: { root: [Object] } } }
asynclog
arguments: {
'0': 'tariffDatetimeLb',
'1': { name: 'log', hash: {}, data: { root: [Object] } },
'2': [Function]
}
so why when I use the Async helper I lose the "global" context
I don't know how to call the "{ name: 'log', hash: {}, data: .... } object ๐
but I really need it, so could you help me ? :)
Thanks in advance
Can you add an example of using layout and a partial and passing data to the partial?
What title saids. They are just better.
Apparently, latest handlebars package breaks hbs.
The arg passed to helpers is now an obj, not a function.
hbs looks for layout by default, and it's been deprected in latest express.js
It should be documented so that users don't have to read the code.
this.__get__
function is supposed to be there but is not.
It's not clear if this is a Handlebars bug or not.
In the currently-referenced version of Handlebars, if there is an empty template file the server will crash on the following exception:
Error: You must pass a string or Handlebars AST to Handlebars.compile. You passed
I noticed this when I was early in development on a new project and had an empty template so I could test a case for template inheritance. I had planned to leave this file empty, but instead had to enter some dummy info to prevent this exception.
This issue was reported to the handlebars project earlier this year and has since been corrected: handlebars-lang/handlebars.js/issues/461. Please update the hbs project to require handlebars 1.0.12 (the latest) to eliminate this defect.
I get this error: 500 Error: ENOENT, open 'C:\Users\Gilbert\WebstormProjects\games\views\layout.hbs' but my project has no reference to this file.
app.js: https://gist.github.com/3349334
routes/index.js: https://gist.github.com/3349341
views/hi.hbs: <h1>IT WORKS</h1>
If the layout file is not present, the current behavior is to fail and inform the user. It has been suggested it it should instead render the file without a layout.
The behavior would be as follows:
see issue #38 for additional notes
In addition to partials, would be nice to support having a layout template that we flow content into.
Error dump
TypeError: Object #<Object> has no method '__get__'
at Object.<anonymous> (/Users/don/dev/github/hbs/test/server/app.js:48:37)
at program9 (eval at <anonymous> (/Users/don/dev/github/hbs/node_modules/handlebars/lib/handlebars/compiler/compiler.js:468:25))
at /Users/don/dev/github/hbs/node_modules/handlebars/lib/handlebars/vm.js:45:14
at Object.<anonymous> (/Users/don/dev/github/hbs/node_modules/handlebars/lib/handlebars/base.js:44:21)
at Object.anonymous (eval at <anonymous> (/Users/don/dev/github/hbs/node_modules/handlebars/lib/handlebars/compiler/compiler.js:468:25))
at /Users/don/dev/github/hbs/node_modules/handlebars/lib/handlebars/vm.js:28:27
at Object.<anonymous> (/Users/don/dev/github/hbs/lib/hbs.js:10:12)
at ServerResponse._render (/Users/don/dev/github/hbs/node_modules/express/lib/view.js:422:21)
at ServerResponse.render (/Users/don/dev/github/hbs/node_modules/express/lib/view.js:315:17)
at /Users/don/dev/github/hbs/test/server/app.js:54:7
Just like partials, where can i define witch layout to use? I saw your example, but its really basic and looks like we need to put layout.html in same directory as view file.
Also, can we have multiple layouts?
Sorry for the obvious question - what's the difference between this and https://github.com/barc/express-hbs?
Is there a way to handle pre-compiled handlebars templates?
I have a class, which contains both data elements, and methods/functions. For an instance of the class, if I access the methods within the application, they work as intended, but when I reference them from a template, they are called, but "this" has the wrong content.
I'll try and include a cut-down example to illustrate:
// Class "User"
function User(name) {
this.initial_name = name;
this.default_name = 'Barry';
this.custom_name = null;
}
User.prototype.name = function() {
return this.custom_name || this.initial_name || this.default_name;
}
// Init a user
a_user = new User('Bilbo');
// Add it to locals
app.locals.user = a_user;
Then, in my template, I try and use:
Hello {{user.name}}!
It calls the name method, but "this" seems to be all the template data, and not the User object data as expected. Calling a_user.name() and app.locals.user.name() work fine - it just seems to be the template reference that it gets wrong.
Is this a bug/feature of hbs, or a bigger issue with express?
What is the recommended way to work around this?
Thanks.
Supporting registerPartial and registerHelper would be very helpful. It doesn't seem straightforward though. The latest handlebars doesn't run in node (missing handlebars/parser), and the compiled version doesn't expose the Handlebars object.
I'm sure you've thought about this. Are you more familiar with Handlebars' progress?
I've got a helper that I register when called back from hbsutils.registerPartials():
hbs.registerHelper('include', function(template, options) {
var partial = hbs.handlebars.partials[template];
// partial will usually be a [Function], but is sometimes the raw html string
console.log(partial)
var context = _.extend({}, this, options.hash);
return new hbs.handlebars.SafeString(partial(context)); // this will blow if partial is a string
});
I've had one partial file work and another not work, even if both files contain the same content.
ptraci:~ adrian$ sudo npm install hbs
Password:
npm info it worked if it ends with ok
npm info using [email protected]
npm info using [email protected]
npm ERR! Error: ucs {bad_utf8_character_code}: hbs
npm ERR! at IncomingMessage. (/usr/local/lib/node/.npm/npm/0.3.18/package/lib/utils/registr/request.js:173:16)
npm ERR! at IncomingMessage.emit (events.js:81:20)
npm ERR! at HTTPParser.onMessageComplete (http.js:133:23)
npm ERR! at Socket.ondata (http.js:1226:22)
npm ERR! at Socket._onReadable (net.js:683:27)
npm ERR! at IOWatcher.onReadable as callback
npm ERR! Report this entire log at http://github.com/isaacs/npm/issues
npm ERR! or email it to [email protected]
npm ERR! Just tweeting a tiny part of the error will not be helpful.
npm ERR! System Darwin 10.7.4
npm ERR! argv { remain: [ 'hbs' ],
npm ERR! argv cooked: [ 'install', 'hbs' ],
npm ERR! argv original: [ 'install', 'hbs' ] }
npm not ok
Hello Don,
Thanks for your work on this!
Could you add a LICENSE file to the root directory or add licenses to the end of the readme? Given that express itself is only MIT licensed (https://github.com/visionmedia/express/blob/master/LICENSE ) that would probably make the most sense.
Thanks!
Need to wrap Express helpers and partials so they can be used in Handlebars template.
I'm seeing any way to change the handlebars delimiter. I mustache, the spec indicates that you can escape like this.
But when I try to do this using hbs is fails after trying to evaluate the content of my AngularJS variables. Is changing the delimiter supported in hbs?
In this simple layout I have the {{{body}}}
tag implemented once. But on the page it outputs this whole layout within that body tag 3 times. (It also renders the appropriate view)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>MyTrainerMapS</title>
{{{stylesheet 'styles.css'}}
</head>
<body>
{{{body}}}
<script>
document.write('<script src=' +
('__proto__' in {} ? 'http://zeptojs.com/zepto.min.js' : 'http://code.jquery.com/jquery-1.7.2.min.js') +
'><\/script>')
</script>
{{{javascript 'scripts.js'}}}
</body>
</html>
I do not think it is clear in your readme.md
that the hbs.registerPartials
function is actually async. Can I suggest either:
done
callback that I am now using.walk.walkSync
rather than walk.on
I do not see why this method should be async. Given that partial registration should happen once at start up I think a sync function would be more appropriate.
likely Expresso but prefer something lighter.
I've got an express app that loads other express apps as middleware. They all share views in the same directory but the various express apps are in different directories.
Correct me if I'm wrong, but it looks like the views are being loaded by a relative path, instead of where I set them in the master app: app.set("views", __dirname + "/views");
Is that what's happening?
Edit: it looks like it's trying to get a view_dir but it seems to be undefined. var view_dir = options.settings.views;
When a layout is chosen using on object sent to the res.render('...', { layout: 'myLayout' })
method the view seems to be nested several times in the chosen layout. This problem doesn't seem to occur with the default layout that can be supplied via app.set('layout', '...')
.
I made an example app to demonstrate the issue: https://github.com/jfelsinger/layout-bug
The expected response for the returned page would be:
<html>
<h1>Hello</h1>
</html>
But this is what the response looks like instead:
<html>
<html>
<html>
<h1>Hello</h1>
</html>
</html>
</html>
This is quite annoying for more complex layouts, because script tags and a number of other things get repeated, potentially breaking a site.
Disclaimer: I am not sure if this is a problem with hbs or express-layout, so I'm making an issue on both. :(
I know that handlebars is supposed to be logic-less, and that's a good thing, but I feel like something is wrong when I have to pass a parameter to the view like { is_production: (app.setting.env == 'production') }
because I am not allowed to do {{#if app.settings.env == 'production') }}
.
This seems like a really common problem: it makes a lot of sense that I would want to tweak the views based on whether or not I'm in production mode.
Any thoughts on adding some feature like this for express. Perhaps adding a built-in function that might accomplish this?
Just tried the example:
app = express.createServer()
app.configure ->
...
app.engine 'html', require('hbs').__express
...and I get:
Object #<HTTPServer> has no method 'engine'
Thoughts?
I have raw code to be printed, I'm working with Angular too. I create a custom block helper called raw, and {{string}} like this works good, but string like {{modulo.editing ? 'Editando':'Salir' }} goes wrong.
hbs.registerHelper('raw', function(name, context) {
return name;
});
{{{raw '
My HTML code for {{angular}} but goes wrong with {{anyBool?'ok':'Not'}}.
' }}}
Is there any way for {{raw}} All my stuff {{/raw}}
Thanks.
Hi,
How to get the response or app locals passed to the main layout or the partials.
It's works fine for the view called from the res.render('myview')
but not any other.
Data passed to the render function get exppsed to all layout and partial (using this
)
thanks,
Hey @donpark
How do you feel about pushing the Handlebars dependency to v2.0 (it is stable now : https://github.com/wycats/handlebars.js/releases/tag/v2.0.0)
Cheers
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.