handlebars-lang / handlebars.js Goto Github PK
View Code? Open in Web Editor NEWMinimal templating on steroids.
Home Page: http://handlebarsjs.com
License: MIT License
Minimal templating on steroids.
Home Page: http://handlebarsjs.com
License: MIT License
when evaluating a block, handlebars fails if there is no content. eg
{{#my_list}}{{/my_list}}
or
{{^my_list}}{{/my_list}}
Not sure if this is a bug, but it would be nice to be able to do.
I'm looking at using Handlebars.js in a product at my day-job. Unfortunately, I've got to get permission from legal, and they won't bless its use without a license. Is there a particular license you're releasing Handlebars under? I couldn't find one in the repository.
In FF 3.6.9 the example template doesn't render the nested data structures and the unit tests fail on test 3 onwards.
Block helper functions aren't able to call get or fn as functions don't seem to survive the contextWrapper. Tested in FF, Chrome and Safari.
From the example function...
this.get is not a function
[Break on this error] return '<a href="/people/' + this.__...+ this.get("id") + '">' + '';
line: Handlebars.compile("num1: {{num1}}, num2: {{num2}}")({num1: 42, num2: 0});
output: 'num1: 42, num2:'
output should be: 'num1: 42, num2: 0'
I might have missed it, but I had a hard time to find the documentation site: http://handlebars.strobeapp.com/ . Eventually I found it with some help of Google. Please at it to the README or in the github description.
Thanks,
Jeroen
Memoized paths can sometimes collide with methods on the array object. I updated it to use the following code instead, and it fixed the problem:
parsePath: function(path) {
if (path == null) {
return [0, []];
} else if (Handlebars.pathPatterns["hbr-" + path] != null) {
return Handlebars.pathPatterns["hbr-" + path];
}
var parts = path.split("/");
var readDepth = false;
var depth = 0;
var dig = [];
for (var i = 0, j = parts.length; i < j; i++) {
switch(parts[i]) {
case "..":
if (readDepth) {
throw new Handlebars.Exception("Cannot jump out of context after moving into a context.");
} else {
depth += 1;
}
break;
case ".":
// do nothing - using .'s is pretty dumb, but it's also basically free for us to support
case "this":
// if we do nothing you'll end up sticking in the same context
break;
default:
readDepth = true;
dig.push(parts[i]);
}
}
var ret = [depth, dig];
Handlebars.pathPatterns["hbr-" + path] = ret;
return ret;
},
I'm not a Ruby programmer, but I wanted to build handlebars on my (Ubuntu) machine. It would be nice to have better documentation on how to build. Your readme states:
just run 'rake release'
I did not find it that simple. I had to:
apt-get install ruby
apt-get install rubygems
gem install bundler
gem install diff-lcs
gem install rspec
gem install rspec-core
And now I'm stuck with the error message:
Could not find rspec-core-2.1.0 in any of the sources
Sorry if I'm being stupid - thanks for the help.
evalExpression is a lot more stable than the attempt at generating array notation for shorter expressions, so we need to use it.
I'm pretty New to Mustache and Handlebars and seem to be missing some critical piece.
I am getting an error on line 1 of handlebars.js -> var Handlebars = require("handlebars/base");
It seems to be using a require wrapper function but I get an undefined error so I'm assuming i am missing a dependency?
Can anybody point me in the right direction. Any help would be greatly appreciated. Thanks.
The "Learn more: Expressions" button near the top of the page is throwing a 404:
When you use paths inside a section block ({{/some/thing}}
), the context is wrong when handlebars calls thing().
See the following code:
var templateSrc1 = "Testing the context blocks with paths: {{#nestedObject/bar}} Yes {{/nestedObject/bar}}";
function SomeObject(nestedObject) {
this.name = 'SomeObject';
this.nestedObject = nestedObject;
}
function AnotherObject(_bar) {
this.name = 'AnotherObject';
this._bar = _bar;
this.bar = function() {
console.log('this inside AnotherObject.bar', this, this.name);
return this.bar;
}
}
var view = new SomeObject(new AnotherObject("the bar value")),
template = Handlebars.compile(templateSrc1);
console.log('Template output: ', template(view));
The output I'd expect:
This when inside AnotherObject.bar: Object {...} AnotherObject
Template output: Testing the context blocks with paths: Yes
But when you run it, you really get:
This when inside AnotherObject.bar: Object {...} SomeObject
Template output: Testing the context blocks with paths: undefined
Maybe I'm wrong, but I'd expect that bar()
would be called with the context set to nestedObject
.
ps: No offense intended, but I think that handlebars.js isn't quite ready for "serious" usage yet. You've done some great work and I can't wait until I can use it, but I think that I'm going to have to switch back to our own custom hacked mustache.js for now. (Maybe I can help and commit fixes later, but I unfortunately don't have the time to do it now).
edit: Looks like the same thing happens in expressions too ({{some/path}}
).
The parser doesn't recognize hyphens as part of the key / ID. This is a problem with cross-site Ajax requests.
I tried to change line 24 in src/handlebars.l
( see rmetzler@56ec990#L1L24 ) but there was another problem I didn't found a simple solution yet.
current workaround: renaming the keys-with-dashes of the object into keys_with_underscores.
Though the tests pass, when I re-create the test scenario on a web page, a simple helper does not work as expected.
var template = Handlebars.compile("{{#goodbyes}}{{{link}}}{{/goodbyes}}"),
data = {prefix: "/root", goodbyes: [{text: "Goodbye", url: "goodbye"}, {text: "Hello", url: "hello"}]},
helpers = {link: function() {
return "<a href='" + this.__get__("../prefix") + "/" + this.url + "'>" + this.text + "</a>";
}},
result = template(data, helpers);
console.log(result);
The code above results in an error-- data is undefined
--and refers me to line 757 of handlebars.js from dist/:
result = data.apply(this.wrapContext(), params);
My suspicion is that my not having defined helperMissing
has something to do with it.
I am getting this error in all versions of IE with handlebars pre 3.
I can't use 'rake release' as stated in the docs I get this error:
no such file to load -- bundler/setup
Can you link to a built .js file too?
I have a template that uses expressions like {{de.tabtext}} and {{en.tabtext}} for a translation interface. While de.tabtext works, de.title and other variations throw a:
TypeError: 'undefined' is not an object (evaluating 'helpers.helperMissing.call')
The en.* expressions all seem to work. I assume that some parsing is going wrong but I couldn't figure out where to look. For now I changed it to german.* and english.* as this doesn't seem to have any issues. The context I'm feeding was:
de : {
tabtext : "foo",
previewtext : "preview",
title : "title",
text : "text",
caption : "caption"
},
en : {
tabtext : "foo",
previewtext : "preview",
title : "title",
text : "text",
caption : "caption"
}
<div class="template redirect" data-path="{{data-path}}" data-template-id="{{data-template-id}}">
</div>
Error: Parse error on line 1:
...irect" data-path="{{data-path}}" data-te
--------------------^
Expecting 'ID'
I had to alter the the error message a bit to show exactly what the line with arrow (-----^)
was pointing to in firebug.
Given the following code:
var source = "{{#should_test}}{{test}}{{/should_test}}";
var helpers = {
test: function() {
return "test";
}
};
var data = { "should_test": "true" };
var template = Handlebars.compile(source);
var result = template(data, helpers);
This will result in an exception such as:
TypeError: Cannot call method 'call' of undefined at Object.anonymous [as render] (eval at <anonymous> (/usr/local/lib/node/.npm/handlebars/0.9.0/package/lib/handlebars/vm.js:407:25))
I traced this to the fact when the 'helpers' are passed into the compiled template they replace the default helpers registered in base.js. Specifically the 'blockHelperMissing' helper is lost.
I'm not sure if it's the intention to replace these helpers, or if this is a bug.
Require.js (http://requirejs.org/) adds the name require
to the global namespace. If Require.js is included in the HTML template (simply a <script src>
, without even being used), this causes Handlebars.js to throw an exception that exports
is undefined at line 538.
537 if (typeof require !== 'undefined') {
538 exports.parser = handlebars;
539 exports.parse = function () { return handlebars.parse.apply(handlebars, arguments); }
Shouldn't that be
else if(context === false || context == null || context == undefined)
in https://github.com/wycats/handlebars.js/blob/master/lib/handlebars/compiler.js#L56 ?
That at least seems to be Mustache's behaviour :)
of course it can be done with the existing helpers (if, else, unless), but often elsif is just the natural choice people are used too.
Please add a copy of the MIT license in a file named LICENSE
or ./MIT-LICENSE
.
I understand that the README
lists "Handlebars.js is released under the MIT license." But some people suffer a combination of maladies, of being finicky about licenses and of being ADHD, and this suggestion would make it take just that much less time to check the license.
I am trying to integrate Handlebars.js into Sammy.js, and I can't get one of Sammy's tests passing. In the test, a partial is used and immediately followed by a normal {{something}}, but Handlebars.js raises an excaption stating that {{something}} is an undefined partial, even though it is just a regular selector. I have verified this behavior via a failing test which is here:
Thanks for a great library! I'm hoping to get a patch into Sammy.js for a Handlebars.js plugin, as I think your library is faster and far more flexible, but I'd like to get all the tests passing before I try.
Am I crazy?
This template:
{{#has_comments}}
<div class="comment_count">
<i></i>{{comment_count}}
</div>
{{/has_comments}}
Is returned as:
false
With the following:
template({
comments: []
},{
has_comments: function(context, fn){
if(context.comments.length > 0) return fn(context);
return false;
}
})
Shouldn't a block helper returning false cause the block to not be rendered? Mustache and Handlebars examples show that to be the case, but my Handlebars seems to not be doing so in the case above.
If a particular replacement is undefined the app would crash. I think it should just replace with empty, as jquery tmpl does, without crashing the app.
How do I change this? Thanks.
How do I fix this?
var handlebars = require("./handlebars.js")
var source = "hi {{dude}}";
var template = handlebars.compile(source);
I tried everything, I tried pre4+pre5, both precompiled and compiled myself.
I copied all the files from the 'dist' directory into my working directory. I also tried it with the older tag 0.9.0.pre.4.
Using IE7 you will get:
SCRIPT1028: Expected identifier, string or number
handlebars-0.9.0.pre.5.js?1302572252, line 243 character 17
This can be fixed by removing the trailing comma at the end of line 242.
I fixed a bug with my copy of handlebars, forked the repo, searched for quite some time to find where my fix was in the source ... gave up.
I've never felt like an idiot trying to to contribute to a JavaScript project. I guess there's a first time for everything.
A quick "contributing" section would be nice that would explain what on earth is going on with the source code.
Line 242 of handlebars-0.9.0.pre.5.js
last_column: lstack[lstack.length-1].last_column,
Delete comma to fix.
I have the following case:
<select name="category">
<option value="-1">Select One</option>
{{#each categories}}
{{#each subcategories}}
<option value="{{id}}">{{description}}</option>
{{/each}}
{{/each}}
</select>
In IE and Chrome, this renders fine; in Firefox only one blank option gets rendered. If I take the block outside of the <select></select> it renders fine.
Any ideas?
When calling Handlebars.compile on IE 8, I get an "Object does not support this property or method" error. The culprit seems to be Handlebars.Runtime.mustache Line 117.
For some reason, the toString method isn't on the Handlebars.Runtime prototype. The same code works perfectly in Firefox and Chrome, but IE 8 chokes on it. I believe Firefox and Chrome are implicitly pulling in the Object prototype, but IE isn't.
There should be some sort of rescue or return undefined if a path {{foo/bar}} points to a foo.bar = null. Currently, it just throws an error that there is no bar. There is, it is just null.
I've observed some wrong behavior of handlebars.js. The behaviour is reproduced by the test introduced in SHA: 89034d3 :
test("iterating over an array with different partials should result in different output", function() {
var aPartial = Handlebars.compile("A");
var anotherPartial = Handlebars.compile("B");
var template = Handlebars.compile("{{#each .}}{{> item }}{{/each}}");
template(["A", "B"], null, { item: aPartial });
var result = template(["A", "B"], null, { item: anotherPartial });
equal("BB", result, "uses the second partial: " + result + " should be BB.");
});
I've investigated the issue and found out that it is related to the caching done in createFunction
in JavascriptCompiler
. It caches helpers and partials in a closure but doesn't check if the partials or the helpers changed since the last invocation. The simplest solution would be to simply remove the caching of the closures or to disable it if partials and helpers are involved. But i actually don't understand the impact of this changes.
handlebars.js
expected to be used in node.js?I see that object handlebars
is being exported as exports.parser
but the full Handlebars functionality as documented is only implemented only by Handlebars
object.
Is there a reason why it's this way? Also, Is there a reason why handlebars.js is not a npm
package?
I'm trying to call handlebars from a RingoJS web application, however the current code base seems to be throwing some errors. Basically, when I call the compile() function, it makes a call to Handlebars.parse(), however parse() is an undefined property on Handlebars.
I added some code to the compile() function to display the properties which are on the Handlebars object. No parse method discovered this way either.
js: warning: "handlebars/vm.js", line 591: Assignment to undeclared variable compilerWords
15378 [qtp448511246-20] INFO actions - Initializing actions.js
15403 [qtp448511246-20] INFO actions - Handling request
15412 [qtp448511246-20] INFO handlebars.vm - Exception:
15415 [qtp448511246-20] INFO handlebars.vm - SafeString:
15421 [qtp448511246-20] INFO handlebars.vm - Utils: [object Object]
15422 [qtp448511246-20] INFO handlebars.vm - AST: [object Object]
15438 [qtp448511246-20] INFO handlebars.vm - Visitor:
15439 [qtp448511246-20] INFO handlebars.vm - PrintVisitor:
15439 [qtp448511246-20] INFO handlebars.vm - Context:
15453 [qtp448511246-20] INFO handlebars.vm - K:
15454 [qtp448511246-20] INFO handlebars.vm - proxy:
15455 [qtp448511246-20] INFO handlebars.vm - Runtime:
15455 [qtp448511246-20] INFO handlebars.vm - Compiler:
15457 [qtp448511246-20] INFO handlebars.vm - JavaScriptCompiler:
15458 [qtp448511246-20] INFO handlebars.vm - VM: [object Object]
15458 [qtp448511246-20] INFO handlebars.vm - compile:
15492 [qtp448511246-20] ERROR stick.middleware.error - TypeError: Cannot find function parse in object [object Object]. (handlebars/vm.js#617)
Script stack:
at handlebars/vm.js:617 (anonymous)
at actions.js:37 (anonymous)
at stick/middleware/route.js:174 (route)
at stick/middleware/params.js:82 (anonymous)
at stick/middleware/notfound.js:28 (notfound)
at stick/middleware/error.js:42 (error)
at stick/middleware/mount.js:108 (mount)
at stick/middleware/responselog.js:39 (responselog)
at stick/middleware/static.js:49 (static)
at stick/middleware/etag.js:22 (etag)
at stick/middleware/gzip.js:39 (gzip)
at stick.js:36 (app)
at ringo/jsgi.js:41 (handleRequest)
The unless helper is missing a "return" causing it to not render anything at all.
Please add a header comment to the handlebars.js
compiled output file.
Please include
If you have a minifying build step (e.g., Closure Compiler), please ensure that the header comment is preserved in the build output.
This helps when we have a copy of handlebars.js in a project, and want to remind ourselves quickly of what this file is, what version it is, and where exactly to go to check for an updated version.
Here is a test case: http://gist.github.com/639221
I've only had a little bit of time to look at the handlebars code, but it seems like a few things are out of place for inverted sections. Like, why is "fn70Not" referred to, but never defined? (see the compiled template output at the bottom of the gist)
I'll try to dig a little more.
I'm testing my project on IE but I'm finding that the "compile" function fails everytime: it even refuses to compile the examples in the readme or something as simple as this:
var t = Handlebars.compile("<li></li>");
I think it has a problem with each and every special character including slashes, quotes, dots and commas. Is this a known issue? Is there a workaround?
why not merge the hbs(https://github.com/donpark/hbs) to handlebars.js for support express?
In lib/handlebars/utils.js line 19 has a trailing comma:
var escape = {
"<": "<",
">": ">",
};
Should be:
var escape = {
"<": "<",
">": ">"
};
Currently if template function is called with both data object and helpers object as parameters then you cannot use default helpers (that are registered with Handlebars.registerHelper) in your template. See https://github.com/wycats/handlebars.js/blob/master/lib/handlebars/base.js#L23
As I result I almost always need to call templates with
template(object, _.defaults({additionalHelper: ...}, Handlebars.helpers))
to ensure that I can use both additionalHelper as well as registered helpers in my template (_.defaults
is utility function from underscore.js).
It would be better if Handlebars would always fallback to Handlebars.helpers when property is not found in data object as well as in provided helpers object. If helper with the same name as registered helper is provided in template function call then it would take precedence over registered helper.
I'm using v0.9.0.pre.4
The data
{
names: [
{ first: "Peter", last: "Griffin" },
{ first: "Meg", last: "Griffin" }
]
}
the template
now if I change the dot into slash (which is deprecated according to the docs), it works fine.
I'm currently struggling to see the purpose of the first parameter of block helper functions (context
). Could you explain how it differs from this
?
A brief look at the code suggests that what a block helper calls this
is actually called context
or wrappedContext
internally, and what a block helper calls context
is called proxy
internally. (In the addBlock
and handleBlock
methods.) Beyond that I find it gets a bit involved. A few experiments suggest that they behave quite similarly, with subtle differences (e.g. issue #11 doesn't occur with this
replaced by context
).
Moreover, the README suggests that:
Whenever the block helper is called it is given a single parameter, the compiled contents of the block.
...which is not the case, unless I misunderstand the sentence. Should that be more something like:
Whenever the block helper is called it is given two parameters: a context (which differs from
this
as follows: ...) and the precompiled contents of the block.
Hope you could shed some light on the intentions behind this
vs. context
. Thanks!
Hi Yehuda,
Thanks for another great open-source tool!
I'm looking to switch from Mustache to Handlebars for some of the cool path and helper additions but mostly for the speed increase thanks to use of compilation. I'm having a small problem though with creating templates that I have used previously with Mustache. Here's an example:
html = '<div title="Look at me" id="{{id}}">...</div>';
template = Handlebars.compile(html)
…produces a SyntaxError: Unexpected string
.
A similar procedure in Mustache works:
html = '<div title="Look at me" id="{{id}}">...</div>';
Mustache.to_html(html, {id: 'unique'})
I can of course use a quoted string in my view like so…
html = '<div title={{quoted_title}} id={{quoted_id}}>...</div>';
template = Handlebars.compile(html)
template({quoted_title: '"Look at me"', quoted_id: '"unique"'})
…but this feels a bit messy when I only want to insert a double quoted string.
I believe the issue stems from double quotes not being escaped properly as things like Handlebars.compile(' " " ')
also produce syntax errors. Interestingly, due to compilation three double quotes produce an illegal token error.
Kind regards,
James
The compilerWords variable is in global scope due to missing var. This is on line 1403 of the built version of handlebars 1.0.0-beta.1
Make it possible to access the full path to the current context somehow, may with this.__fullPath or something similar.
I can see the thinking behind this: backslashes are JavaScript-escaped so that data inserted into JavaScript code aren't messed up. However, for my particular use-case I don't actually want backslashes to be escaped as this results in a double-backslash being shown to the user.
I'm a big fan of escaping being on by default to prevent XSS, but conflating both HTML and JavaScript-escaping together seems inelegant. I can see two main options, and of course alternatively we can just suggest that people like me use triple-mustaches!
Thanks.
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.