From 4692055d8a058dbfa3c30f1165d0bbb09cf7f80c Mon Sep 17 00:00:00 2001 From: Dennis Collinson Date: Sun, 22 Jan 2012 16:09:29 -0800 Subject: [PATCH] now using handlebars for client side templates --- app/views/layouts/_templates.haml | 6 + app/views/templates/static_text.handlebars | 1 + app/views/templates/static_text.jst | 1 - app/views/templates/stream_faces.handlebars | 5 + app/views/templates/stream_faces.jst | 5 - config/assets.yml | 1 + public/javascripts/app/views.js | 13 +- public/javascripts/app/views/comment_view.js | 1 + .../app/views/commment_stream_view.js | 1 + public/javascripts/app/views/content_view.js | 1 + public/javascripts/app/views/feedback_view.js | 1 + public/javascripts/app/views/header_view.js | 1 + .../javascripts/app/views/likes_info_view.js | 15 +- public/javascripts/app/views/post_view.js | 6 +- .../app/views/stream_faces_view.js | 3 +- public/javascripts/app/views/stream_view.js | 1 + .../vendor/handlebars-1.0.0.beta.6.js | 1550 +++++++++++++++++ spec/javascripts/app/views_spec.js | 4 +- spec/javascripts/support/jasmine.yml | 1 + 19 files changed, 1597 insertions(+), 20 deletions(-) create mode 100644 app/views/templates/static_text.handlebars delete mode 100644 app/views/templates/static_text.jst create mode 100644 app/views/templates/stream_faces.handlebars delete mode 100644 app/views/templates/stream_faces.jst create mode 100644 public/javascripts/vendor/handlebars-1.0.0.beta.6.js diff --git a/app/views/layouts/_templates.haml b/app/views/layouts/_templates.haml index 625d7bb8f..70d26edcf 100644 --- a/app/views/layouts/_templates.haml +++ b/app/views/layouts/_templates.haml @@ -3,3 +3,9 @@ - template_name = File.basename(template, ".jst").gsub("_","-") %script{:id => "#{template_name}-template", :type => 'text/template'} != File.read(templates_dir.join(template)) + +- #don't tell my mom I did this, okay? +- Dir[templates_dir.to_s + "/*.handlebars"].each do |template| + - template_name = File.basename(template, ".handlebars").gsub("_","-") + %script{:id => "#{template_name}-template", :type => 'text/template'} + != File.read(templates_dir.join(template)) diff --git a/app/views/templates/static_text.handlebars b/app/views/templates/static_text.handlebars new file mode 100644 index 000000000..1c37e4a9c --- /dev/null +++ b/app/views/templates/static_text.handlebars @@ -0,0 +1 @@ +{{ text }} diff --git a/app/views/templates/static_text.jst b/app/views/templates/static_text.jst deleted file mode 100644 index 41f6ae6d9..000000000 --- a/app/views/templates/static_text.jst +++ /dev/null @@ -1 +0,0 @@ -<%= text %> diff --git a/app/views/templates/stream_faces.handlebars b/app/views/templates/stream_faces.handlebars new file mode 100644 index 000000000..981fb390a --- /dev/null +++ b/app/views/templates/stream_faces.handlebars @@ -0,0 +1,5 @@ +{{#people}} + + + +{{/people}} diff --git a/app/views/templates/stream_faces.jst b/app/views/templates/stream_faces.jst deleted file mode 100644 index 687793d5b..000000000 --- a/app/views/templates/stream_faces.jst +++ /dev/null @@ -1,5 +0,0 @@ -<% _.each(people, function(person) { %> - - - -<% }) %> diff --git a/config/assets.yml b/config/assets.yml index 18ab3a21b..375a1fa4b 100644 --- a/config/assets.yml +++ b/config/assets.yml @@ -9,6 +9,7 @@ javascripts: main: - public/javascripts/vendor/underscore.js - public/javascripts/vendor/backbone.js + - public/javascripts/vendor/handlebars-1.0.0.beta.6.js - public/javascripts/vendor/markdown/* - public/javascripts/app/app.js - public/javascripts/app/helpers/* diff --git a/public/javascripts/app/views.js b/public/javascripts/app/views.js index 4ff454ecb..bd3c24301 100644 --- a/public/javascripts/app/views.js +++ b/public/javascripts/app/views.js @@ -22,9 +22,18 @@ app.views.Base = Backbone.View.extend({ }, renderTemplate : function(){ - var templateHTML = $(this.template_name).html(); //don't forget to regenerate your jasmine fixtures ;-) - this.template = _.template(templateHTML); + var templateHTML //don't forget to regenerate your jasmine fixtures ;-) var presenter = _.isFunction(this.presenter) ? this.presenter() : this.presenter + + if(this.legacyTemplate) { + templateHTML = $(this.template_name).html(); + this.template = _.template(templateHTML); + } else { + window.templateCache = window.templateCache || {} + templateHTML = $("#" + this.templateName + "-template").html(); //don't forget to regenerate your jasmine fixtures ;-) + this.template = templateCache[this.templateName] = templateCache[this.templateName] || Handlebars.compile(templateHTML); + } + $(this.el).html(this.template(presenter)); this.postRenderTemplate(); }, diff --git a/public/javascripts/app/views/comment_view.js b/public/javascripts/app/views/comment_view.js index 167d4547b..e05fcfc6d 100644 --- a/public/javascripts/app/views/comment_view.js +++ b/public/javascripts/app/views/comment_view.js @@ -1,5 +1,6 @@ app.views.Comment = app.views.Content.extend({ + legacyTemplate : true, template_name: "#comment-template", tagName : "li", diff --git a/public/javascripts/app/views/commment_stream_view.js b/public/javascripts/app/views/commment_stream_view.js index 10fccdb7a..9f8ea5455 100644 --- a/public/javascripts/app/views/commment_stream_view.js +++ b/public/javascripts/app/views/commment_stream_view.js @@ -1,5 +1,6 @@ app.views.CommentStream = app.views.Base.extend({ + legacyTemplate : true, template_name: "#comment-stream-template", className : "comment_stream", diff --git a/public/javascripts/app/views/content_view.js b/public/javascripts/app/views/content_view.js index 461f7f6f8..ba0a5feca 100644 --- a/public/javascripts/app/views/content_view.js +++ b/public/javascripts/app/views/content_view.js @@ -1,4 +1,5 @@ app.views.Content = app.views.StreamObject.extend({ + legacyTemplate : true, presenter : function(){ var model = this.model return _.extend(this.defaultPresenter(), { diff --git a/public/javascripts/app/views/feedback_view.js b/public/javascripts/app/views/feedback_view.js index bfa7110ad..4ab7c4c63 100644 --- a/public/javascripts/app/views/feedback_view.js +++ b/public/javascripts/app/views/feedback_view.js @@ -1,4 +1,5 @@ app.views.Feedback = app.views.StreamObject.extend({ + legacyTemplate : true, template_name: "#feedback-template", className : "info", diff --git a/public/javascripts/app/views/header_view.js b/public/javascripts/app/views/header_view.js index 287aea407..c9a2db120 100644 --- a/public/javascripts/app/views/header_view.js +++ b/public/javascripts/app/views/header_view.js @@ -1,4 +1,5 @@ app.views.Header = app.views.Base.extend({ + legacyTemplate : true, template_name : "#header-template", diff --git a/public/javascripts/app/views/likes_info_view.js b/public/javascripts/app/views/likes_info_view.js index d889b1c67..9d87af7be 100644 --- a/public/javascripts/app/views/likes_info_view.js +++ b/public/javascripts/app/views/likes_info_view.js @@ -1,11 +1,12 @@ app.views.LikesInfo = app.views.StreamObject.extend({ + legacyTemplate : true, template_name : "#likes-info-template", className : "likes_container", events : { - "click .expand_likes" : "showAvatars" + "click .expand_likes" : "showAvatars" }, tooltipSelector : ".avatar", @@ -15,12 +16,12 @@ app.views.LikesInfo = app.views.StreamObject.extend({ }, showAvatars : function(evt){ - if(evt) { evt.preventDefault() } - var self = this; - this.model.likes.fetch() - .done(function(resp){ + if(evt) { evt.preventDefault() } + var self = this; + this.model.likes.fetch() + .done(function(resp){ // set like attribute and like collection self.model.set({likes : self.model.likes.reset(resp)}) - }) - } + }) + } }); diff --git a/public/javascripts/app/views/post_view.js b/public/javascripts/app/views/post_view.js index 94011ecfc..de99742d5 100644 --- a/public/javascripts/app/views/post_view.js +++ b/public/javascripts/app/views/post_view.js @@ -1,4 +1,5 @@ app.views.Post = app.views.StreamObject.extend({ + legacyTemplate : true, template_name: "#stream-element-template", @@ -28,11 +29,14 @@ app.views.Post = app.views.StreamObject.extend({ //subviews this.commentStreamView = new app.views.CommentStream({ model : this.model}); - this.likesInfoView = new app.views.LikesInfo({ model : this.model}); return this; }, + likesInfoView : function(){ + return new app.views.LikesInfo({ model : this.model}); + }, + feedbackView : function(){ if(!window.app.user().current_user ) { return null } return new app.views.Feedback({model : this.model}); diff --git a/public/javascripts/app/views/stream_faces_view.js b/public/javascripts/app/views/stream_faces_view.js index ae5232fc7..eb2075462 100644 --- a/public/javascripts/app/views/stream_faces_view.js +++ b/public/javascripts/app/views/stream_faces_view.js @@ -1,6 +1,5 @@ app.views.StreamFaces = app.views.Base.extend({ - - template_name : "#stream-faces-template", + templateName : "stream-faces", className : "stream-faces", diff --git a/public/javascripts/app/views/stream_view.js b/public/javascripts/app/views/stream_view.js index 837dacffe..99d1dbcd2 100644 --- a/public/javascripts/app/views/stream_view.js +++ b/public/javascripts/app/views/stream_view.js @@ -1,4 +1,5 @@ app.views.Stream = Backbone.View.extend({ + legacyTemplate : true, events: { "click #paginate": "render" }, diff --git a/public/javascripts/vendor/handlebars-1.0.0.beta.6.js b/public/javascripts/vendor/handlebars-1.0.0.beta.6.js new file mode 100644 index 000000000..83119ff88 --- /dev/null +++ b/public/javascripts/vendor/handlebars-1.0.0.beta.6.js @@ -0,0 +1,1550 @@ +// lib/handlebars/base.js +var Handlebars = {}; + +Handlebars.VERSION = "1.0.beta.6"; + +Handlebars.helpers = {}; +Handlebars.partials = {}; + +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.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]"; + +Handlebars.registerHelper('blockHelperMissing', function(context, options) { + var inverse = options.inverse || function() {}, fn = options.fn; + + + var ret = ""; + var type = toString.call(context); + + 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) { + for(var i=0, j=context.length; i 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + var errStr = ""; + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + this.terminals_[symbol] + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column}; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; +} +};/* Jison generated lexer */ +var lexer = (function(){ + +var lexer = ({EOF:1, +parseError:function parseError(str, hash) { + if (this.yy.parseError) { + this.yy.parseError(str, hash); + } else { + throw new Error(str); + } + }, +setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + return this; + }, +input:function () { + var ch = this._input[0]; + this.yytext+=ch; + this.yyleng++; + this.match+=ch; + this.matched+=ch; + var lines = ch.match(/\n/); + if (lines) this.yylineno++; + this._input = this._input.slice(1); + return ch; + }, +unput:function (ch) { + this._input = ch + this._input; + return this; + }, +more:function () { + this._more = true; + return this; + }, +pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, +upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, +showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, +next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + match = this._input.match(this.rules[rules[i]]); + if (match) { + lines = match[0].match(/\n.*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]); + if (token) return token; + else return; + } + } + if (this._input === "") { + return this.EOF; + } else { + this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, +lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, +begin:function begin(condition) { + this.conditionStack.push(condition); + }, +popState:function popState() { + return this.conditionStack.pop(); + }, +_currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, +topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, +pushState:function begin(condition) { + this.begin(condition); + }}); +lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + +var YYSTATE=YY_START +switch($avoiding_name_collisions) { +case 0: + if(yy_.yytext.slice(-1) !== "\\") this.begin("mu"); + if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu"); + if(yy_.yytext) return 14; + +break; +case 1: return 14; +break; +case 2: this.popState(); return 14; +break; +case 3: return 24; +break; +case 4: return 16; +break; +case 5: return 20; +break; +case 6: return 19; +break; +case 7: return 19; +break; +case 8: return 23; +break; +case 9: return 23; +break; +case 10: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15; +break; +case 11: return 22; +break; +case 12: return 34; +break; +case 13: return 33; +break; +case 14: return 33; +break; +case 15: return 36; +break; +case 16: /*ignore whitespace*/ +break; +case 17: this.popState(); return 18; +break; +case 18: this.popState(); return 18; +break; +case 19: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 28; +break; +case 20: return 30; +break; +case 21: return 30; +break; +case 22: return 29; +break; +case 23: return 33; +break; +case 24: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 33; +break; +case 25: return 'INVALID'; +break; +case 26: return 5; +break; +} +}; +lexer.rules = [/^[^\x00]*?(?=(\{\{))/,/^[^\x00]+/,/^[^\x00]{2,}?(?=(\{\{))/,/^\{\{>/,/^\{\{#/,/^\{\{\//,/^\{\{\^/,/^\{\{\s*else\b/,/^\{\{\{/,/^\{\{&/,/^\{\{![\s\S]*?\}\}/,/^\{\{/,/^=/,/^\.(?=[} ])/,/^\.\./,/^[\/.]/,/^\s+/,/^\}\}\}/,/^\}\}/,/^"(\\["]|[^"])*"/,/^true(?=[}\s])/,/^false(?=[}\s])/,/^[0-9]+(?=[}\s])/,/^[a-zA-Z0-9_$-]+(?=[=}\s\/.])/,/^\[[^\]]*\]/,/^./,/^$/]; +lexer.conditions = {"mu":{"rules":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"INITIAL":{"rules":[0,1,26],"inclusive":true}};return lexer;})() +parser.lexer = lexer; +return parser; +})(); +if (typeof require !== 'undefined' && typeof exports !== 'undefined') { +exports.parser = handlebars; +exports.parse = function () { return handlebars.parse.apply(handlebars, arguments); } +exports.main = function commonjsMain(args) { + if (!args[1]) + throw new Error('Usage: '+args[0]+' FILE'); + if (typeof process !== 'undefined') { + var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8"); + } else { + var cwd = require("file").path(require("file").cwd()); + var source = cwd.join(args[1]).read({charset: "utf-8"}); + } + return exports.parser.parse(source); +} +if (typeof module !== 'undefined' && require.main === module) { + exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args); +} +}; +; +// lib/handlebars/compiler/base.js +Handlebars.Parser = handlebars; + +Handlebars.parse = function(string) { + Handlebars.Parser.yy = Handlebars.AST; + return Handlebars.Parser.parse(string); +}; + +Handlebars.print = function(ast) { + return new Handlebars.PrintVisitor().accept(ast); +}; + +Handlebars.logger = { + DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3, + + // override in the host environment + log: function(level, str) {} +}; + +Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); }; +; +// lib/handlebars/compiler/ast.js +(function() { + + Handlebars.AST = {}; + + Handlebars.AST.ProgramNode = function(statements, inverse) { + this.type = "program"; + this.statements = statements; + if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); } + }; + + Handlebars.AST.MustacheNode = function(params, hash, unescaped) { + this.type = "mustache"; + this.id = params[0]; + this.params = params.slice(1); + this.hash = hash; + this.escaped = !unescaped; + }; + + Handlebars.AST.PartialNode = function(id, context) { + this.type = "partial"; + + // TODO: disallow complex IDs + + this.id = id; + 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, close) { + verifyMatch(mustache.id, close); + this.type = "block"; + this.mustache = mustache; + this.program = program; + }; + + Handlebars.AST.InverseNode = function(mustache, program, close) { + verifyMatch(mustache.id, close); + this.type = "inverse"; + this.mustache = mustache; + this.program = program; + }; + + Handlebars.AST.ContentNode = function(string) { + this.type = "content"; + this.string = string; + }; + + Handlebars.AST.HashNode = function(pairs) { + this.type = "hash"; + this.pairs = pairs; + }; + + Handlebars.AST.IdNode = function(parts) { + this.type = "ID"; + this.original = parts.join("."); + + var dig = [], depth = 0; + + for(var i=0,l=parts.length; i": ">", + '"': """, + "'": "'", + "`": "`" + }; + + 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; + } + } + }; +})();; +// lib/handlebars/compiler/compiler.js +Handlebars.Compiler = function() {}; +Handlebars.JavaScriptCompiler = function() {}; + +(function(Compiler, JavaScriptCompiler) { + Compiler.OPCODE_MAP = { + appendContent: 1, + getContext: 2, + lookupWithHelpers: 3, + lookup: 4, + append: 5, + invokeMustache: 6, + appendEscaped: 7, + pushString: 8, + truthyOrFallback: 9, + functionOrFallback: 10, + invokeProgram: 11, + invokePartial: 12, + push: 13, + assignToHash: 15, + pushStringParam: 16 + }; + + Compiler.MULTI_PARAM_OPCODES = { + appendContent: 1, + getContext: 1, + lookupWithHelpers: 2, + lookup: 1, + invokeMustache: 3, + pushString: 1, + truthyOrFallback: 1, + functionOrFallback: 1, + invokeProgram: 3, + invokePartial: 1, + push: 1, + assignToHash: 1, + pushStringParam: 1 + }; + + Compiler.DISASSEMBLE_MAP = {}; + + for(var prop in Compiler.OPCODE_MAP) { + var value = Compiler.OPCODE_MAP[prop]; + Compiler.DISASSEMBLE_MAP[value] = prop; + } + + Compiler.multiParamSize = function(code) { + return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]]; + }; + + Compiler.prototype = { + compiler: Compiler, + + disassemble: function() { + var opcodes = this.opcodes, opcode, nextCode; + var out = [], str, name, value; + + for(var i=0, l=opcodes.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() { + return "stack" + this.stackSlot--; + }, + + topStack: function() { + return "stack" + this.stackSlot; + }, + + quotedString: function(str) { + return '"' + str + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + '"'; + } + }; + + var reservedWords = ( + "break else new var" + + " case finally return void" + + " catch for switch while" + + " continue function this with" + + " default if throw" + + " delete in try" + + " do instanceof typeof" + + " abstract enum int short" + + " boolean export interface static" + + " byte extends long super" + + " char final native synchronized" + + " class float package throws" + + " const goto private transient" + + " debugger implements protected volatile" + + " double import public let yield" + ).split(" "); + + var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; + + for(var i=0, l=reservedWords.length; i