From 7c4813b417eaf4b9aab597dcd618857b8419f301 Mon Sep 17 00:00:00 2001 From: Tommy Messbauer Date: Wed, 29 Aug 2012 12:48:22 -0500 Subject: [PATCH 1/5] Commiting initial factory code --- lib/handlebars.js | 28 +- lib/handlebars/base.js | 190 +-- lib/handlebars/compiler/ast.js | 7 +- lib/handlebars/compiler/base.js | 49 +- lib/handlebars/compiler/compiler.js | 1999 ++++++++++++++------------- lib/handlebars/compiler/index.js | 19 +- lib/handlebars/compiler/printer.js | 229 +-- lib/handlebars/compiler/visitor.js | 23 +- lib/handlebars/runtime.js | 118 +- lib/handlebars/utils.js | 130 +- 10 files changed, 1425 insertions(+), 1367 deletions(-) diff --git a/lib/handlebars.js b/lib/handlebars.js index 8705269c..78244969 100644 --- a/lib/handlebars.js +++ b/lib/handlebars.js @@ -1,14 +1,32 @@ -var Handlebars = require("./handlebars/base"); -module.exports = Handlebars; +var handlebars = require("./handlebars/base"), // Each of these augment the Handlebars object. No need to setup here. // (This is done to easily share code between commonjs and browse envs) -require("./handlebars/utils"); + utils = require("./handlebars/utils"), + compiler = require("./handlebars/compiler"), + runtime = require("./handlebars/runtime"); -require("./handlebars/compiler"); -require("./handlebars/runtime"); +var create = function() { + var hb = handlebars.create(); + + utils.attach(hb); + compiler.attach(hb); + runtime.attach(hb); + + return hb; +}; + +var Handlebars = create(); +Handlebars.create = create; + +module.exports = Handlebars; // instantiate an instance // BEGIN(BROWSER) // END(BROWSER) +// USAGE: +// var handlebars = require('handlebars'); + +// var singleton = handlebars.Handlebars, +// local = handlebars.create(); diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js index ca4b1596..656f0fb9 100644 --- a/lib/handlebars/base.js +++ b/lib/handlebars/base.js @@ -1,119 +1,119 @@ -// BEGIN(BROWSER) +module.exports.create = function() { -/*jshint eqnull:true*/ -this.Handlebars = {}; + // BEGIN(BROWSER) -(function(Handlebars) { + var Handlebars = {}; -Handlebars.VERSION = "1.0.rc.1"; + Handlebars.VERSION = "1.0.rc.1"; -Handlebars.helpers = {}; -Handlebars.partials = {}; + Handlebars.helpers = {}; + Handlebars.partials = {}; -Handlebars.registerHelper = function(name, fn, inverse) { - if(inverse) { fn.not = inverse; } - this.helpers[name] = fn; -}; + Handlebars.registerHelper = function(name, fn, inverse) { + if(inverse) { fn.not = inverse; } + this.helpers[name] = fn; + }; -Handlebars.registerPartial = function(name, str) { - this.partials[name] = str; -}; + Handlebars.registerPartial = function(name, str) { + this.partials[name] = str; + }; -Handlebars.registerHelper('helperMissing', function(arg) { - if(arguments.length === 2) { - return undefined; - } else { - throw new Error("Could not find property '" + arg + "'"); - } -}); + Handlebars.registerHelper('helperMissing', function(arg) { + if(arguments.length === 2) { + return undefined; + } else { + throw new Error("Could not find property '" + arg + "'"); + } + }); -var toString = Object.prototype.toString, functionType = "[object Function]"; + var toString = Object.prototype.toString, functionType = "[object Function]"; -Handlebars.registerHelper('blockHelperMissing', function(context, options) { - var inverse = options.inverse || function() {}, fn = options.fn; + Handlebars.registerHelper('blockHelperMissing', function(context, options) { + var inverse = options.inverse || function() {}, fn = options.fn; - var ret = ""; - var type = toString.call(context); + var ret = ""; + var type = toString.call(context); - if(type === functionType) { context = context.call(this); } + if(type === functionType) { context = context.call(this); } - if(context === true) { - return fn(this); - } else if(context === false || context == null) { - return inverse(this); - } else if(type === "[object Array]") { - if(context.length > 0) { + if(context === true) { + return fn(this); + } else if(context === false || context == null) { + return inverse(this); + } else if(type === "[object Array]") { + if(context.length > 0) { + for(var i=0, j=context.length; i 0) { for(var i=0, j=context.length; i 0) { - for(var i=0, j=context.length; i 0) { + this.source[1] = this.source[1] + ", " + locals.join(", "); + } + + // Generate minimizer alias mappings + if (!this.isChild) { + var aliases = []; + for (var alias in this.context.aliases) { + this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias]; + } + } + + if (this.source[1]) { + this.source[1] = "var " + this.source[1].substring(2) + ";"; + } + + // Merge children + if (!this.isChild) { + this.source[1] += '\n' + this.context.programs.join('\n') + '\n'; + } + + if (!this.environment.isSimple) { + this.source.push("return buffer;"); + } + + var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"]; + + for(var i=0, l=this.environment.depths.list.length; i this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } + return "stack" + this.stackSlot; + }, + + popStack: function() { + var item = this.compileStack.pop(); + + if (item instanceof Literal) { + return item.value; + } else { + this.stackSlot--; + return item; + } + }, + + topStack: function() { + var item = this.compileStack[this.compileStack.length - 1]; + + if (item instanceof Literal) { + return item.value; + } else { + return item; + } + }, + + quotedString: function(str) { + return '"' + str + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + '"'; + }, + + setupHelper: function(paramSize, name) { + var params = []; + this.setupParams(paramSize, params); + var foundHelper = this.nameLookup('helpers', name, 'helper'); + + return { + params: params, + name: foundHelper, + callParams: ["depth0"].concat(params).join(", "), + helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ") + }; + }, + + // the params and contexts arguments are passed in arrays + // to fill in + setupParams: function(paramSize, params) { + var options = [], contexts = [], param, inverse, program; + + options.push("hash:" + this.popStack()); + + inverse = this.popStack(); + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + if (!program) { + this.context.aliases.self = "this"; + program = "self.noop"; } - this.opcode('getContext', param.depth || 0); - this.opcode('pushStringParam', param.string); - } else { - this[param.type](param); + if (!inverse) { + this.context.aliases.self = "this"; + inverse = "self.noop"; + } + + options.push("inverse:" + inverse); + options.push("fn:" + program); } + + for(var i=0; i 0) { - this.source[1] = this.source[1] + ", " + locals.join(", "); - } - - // Generate minimizer alias mappings - if (!this.isChild) { - var aliases = []; - for (var alias in this.context.aliases) { - this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias]; - } - } - - if (this.source[1]) { - this.source[1] = "var " + this.source[1].substring(2) + ";"; - } - - // Merge children - if (!this.isChild) { - this.source[1] += '\n' + this.context.programs.join('\n') + '\n'; - } - - if (!this.environment.isSimple) { - this.source.push("return buffer;"); - } - - var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"]; - - for(var i=0, l=this.environment.depths.list.length; i this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } - return "stack" + this.stackSlot; - }, - - popStack: function() { - var item = this.compileStack.pop(); - - if (item instanceof Literal) { - return item.value; - } else { - this.stackSlot--; - return item; - } - }, - - topStack: function() { - var item = this.compileStack[this.compileStack.length - 1]; - - if (item instanceof Literal) { - return item.value; - } else { - return item; - } - }, - - quotedString: function(str) { - return '"' + str - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') - .replace(/\n/g, '\\n') - .replace(/\r/g, '\\r') + '"'; - }, - - setupHelper: function(paramSize, name) { - var params = []; - this.setupParams(paramSize, params); - var foundHelper = this.nameLookup('helpers', name, 'helper'); - - return { - params: params, - name: foundHelper, - callParams: ["depth0"].concat(params).join(", "), - helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ") - }; - }, - - // the params and contexts arguments are passed in arrays - // to fill in - setupParams: function(paramSize, params) { - var options = [], contexts = [], param, inverse, program; - - options.push("hash:" + this.popStack()); - - inverse = this.popStack(); - program = this.popStack(); - - // Avoid setting fn and inverse if neither are set. This allows - // helpers to do a check for `if (options.fn)` - if (program || inverse) { - if (!program) { - this.context.aliases.self = "this"; - program = "self.noop"; - } - - if (!inverse) { - this.context.aliases.self = "this"; - inverse = "self.noop"; - } - - options.push("inverse:" + inverse); - options.push("fn:" + program); - } - - for(var i=0; i " + content + " }}"); + }; + + Handlebars.PrintVisitor.prototype.hash = function(hash) { + var pairs = hash.pairs; + var joinedPairs = [], left, right; + + for(var i=0, l=pairs.length; i 1) { + return "PATH:" + path; + } else { + return "ID:" + path; + } + }; + + Handlebars.PrintVisitor.prototype.DATA = function(data) { + return "@" + data.id; + }; + + Handlebars.PrintVisitor.prototype.content = function(content) { + return this.pad("CONTENT[ '" + content.string + "' ]"); + }; + + Handlebars.PrintVisitor.prototype.comment = function(comment) { + return this.pad("{{! '" + comment.comment + "' }}"); + }; + // END(BROWSER) + + return Handlebars; }; -Handlebars.PrintVisitor.prototype.mustache = function(mustache) { - var params = mustache.params, paramStrings = [], hash; - - for(var i=0, l=params.length; i " + content + " }}"); -}; - -Handlebars.PrintVisitor.prototype.hash = function(hash) { - var pairs = hash.pairs; - var joinedPairs = [], left, right; - - for(var i=0, l=pairs.length; i 1) { - return "PATH:" + path; - } else { - return "ID:" + path; - } -}; - -Handlebars.PrintVisitor.prototype.DATA = function(data) { - return "@" + data.id; -}; - -Handlebars.PrintVisitor.prototype.content = function(content) { - return this.pad("CONTENT[ '" + content.string + "' ]"); -}; - -Handlebars.PrintVisitor.prototype.comment = function(comment) { - return this.pad("{{! '" + comment.comment + "' }}"); -}; -// END(BROWSER) - -exports.PrintVisitor = Handlebars.PrintVisitor; diff --git a/lib/handlebars/compiler/visitor.js b/lib/handlebars/compiler/visitor.js index a557dd3d..56f262ab 100644 --- a/lib/handlebars/compiler/visitor.js +++ b/lib/handlebars/compiler/visitor.js @@ -1,13 +1,20 @@ -var Handlebars = require("./base"); -// BEGIN(BROWSER) +exports.attach = function(Handlebars) { -Handlebars.Visitor = function() {}; + // BEGIN(BROWSER) + + Handlebars.Visitor = function() {}; + + Handlebars.Visitor.prototype = { + accept: function(object) { + return this[object.type](object); + } + }; + + // END(BROWSER) + + return Handlebars; -Handlebars.Visitor.prototype = { - accept: function(object) { - return this[object.type](object); - } }; -// END(BROWSER) + diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js index eb6d7570..edf10257 100644 --- a/lib/handlebars/runtime.js +++ b/lib/handlebars/runtime.js @@ -1,68 +1,72 @@ -var Handlebars = require("./base"); +exports.attach = function(Handlebars) { -// BEGIN(BROWSER) -Handlebars.VM = { - template: function(templateSpec) { - // Just add water - var container = { - escapeExpression: Handlebars.Utils.escapeExpression, - invokePartial: Handlebars.VM.invokePartial, - programs: [], - program: function(i, fn, data) { - var programWrapper = this.programs[i]; - if(data) { - return Handlebars.VM.program(fn, data); - } else if(programWrapper) { - return programWrapper; - } else { - programWrapper = this.programs[i] = Handlebars.VM.program(fn); - return programWrapper; - } - }, - programWithDepth: Handlebars.VM.programWithDepth, - noop: Handlebars.VM.noop - }; + // BEGIN(BROWSER) + + Handlebars.VM = { + template: function(templateSpec) { + // Just add water + var container = { + escapeExpression: Handlebars.Utils.escapeExpression, + invokePartial: Handlebars.VM.invokePartial, + programs: [], + program: function(i, fn, data) { + var programWrapper = this.programs[i]; + if(data) { + return Handlebars.VM.program(fn, data); + } else if(programWrapper) { + return programWrapper; + } else { + programWrapper = this.programs[i] = Handlebars.VM.program(fn); + return programWrapper; + } + }, + programWithDepth: Handlebars.VM.programWithDepth, + noop: Handlebars.VM.noop + }; - return function(context, options) { - options = options || {}; - return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data); - }; - }, + return function(context, options) { + options = options || {}; + return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data); + }; + }, - programWithDepth: function(fn, data, $depth) { - var args = Array.prototype.slice.call(arguments, 2); + programWithDepth: function(fn, data, $depth) { + var args = Array.prototype.slice.call(arguments, 2); - return function(context, options) { - options = options || {}; + return function(context, options) { + options = options || {}; - return fn.apply(this, [context, options.data || data].concat(args)); - }; - }, - program: function(fn, data) { - return function(context, options) { - options = options || {}; + return fn.apply(this, [context, options.data || data].concat(args)); + }; + }, + program: function(fn, data) { + return function(context, options) { + options = options || {}; - return fn(context, options.data || data); - }; - }, - noop: function() { return ""; }, - invokePartial: function(partial, name, context, helpers, partials, data) { - var options = { helpers: helpers, partials: partials, data: data }; + return fn(context, options.data || data); + }; + }, + noop: function() { return ""; }, + invokePartial: function(partial, name, context, helpers, partials, data) { + var options = { helpers: helpers, partials: partials, data: data }; - if(partial === undefined) { - throw new Handlebars.Exception("The partial " + name + " could not be found"); - } else if(partial instanceof Function) { - return partial(context, options); - } else if (!Handlebars.compile) { - throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode"); - } else { - partials[name] = Handlebars.compile(partial); - return partials[name](context, options); + if(partial === undefined) { + throw new Handlebars.Exception("The partial " + name + " could not be found"); + } else if(partial instanceof Function) { + return partial(context, options); + } else if (!Handlebars.compile) { + throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode"); + } else { + partials[name] = Handlebars.compile(partial); + return partials[name](context, options); + } } - } -}; + }; -Handlebars.template = Handlebars.VM.template; + Handlebars.template = Handlebars.VM.template; -// END(BROWSER) + // END(BROWSER) + return Handlebars; + +}; \ No newline at end of file diff --git a/lib/handlebars/utils.js b/lib/handlebars/utils.js index bd5d0eb8..0aa89b84 100644 --- a/lib/handlebars/utils.js +++ b/lib/handlebars/utils.js @@ -1,68 +1,72 @@ -var Handlebars = require("./base"); +exports.attach = function(Handlebars) { -// BEGIN(BROWSER) -Handlebars.Exception = function(message) { - var tmp = Error.prototype.constructor.apply(this, arguments); + // BEGIN(BROWSER) - for (var p in tmp) { - if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; } - } + Handlebars.Exception = function(message) { + var tmp = Error.prototype.constructor.apply(this, arguments); - this.message = tmp.message; -}; -Handlebars.Exception.prototype = new Error(); - -// Build out our basic SafeString type -Handlebars.SafeString = function(string) { - this.string = string; -}; -Handlebars.SafeString.prototype.toString = function() { - return this.string.toString(); -}; - -(function() { - var escape = { - "<": "<", - ">": ">", - '"': """, - "'": "'", - "`": "`" - }; - - var badChars = /&(?!\w+;)|[<>"'`]/g; - var possible = /[&<>"'`]/; - - var escapeChar = function(chr) { - return escape[chr] || "&"; - }; - - Handlebars.Utils = { - escapeExpression: function(string) { - // don't escape SafeStrings, since they're already safe - if (string instanceof Handlebars.SafeString) { - return string.toString(); - } else if (string == null || string === false) { - return ""; - } - - if(!possible.test(string)) { return string; } - return string.replace(badChars, escapeChar); - }, - - isEmpty: function(value) { - if (typeof value === "undefined") { - return true; - } else if (value === null) { - return true; - } else if (value === false) { - return true; - } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) { - return true; - } else { - return false; - } + for (var p in tmp) { + if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; } } - }; -})(); -// END(BROWSER) + this.message = tmp.message; + }; + Handlebars.Exception.prototype = new Error(); + + // Build out our basic SafeString type + Handlebars.SafeString = function(string) { + this.string = string; + }; + Handlebars.SafeString.prototype.toString = function() { + return this.string.toString(); + }; + + (function() { + var escape = { + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + + var badChars = /&(?!\w+;)|[<>"'`]/g; + var possible = /[&<>"'`]/; + + var escapeChar = function(chr) { + return escape[chr] || "&"; + }; + + Handlebars.Utils = { + escapeExpression: function(string) { + // don't escape SafeStrings, since they're already safe + if (string instanceof Handlebars.SafeString) { + return string.toString(); + } else if (string == null || string === false) { + return ""; + } + + if(!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); + }, + + isEmpty: function(value) { + if (typeof value === "undefined") { + return true; + } else if (value === null) { + return true; + } else if (value === false) { + return true; + } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) { + return true; + } else { + return false; + } + } + }; + })(); + + // END(BROWSER) + + return Handlebars; +}; From eccc7c35ca3221b0a168485d5c323d6054958a3e Mon Sep 17 00:00:00 2001 From: Tommy Messbauer Date: Wed, 29 Aug 2012 15:07:15 -0500 Subject: [PATCH 2/5] Finished factory pattern --- lib/handlebars/compiler/base.js | 2 +- lib/handlebars/compiler/compiler.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/handlebars/compiler/base.js b/lib/handlebars/compiler/base.js index 1f97c0ba..28150d9d 100644 --- a/lib/handlebars/compiler/base.js +++ b/lib/handlebars/compiler/base.js @@ -1,7 +1,7 @@ var handlebars = require("./parser").parser; exports.attach = function(Handlebars) { - + // BEGIN(BROWSER) Handlebars.Parser = handlebars; diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js index 51582947..33bf1208 100644 --- a/lib/handlebars/compiler/compiler.js +++ b/lib/handlebars/compiler/compiler.js @@ -1,8 +1,9 @@ - - +var compilerbase = require("./base"); exports.attach = function(Handlebars) { + compilerbase.attach(Handlebars); + // BEGIN(BROWSER) /*jshint eqnull:true*/ From 79632184953284603b64a3179d087ebcda9d0ab6 Mon Sep 17 00:00:00 2001 From: Tommy Messbauer Date: Mon, 26 Nov 2012 09:39:08 -0600 Subject: [PATCH 3/5] Factory update with tabs to spaces.. sorry :( --- lib/handlebars.js | 18 +- lib/handlebars/base.js | 170 +-- lib/handlebars/compiler/ast.js | 186 +-- lib/handlebars/compiler/base.js | 46 +- lib/handlebars/compiler/compiler.js | 2002 +++++++++++++-------------- lib/handlebars/compiler/index.js | 6 +- lib/handlebars/compiler/printer.js | 242 ++-- lib/handlebars/compiler/visitor.js | 20 +- lib/handlebars/runtime.js | 116 +- lib/handlebars/utils.js | 132 +- 10 files changed, 1469 insertions(+), 1469 deletions(-) diff --git a/lib/handlebars.js b/lib/handlebars.js index 78244969..7d85c261 100644 --- a/lib/handlebars.js +++ b/lib/handlebars.js @@ -2,18 +2,18 @@ var handlebars = require("./handlebars/base"), // Each of these augment the Handlebars object. No need to setup here. // (This is done to easily share code between commonjs and browse envs) - utils = require("./handlebars/utils"), - compiler = require("./handlebars/compiler"), - runtime = require("./handlebars/runtime"); + utils = require("./handlebars/utils"), + compiler = require("./handlebars/compiler"), + runtime = require("./handlebars/runtime"); var create = function() { - var hb = handlebars.create(); + var hb = handlebars.create(); - utils.attach(hb); - compiler.attach(hb); - runtime.attach(hb); + utils.attach(hb); + compiler.attach(hb); + runtime.attach(hb); - return hb; + return hb; }; var Handlebars = create(); @@ -29,4 +29,4 @@ module.exports = Handlebars; // instantiate an instance // var handlebars = require('handlebars'); // var singleton = handlebars.Handlebars, -// local = handlebars.create(); +// local = handlebars.create(); diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js index 656f0fb9..8640cb85 100644 --- a/lib/handlebars/base.js +++ b/lib/handlebars/base.js @@ -1,116 +1,116 @@ module.exports.create = function() { - // BEGIN(BROWSER) +// BEGIN(BROWSER) - var Handlebars = {}; +var Handlebars = {}; - Handlebars.VERSION = "1.0.rc.1"; +Handlebars.VERSION = "1.0.rc.1"; - Handlebars.helpers = {}; - Handlebars.partials = {}; +Handlebars.helpers = {}; +Handlebars.partials = {}; - Handlebars.registerHelper = function(name, fn, inverse) { - if(inverse) { fn.not = inverse; } - this.helpers[name] = fn; - }; +Handlebars.registerHelper = function(name, fn, inverse) { + if(inverse) { fn.not = inverse; } + this.helpers[name] = fn; +}; - Handlebars.registerPartial = function(name, str) { - this.partials[name] = str; - }; +Handlebars.registerPartial = function(name, str) { + this.partials[name] = str; +}; - Handlebars.registerHelper('helperMissing', function(arg) { - if(arguments.length === 2) { - return undefined; - } else { - throw new Error("Could not find property '" + arg + "'"); - } - }); +Handlebars.registerHelper('helperMissing', function(arg) { + if(arguments.length === 2) { + return undefined; + } else { + throw new Error("Could not find property '" + arg + "'"); + } +}); - var toString = Object.prototype.toString, functionType = "[object Function]"; +var toString = Object.prototype.toString, functionType = "[object Function]"; - Handlebars.registerHelper('blockHelperMissing', function(context, options) { - var inverse = options.inverse || function() {}, fn = options.fn; +Handlebars.registerHelper('blockHelperMissing', function(context, options) { + var inverse = options.inverse || function() {}, fn = options.fn; - var ret = ""; - var type = toString.call(context); + var ret = ""; + var type = toString.call(context); - if(type === functionType) { context = context.call(this); } + if(type === functionType) { context = context.call(this); } - if(context === true) { - return fn(this); - } else if(context === false || context == null) { - return inverse(this); - } else if(type === "[object Array]") { - if(context.length > 0) { - for(var i=0, j=context.length; i 0) { + if(context === true) { + return fn(this); + } else if(context === false || context == null) { + return inverse(this); + } else if(type === "[object Array]") { + if(context.length > 0) { for(var i=0, j=context.length; i 0) { + for(var i=0, j=context.length; i 0) { - this.source[1] = this.source[1] + ", " + locals.join(", "); - } - - // Generate minimizer alias mappings - if (!this.isChild) { - var aliases = []; - for (var alias in this.context.aliases) { - this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias]; - } - } - - if (this.source[1]) { - this.source[1] = "var " + this.source[1].substring(2) + ";"; - } - - // Merge children - if (!this.isChild) { - this.source[1] += '\n' + this.context.programs.join('\n') + '\n'; - } - - if (!this.environment.isSimple) { - this.source.push("return buffer;"); - } - - var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"]; - - for(var i=0, l=this.environment.depths.list.length; i this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } - return "stack" + this.stackSlot; - }, - - popStack: function() { - var item = this.compileStack.pop(); - - if (item instanceof Literal) { - return item.value; - } else { - this.stackSlot--; - return item; - } - }, - - topStack: function() { - var item = this.compileStack[this.compileStack.length - 1]; - - if (item instanceof Literal) { - return item.value; - } else { - return item; - } - }, - - quotedString: function(str) { - return '"' + str - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') - .replace(/\n/g, '\\n') - .replace(/\r/g, '\\r') + '"'; - }, - - setupHelper: function(paramSize, name) { - var params = []; - this.setupParams(paramSize, params); - var foundHelper = this.nameLookup('helpers', name, 'helper'); - - return { - params: params, - name: foundHelper, - callParams: ["depth0"].concat(params).join(", "), - helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ") - }; - }, - - // the params and contexts arguments are passed in arrays - // to fill in - setupParams: function(paramSize, params) { - var options = [], contexts = [], param, inverse, program; - - options.push("hash:" + this.popStack()); - - inverse = this.popStack(); - program = this.popStack(); - - // Avoid setting fn and inverse if neither are set. This allows - // helpers to do a check for `if (options.fn)` - if (program || inverse) { - if (!program) { - this.context.aliases.self = "this"; - program = "self.noop"; - } - - if (!inverse) { - this.context.aliases.self = "this"; - inverse = "self.noop"; - } - - options.push("inverse:" + inverse); - options.push("fn:" + program); - } - - for(var i=0; i 0) { + this.source[1] = this.source[1] + ", " + locals.join(", "); + } + + // Generate minimizer alias mappings + if (!this.isChild) { + var aliases = []; + for (var alias in this.context.aliases) { + this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias]; + } + } + + if (this.source[1]) { + this.source[1] = "var " + this.source[1].substring(2) + ";"; + } + + // Merge children + if (!this.isChild) { + this.source[1] += '\n' + this.context.programs.join('\n') + '\n'; + } + + if (!this.environment.isSimple) { + this.source.push("return buffer;"); + } + + var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"]; + + for(var i=0, l=this.environment.depths.list.length; i this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } + return "stack" + this.stackSlot; + }, + + popStack: function() { + var item = this.compileStack.pop(); + + if (item instanceof Literal) { + return item.value; + } else { + this.stackSlot--; + return item; + } + }, + + topStack: function() { + var item = this.compileStack[this.compileStack.length - 1]; + + if (item instanceof Literal) { + return item.value; + } else { + return item; + } + }, + + quotedString: function(str) { + return '"' + str + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + '"'; + }, + + setupHelper: function(paramSize, name) { + var params = []; + this.setupParams(paramSize, params); + var foundHelper = this.nameLookup('helpers', name, 'helper'); + + return { + params: params, + name: foundHelper, + callParams: ["depth0"].concat(params).join(", "), + helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ") + }; + }, + + // the params and contexts arguments are passed in arrays + // to fill in + setupParams: function(paramSize, params) { + var options = [], contexts = [], param, inverse, program; + + options.push("hash:" + this.popStack()); + + inverse = this.popStack(); + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + if (!program) { + this.context.aliases.self = "this"; + program = "self.noop"; + } + + if (!inverse) { + this.context.aliases.self = "this"; + inverse = "self.noop"; + } + + options.push("inverse:" + inverse); + options.push("fn:" + program); + } + + for(var i=0; i " + content + " }}"); - }; - - Handlebars.PrintVisitor.prototype.hash = function(hash) { - var pairs = hash.pairs; - var joinedPairs = [], left, right; - - for(var i=0, l=pairs.length; i 1) { - return "PATH:" + path; - } else { - return "ID:" + path; - } - }; - - Handlebars.PrintVisitor.prototype.DATA = function(data) { - return "@" + data.id; - }; - - Handlebars.PrintVisitor.prototype.content = function(content) { - return this.pad("CONTENT[ '" + content.string + "' ]"); - }; - - Handlebars.PrintVisitor.prototype.comment = function(comment) { - return this.pad("{{! '" + comment.comment + "' }}"); - }; - // END(BROWSER) - - return Handlebars; + if(newline !== false) { out = out + "\n"; } + return out; +}; + +Handlebars.PrintVisitor.prototype.program = function(program) { + var out = "", + statements = program.statements, + inverse = program.inverse, + i, l; + + for(i=0, l=statements.length; i " + content + " }}"); +}; + +Handlebars.PrintVisitor.prototype.hash = function(hash) { + var pairs = hash.pairs; + var joinedPairs = [], left, right; + + for(var i=0, l=pairs.length; i 1) { + return "PATH:" + path; + } else { + return "ID:" + path; + } +}; + +Handlebars.PrintVisitor.prototype.DATA = function(data) { + return "@" + data.id; +}; + +Handlebars.PrintVisitor.prototype.content = function(content) { + return this.pad("CONTENT[ '" + content.string + "' ]"); +}; + +Handlebars.PrintVisitor.prototype.comment = function(comment) { + return this.pad("{{! '" + comment.comment + "' }}"); +}; +// END(BROWSER) + +return Handlebars; }; diff --git a/lib/handlebars/compiler/visitor.js b/lib/handlebars/compiler/visitor.js index 56f262ab..5d073140 100644 --- a/lib/handlebars/compiler/visitor.js +++ b/lib/handlebars/compiler/visitor.js @@ -1,20 +1,18 @@ - exports.attach = function(Handlebars) { - // BEGIN(BROWSER) +// BEGIN(BROWSER) - Handlebars.Visitor = function() {}; +Handlebars.Visitor = function() {}; - Handlebars.Visitor.prototype = { - accept: function(object) { - return this[object.type](object); - } - }; +Handlebars.Visitor.prototype = { + accept: function(object) { + return this[object.type](object); + } +}; - // END(BROWSER) - - return Handlebars; +// END(BROWSER) +return Handlebars; }; diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js index edf10257..6fd38fd9 100644 --- a/lib/handlebars/runtime.js +++ b/lib/handlebars/runtime.js @@ -1,72 +1,72 @@ exports.attach = function(Handlebars) { - // BEGIN(BROWSER) - - Handlebars.VM = { - template: function(templateSpec) { - // Just add water - var container = { - escapeExpression: Handlebars.Utils.escapeExpression, - invokePartial: Handlebars.VM.invokePartial, - programs: [], - program: function(i, fn, data) { - var programWrapper = this.programs[i]; - if(data) { - return Handlebars.VM.program(fn, data); - } else if(programWrapper) { - return programWrapper; - } else { - programWrapper = this.programs[i] = Handlebars.VM.program(fn); - return programWrapper; - } - }, - programWithDepth: Handlebars.VM.programWithDepth, - noop: Handlebars.VM.noop - }; +// BEGIN(BROWSER) - return function(context, options) { - options = options || {}; - return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data); - }; - }, +Handlebars.VM = { + template: function(templateSpec) { + // Just add water + var container = { + escapeExpression: Handlebars.Utils.escapeExpression, + invokePartial: Handlebars.VM.invokePartial, + programs: [], + program: function(i, fn, data) { + var programWrapper = this.programs[i]; + if(data) { + return Handlebars.VM.program(fn, data); + } else if(programWrapper) { + return programWrapper; + } else { + programWrapper = this.programs[i] = Handlebars.VM.program(fn); + return programWrapper; + } + }, + programWithDepth: Handlebars.VM.programWithDepth, + noop: Handlebars.VM.noop + }; - programWithDepth: function(fn, data, $depth) { - var args = Array.prototype.slice.call(arguments, 2); + return function(context, options) { + options = options || {}; + return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data); + }; + }, - return function(context, options) { - options = options || {}; + programWithDepth: function(fn, data, $depth) { + var args = Array.prototype.slice.call(arguments, 2); - return fn.apply(this, [context, options.data || data].concat(args)); - }; - }, - program: function(fn, data) { - return function(context, options) { - options = options || {}; + return function(context, options) { + options = options || {}; - return fn(context, options.data || data); - }; - }, - noop: function() { return ""; }, - invokePartial: function(partial, name, context, helpers, partials, data) { - var options = { helpers: helpers, partials: partials, data: data }; + return fn.apply(this, [context, options.data || data].concat(args)); + }; + }, + program: function(fn, data) { + return function(context, options) { + options = options || {}; - if(partial === undefined) { - throw new Handlebars.Exception("The partial " + name + " could not be found"); - } else if(partial instanceof Function) { - return partial(context, options); - } else if (!Handlebars.compile) { - throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode"); - } else { - partials[name] = Handlebars.compile(partial); - return partials[name](context, options); - } + return fn(context, options.data || data); + }; + }, + noop: function() { return ""; }, + invokePartial: function(partial, name, context, helpers, partials, data) { + var options = { helpers: helpers, partials: partials, data: data }; + + if(partial === undefined) { + throw new Handlebars.Exception("The partial " + name + " could not be found"); + } else if(partial instanceof Function) { + return partial(context, options); + } else if (!Handlebars.compile) { + throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode"); + } else { + partials[name] = Handlebars.compile(partial); + return partials[name](context, options); } - }; + } +}; - Handlebars.template = Handlebars.VM.template; +Handlebars.template = Handlebars.VM.template; - // END(BROWSER) +// END(BROWSER) - return Handlebars; +return Handlebars; }; \ No newline at end of file diff --git a/lib/handlebars/utils.js b/lib/handlebars/utils.js index 0aa89b84..d467205a 100644 --- a/lib/handlebars/utils.js +++ b/lib/handlebars/utils.js @@ -1,72 +1,72 @@ exports.attach = function(Handlebars) { - // BEGIN(BROWSER) +// BEGIN(BROWSER) - Handlebars.Exception = function(message) { - var tmp = Error.prototype.constructor.apply(this, arguments); +Handlebars.Exception = function(message) { + var tmp = Error.prototype.constructor.apply(this, arguments); - for (var p in tmp) { - if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; } - } + for (var p in tmp) { + if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; } + } - this.message = tmp.message; - }; - Handlebars.Exception.prototype = new Error(); - - // Build out our basic SafeString type - Handlebars.SafeString = function(string) { - this.string = string; - }; - Handlebars.SafeString.prototype.toString = function() { - return this.string.toString(); - }; - - (function() { - var escape = { - "<": "<", - ">": ">", - '"': """, - "'": "'", - "`": "`" - }; - - var badChars = /&(?!\w+;)|[<>"'`]/g; - var possible = /[&<>"'`]/; - - var escapeChar = function(chr) { - return escape[chr] || "&"; - }; - - Handlebars.Utils = { - escapeExpression: function(string) { - // don't escape SafeStrings, since they're already safe - if (string instanceof Handlebars.SafeString) { - return string.toString(); - } else if (string == null || string === false) { - return ""; - } - - if(!possible.test(string)) { return string; } - return string.replace(badChars, escapeChar); - }, - - isEmpty: function(value) { - if (typeof value === "undefined") { - return true; - } else if (value === null) { - return true; - } else if (value === false) { - return true; - } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) { - return true; - } else { - return false; - } - } - }; - })(); - - // END(BROWSER) - - return Handlebars; + this.message = tmp.message; +}; +Handlebars.Exception.prototype = new Error(); + +// Build out our basic SafeString type +Handlebars.SafeString = function(string) { + this.string = string; +}; +Handlebars.SafeString.prototype.toString = function() { + return this.string.toString(); +}; + +(function() { + var escape = { + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + + var badChars = /&(?!\w+;)|[<>"'`]/g; + var possible = /[&<>"'`]/; + + var escapeChar = function(chr) { + return escape[chr] || "&"; + }; + + Handlebars.Utils = { + escapeExpression: function(string) { + // don't escape SafeStrings, since they're already safe + if (string instanceof Handlebars.SafeString) { + return string.toString(); + } else if (string == null || string === false) { + return ""; + } + + if(!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); + }, + + isEmpty: function(value) { + if (typeof value === "undefined") { + return true; + } else if (value === null) { + return true; + } else if (value === false) { + return true; + } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) { + return true; + } else { + return false; + } + } + }; +})(); + +// END(BROWSER) + +return Handlebars; }; From 514c9391e0fbee8a0c8c184bcef77d6be38722aa Mon Sep 17 00:00:00 2001 From: Tommy Messbauer Date: Mon, 11 Feb 2013 22:50:23 -0600 Subject: [PATCH 4/5] restored scope of var verifyMatch --- lib/handlebars/compiler/ast.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/handlebars/compiler/ast.js b/lib/handlebars/compiler/ast.js index 9648ef07..27cd6cc1 100644 --- a/lib/handlebars/compiler/ast.js +++ b/lib/handlebars/compiler/ast.js @@ -41,13 +41,13 @@ Handlebars.AST.PartialNode = function(id, context) { this.context = context; }; -var verifyMatch = function(open, close) { - if(open.original !== close.original) { - throw new Handlebars.Exception(open.original + " doesn't match " + close.original); - } -}; - Handlebars.AST.BlockNode = function(mustache, program, inverse, close) { + var verifyMatch = function(open, close) { + if(open.original !== close.original) { + throw new Handlebars.Exception(open.original + " doesn't match " + close.original); + } + }; + verifyMatch(mustache.id, close); this.type = "block"; this.mustache = mustache; From 7f9e3fea8126ec0111946cd4e4ffa088d29c0768 Mon Sep 17 00:00:00 2001 From: Tommy Messbauer Date: Mon, 11 Feb 2013 23:13:37 -0600 Subject: [PATCH 5/5] tests passing --- dist/handlebars.js | 25 ++++++++++++------------- lib/handlebars/base.js | 2 +- lib/handlebars/compiler/base.js | 2 +- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/dist/handlebars.js b/dist/handlebars.js index c6b8e719..a2789feb 100644 --- a/dist/handlebars.js +++ b/dist/handlebars.js @@ -24,10 +24,7 @@ THE SOFTWARE. // lib/handlebars/base.js -/*jshint eqnull:true*/ -this.Handlebars = {}; - -(function(Handlebars) { +var Handlebars = {}; Handlebars.VERSION = "1.0.rc.2"; Handlebars.COMPILER_REVISION = 2; @@ -169,8 +166,6 @@ Handlebars.registerHelper('log', function(context, options) { var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1; Handlebars.log(level, context); }); - -}(this.Handlebars)); ; // lib/handlebars/compiler/parser.js /* Jison generated parser */ @@ -646,6 +641,7 @@ function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Pa return new Parser; })();; // lib/handlebars/compiler/base.js + Handlebars.Parser = handlebars; Handlebars.parse = function(input) { @@ -699,13 +695,13 @@ Handlebars.print = function(ast) { this.context = context; }; - var verifyMatch = function(open, close) { - if(open.original !== close.original) { - throw new Handlebars.Exception(open.original + " doesn't match " + close.original); - } - }; - Handlebars.AST.BlockNode = function(mustache, program, inverse, close) { + var verifyMatch = function(open, close) { + if(open.original !== close.original) { + throw new Handlebars.Exception(open.original + " doesn't match " + close.original); + } + }; + verifyMatch(mustache.id, close); this.type = "block"; this.mustache = mustache; @@ -851,7 +847,8 @@ Handlebars.SafeString.prototype.toString = function() { } } }; -})();; +})(); +; // lib/handlebars/compiler/compiler.js /*jshint eqnull:true*/ @@ -2114,8 +2111,10 @@ Handlebars.compile = function(input, options) { return compiled.call(this, context, options); }; }; + ; // lib/handlebars/runtime.js + Handlebars.VM = { template: function(templateSpec) { // Just add water diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js index 32436869..63f4d135 100644 --- a/lib/handlebars/base.js +++ b/lib/handlebars/base.js @@ -147,7 +147,7 @@ Handlebars.registerHelper('log', function(context, options) { // END(BROWSER) - return Handlebars; +return Handlebars; }; diff --git a/lib/handlebars/compiler/base.js b/lib/handlebars/compiler/base.js index 791f56cb..8ff1101d 100644 --- a/lib/handlebars/compiler/base.js +++ b/lib/handlebars/compiler/base.js @@ -1,4 +1,4 @@ -var handlebars = require("./parser").parser; +var handlebars = require("./parser"); exports.attach = function(Handlebars) {