diff options
author | Yehuda Katz <wycats@gmail.com> | 2013-07-01 13:59:58 -0700 |
---|---|---|
committer | Yehuda Katz <wycats@gmail.com> | 2013-07-01 13:59:58 -0700 |
commit | 88ee4757e77f97afb206132eddb64e688700eb37 (patch) | |
tree | 08f7db62a3151dfbd44bfd6f1ec4ec6737a2bdb6 | |
parent | 8e2416dabb2056c07357a55b9259322f0d794ada (diff) | |
download | handlebars.js-88ee4757e77f97afb206132eddb64e688700eb37.zip handlebars.js-88ee4757e77f97afb206132eddb64e688700eb37.tar.gz handlebars.js-88ee4757e77f97afb206132eddb64e688700eb37.tar.bz2 |
Initial work on ES6 modules
-rw-r--r-- | Gruntfile.js | 51 | ||||
-rw-r--r-- | configurations/browser.js | 6 | ||||
-rw-r--r-- | configurations/concat.js | 16 | ||||
-rw-r--r-- | configurations/connect.js | 8 | ||||
-rw-r--r-- | configurations/transpile.js | 25 | ||||
-rw-r--r-- | configurations/watch.js | 4 | ||||
-rw-r--r-- | lib/handlebars.js | 22 | ||||
-rw-r--r-- | lib/handlebars/base.js | 246 | ||||
-rw-r--r-- | lib/handlebars/compiler/ast.js | 39 | ||||
-rw-r--r-- | lib/handlebars/compiler/base.js | 25 | ||||
-rw-r--r-- | lib/handlebars/compiler/compiler.js | 46 | ||||
-rw-r--r-- | lib/handlebars/compiler/javascript-compiler.js | 24 | ||||
-rw-r--r-- | lib/handlebars/runtime.js | 202 | ||||
-rw-r--r-- | lib/handlebars/utils.js | 83 | ||||
-rw-r--r-- | package.json | 54 |
15 files changed, 452 insertions, 399 deletions
diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..56231b7 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,51 @@ +function config(name) { + return require('./configurations/' + name); +} + +module.exports = function(grunt) { + + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + + clean: ["dist"], + watch: config('watch') , + concat: config('concat'), + browser: config('browser'), + connect: config('connect'), + transpile: config('transpile') + }); + + // By default, (i.e., if you invoke `grunt` without arguments), do + // a new build. + this.registerTask('default', ['build']); + + // Build a new version of the library + this.registerTask('build', "Builds a distributable version of the current project", [ + 'clean', + 'transpile:amd', + 'concat:library', + 'concat:browser', + 'browser:dist', + 'bytes']); + + this.registerTask('tests', "Builds the test package", [ + 'build', + 'concat:deps', + 'transpile:tests']); + + // Run a server. This is ideal for running the QUnit tests in the browser. + this.registerTask('server', [ + 'build', + 'tests', + 'connect', + 'watch']); + + // Load tasks from npm + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-concat'); + grunt.loadNpmTasks('grunt-contrib-connect'); + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-es6-module-transpiler'); + + grunt.task.loadTasks('tasks'); +}; diff --git a/configurations/browser.js b/configurations/browser.js new file mode 100644 index 0000000..e3d0dc3 --- /dev/null +++ b/configurations/browser.js @@ -0,0 +1,6 @@ +module.exports = { + dist: { + src: 'tmp/<%= pkg.barename %>.browser1.js', + dest: 'dist/<%= pkg.name %>-<%= pkg.version %>.js' + } +}; diff --git a/configurations/concat.js b/configurations/concat.js new file mode 100644 index 0000000..4111eee --- /dev/null +++ b/configurations/concat.js @@ -0,0 +1,16 @@ +module.exports = { + library: { + src: ['tmp/<%= pkg.barename %>.amd.js'], + dest: 'dist/<%= pkg.name %>-<%= pkg.version %>.amd.js' + }, + + deps: { + src: ['vendor/deps/*.js'], + dest: 'tmp/deps.amd.js' + }, + + browser: { + src: ['vendor/loader.js', 'tmp/<%= pkg.barename %>.amd.js'], + dest: 'tmp/<%= pkg.barename %>.browser1.js' + } +}; diff --git a/configurations/connect.js b/configurations/connect.js new file mode 100644 index 0000000..dacc760 --- /dev/null +++ b/configurations/connect.js @@ -0,0 +1,8 @@ +module.exports = { + server: {}, + options: { + hostname: '0.0.0.0', + port: 8000, + base: '.' + } +}; diff --git a/configurations/transpile.js b/configurations/transpile.js new file mode 100644 index 0000000..e912ecf --- /dev/null +++ b/configurations/transpile.js @@ -0,0 +1,25 @@ +module.exports = { + amd: { + type: 'amd', + src: ["lib/<%= pkg.barename %>.js", "lib/*/**/*.js"], + dest: "tmp/<%= pkg.barename %>.amd.js" + }, + + cjs: { + type: 'cjs', + src: ["lib/<%= pkg.barename %>.js", "lib/*/**/*.js"], + dest: "tmp/<%= pkg.barename %>.cjs.js" + }, + + globals: { + type: 'globals', + src: ["lib/<%= pkg.barename %>.js", "lib/*/**/*.js"], + dest: "tmp/<%= pkg.barename %>.globals.js" + }, + + tests: { + type: 'amd', + src: ['test/test_helpers.js', 'test/tests.js', 'test/tests/**/*_test.js'], + dest: 'tmp/tests.amd.js' + } +}; diff --git a/configurations/watch.js b/configurations/watch.js new file mode 100644 index 0000000..49b1c49 --- /dev/null +++ b/configurations/watch.js @@ -0,0 +1,4 @@ +module.exports = { + files: ['lib/**', 'vendor/*', 'test/**/*'], + tasks: ['build', 'tests'] +}; diff --git a/lib/handlebars.js b/lib/handlebars.js index f82ec3b..e051aa5 100644 --- a/lib/handlebars.js +++ b/lib/handlebars.js @@ -1,15 +1,19 @@ -var handlebars = require("./handlebars/base"), +import handlebars from "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"); +import { SafeString, Exception, extend, escapeExpression, isEmpty } from "handlebars/utils"; +import compiler from "handlebars/compiler"; +import runtime from "handlebars/runtime"; +// For compatibility and usage outside of module systems, make the Handlebars object a namespace var create = function() { var hb = handlebars.create(); - utils.attach(hb); + hb.SafeString = SafeString; + hb.Exception = Exception; + hb.utils = { extend: extend, escapeExpression: escapeExpression, isEmpty: isEmpty }; + compiler.attach(hb); runtime.attach(hb); @@ -19,10 +23,10 @@ var create = function() { var Handlebars = create(); Handlebars.create = create; -module.exports = Handlebars; // instantiate an instance +export default Handlebars; // Publish a Node.js require() handler for .handlebars and .hbs files -if (require.extensions) { +if (typeof require !== 'undefined' && require.extensions) { var extension = function(module, filename) { var fs = require("fs"); var templateString = fs.readFileSync(filename, "utf8"); @@ -32,10 +36,6 @@ if (require.extensions) { require.extensions[".hbs"] = extension; } -// BEGIN(BROWSER) - -// END(BROWSER) - // USAGE: // var handlebars = require('handlebars'); diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js index 44a369c..9849678 100644 --- a/lib/handlebars/base.js +++ b/lib/handlebars/base.js @@ -1,166 +1,168 @@ /*jshint eqnull: true */ -module.exports.create = function() { +import { Exception, extend } from "handlebars/utils"; -var Handlebars = {}; +var K = function() { return this; }; -// BEGIN(BROWSER) +export VERSION = "1.0.0"; +export COMPILER_REVISION = 4; -Handlebars.VERSION = "1.0.0"; -Handlebars.COMPILER_REVISION = 4; - -Handlebars.REVISION_CHANGES = { +export 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 = {}; +// TODO: Make this a class +export default function(helpers, partials) { -var toString = Object.prototype.toString, - functionType = '[object Function]', - objectType = '[object Object]'; + var exports = {}; -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; - } -}; -Handlebars.registerPartial = function(name, str) { - if (toString.call(name) === objectType) { - Handlebars.Utils.extend(this.partials, name); - } else { - this.partials[name] = str; - } -}; - -Handlebars.registerHelper('helperMissing', function(arg) { - if(arguments.length === 2) { - return undefined; - } else { - throw new Error("Missing helper: '" + arg + "'"); - } -}); + helpers = helpers || {}; + partials = partials || {}; -Handlebars.registerHelper('blockHelperMissing', function(context, options) { - var inverse = options.inverse || function() {}, fn = options.fn; + var toString = Object.prototype.toString, + functionType = '[object Function]', + objectType = '[object Object]'; - var type = toString.call(context); + exports.registerHelper(name, fn, inverse) { + if (toString.call(name) === objectType) { + if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); } + extend(helpers, name); + } else { + if (inverse) { fn.not = inverse; } + helpers[name] = fn; + } + }; - if(type === functionType) { context = context.call(this); } + exports.registerPartial(name, str) { + if (toString.call(name) === objectType) { + extend(partials, name); + } else { + partials[name] = str; + } + }; - if(context === true) { - return fn(this); - } else if(context === false || context == null) { - return inverse(this); - } else if(type === "[object Array]") { - if(context.length > 0) { - return Handlebars.helpers.each(context, options); + exports.registerHelper('helperMissing', function(arg) { + if(arguments.length === 2) { + return undefined; } else { - return inverse(this); + throw new Error("Missing helper: '" + arg + "'"); } - } else { - return fn(context); - } -}); + }); -Handlebars.K = function() {}; + exports.registerHelper('blockHelperMissing', function(context, options) { + var inverse = options.inverse || function() {}, fn = options.fn; -Handlebars.createFrame = Object.create || function(object) { - Handlebars.K.prototype = object; - var obj = new Handlebars.K(); - Handlebars.K.prototype = null; - return obj; -}; - -Handlebars.logger = { - DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3, + var type = toString.call(context); - methodMap: {0: 'debug', 1: 'info', 2: 'warn', 3: 'error'}, + if(type === functionType) { 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(type === "[object Array]") { + if(context.length > 0) { + return Handlebars.helpers.each(context, options); + } else { + return inverse(this); } + } else { + return fn(context); } - } -}; - -Handlebars.log = function(level, obj) { Handlebars.logger.log(level, obj); }; + }); -Handlebars.registerHelper('each', function(context, options) { - var fn = options.fn, inverse = options.inverse; - var i = 0, ret = "", data; + exports.registerHelper('each', function(context, options) { + var fn = options.fn, inverse = options.inverse; + var i = 0, ret = "", data; - var type = toString.call(context); - if(type === functionType) { context = context.call(this); } + var type = toString.call(context); + if(type === functionType) { context = context.call(this); } - if (options.data) { - data = Handlebars.createFrame(options.data); - } + if (options.data) { + data = Handlebars.createFrame(options.data); + } - if(context && typeof context === 'object') { - if(context instanceof Array){ - 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(context instanceof Array){ + 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) { - var type = toString.call(conditional); - if(type === functionType) { conditional = conditional.call(this); } + exports.registerHelper('if', function(conditional, options) { + var type = toString.call(conditional); + if(type === functionType) { conditional = conditional.call(this); } - if(!conditional || Handlebars.Utils.isEmpty(conditional)) { - return options.inverse(this); - } else { - return options.fn(this); - } -}); + if(!conditional || Handlebars.Utils.isEmpty(conditional)) { + return options.inverse(this); + } else { + return options.fn(this); + } + }); + + exports.registerHelper('unless', function(conditional, options) { + return Handlebars.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn}); + }); + + exports.registerHelper('with', function(context, options) { + var type = toString.call(context); + if(type === functionType) { context = context.call(this); } -Handlebars.registerHelper('unless', function(conditional, options) { - return Handlebars.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn}); -}); + if (!Handlebars.Utils.isEmpty(context)) return options.fn(context); + }); -Handlebars.registerHelper('with', function(context, options) { - var type = toString.call(context); - if(type === functionType) { context = context.call(this); } + exports.registerHelper('log', function(context, options) { + var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1; + Handlebars.log(level, context); + }); - if (!Handlebars.Utils.isEmpty(context)) return options.fn(context); -}); + return Handlebars; +} -Handlebars.registerHelper('log', function(context, options) { - var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1; - Handlebars.log(level, context); -}); +var levels = { + DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3 +} -// END(BROWSER) +var methodMap = { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' }; -return Handlebars; +export logger = { + // 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); + } + } + } +}; + +export function log(level, obj) { logger.log(level, obj); }; + +export createFrame = Object.create || function(object) { + K.prototype = object; + var obj = new K(); + K.prototype = null; + return obj; }; diff --git a/lib/handlebars/compiler/ast.js b/lib/handlebars/compiler/ast.js index 567e297..fcf5c6e 100644 --- a/lib/handlebars/compiler/ast.js +++ b/lib/handlebars/compiler/ast.js @@ -1,15 +1,12 @@ -exports.attach = function(Handlebars) { +import { Exception } from "handlebars/utils"; -// 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); } }; -Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) { +export function MustacheNode(rawParams, hash, unescaped) { this.type = "mustache"; this.escaped = !unescaped; this.hash = hash; @@ -31,15 +28,15 @@ Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) { // 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"; @@ -52,17 +49,17 @@ Handlebars.AST.BlockNode = function(mustache, program, inverse, close) { } }; -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(part) { this.type = "ID"; var original = "", @@ -93,43 +90,37 @@ Handlebars.AST.IdNode = function(parts) { 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..525cd5b 100644 --- a/lib/handlebars/compiler/base.js +++ b/lib/handlebars/compiler/base.js @@ -1,21 +1,12 @@ -var handlebars = require("./parser"); +import { parser } from "handlebars/compiler/parser"; +module AST from "handlebars/compiler/ast": -exports.attach = function(Handlebars) { - -// BEGIN(BROWSER) - -Handlebars.Parser = handlebars; - -Handlebars.parse = function(input) { +export Parser = parser; +export function(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..a21ccc0 100644 --- a/lib/handlebars/compiler/compiler.js +++ b/lib/handlebars/compiler/compiler.js @@ -1,13 +1,11 @@ -var compilerbase = require("./base"); - -exports.attach = function(Handlebars) { - -compilerbase.attach(Handlebars); - -// BEGIN(BROWSER) +import { Exception } from "handlebars/utils"; +import parse from "handlebars/compiler/base"; +import { template } from "handlebars/runtime"; /*jshint eqnull:true*/ -var Compiler = Handlebars.Compiler = function() {}; + +var Compiler = function() {}; +export default Compiler; // the foundHelper register will disambiguate helper lookup from finding a // function in a context. This is necessary for mustache compatibility, which @@ -40,6 +38,7 @@ Compiler.prototype = { return out.join("\n"); }, + equals: function(other) { var len = this.opcodes.length; if (other.opcodes.length !== len) { @@ -301,7 +300,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,35 +414,39 @@ Compiler.prototype = { } }; -Handlebars.precompile = function(input, options) { +export function precompile(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); + 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) { +export function 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); + 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); + 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 template(templateSpec); } // Template is only compiled on first use and cached after that point. @@ -454,10 +457,3 @@ Handlebars.compile = function(input, options) { return compiled.call(this, context, options); }; }; - - -// END(BROWSER) - -return Handlebars; - -}; diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js index 4548c6a..49660ff 100644 --- a/lib/handlebars/compiler/javascript-compiler.js +++ b/lib/handlebars/compiler/javascript-compiler.js @@ -1,18 +1,12 @@ -var compilerbase = require("./base"); +import { COMPILER_REVISION, REVISION_CHANGES } from "handlebars/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() {}; +export default JavaScriptCompiler; JavaScriptCompiler.prototype = { // PUBLIC API: You can override these methods in a subclass to provide @@ -162,8 +156,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; } @@ -848,9 +842,3 @@ JavaScriptCompiler.isValidJavaScriptVariableName = function(name) { } return false; }; - -// END(BROWSER) - -return Handlebars; - -}; diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js index 2e845c4..2585ef3 100644 --- a/lib/handlebars/runtime.js +++ b/lib/handlebars/runtime.js @@ -1,106 +1,102 @@ -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) { - 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) { - ret = {}; - Handlebars.Utils.extend(ret, common); - Handlebars.Utils.extend(ret, param); - } - return ret; - }, - programWithDepth: Handlebars.VM.programWithDepth, - noop: Handlebars.VM.noop, - compilerInfo: null - }; - - return function(context, options) { - options = options || {}; - var result = templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data); - - var compilerInfo = container.compilerInfo || [], - compilerRevision = compilerInfo[0] || 1, - currentRevision = Handlebars.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+")."; - } 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]+")."; - } +import { escapeExpression, extend, Exceptions } from "handlebars/utils"; +import { COMPILER_REVISION, REVISION_CHANGES } from "handlebars/base"; + +// TODO: Deal with the fact that compile is necessary for on-the-fly partial +// compilation but won't be present for precompiled templates. + +export function template(templateSpec) { + // Just add water + var container = { + escapeExpression: escapeExpression, + invokePartial: invokePartial, + 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); + } + return programWrapper; + }, + merge: function(param, common) { + var ret = param || common; + + if (param && common) { + ret = {}; + extend(ret, common); + extend(ret, param); + } + return ret; + }, + programWithDepth: programWithDepth, + noop: noop, + compilerInfo: null + }; + + return function(context, options) { + options = options || {}; + // TODO: Why does templateSpec require a reference to the global Handlebars? + var result = templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data); + + var compilerInfo = container.compilerInfo || [], + compilerRevision = compilerInfo[0] || 1, + currentRevision = COMPILER_REVISION; + + if (compilerRevision !== currentRevision) { + if (compilerRevision < currentRevision) { + var runtimeVersions = REVISION_CHANGES[currentRevision], + compilerVersions = 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+")."; + } 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]+")."; } - - return result; - }; - }, - - programWithDepth: function(i, fn, data /*, $depth */) { - var args = Array.prototype.slice.call(arguments, 3); - - var program = function(context, options) { - options = options || {}; - - 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 = { 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); } - } -}; -Handlebars.template = Handlebars.VM.template; - -// END(BROWSER) - -return Handlebars; - -}; + return result; + }; +} + +export function programWithDepth(i, fn, data /*, $depth */) { + var args = Array.prototype.slice.call(arguments, 3); + + var program = function(context, options) { + options = options || {}; + + return fn.apply(this, [context, options.data || data].concat(args)); + }; + program.program = i; + program.depth = args.length; + return program; +} + +export function program(i, fn, data) { + var program = function(context, options) { + options = options || {}; + + return fn(context, options.data || data); + }; + program.program = i; + program.depth = 0; + return program; +} + +export function noop() { return ""; } + +export function invokePartial(partial, name, context, helpers, partials, data) { + var options = { helpers: helpers, partials: partials, data: data }; + + if(partial === undefined) { + throw new Exception("The partial " + name + " could not be found"); + } else if(partial instanceof Function) { + return partial(context, options); + } else if (!compile) { + throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode"); + } else { + partials[name] = compile(partial, {data: data !== undefined}); + return partials[name](context, options); + } +} diff --git a/lib/handlebars/utils.js b/lib/handlebars/utils.js index 1e0e4c9..d14795c 100644 --- a/lib/handlebars/utils.js +++ b/lib/handlebars/utils.js @@ -1,12 +1,8 @@ -exports.attach = function(Handlebars) { - var toString = Object.prototype.toString; -// BEGIN(BROWSER) - var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; -Handlebars.Exception = function(message) { +export 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. @@ -14,13 +10,15 @@ Handlebars.Exception = function(message) { this[errorProps[idx]] = tmp[errorProps[idx]]; } }; -Handlebars.Exception.prototype = new Error(); + +Exception.prototype = new Error(); // Build out our basic SafeString type -Handlebars.SafeString = function(string) { +export function SafeString(string) { this.string = string; }; -Handlebars.SafeString.prototype.toString = function() { + +SafeString.prototype.toString = function() { return this.string.toString(); }; @@ -40,44 +38,37 @@ var escapeChar = function(chr) { return escape[chr] || "&"; }; -Handlebars.Utils = { - extend: function(obj, value) { - for(var key in value) { - if(value.hasOwnProperty(key)) { - obj[key] = value[key]; - } - } - }, - - 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 ""; - } - - // 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.toString(); - - if(!possible.test(string)) { return string; } - return string.replace(badChars, escapeChar); - }, - - isEmpty: function(value) { - if (!value && value !== 0) { - return true; - } else if(toString.call(value) === "[object Array]" && 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 == null || string === false) { + 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.toString(); + + if(!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); +} + +export function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if(toString.call(value) === "[object Array]" && value.length === 0) { + return true; + } else { + return false; + } +} diff --git a/package.json b/package.json index 13fdc74..024ba0a 100644 --- a/package.json +++ b/package.json @@ -1,39 +1,27 @@ { - "name": "handlebars", - "description": "Extension of the Mustache logicless template language", - "version": "1.0.12", - "homepage": "http://www.handlebarsjs.com/", - "keywords": [ - "handlebars", - "mustache", - "template", - "html" - ], + "name": "handlebars.js", + "barename": "handlebars", + "version": "1.1.0", + "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, "repository": { "type": "git", - "url": "git://github.com/wycats/handlebars.js.git" - }, - "engines": { - "node": ">=0.4.7" - }, - "dependencies": { - "optimist": "~0.3", - "uglify-js": "~2.3" + "url": "https://github.com/wycats/handlebars.js.git" }, + "author": "Yehuda Katz", + "license": "BSD", + "readmeFilename": "README.md", "devDependencies": { - "benchmark": "~1.0", - "dust": "~0.3", - "jison": "~0.3", - "mocha": "*", - "mustache": "~0.7.2", - "should": "~1.2.2" - }, - "main": "lib/handlebars.js", - "bin": { - "handlebars": "bin/handlebars" - }, - "scripts": { - "test": "node ./spec/env/runner" - }, - "optionalDependencies": {} + "grunt": "~0.4.1", + "connect": "~2.7.4", + "grunt-contrib-concat": "~0.3.0", + "grunt-contrib-clean": "~0.4.1", + "grunt-contrib-connect": "~0.3.0", + "grunt-contrib-watch": "~0.4.4", + "grunt-hang": "~0.1.2", + "grunt-es6-module-transpiler": "~0.3.0" + } } |