ember-intl
Version:
Ember toolbox for internationalization.
1,557 lines (1,270 loc) • 218 kB
JavaScript
/*!
* @overview Ember - JavaScript Application Framework
* @copyright Copyright 2011-2014 Tilde Inc. and contributors
* Portions Copyright 2006-2011 Strobe Inc.
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
* @license Licensed under MIT license
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
* @version 1.10.0
*/
(function() {
var define, requireModule, require, requirejs, Ember;
(function() {
Ember = this.Ember = this.Ember || {};
if (typeof Ember === 'undefined') { Ember = {}; };
function UNDEFINED() { }
if (typeof Ember.__loader === 'undefined') {
var registry = {}, seen = {};
define = function(name, deps, callback) {
registry[name] = { deps: deps, callback: callback };
};
requirejs = require = requireModule = function(name) {
var s = seen[name];
if (s !== undefined) { return seen[name]; }
if (s === UNDEFINED) { return undefined; }
seen[name] = {};
if (!registry[name]) {
throw new Error('Could not find module ' + name);
}
var mod = registry[name];
var deps = mod.deps;
var callback = mod.callback;
var reified = [];
var exports;
var length = deps.length;
for (var i=0; i<length; i++) {
if (deps[i] === 'exports') {
reified.push(exports = {});
} else {
reified.push(requireModule(resolve(deps[i], name)));
}
}
var value = length === 0 ? callback.call(this) : callback.apply(this, reified);
return seen[name] = exports || (value === undefined ? UNDEFINED : value);
};
function resolve(child, name) {
if (child.charAt(0) !== '.') {
return child;
}
var parts = child.split('/');
var parentBase = name.split('/').slice(0, -1);
for (var i=0, l=parts.length; i<l; i++) {
var part = parts[i];
if (part === '..') { parentBase.pop(); }
else if (part === '.') { continue; }
else { parentBase.push(part); }
}
return parentBase.join('/');
}
requirejs._eak_seen = registry;
Ember.__loader = {
define: define,
require: require,
registry: registry
};
} else {
define = Ember.__loader.define;
requirejs = require = requireModule = Ember.__loader.require;
}
})();
define("ember-metal/core",
["exports"],
function(__exports__) {
"use strict";
/*globals Ember:true,ENV,EmberENV,MetamorphENV:true */
/**
@module ember
@submodule ember-metal
*/
/**
All Ember methods and functions are defined inside of this namespace. You
generally should not add new properties to this namespace as it may be
overwritten by future versions of Ember.
You can also use the shorthand `Em` instead of `Ember`.
Ember-Runtime is a framework that provides core functions for Ember including
cross-platform functions, support for property observing and objects. Its
focus is on small size and performance. You can use this in place of or
along-side other cross-platform libraries such as jQuery.
The core Runtime framework is based on the jQuery API with a number of
performance optimizations.
@class Ember
@static
@version 1.10.0
*/
if ('undefined' === typeof Ember) {
// Create core object. Make it act like an instance of Ember.Namespace so that
// objects assigned to it are given a sane string representation.
Ember = {};
}
// Default imports, exports and lookup to the global object;
Ember.imports = Ember.imports || this;
Ember.lookup = Ember.lookup || this;
var exports = Ember.exports = Ember.exports || this;
// aliases needed to keep minifiers from removing the global context
exports.Em = exports.Ember = Ember;
// Make sure these are set whether Ember was already defined or not
Ember.isNamespace = true;
Ember.toString = function() { return "Ember"; };
/**
@property VERSION
@type String
@default '1.10.0'
@static
*/
Ember.VERSION = '1.10.0';
/**
Standard environmental variables. You can define these in a global `EmberENV`
variable before loading Ember to control various configuration settings.
For backwards compatibility with earlier versions of Ember the global `ENV`
variable will be used if `EmberENV` is not defined.
@property ENV
@type Hash
*/
if (Ember.ENV) {
// do nothing if Ember.ENV is already setup
} else if ('undefined' !== typeof EmberENV) {
Ember.ENV = EmberENV;
} else if('undefined' !== typeof ENV) {
Ember.ENV = ENV;
} else {
Ember.ENV = {};
}
Ember.config = Ember.config || {};
// We disable the RANGE API by default for performance reasons
if ('undefined' === typeof Ember.ENV.DISABLE_RANGE_API) {
Ember.ENV.DISABLE_RANGE_API = true;
}
if ("undefined" === typeof MetamorphENV) {
exports.MetamorphENV = {};
}
MetamorphENV.DISABLE_RANGE_API = Ember.ENV.DISABLE_RANGE_API;
/**
Hash of enabled Canary features. Add to this before creating your application.
You can also define `EmberENV.FEATURES` if you need to enable features flagged at runtime.
@class FEATURES
@namespace Ember
@static
@since 1.1.0
*/
Ember.FEATURES = Ember.ENV.FEATURES || {};
/**
Test that a feature is enabled. Parsed by Ember's build tools to leave
experimental features out of beta/stable builds.
You can define the following configuration options:
* `EmberENV.ENABLE_ALL_FEATURES` - force all features to be enabled.
* `EmberENV.ENABLE_OPTIONAL_FEATURES` - enable any features that have not been explicitly
enabled/disabled.
@method isEnabled
@param {String} feature
@return {Boolean}
@for Ember.FEATURES
@since 1.1.0
*/
Ember.FEATURES.isEnabled = function(feature) {
var featureValue = Ember.FEATURES[feature];
if (Ember.ENV.ENABLE_ALL_FEATURES) {
return true;
} else if (featureValue === true || featureValue === false || featureValue === undefined) {
return featureValue;
} else if (Ember.ENV.ENABLE_OPTIONAL_FEATURES) {
return true;
} else {
return false;
}
};
// ..........................................................
// BOOTSTRAP
//
/**
Determines whether Ember should enhance some built-in object prototypes to
provide a more friendly API. If enabled, a few methods will be added to
`Function`, `String`, and `Array`. `Object.prototype` will not be enhanced,
which is the one that causes most trouble for people.
In general we recommend leaving this option set to true since it rarely
conflicts with other code. If you need to turn it off however, you can
define an `EmberENV.EXTEND_PROTOTYPES` config to disable it.
@property EXTEND_PROTOTYPES
@type Boolean
@default true
@for Ember
*/
Ember.EXTEND_PROTOTYPES = Ember.ENV.EXTEND_PROTOTYPES;
if (typeof Ember.EXTEND_PROTOTYPES === 'undefined') {
Ember.EXTEND_PROTOTYPES = true;
}
/**
Determines whether Ember logs a full stack trace during deprecation warnings
@property LOG_STACKTRACE_ON_DEPRECATION
@type Boolean
@default true
*/
Ember.LOG_STACKTRACE_ON_DEPRECATION = (Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false);
/**
Determines whether Ember should add ECMAScript 5 Array shims to older browsers.
@property SHIM_ES5
@type Boolean
@default Ember.EXTEND_PROTOTYPES
*/
Ember.SHIM_ES5 = (Ember.ENV.SHIM_ES5 === false) ? false : Ember.EXTEND_PROTOTYPES;
/**
Determines whether Ember logs info about version of used libraries
@property LOG_VERSION
@type Boolean
@default true
*/
Ember.LOG_VERSION = (Ember.ENV.LOG_VERSION === false) ? false : true;
/**
Empty function. Useful for some operations. Always returns `this`.
@method K
@private
@return {Object}
*/
function K() { return this; }
__exports__.K = K;
Ember.K = K;
//TODO: ES6 GLOBAL TODO
// Stub out the methods defined by the ember-debug package in case it's not loaded
if ('undefined' === typeof Ember.assert) { Ember.assert = K; }
if ('undefined' === typeof Ember.warn) { Ember.warn = K; }
if ('undefined' === typeof Ember.debug) { Ember.debug = K; }
if ('undefined' === typeof Ember.runInDebug) { Ember.runInDebug = K; }
if ('undefined' === typeof Ember.deprecate) { Ember.deprecate = K; }
if ('undefined' === typeof Ember.deprecateFunc) {
Ember.deprecateFunc = function(_, func) { return func; };
}
__exports__["default"] = Ember;
});
define("ember-template-compiler",
["ember-metal/core","ember-template-compiler/system/precompile","ember-template-compiler/system/compile","ember-template-compiler/system/template","ember-template-compiler/plugins","ember-template-compiler/plugins/transform-each-in-to-hash","ember-template-compiler/plugins/transform-with-as-to-hash","ember-template-compiler/compat","exports"],
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
"use strict";
var _Ember = __dependency1__["default"];
var precompile = __dependency2__["default"];
var compile = __dependency3__["default"];
var template = __dependency4__["default"];
var registerPlugin = __dependency5__.registerPlugin;
var TransformEachInToHash = __dependency6__["default"];
var TransformWithAsToHash = __dependency7__["default"];
// used for adding Ember.Handlebars.compile for backwards compat
registerPlugin('ast', TransformWithAsToHash);
registerPlugin('ast', TransformEachInToHash);
__exports__._Ember = _Ember;
__exports__.precompile = precompile;
__exports__.compile = compile;
__exports__.template = template;
__exports__.registerPlugin = registerPlugin;
});
define("ember-template-compiler/compat",
["ember-metal/core","ember-template-compiler/compat/precompile","ember-template-compiler/system/compile","ember-template-compiler/system/template"],
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__) {
"use strict";
var Ember = __dependency1__["default"];
var precompile = __dependency2__["default"];
var compile = __dependency3__["default"];
var template = __dependency4__["default"];
var EmberHandlebars = Ember.Handlebars = Ember.Handlebars || {};
EmberHandlebars.precompile = precompile;
EmberHandlebars.compile = compile;
EmberHandlebars.template = template;
});
define("ember-template-compiler/compat/precompile",
["exports"],
function(__exports__) {
"use strict";
/**
@module ember
@submodule ember-template-compiler
*/
var compile, compileSpec;
__exports__["default"] = function(string) {
if ((!compile || !compileSpec) && Ember.__loader.registry['htmlbars-compiler/compiler']) {
var Compiler = requireModule('htmlbars-compiler/compiler');
compile = Compiler.compile;
compileSpec = Compiler.compileSpec;
}
if (!compile || !compileSpec) {
throw new Error('Cannot call `precompile` without the template compiler loaded. Please load `ember-template-compiler.js` prior to calling `precompile`.');
}
var asObject = arguments[1] === undefined ? true : arguments[1];
var compileFunc = asObject ? compile : compileSpec;
return compileFunc(string);
}
});
define("ember-template-compiler/plugins",
["exports"],
function(__exports__) {
"use strict";
/**
@module ember
@submodule ember-template-compiler
*/
/**
@private
@property helpers
*/
var plugins = {
ast: [ ]
};
/**
Adds an AST plugin to be used by Ember.HTMLBars.compile.
@private
@method registerASTPlugin
*/
function registerPlugin(type, Plugin) {
if (!plugins[type]) {
throw new Error('Attempting to register "' + Plugin + '" as "' + type + '" which is not a valid HTMLBars plugin type.');
}
plugins[type].push(Plugin);
}
__exports__.registerPlugin = registerPlugin;__exports__["default"] = plugins;
});
define("ember-template-compiler/plugins/transform-each-in-to-hash",
["exports"],
function(__exports__) {
"use strict";
/**
@module ember
@submodule ember-htmlbars
*/
/**
An HTMLBars AST transformation that replaces all instances of
```handlebars
{{#each item in items}}
{{/each}}
```
with
```handlebars
{{#each items keyword="item"}}
{{/each}}
```
@class TransformEachInToHash
@private
*/
function TransformEachInToHash() {
// set later within HTMLBars to the syntax package
this.syntax = null;
}
/**
@private
@method transform
@param {AST} The AST to be transformed.
*/
TransformEachInToHash.prototype.transform = function TransformEachInToHash_transform(ast) {
var pluginContext = this;
var walker = new pluginContext.syntax.Walker();
var b = pluginContext.syntax.builders;
walker.visit(ast, function(node) {
if (pluginContext.validate(node)) {
if (node.program && node.program.blockParams.length) {
throw new Error('You cannot use keyword (`{{each foo in bar}}`) and block params (`{{each bar as |foo|}}`) at the same time.');
}
var removedParams = node.sexpr.params.splice(0, 2);
var keyword = removedParams[0].original;
// TODO: This may not be necessary.
if (!node.sexpr.hash) {
node.sexpr.hash = b.hash();
}
node.sexpr.hash.pairs.push(b.pair(
'keyword',
b.string(keyword)
));
}
});
return ast;
};
TransformEachInToHash.prototype.validate = function TransformEachInToHash_validate(node) {
return (node.type === 'BlockStatement' || node.type === 'MustacheStatement') &&
node.sexpr.path.original === 'each' &&
node.sexpr.params.length === 3 &&
node.sexpr.params[1].type === 'PathExpression' &&
node.sexpr.params[1].original === 'in';
};
__exports__["default"] = TransformEachInToHash;
});
define("ember-template-compiler/plugins/transform-with-as-to-hash",
["exports"],
function(__exports__) {
"use strict";
/**
@module ember
@submodule ember-htmlbars
*/
/**
An HTMLBars AST transformation that replaces all instances of
```handlebars
{{#with foo.bar as bar}}
{{/with}}
```
with
```handlebars
{{#with foo.bar as |bar|}}
{{/with}}
```
@private
@class TransformWithAsToHash
*/
function TransformWithAsToHash() {
// set later within HTMLBars to the syntax package
this.syntax = null;
}
/**
@private
@method transform
@param {AST} The AST to be transformed.
*/
TransformWithAsToHash.prototype.transform = function TransformWithAsToHash_transform(ast) {
var pluginContext = this;
var walker = new pluginContext.syntax.Walker();
walker.visit(ast, function(node) {
if (pluginContext.validate(node)) {
if (node.program && node.program.blockParams.length) {
throw new Error('You cannot use keyword (`{{with foo as bar}}`) and block params (`{{with foo as |bar|}}`) at the same time.');
}
var removedParams = node.sexpr.params.splice(1, 2);
var keyword = removedParams[1].original;
node.program.blockParams = [ keyword ];
}
});
return ast;
};
TransformWithAsToHash.prototype.validate = function TransformWithAsToHash_validate(node) {
return node.type === 'BlockStatement' &&
node.sexpr.path.original === 'with' &&
node.sexpr.params.length === 3 &&
node.sexpr.params[1].type === 'PathExpression' &&
node.sexpr.params[1].original === 'as';
};
__exports__["default"] = TransformWithAsToHash;
});
define("ember-template-compiler/system/compile",
["ember-template-compiler/system/compile_options","ember-template-compiler/system/template","exports"],
function(__dependency1__, __dependency2__, __exports__) {
"use strict";
/**
@module ember
@submodule ember-template-compiler
*/
var compile;
var compileOptions = __dependency1__["default"];
var template = __dependency2__["default"];
/**
Uses HTMLBars `compile` function to process a string into a compiled template.
This is not present in production builds.
@private
@method compile
@param {String} templateString This is the string to be compiled by HTMLBars.
*/
__exports__["default"] = function(templateString) {
if (!compile && Ember.__loader.registry['htmlbars-compiler/compiler']) {
compile = requireModule('htmlbars-compiler/compiler').compile;
}
if (!compile) {
throw new Error('Cannot call `compile` without the template compiler loaded. Please load `ember-template-compiler.js` prior to calling `compile`.');
}
var templateSpec = compile(templateString, compileOptions());
return template(templateSpec);
}
});
define("ember-template-compiler/system/compile_options",
["ember-metal/core","ember-template-compiler/plugins","exports"],
function(__dependency1__, __dependency2__, __exports__) {
"use strict";
/**
@module ember
@submodule ember-template-compiler
*/
var Ember = __dependency1__["default"];
var plugins = __dependency2__["default"];
/**
@private
@property compileOptions
*/
__exports__["default"] = function() {
var disableComponentGeneration = true;
return {
disableComponentGeneration: disableComponentGeneration,
plugins: plugins
};
}
});
define("ember-template-compiler/system/precompile",
["ember-template-compiler/system/compile_options","exports"],
function(__dependency1__, __exports__) {
"use strict";
/**
@module ember
@submodule ember-template-compiler
*/
var compileOptions = __dependency1__["default"];
var compileSpec;
/**
Uses HTMLBars `compile` function to process a string into a compiled template string.
The returned string must be passed through `Ember.HTMLBars.template`.
This is not present in production builds.
@private
@method precompile
@param {String} templateString This is the string to be compiled by HTMLBars.
*/
__exports__["default"] = function(templateString) {
if (!compileSpec && Ember.__loader.registry['htmlbars-compiler/compiler']) {
compileSpec = requireModule('htmlbars-compiler/compiler').compileSpec;
}
if (!compileSpec) {
throw new Error('Cannot call `compileSpec` without the template compiler loaded. Please load `ember-template-compiler.js` prior to calling `compileSpec`.');
}
return compileSpec(templateString, compileOptions());
}
});
define("ember-template-compiler/system/template",
["exports"],
function(__exports__) {
"use strict";
/**
@module ember
@submodule ember-template-compiler
*/
/**
Augments the detault precompiled output of an HTMLBars template with
additional information needed by Ember.
@private
@method template
@param {Function} templateSpec This is the compiled HTMLBars template spec.
*/
__exports__["default"] = function(templateSpec) {
templateSpec.isTop = true;
templateSpec.isMethod = false;
return templateSpec;
}
});
define("htmlbars-compiler",
["./htmlbars-compiler/compiler","exports"],
function(__dependency1__, __exports__) {
"use strict";
var compile = __dependency1__.compile;
var compilerSpec = __dependency1__.compilerSpec;
__exports__.compile = compile;
__exports__.compilerSpec = compilerSpec;
});
define("htmlbars-compiler/compiler",
["../htmlbars-syntax/parser","./template-compiler","exports"],
function(__dependency1__, __dependency2__, __exports__) {
"use strict";
/*jshint evil:true*/
var preprocess = __dependency1__.preprocess;
var TemplateCompiler = __dependency2__["default"];
/*
* Compile a string into a template rendering function
*
* Example usage:
*
* // Template is the hydration portion of the compiled template
* var template = compile("Howdy {{name}}");
*
* // Template accepts three arguments:
* //
* // 1. A context object
* // 2. An env object
* // 3. A contextualElement (optional, document.body is the default)
* //
* // The env object *must* have at least these two properties:
* //
* // 1. `hooks` - Basic hooks for rendering a template
* // 2. `dom` - An instance of DOMHelper
* //
* import {hooks} from 'htmlbars-runtime';
* import {DOMHelper} from 'morph';
* var context = {name: 'whatever'},
* env = {hooks: hooks, dom: new DOMHelper()},
* contextualElement = document.body;
* var domFragment = template(context, env, contextualElement);
*
* @method compile
* @param {String} string An htmlbars template string
* @param {Object} options A set of options to provide to the compiler
* @return {Function} A function for rendering the template
*/
function compile(string, options) {
var program = compileSpec(string, options);
return new Function("return " + program)();
}
__exports__.compile = compile;/*
* Compile a string into a template spec string. The template spec is a string
* representation of a template. Usually, you would use compileSpec for
* pre-compilation of a template on the server.
*
* Example usage:
*
* var templateSpec = compileSpec("Howdy {{name}}");
* // This next step is basically what plain compile does
* var template = new Function("return " + templateSpec)();
*
* @method compileSpec
* @param {String} string An htmlbars template string
* @return {Function} A template spec string
*/
function compileSpec(string, options) {
var ast = preprocess(string, options);
var compiler = new TemplateCompiler(options);
var program = compiler.compile(ast);
return program;
}
__exports__.compileSpec = compileSpec;
});
define("htmlbars-compiler/fragment-javascript-compiler",
["./utils","../htmlbars-util/quoting","exports"],
function(__dependency1__, __dependency2__, __exports__) {
"use strict";
var processOpcodes = __dependency1__.processOpcodes;
var string = __dependency2__.string;
var svgNamespace = "http://www.w3.org/2000/svg",
// http://www.w3.org/html/wg/drafts/html/master/syntax.html#html-integration-point
svgHTMLIntegrationPoints = {'foreignObject':true, 'desc':true, 'title':true};
function FragmentJavaScriptCompiler() {
this.source = [];
this.depth = -1;
}
__exports__["default"] = FragmentJavaScriptCompiler;
FragmentJavaScriptCompiler.prototype.compile = function(opcodes, options) {
this.source.length = 0;
this.depth = -1;
this.indent = (options && options.indent) || "";
this.namespaceFrameStack = [{namespace: null, depth: null}];
this.domNamespace = null;
this.source.push('function build(dom) {\n');
processOpcodes(this, opcodes);
this.source.push(this.indent+'}');
return this.source.join('');
};
FragmentJavaScriptCompiler.prototype.createFragment = function() {
var el = 'el'+(++this.depth);
this.source.push(this.indent+' var '+el+' = dom.createDocumentFragment();\n');
};
FragmentJavaScriptCompiler.prototype.createElement = function(tagName) {
var el = 'el'+(++this.depth);
if (tagName === 'svg') {
this.pushNamespaceFrame({namespace: svgNamespace, depth: this.depth});
}
this.ensureNamespace();
this.source.push(this.indent+' var '+el+' = dom.createElement('+string(tagName)+');\n');
if (svgHTMLIntegrationPoints[tagName]) {
this.pushNamespaceFrame({namespace: null, depth: this.depth});
}
};
FragmentJavaScriptCompiler.prototype.createText = function(str) {
var el = 'el'+(++this.depth);
this.source.push(this.indent+' var '+el+' = dom.createTextNode('+string(str)+');\n');
};
FragmentJavaScriptCompiler.prototype.createComment = function(str) {
var el = 'el'+(++this.depth);
this.source.push(this.indent+' var '+el+' = dom.createComment('+string(str)+');\n');
};
FragmentJavaScriptCompiler.prototype.returnNode = function() {
var el = 'el'+this.depth;
this.source.push(this.indent+' return '+el+';\n');
};
FragmentJavaScriptCompiler.prototype.setAttribute = function(name, value, namespace) {
var el = 'el'+this.depth;
if (namespace) {
this.source.push(this.indent+' dom.setAttributeNS('+el+','+string(namespace)+','+string(name)+','+string(value)+');\n');
} else {
this.source.push(this.indent+' dom.setAttribute('+el+','+string(name)+','+string(value)+');\n');
}
};
FragmentJavaScriptCompiler.prototype.appendChild = function() {
if (this.depth === this.getCurrentNamespaceFrame().depth) {
this.popNamespaceFrame();
}
var child = 'el'+(this.depth--);
var el = 'el'+this.depth;
this.source.push(this.indent+' dom.appendChild('+el+', '+child+');\n');
};
FragmentJavaScriptCompiler.prototype.getCurrentNamespaceFrame = function() {
return this.namespaceFrameStack[this.namespaceFrameStack.length-1];
};
FragmentJavaScriptCompiler.prototype.pushNamespaceFrame = function(frame) {
this.namespaceFrameStack.push(frame);
};
FragmentJavaScriptCompiler.prototype.popNamespaceFrame = function() {
return this.namespaceFrameStack.pop();
};
FragmentJavaScriptCompiler.prototype.ensureNamespace = function() {
var correctNamespace = this.getCurrentNamespaceFrame().namespace;
if (this.domNamespace !== correctNamespace) {
this.source.push(this.indent+' dom.setNamespace('+(correctNamespace ? string(correctNamespace) : 'null')+');\n');
this.domNamespace = correctNamespace;
}
};
});
define("htmlbars-compiler/fragment-opcode-compiler",
["./template-visitor","./utils","../htmlbars-util","../htmlbars-util/array-utils","exports"],
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
"use strict";
var TemplateVisitor = __dependency1__["default"];
var processOpcodes = __dependency2__.processOpcodes;
var getAttrNamespace = __dependency3__.getAttrNamespace;
var forEach = __dependency4__.forEach;
function FragmentOpcodeCompiler() {
this.opcodes = [];
}
__exports__["default"] = FragmentOpcodeCompiler;
FragmentOpcodeCompiler.prototype.compile = function(ast) {
var templateVisitor = new TemplateVisitor();
templateVisitor.visit(ast);
processOpcodes(this, templateVisitor.actions);
return this.opcodes;
};
FragmentOpcodeCompiler.prototype.opcode = function(type, params) {
this.opcodes.push([type, params]);
};
FragmentOpcodeCompiler.prototype.text = function(text, childIndex, childCount, isSingleRoot) {
this.opcode('createText', [text.chars]);
if (!isSingleRoot) { this.opcode('appendChild'); }
};
FragmentOpcodeCompiler.prototype.comment = function(comment, childIndex, childCount, isSingleRoot) {
this.opcode('createComment', [comment.value]);
if (!isSingleRoot) { this.opcode('appendChild'); }
};
FragmentOpcodeCompiler.prototype.openElement = function(element) {
this.opcode('createElement', [element.tag]);
forEach(element.attributes, this.attribute, this);
};
FragmentOpcodeCompiler.prototype.closeElement = function(element, childIndex, childCount, isSingleRoot) {
if (!isSingleRoot) { this.opcode('appendChild'); }
};
FragmentOpcodeCompiler.prototype.startProgram = function(program) {
this.opcodes.length = 0;
if (program.body.length !== 1) {
this.opcode('createFragment');
}
};
FragmentOpcodeCompiler.prototype.endProgram = function(/* program */) {
this.opcode('returnNode');
};
FragmentOpcodeCompiler.prototype.mustache = function () {};
FragmentOpcodeCompiler.prototype.component = function () {};
FragmentOpcodeCompiler.prototype.block = function () {};
FragmentOpcodeCompiler.prototype.attribute = function(attr) {
if (attr.value.type === 'TextNode') {
var namespace = getAttrNamespace(attr.name);
this.opcode('setAttribute', [attr.name, attr.value.chars, namespace]);
}
};
FragmentOpcodeCompiler.prototype.setNamespace = function(namespace) {
this.opcode('setNamespace', [namespace]);
};
});
define("htmlbars-compiler/hydration-javascript-compiler",
["./utils","../htmlbars-util/quoting","exports"],
function(__dependency1__, __dependency2__, __exports__) {
"use strict";
var processOpcodes = __dependency1__.processOpcodes;
var string = __dependency2__.string;
var array = __dependency2__.array;
function HydrationJavaScriptCompiler() {
this.stack = [];
this.source = [];
this.mustaches = [];
this.parents = [['fragment']];
this.parentCount = 0;
this.morphs = [];
this.fragmentProcessing = [];
this.hooks = undefined;
}
__exports__["default"] = HydrationJavaScriptCompiler;
var prototype = HydrationJavaScriptCompiler.prototype;
prototype.compile = function(opcodes, options) {
this.stack.length = 0;
this.mustaches.length = 0;
this.source.length = 0;
this.parents.length = 1;
this.parents[0] = ['fragment'];
this.morphs.length = 0;
this.fragmentProcessing.length = 0;
this.parentCount = 0;
this.indent = (options && options.indent) || "";
this.hooks = {};
processOpcodes(this, opcodes);
var i, l;
if (this.morphs.length) {
var morphs = "";
for (i = 0, l = this.morphs.length; i < l; ++i) {
var morph = this.morphs[i];
morphs += this.indent+' var '+morph[0]+' = '+morph[1]+';\n';
}
this.source.unshift(morphs);
}
if (this.fragmentProcessing.length) {
var processing = "";
for (i = 0, l = this.fragmentProcessing.length; i < l; ++i) {
processing += this.indent+' '+this.fragmentProcessing[i]+'\n';
}
this.source.unshift(processing);
}
return this.source.join('');
};
prototype.prepareArray = function(length) {
var values = [];
for (var i = 0; i < length; i++) {
values.push(this.stack.pop());
}
this.stack.push('[' + values.join(', ') + ']');
};
prototype.prepareObject = function(size) {
var pairs = [];
for (var i = 0; i < size; i++) {
pairs.push(this.stack.pop() + ': ' + this.stack.pop());
}
this.stack.push('{' + pairs.join(', ') + '}');
};
prototype.pushRaw = function(value) {
this.stack.push(value);
};
prototype.pushLiteral = function(value) {
if (typeof value === 'string') {
this.stack.push(string(value));
} else {
this.stack.push(value.toString());
}
};
prototype.pushHook = function(name, args) {
this.hooks[name] = true;
this.stack.push(name + '(' + args.join(', ') + ')');
};
prototype.pushGetHook = function(path) {
this.pushHook('get', [
'env',
'context',
string(path)
]);
};
prototype.pushSexprHook = function() {
this.pushHook('subexpr', [
'env',
'context',
this.stack.pop(), // path
this.stack.pop(), // params
this.stack.pop() // hash
]);
};
prototype.pushConcatHook = function() {
this.pushHook('concat', [
'env',
this.stack.pop() // parts
]);
};
prototype.printHook = function(name, args) {
this.hooks[name] = true;
this.source.push(this.indent + ' ' + name + '(' + args.join(', ') + ');\n');
};
prototype.printSetHook = function(name, index) {
this.printHook('set', [
'env',
'context',
string(name),
'blockArguments[' + index + ']'
]);
};
prototype.printBlockHook = function(morphNum, templateId, inverseId) {
this.printHook('block', [
'env',
'morph' + morphNum,
'context',
this.stack.pop(), // path
this.stack.pop(), // params
this.stack.pop(), // hash
templateId === null ? 'null' : 'child' + templateId,
inverseId === null ? 'null' : 'child' + inverseId
]);
};
prototype.printInlineHook = function(morphNum) {
this.printHook('inline', [
'env',
'morph' + morphNum,
'context',
this.stack.pop(), // path
this.stack.pop(), // params
this.stack.pop() // hash
]);
};
prototype.printContentHook = function(morphNum) {
this.printHook('content', [
'env',
'morph' + morphNum,
'context',
this.stack.pop() // path
]);
};
prototype.printComponentHook = function(morphNum, templateId) {
this.printHook('component', [
'env',
'morph' + morphNum,
'context',
this.stack.pop(), // path
this.stack.pop(), // attrs
templateId === null ? 'null' : 'child' + templateId
]);
};
prototype.printAttributeHook = function(attrMorphNum, elementNum) {
this.printHook('attribute', [
'env',
'attrMorph' + attrMorphNum,
'element' + elementNum,
this.stack.pop(), // name
this.stack.pop() // value
]);
};
prototype.printElementHook = function(elementNum) {
this.printHook('element', [
'env',
'element' + elementNum,
'context',
this.stack.pop(), // path
this.stack.pop(), // params
this.stack.pop() // hash
]);
};
prototype.createMorph = function(morphNum, parentPath, startIndex, endIndex, escaped) {
var isRoot = parentPath.length === 0;
var parent = this.getParent();
var morphMethod = escaped ? 'createMorphAt' : 'createUnsafeMorphAt';
var morph = "dom."+morphMethod+"("+parent+
","+(startIndex === null ? "-1" : startIndex)+
","+(endIndex === null ? "-1" : endIndex)+
(isRoot ? ",contextualElement)" : ")");
this.morphs.push(['morph' + morphNum, morph]);
};
prototype.createAttrMorph = function(attrMorphNum, elementNum, name, escaped, namespace) {
var morphMethod = escaped ? 'createAttrMorph' : 'createUnsafeAttrMorph';
var morph = "dom."+morphMethod+"(element"+elementNum+", '"+name+(namespace ? "', '"+namespace : '')+"')";
this.morphs.push(['attrMorph' + attrMorphNum, morph]);
};
prototype.repairClonedNode = function(blankChildTextNodes, isElementChecked) {
var parent = this.getParent(),
processing = 'if (this.cachedFragment) { dom.repairClonedNode('+parent+','+
array(blankChildTextNodes)+
( isElementChecked ? ',true' : '' )+
'); }';
this.fragmentProcessing.push(
processing
);
};
prototype.shareElement = function(elementNum){
var elementNodesName = "element" + elementNum;
this.fragmentProcessing.push('var '+elementNodesName+' = '+this.getParent()+';');
this.parents[this.parents.length-1] = [elementNodesName];
};
prototype.consumeParent = function(i) {
var newParent = this.lastParent().slice();
newParent.push(i);
this.parents.push(newParent);
};
prototype.popParent = function() {
this.parents.pop();
};
prototype.getParent = function() {
var last = this.lastParent().slice();
var frag = last.shift();
if (!last.length) {
return frag;
}
return 'dom.childAt(' + frag + ', [' + last.join(', ') + '])';
};
prototype.lastParent = function() {
return this.parents[this.parents.length-1];
};
});
define("htmlbars-compiler/hydration-opcode-compiler",
["./template-visitor","./utils","../htmlbars-util","../htmlbars-util/array-utils","../htmlbars-syntax/utils","exports"],
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
"use strict";
var TemplateVisitor = __dependency1__["default"];
var processOpcodes = __dependency2__.processOpcodes;
var getAttrNamespace = __dependency3__.getAttrNamespace;
var forEach = __dependency4__.forEach;
var isHelper = __dependency5__.isHelper;
function unwrapMustache(mustache) {
if (isHelper(mustache.sexpr)) {
return mustache.sexpr;
} else {
return mustache.sexpr.path;
}
}
function detectIsElementChecked(element){
for (var i=0, len=element.attributes.length;i<len;i++) {
if (element.attributes[i].name === 'checked') {
return true;
}
}
return false;
}
function HydrationOpcodeCompiler() {
this.opcodes = [];
this.paths = [];
this.templateId = 0;
this.currentDOMChildIndex = 0;
this.morphs = [];
this.morphNum = 0;
this.attrMorphNum = 0;
this.element = null;
this.elementNum = -1;
}
__exports__["default"] = HydrationOpcodeCompiler;
HydrationOpcodeCompiler.prototype.compile = function(ast) {
var templateVisitor = new TemplateVisitor();
templateVisitor.visit(ast);
processOpcodes(this, templateVisitor.actions);
return this.opcodes;
};
HydrationOpcodeCompiler.prototype.accept = function(node) {
this[node.type](node);
};
HydrationOpcodeCompiler.prototype.opcode = function(type) {
var params = [].slice.call(arguments, 1);
this.opcodes.push([type, params]);
};
HydrationOpcodeCompiler.prototype.startProgram = function(program, c, blankChildTextNodes) {
this.opcodes.length = 0;
this.paths.length = 0;
this.morphs.length = 0;
this.templateId = 0;
this.currentDOMChildIndex = -1;
this.morphNum = 0;
this.attrMorphNum = 0;
var blockParams = program.blockParams || [];
for (var i = 0; i < blockParams.length; i++) {
this.opcode('printSetHook', blockParams[i], i);
}
if (blankChildTextNodes.length > 0) {
this.opcode('repairClonedNode', blankChildTextNodes);
}
};
HydrationOpcodeCompiler.prototype.endProgram = function(/* program */) {
distributeMorphs(this.morphs, this.opcodes);
};
HydrationOpcodeCompiler.prototype.text = function(/* string, pos, len */) {
++this.currentDOMChildIndex;
};
HydrationOpcodeCompiler.prototype.comment = function(/* string, pos, len */) {
++this.currentDOMChildIndex;
};
HydrationOpcodeCompiler.prototype.openElement = function(element, pos, len, isSingleRoot, mustacheCount, blankChildTextNodes) {
distributeMorphs(this.morphs, this.opcodes);
++this.currentDOMChildIndex;
this.element = this.currentDOMChildIndex;
if (!isSingleRoot) {
this.opcode('consumeParent', this.currentDOMChildIndex);
// If our parent reference will be used more than once, cache its reference.
if (mustacheCount > 1) {
this.opcode('shareElement', ++this.elementNum);
this.element = null; // Set element to null so we don't cache it twice
}
}
var isElementChecked = detectIsElementChecked(element);
if (blankChildTextNodes.length > 0 || isElementChecked) {
this.opcode( 'repairClonedNode',
blankChildTextNodes,
isElementChecked );
}
this.paths.push(this.currentDOMChildIndex);
this.currentDOMChildIndex = -1;
forEach(element.attributes, this.attribute, this);
forEach(element.helpers, this.elementHelper, this);
};
HydrationOpcodeCompiler.prototype.closeElement = function(element, pos, len, isSingleRoot) {
distributeMorphs(this.morphs, this.opcodes);
if (!isSingleRoot) { this.opcode('popParent'); }
this.currentDOMChildIndex = this.paths.pop();
};
HydrationOpcodeCompiler.prototype.block = function(block, childIndex, childrenLength) {
var sexpr = block.sexpr;
var currentDOMChildIndex = this.currentDOMChildIndex;
var start = (currentDOMChildIndex < 0) ? null : currentDOMChildIndex;
var end = (childIndex === childrenLength - 1) ? null : currentDOMChildIndex + 1;
var morphNum = this.morphNum++;
this.morphs.push([morphNum, this.paths.slice(), start, end, true]);
var templateId = this.templateId++;
var inverseId = block.inverse === null ? null : this.templateId++;
prepareSexpr(this, sexpr);
this.opcode('printBlockHook', morphNum, templateId, inverseId);
};
HydrationOpcodeCompiler.prototype.component = function(component, childIndex, childrenLength) {
var currentDOMChildIndex = this.currentDOMChildIndex;
var program = component.program || {};
var blockParams = program.blockParams || [];
var start = (currentDOMChildIndex < 0 ? null : currentDOMChildIndex),
end = (childIndex === childrenLength - 1 ? null : currentDOMChildIndex + 1);
var morphNum = this.morphNum++;
this.morphs.push([morphNum, this.paths.slice(), start, end, true]);
var attrs = component.attributes;
for (var i = attrs.length - 1; i >= 0; i--) {
var name = attrs[i].name;
var value = attrs[i].value;
// TODO: Introduce context specific AST nodes to avoid switching here.
if (value.type === 'TextNode') {
this.opcode('pushLiteral', value.chars);
} else if (value.type === 'MustacheStatement') {
this.accept(unwrapMustache(value));
} else if (value.type === 'ConcatStatement') {
prepareParams(this, value.parts);
this.opcode('pushConcatHook');
}
this.opcode('pushLiteral', name);
}
this.opcode('prepareObject', attrs.length);
this.opcode('pushLiteral', component.tag);
this.opcode('printComponentHook', morphNum, this.templateId++, blockParams.length);
};
HydrationOpcodeCompiler.prototype.attribute = function(attr) {
var value = attr.value;
var escaped = true;
var namespace = getAttrNamespace(attr.name);
// TODO: Introduce context specific AST nodes to avoid switching here.
if (value.type === 'TextNode') {
return;
} else if (value.type === 'MustacheStatement') {
escaped = value.escaped;
this.accept(unwrapMustache(value));
} else if (value.type === 'ConcatStatement') {
prepareParams(this, value.parts);
this.opcode('pushConcatHook');
}
this.opcode('pushLiteral', attr.name);
if (this.element !== null) {
this.opcode('shareElement', ++this.elementNum);
this.element = null;
}
var attrMorphNum = this.attrMorphNum++;
this.opcode('createAttrMorph', attrMorphNum, this.elementNum, attr.name, escaped, namespace);
this.opcode('printAttributeHook', attrMorphNum, this.elementNum);
};
HydrationOpcodeCompiler.prototype.elementHelper = function(sexpr) {
prepareSexpr(this, sexpr);
// If we have a helper in a node, and this element has not been cached, cache it
if (this.element !== null) {
this.opcode('shareElement', ++this.elementNum);
this.element = null; // Reset element so we don't cache it more than once
}
this.opcode('printElementHook', this.elementNum);
};
HydrationOpcodeCompiler.prototype.mustache = function(mustache, childIndex, childrenLength) {
var sexpr = mustache.sexpr;
var currentDOMChildIndex = this.currentDOMChildIndex;
var start = currentDOMChildIndex,
end = (childIndex === childrenLength - 1 ? -1 : currentDOMChildIndex + 1);
var morphNum = this.morphNum++;
this.morphs.push([morphNum, this.paths.slice(), start, end, mustache.escaped]);
if (isHelper(sexpr)) {
prepareSexpr(this, sexpr);
this.opcode('printInlineHook', morphNum);
} else {
preparePath(this, sexpr.path);
this.opcode('printContentHook', morphNum);
}
};
HydrationOpcodeCompiler.prototype.SubExpression = function(sexpr) {
prepareSexpr(this, sexpr);
this.opcode('pushSexprHook');
};
HydrationOpcodeCompiler.prototype.PathExpression = function(path) {
this.opcode('pushGetHook', path.original);
};
HydrationOpcodeCompiler.prototype.StringLiteral = function(node) {
this.opcode('pushLiteral', node.value);
};
HydrationOpcodeCompiler.prototype.BooleanLiteral = function(node) {
this.opcode('pushLiteral', node.value);
};
HydrationOpcodeCompiler.prototype.NumberLiteral = function(node) {
this.opcode('pushLiteral', node.value);
};
function preparePath(compiler, path) {
compiler.opcode('pushLiteral', path.original);
}
function prepareParams(compiler, params) {
for (var i = params.length - 1; i >= 0; i--) {
var param = params[i];
compiler[param.type](param);
}
compiler.opcode('prepareArray', params.length);
}
function prepareHash(compiler, hash) {
var pairs = hash.pairs;
for (var i = pairs.length - 1; i >= 0; i--) {
var key = pairs[i].key;
var value = pairs[i].value;
compiler[value.type](value);
compiler.opcode('pushLiteral', key);
}
compiler.opcode('prepareObject', pairs.length);
}
function prepareSexpr(compiler, sexpr) {
prepareHash(compiler, sexpr.hash);
prepareParams(compiler, sexpr.params);
preparePath(compiler, sexpr.path);
}
function distributeMorphs(morphs, opcodes) {
if (morphs.length === 0) {
return;
}
// Splice morphs after the most recent shareParent/consumeParent.
var o;
for (o = opcodes.length - 1; o >= 0; --o) {
var opcode = opcodes[o][0];
if (opcode === 'shareElement' || opcode === 'consumeParent' || opcode === 'popParent') {
break;
}
}
var spliceArgs = [o + 1, 0];
for (var i = 0; i < morphs.length; ++i) {
spliceArgs.push(['createMorph', morphs[i].slice()]);
}
opcodes.splice.apply(opcodes, spliceArgs);
morphs.length = 0;
}
});
define("htmlbars-compiler/template-compiler",
["./fragment-opcode-compiler","./fragment-javascript-compiler","./hydration-opcode-compiler","./hydration-javascript-compiler","./template-visitor","./utils","../htmlbars-util/quoting","exports"],
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
"use strict";
var FragmentOpcodeCompiler = __dependency1__["default"];
var FragmentJavaScriptCompiler = __dependency2__["default"];
var HydrationOpcodeCompiler = __dependency3__["default"];
var HydrationJavaScriptCompiler = __dependency4__["default"];
var TemplateVisitor = __dependency5__["default"];
var processOpcodes = __dependency6__.processOpcodes;
var repeat = __dependency7__.repeat;
function TemplateCompiler(options) {
this.options = options || {};
this.fragmentOpcodeCompiler = new FragmentOpcodeCompiler();
this.fragmentCompiler = new FragmentJavaScriptCompiler();
this.hydrationOpcodeCompiler = new HydrationOpcodeCompiler();
this.hydrationCompiler = new HydrationJavaScriptCompiler();
this.templates = [];
this.childTemplates = [];
}
__exports__["default"] = TemplateCompiler;
TemplateCompiler.prototype.compile = function(ast) {
var templateVisitor = new TemplateVisitor();
templateVisitor.visit(ast);
processOpcodes(this, templateVisitor.actions);
return this.templates.pop();
};
TemplateCompiler.prototype.startProgram = function(program, childTemplateCount, blankChildTextNodes) {
this.fragmentOpcodeCompiler.startProgram(program, childTemplateCount, blankChildTextNodes);
this.hydrationOpcodeCompiler.startProgram(program, childTemplateCount, blankChildTextNodes);
this.childTemplates.length = 0;
while(childTemplateCount--) {
this.childTemplates.push(this.templates.pop());
}
};
TemplateCompiler.prototype.getChildTemplateVars = function(indent) {
var vars = '';
if (this.childTemplates) {
for (var i = 0; i < this.childTemplates.length; i++) {
vars += indent + 'var child' + i + ' = ' + this.childTemplates[i] + ';\n';
}
}
return vars;
};
TemplateCompiler.prototype.getHydrationHooks = function(indent, hooks) {
var hookVars = [];