summaryrefslogtreecommitdiffstats
path: root/lib/handlebars
diff options
context:
space:
mode:
authorKevin Decker <kpdecker@gmail.com>2013-10-12 14:22:10 -0700
committerKevin Decker <kpdecker@gmail.com>2013-10-12 14:22:10 -0700
commit583141de7cb61eb70eaa6b33c25f475f3048071b (patch)
tree47c419f82f2941fbde5ff5aa33a85b79d6772b4c /lib/handlebars
parent782aae95d0b430058e2f65b8eba1621453f9055e (diff)
parent3f96319f103d1e9dc4a6de220d2a9934e00df0b6 (diff)
downloadhandlebars.js-583141de7cb61eb70eaa6b33c25f475f3048071b.zip
handlebars.js-583141de7cb61eb70eaa6b33c25f475f3048071b.tar.gz
handlebars.js-583141de7cb61eb70eaa6b33c25f475f3048071b.tar.bz2
Merge pull request #628 from wycats/es6-modules
Convert code to ES6 modules
Diffstat (limited to 'lib/handlebars')
-rw-r--r--lib/handlebars/base.js240
-rw-r--r--lib/handlebars/browser-prefix.js2
-rw-r--r--lib/handlebars/browser-suffix.js13
-rw-r--r--lib/handlebars/compiler/ast.js69
-rw-r--r--lib/handlebars/compiler/base.js25
-rw-r--r--lib/handlebars/compiler/compiler.js58
-rw-r--r--lib/handlebars/compiler/index.js18
-rw-r--r--lib/handlebars/compiler/javascript-compiler.js30
-rw-r--r--lib/handlebars/compiler/printer.js47
-rw-r--r--lib/handlebars/compiler/visitor.js15
-rw-r--r--lib/handlebars/exception.js15
-rw-r--r--lib/handlebars/runtime.js214
-rw-r--r--lib/handlebars/safe-string.js10
-rw-r--r--lib/handlebars/utils.js102
14 files changed, 398 insertions, 460 deletions
diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js
index 1decfd2..29c8de8 100644
--- a/lib/handlebars/base.js
+++ b/lib/handlebars/base.js
@@ -1,32 +1,26 @@
/*jshint eqnull: true */
-module.exports.create = function() {
+import { extend, isEmpty } from "./utils";
+import Exception from "./exception";
-var Handlebars = {};
+export var VERSION = "1.0.0";
+export var COMPILER_REVISION = 4;
-// BEGIN(BROWSER)
-
-Handlebars.VERSION = "1.0.0";
-Handlebars.COMPILER_REVISION = 4;
-
-Handlebars.REVISION_CHANGES = {
+export var REVISION_CHANGES = {
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
2: '== 1.0.0-rc.3',
3: '== 1.0.0-rc.4',
4: '>= 1.0.0'
};
-Handlebars.helpers = {};
-Handlebars.partials = {};
-
var toString = Object.prototype.toString,
objectType = '[object Object]';
// Sourced from lodash
// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
-function isFunction(value) {
+var isFunction = function(value) {
return typeof value === 'function';
-}
+};
// fallback for older versions of Chrome and Safari
if (isFunction(/x/)) {
isFunction = function(value) {
@@ -36,138 +30,154 @@ if (isFunction(/x/)) {
function isArray(value) {
return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false;
-};
+}
-Handlebars.registerHelper = function(name, fn, inverse) {
- if (toString.call(name) === objectType) {
- if (inverse || fn) { throw new Handlebars.Exception('Arg not supported with multiple helpers'); }
- Handlebars.Utils.extend(this.helpers, name);
- } else {
- if (inverse) { fn.not = inverse; }
- this.helpers[name] = fn;
- }
-};
+export function HandlebarsEnvironment(helpers, partials) {
+ this.helpers = helpers || {};
+ this.partials = partials || {};
-Handlebars.registerPartial = function(name, str) {
- if (toString.call(name) === objectType) {
- Handlebars.Utils.extend(this.partials, name);
- } else {
- this.partials[name] = str;
- }
-};
+ registerDefaultHelpers(this);
+}
-Handlebars.registerHelper('helperMissing', function(arg) {
- if(arguments.length === 2) {
- return undefined;
- } else {
- throw new Error("Missing helper: '" + arg + "'");
- }
-});
+HandlebarsEnvironment.prototype = {
+ constructor: HandlebarsEnvironment,
-Handlebars.registerHelper('blockHelperMissing', function(context, options) {
- var inverse = options.inverse || function() {}, fn = options.fn;
+ logger: logger,
+ log: log,
- if (isFunction(context)) { context = context.call(this); }
+ registerHelper: function(name, fn, inverse) {
+ if (toString.call(name) === objectType) {
+ if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); }
+ extend(this.helpers, name);
+ } else {
+ if (inverse) { fn.not = inverse; }
+ this.helpers[name] = fn;
+ }
+ },
- if(context === true) {
- return fn(this);
- } else if(context === false || context == null) {
- return inverse(this);
- } else if (isArray(context)) {
- if(context.length > 0) {
- return Handlebars.helpers.each(context, options);
+ registerPartial: function(name, str) {
+ if (toString.call(name) === objectType) {
+ extend(this.partials, name);
} else {
- return inverse(this);
+ this.partials[name] = str;
}
- } else {
- return fn(context);
}
-});
-
-Handlebars.createFrame = function(object) {
- var obj = {};
- Handlebars.Utils.extend(obj, object);
- return obj;
};
-Handlebars.logger = {
- DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,
+function registerDefaultHelpers(instance) {
+ instance.registerHelper('helperMissing', function(arg) {
+ if(arguments.length === 2) {
+ return undefined;
+ } else {
+ throw new Error("Missing helper: '" + arg + "'");
+ }
+ });
+
+ instance.registerHelper('blockHelperMissing', function(context, options) {
+ var inverse = options.inverse || function() {}, fn = options.fn;
- methodMap: {0: 'debug', 1: 'info', 2: 'warn', 3: 'error'},
+ if (isFunction(context)) { context = context.call(this); }
- // can be overridden in the host environment
- log: function(level, obj) {
- if (Handlebars.logger.level <= level) {
- var method = Handlebars.logger.methodMap[level];
- if (typeof console !== 'undefined' && console[method]) {
- console[method].call(console, obj);
+ if(context === true) {
+ return fn(this);
+ } else if(context === false || context == null) {
+ return inverse(this);
+ } else if (isArray(context)) {
+ if(context.length > 0) {
+ return instance.helpers.each(context, options);
+ } else {
+ return inverse(this);
}
+ } else {
+ return fn(context);
}
- }
-};
+ });
-Handlebars.log = function(level, obj) { Handlebars.logger.log(level, obj); };
+ instance.registerHelper('each', function(context, options) {
+ var fn = options.fn, inverse = options.inverse;
+ var i = 0, ret = "", data;
-Handlebars.registerHelper('each', function(context, options) {
- var fn = options.fn, inverse = options.inverse;
- var i = 0, ret = "", data;
+ if (isFunction(context)) { context = context.call(this); }
- if (isFunction(context)) { context = context.call(this); }
-
- if (options.data) {
- data = Handlebars.createFrame(options.data);
- }
+ if (options.data) {
+ data = createFrame(options.data);
+ }
- if(context && typeof context === 'object') {
- if (isArray(context)) {
- for(var j = context.length; i<j; i++) {
- if (data) { data.index = i; }
- ret = ret + fn(context[i], { data: data });
- }
- } else {
- for(var key in context) {
- if(context.hasOwnProperty(key)) {
- if(data) { data.key = key; }
- ret = ret + fn(context[key], {data: data});
- i++;
+ if(context && typeof context === 'object') {
+ if (isArray(context)) {
+ for(var j = context.length; i<j; i++) {
+ if (data) { data.index = i; }
+ ret = ret + fn(context[i], { data: data });
+ }
+ } else {
+ for(var key in context) {
+ if(context.hasOwnProperty(key)) {
+ if(data) { data.key = key; }
+ ret = ret + fn(context[key], {data: data});
+ i++;
+ }
}
}
}
- }
- if(i === 0){
- ret = inverse(this);
- }
+ if(i === 0){
+ ret = inverse(this);
+ }
- return ret;
-});
+ return ret;
+ });
-Handlebars.registerHelper('if', function(conditional, options) {
- if (isFunction(conditional)) { conditional = conditional.call(this); }
+ instance.registerHelper('if', function(conditional, options) {
+ if (isFunction(conditional)) { conditional = conditional.call(this); }
- if(Handlebars.Utils.isEmpty(conditional)) {
- return options.inverse(this);
- } else {
- return options.fn(this);
- }
-});
+ if (isEmpty(conditional)) {
+ return options.inverse(this);
+ } else {
+ return options.fn(this);
+ }
+ });
-Handlebars.registerHelper('unless', function(conditional, options) {
- return Handlebars.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn});
-});
+ instance.registerHelper('unless', function(conditional, options) {
+ return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn});
+ });
-Handlebars.registerHelper('with', function(context, options) {
- if (isFunction(context)) { context = context.call(this); }
+ instance.registerHelper('with', function(context, options) {
+ if (isFunction(context)) { context = context.call(this); }
- if (!Handlebars.Utils.isEmpty(context)) return options.fn(context);
-});
+ if (!isEmpty(context)) return options.fn(context);
+ });
-Handlebars.registerHelper('log', function(context, options) {
- var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
- Handlebars.log(level, context);
-});
+ instance.registerHelper('log', function(context, options) {
+ var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
+ instance.log(level, context);
+ });
+}
+
+export var logger = {
+ methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
+
+ // State enum
+ DEBUG: 0,
+ INFO: 1,
+ WARN: 2,
+ ERROR: 3,
+ level: 3,
+
+ // can be overridden in the host environment
+ log: function(level, obj) {
+ if (logger.level <= level) {
+ var method = logger.methodMap[level];
+ if (typeof console !== 'undefined' && console[method]) {
+ console[method].call(console, obj);
+ }
+ }
+ }
+};
-// END(BROWSER)
+export function log(level, obj) { logger.log(level, obj); }
-return Handlebars;
+export var createFrame = function(object) {
+ var obj = {};
+ extend(obj, object);
+ return obj;
};
diff --git a/lib/handlebars/browser-prefix.js b/lib/handlebars/browser-prefix.js
deleted file mode 100644
index a8f1722..0000000
--- a/lib/handlebars/browser-prefix.js
+++ /dev/null
@@ -1,2 +0,0 @@
-(function(undefined) {
- var Handlebars = {};
diff --git a/lib/handlebars/browser-suffix.js b/lib/handlebars/browser-suffix.js
deleted file mode 100644
index d357c72..0000000
--- a/lib/handlebars/browser-suffix.js
+++ /dev/null
@@ -1,13 +0,0 @@
- if (typeof module === 'object' && module.exports) {
- // CommonJS
- module.exports = Handlebars;
-
- } else if (typeof define === "function" && define.amd) {
- // AMD modules
- define(function() { return Handlebars; });
-
- } else {
- // other, i.e. browser
- this.Handlebars = Handlebars;
- }
-}).call(this);
diff --git a/lib/handlebars/compiler/ast.js b/lib/handlebars/compiler/ast.js
index 567e297..336492d 100644
--- a/lib/handlebars/compiler/ast.js
+++ b/lib/handlebars/compiler/ast.js
@@ -1,15 +1,12 @@
-exports.attach = function(Handlebars) {
+import Exception from "../exception";
-// BEGIN(BROWSER)
-Handlebars.AST = {};
-
-Handlebars.AST.ProgramNode = function(statements, inverse) {
+export function ProgramNode(statements, inverse) {
this.type = "program";
this.statements = statements;
- if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); }
-};
+ if(inverse) { this.inverse = new ProgramNode(inverse); }
+}
-Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) {
+export function MustacheNode(rawParams, hash, unescaped) {
this.type = "mustache";
this.escaped = !unescaped;
this.hash = hash;
@@ -29,17 +26,17 @@ Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) {
// if a mustache is an eligible helper but not a definite
// helper, it is ambiguous, and will be resolved in a later
// pass or at runtime.
-};
+}
-Handlebars.AST.PartialNode = function(partialName, context) {
+export function PartialNode(partialName, context) {
this.type = "partial";
this.partialName = partialName;
this.context = context;
-};
+}
-Handlebars.AST.BlockNode = function(mustache, program, inverse, close) {
+export function BlockNode(mustache, program, inverse, close) {
if(mustache.id.original !== close.original) {
- throw new Handlebars.Exception(mustache.id.original + " doesn't match " + close.original);
+ throw new Exception(mustache.id.original + " doesn't match " + close.original);
}
this.type = "block";
@@ -50,19 +47,19 @@ Handlebars.AST.BlockNode = function(mustache, program, inverse, close) {
if (this.inverse && !this.program) {
this.isInverse = true;
}
-};
+}
-Handlebars.AST.ContentNode = function(string) {
+export function ContentNode(string) {
this.type = "content";
this.string = string;
-};
+}
-Handlebars.AST.HashNode = function(pairs) {
+export function HashNode(pairs) {
this.type = "hash";
this.pairs = pairs;
-};
+}
-Handlebars.AST.IdNode = function(parts) {
+export function IdNode(parts) {
this.type = "ID";
var original = "",
@@ -74,7 +71,7 @@ Handlebars.AST.IdNode = function(parts) {
original += (parts[i].separator || '') + part;
if (part === ".." || part === "." || part === "this") {
- if (dig.length > 0) { throw new Handlebars.Exception("Invalid path: " + original); }
+ if (dig.length > 0) { throw new Exception("Invalid path: " + original); }
else if (part === "..") { depth++; }
else { this.isScoped = true; }
}
@@ -91,45 +88,39 @@ Handlebars.AST.IdNode = function(parts) {
this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
this.stringModeValue = this.string;
-};
+}
-Handlebars.AST.PartialNameNode = function(name) {
+export function PartialNameNode(name) {
this.type = "PARTIAL_NAME";
this.name = name.original;
-};
+}
-Handlebars.AST.DataNode = function(id) {
+export function DataNode(id) {
this.type = "DATA";
this.id = id;
-};
+}
-Handlebars.AST.StringNode = function(string) {
+export function StringNode(string) {
this.type = "STRING";
this.original =
this.string =
this.stringModeValue = string;
-};
+}
-Handlebars.AST.IntegerNode = function(integer) {
+export function IntegerNode(integer) {
this.type = "INTEGER";
this.original =
this.integer = integer;
this.stringModeValue = Number(integer);
-};
+}
-Handlebars.AST.BooleanNode = function(bool) {
+export function BooleanNode(bool) {
this.type = "BOOLEAN";
this.bool = bool;
this.stringModeValue = bool === "true";
-};
+}
-Handlebars.AST.CommentNode = function(comment) {
+export function CommentNode(comment) {
this.type = "comment";
this.comment = comment;
-};
-
-// END(BROWSER)
-
-return Handlebars;
-};
-
+}
diff --git a/lib/handlebars/compiler/base.js b/lib/handlebars/compiler/base.js
index 7594451..d6cb06e 100644
--- a/lib/handlebars/compiler/base.js
+++ b/lib/handlebars/compiler/base.js
@@ -1,21 +1,12 @@
-var handlebars = require("./parser");
+import parser from "./parser";
+module AST from "./ast";
-exports.attach = function(Handlebars) {
-
-// BEGIN(BROWSER)
-
-Handlebars.Parser = handlebars;
-
-Handlebars.parse = function(input) {
+export { parser };
+export function parse(input) {
// Just return if an already-compile AST was passed in.
- if(input.constructor === Handlebars.AST.ProgramNode) { return input; }
-
- Handlebars.Parser.yy = Handlebars.AST;
- return Handlebars.Parser.parse(input);
-};
-
-// END(BROWSER)
+ if(input.constructor === AST.ProgramNode) { return input; }
-return Handlebars;
-};
+ parser.yy = AST;
+ return parser.parse(input);
+}
diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js
index 98e12b1..50195e3 100644
--- a/lib/handlebars/compiler/compiler.js
+++ b/lib/handlebars/compiler/compiler.js
@@ -1,13 +1,9 @@
-var compilerbase = require("./base");
+import Exception from "../exception";
+import { parse } from "./base";
+import JavaScriptCompiler from "./javascript-compiler";
+module AST from "./ast";
-exports.attach = function(Handlebars) {
-
-compilerbase.attach(Handlebars);
-
-// BEGIN(BROWSER)
-
-/*jshint eqnull:true*/
-var Compiler = Handlebars.Compiler = function() {};
+export function Compiler() {}
// the foundHelper register will disambiguate helper lookup from finding a
// function in a context. This is necessary for mustache compatibility, which
@@ -40,6 +36,7 @@ Compiler.prototype = {
return out.join("\n");
},
+
equals: function(other) {
var len = this.opcodes.length;
if (other.opcodes.length !== len) {
@@ -301,7 +298,7 @@ Compiler.prototype = {
DATA: function(data) {
this.options.data = true;
if (data.id.isScoped || data.id.depth) {
- throw new Handlebars.Exception('Scoped data references are not supported: ' + data.original);
+ throw new Exception('Scoped data references are not supported: ' + data.original);
}
this.opcode('lookupData');
@@ -415,49 +412,46 @@ Compiler.prototype = {
}
};
-Handlebars.precompile = function(input, options) {
- if (input == null || (typeof input !== 'string' && input.constructor !== Handlebars.AST.ProgramNode)) {
- throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
+export function precompile(input, options) {
+ if (input == null || (typeof input !== 'string' && input.constructor !== AST.ProgramNode)) {
+ throw new Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
}
options = options || {};
if (!('data' in options)) {
options.data = true;
}
- var ast = Handlebars.parse(input);
+
+ var ast = parse(input);
var environment = new Compiler().compile(ast, options);
- return new Handlebars.JavaScriptCompiler().compile(environment, options);
-};
+ return new JavaScriptCompiler().compile(environment, options);
+}
-Handlebars.compile = function(input, options) {
- if (input == null || (typeof input !== 'string' && input.constructor !== Handlebars.AST.ProgramNode)) {
- throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
+export function compile(input, options, env) {
+ if (input == null || (typeof input !== 'string' && input.constructor !== AST.ProgramNode)) {
+ throw new Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
}
options = options || {};
+
if (!('data' in options)) {
options.data = true;
}
+
var compiled;
- function compile() {
- var ast = Handlebars.parse(input);
+
+ function compileInput() {
+ var ast = parse(input);
var environment = new Compiler().compile(ast, options);
- var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
- return Handlebars.template(templateSpec);
+ var templateSpec = new JavaScriptCompiler().compile(environment, options, undefined, true);
+ return env.template(templateSpec);
}
// Template is only compiled on first use and cached after that point.
return function(context, options) {
if (!compiled) {
- compiled = compile();
+ compiled = compileInput();
}
return compiled.call(this, context, options);
};
-};
-
-
-// END(BROWSER)
-
-return Handlebars;
-
-};
+}
diff --git a/lib/handlebars/compiler/index.js b/lib/handlebars/compiler/index.js
deleted file mode 100644
index 0cc5c01..0000000
--- a/lib/handlebars/compiler/index.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Each of these module will augment the Handlebars object as it loads. No need to perform addition operations
-module.exports.attach = function(Handlebars) {
-
-var visitor = require("./visitor"),
- printer = require("./printer"),
- ast = require("./ast"),
- compiler = require("./compiler"),
- javascriptCompiler = require("./javascript-compiler");
-
-visitor.attach(Handlebars);
-printer.attach(Handlebars);
-ast.attach(Handlebars);
-compiler.attach(Handlebars);
-javascriptCompiler.attach(Handlebars);
-
-return Handlebars;
-
-};
diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js
index 0bb1816..a81a99c 100644
--- a/lib/handlebars/compiler/javascript-compiler.js
+++ b/lib/handlebars/compiler/javascript-compiler.js
@@ -1,18 +1,10 @@
-var compilerbase = require("./base");
+import { COMPILER_REVISION, REVISION_CHANGES, log } from "../base";
-exports.attach = function(Handlebars) {
-
-compilerbase.attach(Handlebars);
-
-// BEGIN(BROWSER)
-/*jshint eqnull:true*/
-
-var Literal = function(value) {
+function Literal(value) {
this.value = value;
-};
-
+}
-var JavaScriptCompiler = Handlebars.JavaScriptCompiler = function() {};
+function JavaScriptCompiler() {}
JavaScriptCompiler.prototype = {
// PUBLIC API: You can override these methods in a subclass to provide
@@ -51,7 +43,7 @@ JavaScriptCompiler.prototype = {
this.environment = environment;
this.options = options || {};
- Handlebars.log(Handlebars.logger.DEBUG, this.environment.disassemble() + "\n\n");
+ log('debug', this.environment.disassemble() + "\n\n");
this.name = this.environment.name;
this.isChild = !!context;
@@ -162,8 +154,8 @@ JavaScriptCompiler.prototype = {
var source = this.mergeSource();
if (!this.isChild) {
- var revision = Handlebars.COMPILER_REVISION,
- versions = Handlebars.REVISION_CHANGES[revision];
+ var revision = COMPILER_REVISION,
+ versions = REVISION_CHANGES[revision];
source = "this.compilerInfo = ["+revision+",'"+versions+"'];\n"+source;
}
@@ -173,7 +165,7 @@ JavaScriptCompiler.prototype = {
return Function.apply(this, params);
} else {
var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + source + '}';
- Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
+ log('debug', functionSource + "\n\n");
return functionSource;
}
},
@@ -849,8 +841,4 @@ JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
return false;
};
-// END(BROWSER)
-
-return Handlebars;
-
-};
+export default JavaScriptCompiler;
diff --git a/lib/handlebars/compiler/printer.js b/lib/handlebars/compiler/printer.js
index d9eb7a5..a35cdf4 100644
--- a/lib/handlebars/compiler/printer.js
+++ b/lib/handlebars/compiler/printer.js
@@ -1,15 +1,16 @@
-exports.attach = function(Handlebars) {
+import Visitor from "./visitor";
-// BEGIN(BROWSER)
+export function print(ast) {
+ return new PrintVisitor().accept(ast);
+}
-Handlebars.print = function(ast) {
- return new Handlebars.PrintVisitor().accept(ast);
-};
+export function PrintVisitor() {
+ this.padding = 0;
+}
-Handlebars.PrintVisitor = function() { this.padding = 0; };
-Handlebars.PrintVisitor.prototype = new Handlebars.Visitor();
+PrintVisitor.prototype = new Visitor();
-Handlebars.PrintVisitor.prototype.pad = function(string, newline) {
+PrintVisitor.prototype.pad = function(string, newline) {
var out = "";
for(var i=0,l=this.padding; i<l; i++) {
@@ -22,7 +23,7 @@ Handlebars.PrintVisitor.prototype.pad = function(string, newline) {
return out;
};
-Handlebars.PrintVisitor.prototype.program = function(program) {
+PrintVisitor.prototype.program = function(program) {
var out = "",
statements = program.statements,
inverse = program.inverse,
@@ -37,7 +38,7 @@ Handlebars.PrintVisitor.prototype.program = function(program) {
return out;
};
-Handlebars.PrintVisitor.prototype.block = function(block) {
+PrintVisitor.prototype.block = function(block) {
var out = "";
out = out + this.pad("BLOCK:");
@@ -62,7 +63,7 @@ Handlebars.PrintVisitor.prototype.block = function(block) {
return out;
};
-Handlebars.PrintVisitor.prototype.mustache = function(mustache) {
+PrintVisitor.prototype.mustache = function(mustache) {
var params = mustache.params, paramStrings = [], hash;
for(var i=0, l=params.length; i<l; i++) {
@@ -76,13 +77,13 @@ Handlebars.PrintVisitor.prototype.mustache = function(mustache) {
return this.pad("{{ " + this.accept(mustache.id) + " " + params + hash + " }}");
};
-Handlebars.PrintVisitor.prototype.partial = function(partial) {
+PrintVisitor.prototype.partial = function(partial) {
var content = this.accept(partial.partialName);
if(partial.context) { content = content + " " + this.accept(partial.context); }
return this.pad("{{> " + content + " }}");
};
-Handlebars.PrintVisitor.prototype.hash = function(hash) {
+PrintVisitor.prototype.hash = function(hash) {
var pairs = hash.pairs;
var joinedPairs = [], left, right;
@@ -95,19 +96,19 @@ Handlebars.PrintVisitor.prototype.hash = function(hash) {
return "HASH{" + joinedPairs.join(", ") + "}";
};
-Handlebars.PrintVisitor.prototype.STRING = function(string) {
+PrintVisitor.prototype.STRING = function(string) {
return '"' + string.string + '"';
};
-Handlebars.PrintVisitor.prototype.INTEGER = function(integer) {
+PrintVisitor.prototype.INTEGER = function(integer) {
return "INTEGER{" + integer.integer + "}";
};
-Handlebars.PrintVisitor.prototype.BOOLEAN = function(bool) {
+PrintVisitor.prototype.BOOLEAN = function(bool) {
return "BOOLEAN{" + bool.bool + "}";
};
-Handlebars.PrintVisitor.prototype.ID = function(id) {
+PrintVisitor.prototype.ID = function(id) {
var path = id.parts.join("/");
if(id.parts.length > 1) {
return "PATH:" + path;
@@ -116,23 +117,19 @@ Handlebars.PrintVisitor.prototype.ID = function(id) {
}
};
-Handlebars.PrintVisitor.prototype.PARTIAL_NAME = function(partialName) {
+PrintVisitor.prototype.PARTIAL_NAME = function(partialName) {
return "PARTIAL:" + partialName.name;
};
-Handlebars.PrintVisitor.prototype.DATA = function(data) {
+PrintVisitor.prototype.DATA = function(data) {
return "@" + this.accept(data.id);
};
-Handlebars.PrintVisitor.prototype.content = function(content) {
+PrintVisitor.prototype.content = function(content) {
return this.pad("CONTENT[ '" + content.string + "' ]");
};
-Handlebars.PrintVisitor.prototype.comment = function(comment) {
+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 5d07314..6a0373e 100644
--- a/lib/handlebars/compiler/visitor.js
+++ b/lib/handlebars/compiler/visitor.js
@@ -1,18 +1,11 @@
-exports.attach = function(Handlebars) {
+function Visitor() {}
-// BEGIN(BROWSER)
+Visitor.prototype = {
+ constructor: Visitor,
-Handlebars.Visitor = function() {};
-
-Handlebars.Visitor.prototype = {
accept: function(object) {
return this[object.type](object);
}
};
-// END(BROWSER)
-
-return Handlebars;
-};
-
-
+export default Visitor;
diff --git a/lib/handlebars/exception.js b/lib/handlebars/exception.js
new file mode 100644
index 0000000..6de9cfd
--- /dev/null
+++ b/lib/handlebars/exception.js
@@ -0,0 +1,15 @@
+
+var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
+
+function Exception(/* message */) {
+ var tmp = Error.prototype.constructor.apply(this, arguments);
+
+ // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
+ for (var idx = 0; idx < errorProps.length; idx++) {
+ this[errorProps[idx]] = tmp[errorProps[idx]];
+ }
+}
+
+Exception.prototype = new Error();
+
+export default Exception;
diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js
index 81e8aef..57a830b 100644
--- a/lib/handlebars/runtime.js
+++ b/lib/handlebars/runtime.js
@@ -1,124 +1,138 @@
-exports.attach = function(Handlebars) {
-
-// BEGIN(BROWSER)
+import Exception from "./exception";
+import { escapeExpression, extend } from "./utils";
+import { COMPILER_REVISION, REVISION_CHANGES } from "./base";
function checkRevision(compilerInfo) {
var compilerRevision = compilerInfo && compilerInfo[0] || 1,
- currentRevision = Handlebars.COMPILER_REVISION;
+ currentRevision = COMPILER_REVISION;
if (compilerRevision !== currentRevision) {
if (compilerRevision < currentRevision) {
- var runtimeVersions = Handlebars.REVISION_CHANGES[currentRevision],
- compilerVersions = Handlebars.REVISION_CHANGES[compilerRevision];
- throw "Template was precompiled with an older version of Handlebars than the current runtime. "+
- "Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").";
+ var runtimeVersions = REVISION_CHANGES[currentRevision],
+ compilerVersions = REVISION_CHANGES[compilerRevision];
+ throw new Error("Template was precompiled with an older version of Handlebars than the current runtime. "+
+ "Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").");
} else {
// Use the embedded version info since the runtime doesn't know about this revision yet
- throw "Template was precompiled with a newer version of Handlebars than the current runtime. "+
- "Please update your runtime to a newer version ("+compilerInfo[1]+").";
+ throw new Error("Template was precompiled with a newer version of Handlebars than the current runtime. "+
+ "Please update your runtime to a newer version ("+compilerInfo[1]+").");
}
}
}
-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) {
- programWrapper = Handlebars.VM.program(i, fn, data);
- } else if (!programWrapper) {
- programWrapper = this.programs[i] = Handlebars.VM.program(i, fn);
- }
- return programWrapper;
- },
- merge: function(param, common) {
- var ret = param || common;
-
- if (param && common && (param !== common)) {
- ret = {};
- Handlebars.Utils.extend(ret, common);
- Handlebars.Utils.extend(ret, param);
- }
- return ret;
- },
- programWithDepth: Handlebars.VM.programWithDepth,
- noop: Handlebars.VM.noop,
- compilerInfo: null
- };
+// TODO: Remove this line and break up compilePartial
- return function(context, options) {
- options = options || {};
- var namespace = options.partial ? options : Handlebars,
- helpers,
- partials;
+export function template(templateSpec, env) {
+ if (!env) {
+ throw new Error("No environment passed to template");
+ }
+
+ var invokePartialWrapper;
+ if (env.compile) {
+ invokePartialWrapper = function(partial, name, context, helpers, partials, data) {
+ // TODO : Check this for all inputs and the options handling (partial flag, etc). This feels
+ // like there should be a common exec path
+ var result = invokePartial.apply(this, arguments);
+ if (result) { return result; }
+
+ var options = { helpers: helpers, partials: partials, data: data };
+ partials[name] = env.compile(partial, { data: data !== undefined }, env);
+ return partials[name](context, options);
+ };
+ } else {
+ invokePartialWrapper = function(partial, name /* , context, helpers, partials, data */) {
+ var result = invokePartial.apply(this, arguments);
+ if (result) { return result; }
+ throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
+ };
+ }
- if (!options.partial) {
- helpers = options.helpers;
- partials = options.partials;
+ // Just add water
+ var container = {
+ escapeExpression: escapeExpression,
+ invokePartial: invokePartialWrapper,
+ programs: [],
+ program: function(i, fn, data) {
+ var programWrapper = this.programs[i];
+ if(data) {
+ programWrapper = program(i, fn, data);
+ } else if (!programWrapper) {
+ programWrapper = this.programs[i] = program(i, fn);
}
- var result = templateSpec.call(
- container,
- namespace, context,
- helpers,
- partials,
- options.data);
-
- if (!options.partial) {
- checkRevision(container.compilerInfo);
+ return programWrapper;
+ },
+ merge: function(param, common) {
+ var ret = param || common;
+
+ if (param && common && (param !== common)) {
+ ret = {};
+ extend(ret, common);
+ extend(ret, param);
}
+ return ret;
+ },
+ programWithDepth: programWithDepth,
+ noop: noop,
+ compilerInfo: null
+ };
+
+ return function(context, options) {
+ options = options || {};
+ var namespace = options.partial ? options : env,
+ helpers,
+ partials;
+
+ if (!options.partial) {
+ helpers = options.helpers;
+ partials = options.partials;
+ }
+ var result = templateSpec.call(
+ container,
+ namespace, context,
+ helpers,
+ partials,
+ options.data);
- return result;
- };
- },
+ if (!options.partial) {
+ checkRevision(container.compilerInfo);
+ }
- programWithDepth: function(i, fn, data /*, $depth */) {
- var args = Array.prototype.slice.call(arguments, 3);
+ return result;
+ };
+}
- var program = function(context, options) {
- options = options || {};
+export function programWithDepth(i, fn, data /*, $depth */) {
+ var args = Array.prototype.slice.call(arguments, 3);
- return fn.apply(this, [context, options.data || data].concat(args));
- };
- program.program = i;
- program.depth = args.length;
- return program;
- },
- program: function(i, fn, data) {
- var program = function(context, options) {
- options = options || {};
-
- return fn(context, options.data || data);
- };
- program.program = i;
- program.depth = 0;
- return program;
- },
- noop: function() { return ""; },
- invokePartial: function(partial, name, context, helpers, partials, data) {
- var options = { partial: true, 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, {data: data !== undefined});
- return partials[name](context, options);
- }
- }
-};
+ var prog = function(context, options) {
+ options = options || {};
-Handlebars.template = Handlebars.VM.template;
+ return fn.apply(this, [context, options.data || data].concat(args));
+ };
+ prog.program = i;
+ prog.depth = args.length;
+ return prog;
+}
+
+export function program(i, fn, data) {
+ var prog = function(context, options) {
+ options = options || {};
+
+ return fn(context, options.data || data);
+ };
+ prog.program = i;
+ prog.depth = 0;
+ return prog;
+}
-// END(BROWSER)
+export function invokePartial(partial, name, context, helpers, partials, data) {
+ var options = { partial: true, helpers: helpers, partials: partials, data: data };
-return Handlebars;
+ if(partial === undefined) {
+ throw new Exception("The partial " + name + " could not be found");
+ } else if(partial instanceof Function) {
+ return partial(context, options);
+ }
+}
-};
+export function noop() { return ""; }
diff --git a/lib/handlebars/safe-string.js b/lib/handlebars/safe-string.js
new file mode 100644
index 0000000..2ae49aa
--- /dev/null
+++ b/lib/handlebars/safe-string.js
@@ -0,0 +1,10 @@
+// Build out our basic SafeString type
+function SafeString(string) {
+ this.string = string;
+}
+
+SafeString.prototype.toString = function() {
+ return "" + this.string;
+};
+
+export default SafeString;
diff --git a/lib/handlebars/utils.js b/lib/handlebars/utils.js
index 59947ca..998c9ca 100644
--- a/lib/handlebars/utils.js
+++ b/lib/handlebars/utils.js
@@ -1,29 +1,6 @@
-exports.attach = function(Handlebars) {
+import SafeString from "./safe-string";
-var toString = Object.prototype.toString,
- isArray = Array.isArray;
-
-// BEGIN(BROWSER)
-
-var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
-
-Handlebars.Exception = function(message) {
- var tmp = Error.prototype.constructor.apply(this, arguments);
-
- // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
- for (var idx = 0; idx < errorProps.length; idx++) {
- this[errorProps[idx]] = tmp[errorProps[idx]];
- }
-};
-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;
-};
+var isArray = Array.isArray;
var escape = {
"&": "&amp;",
@@ -37,50 +14,41 @@ var escape = {
var badChars = /[&<>"'`]/g;
var possible = /[&<>"'`]/;
-var escapeChar = function(chr) {
+function escapeChar(chr) {
return escape[chr] || "&amp;";
-};
-
-Handlebars.Utils = {
- extend: function(obj, value) {
- for(var key in value) {
- if(value.hasOwnProperty(key)) {
- obj[key] = value[key];
- }
- }
- },
-
- escapeExpression: function(string) {
- /*jshint eqnull: true */
-
- // don't escape SafeStrings, since they're already safe
- if (string instanceof Handlebars.SafeString) {
- return string.toString();
- } else if (!string && string !== 0) {
- return "";
- }
-
- // Force a string conversion as this will be done by the append regardless and
- // the regex test will do this transparently behind the scenes, causing issues if
- // an object's to string has escaped characters in it.
- string = "" + string;
-
- if(!possible.test(string)) { return string; }
- return string.replace(badChars, escapeChar);
- },
+}
- isEmpty: function(value) {
- if (!value && value !== 0) {
- return true;
- } else if (isArray(value) && value.length === 0) {
- return true;
- } else {
- return false;
+export function extend(obj, value) {
+ for(var key in value) {
+ if(value.hasOwnProperty(key)) {
+ obj[key] = value[key];
}
}
-};
-
-// END(BROWSER)
+}
+
+export function escapeExpression(string) {
+ // don't escape SafeStrings, since they're already safe
+ if (string instanceof SafeString) {
+ return string.toString();
+ } else if (!string && string !== 0) {
+ return "";
+ }
-return Handlebars;
-};
+ // Force a string conversion as this will be done by the append regardless and
+ // the regex test will do this transparently behind the scenes, causing issues if
+ // an object's to string has escaped characters in it.
+ string = "" + string;
+
+ if(!possible.test(string)) { return string; }
+ return string.replace(badChars, escapeChar);
+}
+
+export function isEmpty(value) {
+ if (!value && value !== 0) {
+ return true;
+ } else if (isArray(value) && value.length === 0) {
+ return true;
+ } else {
+ return false;
+ }
+}