diff options
author | wycats <wycats@gmail.com> | 2010-11-26 23:45:38 -0800 |
---|---|---|
committer | wycats <wycats@gmail.com> | 2010-11-26 23:45:38 -0800 |
commit | 454d0a85b7333fb6675e759ae1259a0e5dc6c6b7 (patch) | |
tree | 19518ae78ffc5d5b4cc306efe240948603ae5e98 /lib/handlebars/runtime.js | |
parent | 3b0970d8aa969c79b19fa737dc990ce7c62699d2 (diff) | |
download | handlebars.js-454d0a85b7333fb6675e759ae1259a0e5dc6c6b7.zip handlebars.js-454d0a85b7333fb6675e759ae1259a0e5dc6c6b7.tar.gz handlebars.js-454d0a85b7333fb6675e759ae1259a0e5dc6c6b7.tar.bz2 |
Add initial support for blocks
Diffstat (limited to 'lib/handlebars/runtime.js')
-rw-r--r-- | lib/handlebars/runtime.js | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js index 80defd8..1e676ea 100644 --- a/lib/handlebars/runtime.js +++ b/lib/handlebars/runtime.js @@ -7,6 +7,10 @@ if(exports) { Handlebars.Visitor = require("handlebars/jison_ext").Visitor; } +// A Context wraps data, and makes it possible to extract a +// new Context given a path. For instance, if the data +// is { person: { name: "Alan" } }, a Context wrapping +// "Alan" can be extracted by searching for "person/name" Handlebars.Context = function(data, fallback) { this.data = data; this.fallback = fallback; @@ -15,6 +19,7 @@ Handlebars.Context = function(data, fallback) { Handlebars.Context.prototype = { isContext: true, + // Make a shallow copy of the Context clone: function() { var context = new Handlebars.Context; context.data = this.data; @@ -22,9 +27,19 @@ Handlebars.Context.prototype = { return context; }, + // Search for an object inside the Context's data. The + // path parameter is an object with parts + // ("person/name" represented as ["person", "name"]), + // and depth (the amount of levels to go up the stack, + // originally represented as ..). The stack parameter + // is the objects already searched from the root of + // the original Context in order to get to this point. + // + // Return a new Context wrapping the data found in + // the search. evaluate: function(path, stack) { var context = this.clone(); - var depth = path.depth, dig = path.dig, parts = path.parts; + var depth = path.depth, parts = path.parts; if(depth > stack.length) { context.data = null; } else if(depth > 0) { context = stack[stack.length - depth].clone(); } @@ -85,7 +100,7 @@ Handlebars.Runtime.prototype = { mustache: function(mustache) { var idObj = this.accept(mustache.id); - var params = mustache.params; + var params = this.evaluateParams(mustache.params); for(var i=0, l=params.length; i<l; i++) { params[i] = this.accept(params[i]).data; @@ -99,18 +114,63 @@ Handlebars.Runtime.prototype = { } }, + block: function(block) { + var mustache = block.mustache, + id = mustache.id; + + var idObj = this.accept(mustache.id), + data = idObj.data; + + if(toString.call(data) !== "[object Function]") { + params = [data]; + data = this.context.evaluate({depth: 0, parts: ["helperMissing"]}, this.stack).data; + } else { + params = this.evaluateParams(mustache.params); + } + + var context = this.wrapContext(); + params.push(this.wrapProgram(block.program)); + this.buffer = this.buffer + data.apply(this.wrapContext(), params); + }, + content: function(content) { this.buffer += content.string; }, + evaluateParams: function(params) { + for(var i=0, l=params.length; i<l; i++) { + params[i] = this.accept(params[i]).data; + } + return params; + }, + wrapContext: function() { - var proxy = Handlebars.proxy(this.context.data); + var data = this.context.data; + var proxy = Handlebars.proxy(data); var context = proxy.__context__ = this.context; var stack = proxy.__stack__ = this.stack.slice(0); proxy.__get__ = function(path) { return context.evaluate(path, stack).data }; + + proxy.isWrappedContext = true; + proxy.__data__ = data; + + return proxy; + }, + + wrapProgram: function(program) { + var runtime = this, stack = this.stack.slice(0); + stack.push(this.context); + var fallback = this.context.fallback; + + return function(context) { + if(context.isWrappedContext) { context = context.__data__; } + var runtime = new Handlebars.Runtime(context, fallback, stack); + runtime.accept(program); + return runtime.buffer; + } } } |