You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ni...@apache.org on 2020/10/20 06:06:36 UTC

[ranger] 02/03: RANGER-3029 : Ranger - Upgrade handlebars 1.3.0 to 4.6.0

This is an automated email from the ASF dual-hosted git repository.

ni3galave pushed a commit to branch ranger-2.2
in repository https://gitbox.apache.org/repos/asf/ranger.git

commit ca303c62100bbe800f5a8cc2d67588c8f4aaa549
Author: Nitin Galave <ni...@apache.org>
AuthorDate: Mon Oct 12 09:07:26 2020 +0530

    RANGER-3029 : Ranger - Upgrade handlebars 1.3.0 to 4.6.0
---
 .../require-handlebars-plugin/js/Handlebars.js     | 6092 ++++++++++++++------
 .../libs/bower/require-handlebars-plugin/js/hbs.js | 1001 ++--
 .../require-handlebars-plugin/js/i18nprecompile.js |   45 -
 .../common/ServiceManagerLayout_tmpl.html          |    2 +-
 .../common/ServiceManagerSidebarLayout_tmpl.html   |    2 +-
 .../templates/policies/RangerPolicyRO_tmpl.html    |    4 +-
 .../policies/RangerPolicyTableLayout_tmpl.html     |   30 +-
 .../PlugableServicePolicyDeleteDiff_tmpl.html      |  761 +--
 .../reports/PlugableServicePolicyDiff_tmpl.html    |  734 +--
 .../PlugableServicePolicyUpdateDiff_tmpl.html      |    4 +-
 .../reports/UserUpdateOperationDiff_tmpl.html      |   32 +-
 11 files changed, 5665 insertions(+), 3042 deletions(-)

diff --git a/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/Handlebars.js b/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/Handlebars.js
index 2f5f321..e7cd517 100644
--- a/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/Handlebars.js
+++ b/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/Handlebars.js
@@ -1,11 +1,9 @@
-// Begin AMD Wrapper
-define(function(){
-// End AMD Wrapper
-/*!
+/**!
 
- handlebars v1.3.0
+ @license
+ handlebars v4.7.6
 
-Copyright (C) 2011 by Yehuda Katz
+Copyright (C) 2011-2019 by Yehuda Katz
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -25,96 +23,457 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 
-@license
 */
-/* exported Handlebars */
-var Handlebars = (function() {
-// handlebars/safe-string.js
-var __module4__ = (function() {
-  "use strict";
-  var __exports__;
-  // Build out our basic SafeString type
-  function SafeString(string) {
-    this.string = string;
+(function webpackUniversalModuleDefinition(root, factory) {
+  if(typeof exports === 'object' && typeof module === 'object')
+    module.exports = factory();
+  else if(typeof define === 'function' && define.amd)
+    define([], factory);
+  else if(typeof exports === 'object')
+    exports["Handlebars"] = factory();
+  else
+    root["Handlebars"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/  // The module cache
+/******/  var installedModules = {};
+
+/******/  // The require function
+/******/  function __webpack_require__(moduleId) {
+
+/******/    // Check if module is in cache
+/******/    if(installedModules[moduleId])
+/******/      return installedModules[moduleId].exports;
+
+/******/    // Create a new module (and put it into the cache)
+/******/    var module = installedModules[moduleId] = {
+/******/      exports: {},
+/******/      id: moduleId,
+/******/      loaded: false
+/******/    };
+
+/******/    // Execute the module function
+/******/    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/    // Flag the module as loaded
+/******/    module.loaded = true;
+
+/******/    // Return the exports of the module
+/******/    return module.exports;
+/******/  }
+
+
+/******/  // expose the modules object (__webpack_modules__)
+/******/  __webpack_require__.m = modules;
+
+/******/  // expose the module cache
+/******/  __webpack_require__.c = installedModules;
+
+/******/  // __webpack_public_path__
+/******/  __webpack_require__.p = "";
+
+/******/  // Load entry module and return exports
+/******/  return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+
+  var _handlebarsRuntime = __webpack_require__(2);
+
+  var _handlebarsRuntime2 = _interopRequireDefault(_handlebarsRuntime);
+
+  // Compiler imports
+
+  var _handlebarsCompilerAst = __webpack_require__(45);
+
+  var _handlebarsCompilerAst2 = _interopRequireDefault(_handlebarsCompilerAst);
+
+  var _handlebarsCompilerBase = __webpack_require__(46);
+
+  var _handlebarsCompilerCompiler = __webpack_require__(51);
+
+  var _handlebarsCompilerJavascriptCompiler = __webpack_require__(52);
+
+  var _handlebarsCompilerJavascriptCompiler2 = _interopRequireDefault(_handlebarsCompilerJavascriptCompiler);
+
+  var _handlebarsCompilerVisitor = __webpack_require__(49);
+
+  var _handlebarsCompilerVisitor2 = _interopRequireDefault(_handlebarsCompilerVisitor);
+
+  var _handlebarsNoConflict = __webpack_require__(44);
+
+  var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict);
+
+  var _create = _handlebarsRuntime2['default'].create;
+  function create() {
+    var hb = _create();
+
+    hb.compile = function (input, options) {
+      return _handlebarsCompilerCompiler.compile(input, options, hb);
+    };
+    hb.precompile = function (input, options) {
+      return _handlebarsCompilerCompiler.precompile(input, options, hb);
+    };
+
+    hb.AST = _handlebarsCompilerAst2['default'];
+    hb.Compiler = _handlebarsCompilerCompiler.Compiler;
+    hb.JavaScriptCompiler = _handlebarsCompilerJavascriptCompiler2['default'];
+    hb.Parser = _handlebarsCompilerBase.parser;
+    hb.parse = _handlebarsCompilerBase.parse;
+    hb.parseWithoutProcessing = _handlebarsCompilerBase.parseWithoutProcessing;
+
+    return hb;
   }
 
-  SafeString.prototype.toString = function() {
-    return "" + this.string;
+  var inst = create();
+  inst.create = create;
+
+  _handlebarsNoConflict2['default'](inst);
+
+  inst.Visitor = _handlebarsCompilerVisitor2['default'];
+
+  inst['default'] = inst;
+
+  exports['default'] = inst;
+  module.exports = exports['default'];
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports) {
+
+  "use strict";
+
+  exports["default"] = function (obj) {
+    return obj && obj.__esModule ? obj : {
+      "default": obj
+    };
   };
 
-  __exports__ = SafeString;
-  return __exports__;
-})();
+  exports.__esModule = true;
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _interopRequireWildcard = __webpack_require__(3)['default'];
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+
+  var _handlebarsBase = __webpack_require__(4);
+
+  var base = _interopRequireWildcard(_handlebarsBase);
+
+  // Each of these augment the Handlebars object. No need to setup here.
+  // (This is done to easily share code between commonjs and browse envs)
+
+  var _handlebarsSafeString = __webpack_require__(37);
+
+  var _handlebarsSafeString2 = _interopRequireDefault(_handlebarsSafeString);
+
+  var _handlebarsException = __webpack_require__(6);
+
+  var _handlebarsException2 = _interopRequireDefault(_handlebarsException);
+
+  var _handlebarsUtils = __webpack_require__(5);
+
+  var Utils = _interopRequireWildcard(_handlebarsUtils);
+
+  var _handlebarsRuntime = __webpack_require__(38);
+
+  var runtime = _interopRequireWildcard(_handlebarsRuntime);
+
+  var _handlebarsNoConflict = __webpack_require__(44);
+
+  var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict);
+
+  // For compatibility and usage outside of module systems, make the Handlebars object a namespace
+  function create() {
+    var hb = new base.HandlebarsEnvironment();
+
+    Utils.extend(hb, base);
+    hb.SafeString = _handlebarsSafeString2['default'];
+    hb.Exception = _handlebarsException2['default'];
+    hb.Utils = Utils;
+    hb.escapeExpression = Utils.escapeExpression;
+
+    hb.VM = runtime;
+    hb.template = function (spec) {
+      return runtime.template(spec, hb);
+    };
+
+    return hb;
+  }
+
+  var inst = create();
+  inst.create = create;
+
+  _handlebarsNoConflict2['default'](inst);
+
+  inst['default'] = inst;
+
+  exports['default'] = inst;
+  module.exports = exports['default'];
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports) {
 
-// handlebars/utils.js
-var __module3__ = (function(__dependency1__) {
   "use strict";
-  var __exports__ = {};
-  /*jshint -W004 */
-  var SafeString = __dependency1__;
 
+  exports["default"] = function (obj) {
+    if (obj && obj.__esModule) {
+      return obj;
+    } else {
+      var newObj = {};
+
+      if (obj != null) {
+        for (var key in obj) {
+          if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
+        }
+      }
+
+      newObj["default"] = obj;
+      return newObj;
+    }
+  };
+
+  exports.__esModule = true;
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+  exports.HandlebarsEnvironment = HandlebarsEnvironment;
+
+  var _utils = __webpack_require__(5);
+
+  var _exception = __webpack_require__(6);
+
+  var _exception2 = _interopRequireDefault(_exception);
+
+  var _helpers = __webpack_require__(10);
+
+  var _decorators = __webpack_require__(30);
+
+  var _logger = __webpack_require__(32);
+
+  var _logger2 = _interopRequireDefault(_logger);
+
+  var _internalProtoAccess = __webpack_require__(33);
+
+  var VERSION = '4.7.6';
+  exports.VERSION = VERSION;
+  var COMPILER_REVISION = 8;
+  exports.COMPILER_REVISION = COMPILER_REVISION;
+  var LAST_COMPATIBLE_COMPILER_REVISION = 7;
+
+  exports.LAST_COMPATIBLE_COMPILER_REVISION = LAST_COMPATIBLE_COMPILER_REVISION;
+  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.x.x',
+    5: '== 2.0.0-alpha.x',
+    6: '>= 2.0.0-beta.1',
+    7: '>= 4.0.0 <4.3.0',
+    8: '>= 4.3.0'
+  };
+
+  exports.REVISION_CHANGES = REVISION_CHANGES;
+  var objectType = '[object Object]';
+
+  function HandlebarsEnvironment(helpers, partials, decorators) {
+    this.helpers = helpers || {};
+    this.partials = partials || {};
+    this.decorators = decorators || {};
+
+    _helpers.registerDefaultHelpers(this);
+    _decorators.registerDefaultDecorators(this);
+  }
+
+  HandlebarsEnvironment.prototype = {
+    constructor: HandlebarsEnvironment,
+
+    logger: _logger2['default'],
+    log: _logger2['default'].log,
+
+    registerHelper: function registerHelper(name, fn) {
+      if (_utils.toString.call(name) === objectType) {
+        if (fn) {
+          throw new _exception2['default']('Arg not supported with multiple helpers');
+        }
+        _utils.extend(this.helpers, name);
+      } else {
+        this.helpers[name] = fn;
+      }
+    },
+    unregisterHelper: function unregisterHelper(name) {
+      delete this.helpers[name];
+    },
+
+    registerPartial: function registerPartial(name, partial) {
+      if (_utils.toString.call(name) === objectType) {
+        _utils.extend(this.partials, name);
+      } else {
+        if (typeof partial === 'undefined') {
+          throw new _exception2['default']('Attempting to register a partial called "' + name + '" as undefined');
+        }
+        this.partials[name] = partial;
+      }
+    },
+    unregisterPartial: function unregisterPartial(name) {
+      delete this.partials[name];
+    },
+
+    registerDecorator: function registerDecorator(name, fn) {
+      if (_utils.toString.call(name) === objectType) {
+        if (fn) {
+          throw new _exception2['default']('Arg not supported with multiple decorators');
+        }
+        _utils.extend(this.decorators, name);
+      } else {
+        this.decorators[name] = fn;
+      }
+    },
+    unregisterDecorator: function unregisterDecorator(name) {
+      delete this.decorators[name];
+    },
+    /**
+     * Reset the memory of illegal property accesses that have already been logged.
+     * @deprecated should only be used in handlebars test-cases
+     */
+    resetLoggedPropertyAccesses: function resetLoggedPropertyAccesses() {
+      _internalProtoAccess.resetLoggedProperties();
+    }
+  };
+
+  var log = _logger2['default'].log;
+
+  exports.log = log;
+  exports.createFrame = _utils.createFrame;
+  exports.logger = _logger2['default'];
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports) {
+
+  'use strict';
+
+  exports.__esModule = true;
+  exports.extend = extend;
+  exports.indexOf = indexOf;
+  exports.escapeExpression = escapeExpression;
+  exports.isEmpty = isEmpty;
+  exports.createFrame = createFrame;
+  exports.blockParams = blockParams;
+  exports.appendContextPath = appendContextPath;
   var escape = {
-    "&": "&amp;",
-    "<": "&lt;",
-    ">": "&gt;",
-    '"': "&quot;",
-    "'": "&#x27;",
-    "`": "&#x60;"
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#x27;',
+    '`': '&#x60;',
+    '=': '&#x3D;'
   };
 
-  var badChars = /[&<>"'`]/g;
-  var possible = /[&<>"'`]/;
+  var badChars = /[&<>"'`=]/g,
+      possible = /[&<>"'`=]/;
 
   function escapeChar(chr) {
-    return escape[chr] || "&amp;";
+    return escape[chr];
   }
 
-  function extend(obj, value) {
-    for(var key in value) {
-      if(Object.prototype.hasOwnProperty.call(value, key)) {
-        obj[key] = value[key];
+  function extend(obj /* , ...source */) {
+    for (var i = 1; i < arguments.length; i++) {
+      for (var key in arguments[i]) {
+        if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
+          obj[key] = arguments[i][key];
+        }
       }
     }
+
+    return obj;
   }
 
-  __exports__.extend = extend;var toString = Object.prototype.toString;
-  __exports__.toString = toString;
+  var toString = Object.prototype.toString;
+
+  exports.toString = toString;
   // Sourced from lodash
   // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
-  var isFunction = function(value) {
+  /* eslint-disable func-style */
+  var isFunction = function isFunction(value) {
     return typeof value === 'function';
   };
   // fallback for older versions of Chrome and Safari
+  /* istanbul ignore next */
   if (isFunction(/x/)) {
-    isFunction = function(value) {
+    exports.isFunction = isFunction = function (value) {
       return typeof value === 'function' && toString.call(value) === '[object Function]';
     };
   }
-  var isFunction;
-  __exports__.isFunction = isFunction;
-  var isArray = Array.isArray || function(value) {
-    return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false;
+  exports.isFunction = isFunction;
+
+  /* eslint-enable func-style */
+
+  /* istanbul ignore next */
+  var isArray = Array.isArray || function (value) {
+    return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false;
   };
-  __exports__.isArray = isArray;
 
-  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 "";
+  exports.isArray = isArray;
+  // Older IE versions do not directly support indexOf so we must implement our own, sadly.
+
+  function indexOf(array, value) {
+    for (var i = 0, len = array.length; i < len; i++) {
+      if (array[i] === value) {
+        return i;
+      }
     }
+    return -1;
+  }
 
-    // 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;
+  function escapeExpression(string) {
+    if (typeof string !== 'string') {
+      // don't escape SafeStrings, since they're already safe
+      if (string && string.toHTML) {
+        return string.toHTML();
+      } else if (string == null) {
+        return '';
+      } else if (!string) {
+        return string + '';
+      }
+
+      // 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; }
+    if (!possible.test(string)) {
+      return string;
+    }
     return string.replace(badChars, escapeChar);
   }
 
-  __exports__.escapeExpression = escapeExpression;function isEmpty(value) {
+  function isEmpty(value) {
     if (!value && value !== 0) {
       return true;
     } else if (isArray(value) && value.length === 0) {
@@ -124,23 +483,46 @@ var __module3__ = (function(__dependency1__) {
     }
   }
 
-  __exports__.isEmpty = isEmpty;
-  return __exports__;
-})(__module4__);
+  function createFrame(object) {
+    var frame = extend({}, object);
+    frame._parent = object;
+    return frame;
+  }
 
-// handlebars/exception.js
-var __module5__ = (function() {
-  "use strict";
-  var __exports__;
+  function blockParams(params, ids) {
+    params.path = ids;
+    return params;
+  }
+
+  function appendContextPath(contextPath, id) {
+    return (contextPath ? contextPath + '.' : '') + id;
+  }
 
-  var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
 
-  function Exception(message, node) {
-    var line;
-    if (node && node.firstLine) {
-      line = node.firstLine;
+  'use strict';
 
-      message += ' - ' + line + ':' + node.firstColumn;
+  var _Object$defineProperty = __webpack_require__(7)['default'];
+
+  exports.__esModule = true;
+  var errorProps = ['description', 'fileName', 'lineNumber', 'endLineNumber', 'message', 'name', 'number', 'stack'];
+
+  function Exception(message, node) {
+    var loc = node && node.loc,
+        line = undefined,
+        endLineNumber = undefined,
+        column = undefined,
+        endColumn = undefined;
+
+    if (loc) {
+      line = loc.start.line;
+      endLineNumber = loc.end.line;
+      column = loc.start.column;
+      endColumn = loc.end.column;
+
+      message += ' - ' + line + ':' + column;
     }
 
     var tmp = Error.prototype.constructor.call(this, message);
@@ -150,1144 +532,2801 @@ var __module5__ = (function() {
       this[errorProps[idx]] = tmp[errorProps[idx]];
     }
 
-    if (line) {
-      this.lineNumber = line;
-      this.column = node.firstColumn;
+    /* istanbul ignore else */
+    if (Error.captureStackTrace) {
+      Error.captureStackTrace(this, Exception);
+    }
+
+    try {
+      if (loc) {
+        this.lineNumber = line;
+        this.endLineNumber = endLineNumber;
+
+        // Work around issue under safari where we can't directly set the column value
+        /* istanbul ignore next */
+        if (_Object$defineProperty) {
+          Object.defineProperty(this, 'column', {
+            value: column,
+            enumerable: true
+          });
+          Object.defineProperty(this, 'endColumn', {
+            value: endColumn,
+            enumerable: true
+          });
+        } else {
+          this.column = column;
+          this.endColumn = endColumn;
+        }
+      }
+    } catch (nop) {
+      /* Ignore if the browser is very particular */
     }
   }
 
   Exception.prototype = new Error();
 
-  __exports__ = Exception;
-  return __exports__;
-})();
+  exports['default'] = Exception;
+  module.exports = exports['default'];
 
-// handlebars/base.js
-var __module2__ = (function(__dependency1__, __dependency2__) {
-  "use strict";
-  var __exports__ = {};
-  var Utils = __dependency1__;
-  var Exception = __dependency2__;
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
 
-  var VERSION = "1.3.0";
-  __exports__.VERSION = VERSION;var COMPILER_REVISION = 4;
-  __exports__.COMPILER_REVISION = COMPILER_REVISION;
-  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'
+  module.exports = { "default": __webpack_require__(8), __esModule: true };
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  var $ = __webpack_require__(9);
+  module.exports = function defineProperty(it, key, desc){
+    return $.setDesc(it, key, desc);
   };
-  __exports__.REVISION_CHANGES = REVISION_CHANGES;
-  var isArray = Utils.isArray,
-      isFunction = Utils.isFunction,
-      toString = Utils.toString,
-      objectType = '[object Object]';
 
-  function HandlebarsEnvironment(helpers, partials) {
-    this.helpers = helpers || {};
-    this.partials = partials || {};
+/***/ }),
+/* 9 */
+/***/ (function(module, exports) {
+
+  var $Object = Object;
+  module.exports = {
+    create:     $Object.create,
+    getProto:   $Object.getPrototypeOf,
+    isEnum:     {}.propertyIsEnumerable,
+    getDesc:    $Object.getOwnPropertyDescriptor,
+    setDesc:    $Object.defineProperty,
+    setDescs:   $Object.defineProperties,
+    getKeys:    $Object.keys,
+    getNames:   $Object.getOwnPropertyNames,
+    getSymbols: $Object.getOwnPropertySymbols,
+    each:       [].forEach
+  };
 
-    registerDefaultHelpers(this);
-  }
+/***/ }),
+/* 10 */
+/***/ (function(module, exports, __webpack_require__) {
 
-  __exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = {
-    constructor: HandlebarsEnvironment,
+  'use strict';
 
-    logger: logger,
-    log: log,
+  var _interopRequireDefault = __webpack_require__(1)['default'];
 
-    registerHelper: function(name, fn, inverse) {
-      if (toString.call(name) === objectType) {
-        if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); }
-        Utils.extend(this.helpers, name);
-      } else {
-        if (inverse) { fn.not = inverse; }
-        this.helpers[name] = fn;
-      }
-    },
+  exports.__esModule = true;
+  exports.registerDefaultHelpers = registerDefaultHelpers;
+  exports.moveHelperToHooks = moveHelperToHooks;
 
-    registerPartial: function(name, str) {
-      if (toString.call(name) === objectType) {
-        Utils.extend(this.partials,  name);
-      } else {
-        this.partials[name] = str;
-      }
-    }
-  };
+  var _helpersBlockHelperMissing = __webpack_require__(11);
+
+  var _helpersBlockHelperMissing2 = _interopRequireDefault(_helpersBlockHelperMissing);
+
+  var _helpersEach = __webpack_require__(12);
+
+  var _helpersEach2 = _interopRequireDefault(_helpersEach);
+
+  var _helpersHelperMissing = __webpack_require__(25);
+
+  var _helpersHelperMissing2 = _interopRequireDefault(_helpersHelperMissing);
+
+  var _helpersIf = __webpack_require__(26);
+
+  var _helpersIf2 = _interopRequireDefault(_helpersIf);
+
+  var _helpersLog = __webpack_require__(27);
+
+  var _helpersLog2 = _interopRequireDefault(_helpersLog);
+
+  var _helpersLookup = __webpack_require__(28);
+
+  var _helpersLookup2 = _interopRequireDefault(_helpersLookup);
+
+  var _helpersWith = __webpack_require__(29);
+
+  var _helpersWith2 = _interopRequireDefault(_helpersWith);
 
   function registerDefaultHelpers(instance) {
-    instance.registerHelper('helperMissing', function(arg) {
-      if(arguments.length === 2) {
-        return undefined;
-      } else {
-        throw new Exception("Missing helper: '" + arg + "'");
+    _helpersBlockHelperMissing2['default'](instance);
+    _helpersEach2['default'](instance);
+    _helpersHelperMissing2['default'](instance);
+    _helpersIf2['default'](instance);
+    _helpersLog2['default'](instance);
+    _helpersLookup2['default'](instance);
+    _helpersWith2['default'](instance);
+  }
+
+  function moveHelperToHooks(instance, helperName, keepHelper) {
+    if (instance.helpers[helperName]) {
+      instance.hooks[helperName] = instance.helpers[helperName];
+      if (!keepHelper) {
+        delete instance.helpers[helperName];
       }
-    });
+    }
+  }
 
-    instance.registerHelper('blockHelperMissing', function(context, options) {
-      var inverse = options.inverse || function() {}, fn = options.fn;
+/***/ }),
+/* 11 */
+/***/ (function(module, exports, __webpack_require__) {
 
-      if (isFunction(context)) { context = context.call(this); }
+  'use strict';
 
-      if(context === true) {
+  exports.__esModule = true;
+
+  var _utils = __webpack_require__(5);
+
+  exports['default'] = function (instance) {
+    instance.registerHelper('blockHelperMissing', function (context, options) {
+      var inverse = options.inverse,
+          fn = options.fn;
+
+      if (context === true) {
         return fn(this);
-      } else if(context === false || context == null) {
+      } else if (context === false || context == null) {
         return inverse(this);
-      } else if (isArray(context)) {
-        if(context.length > 0) {
+      } else if (_utils.isArray(context)) {
+        if (context.length > 0) {
+          if (options.ids) {
+            options.ids = [options.name];
+          }
+
           return instance.helpers.each(context, options);
         } else {
           return inverse(this);
         }
       } else {
-        return fn(context);
+        if (options.data && options.ids) {
+          var data = _utils.createFrame(options.data);
+          data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name);
+          options = { data: data };
+        }
+
+        return fn(context, options);
       }
     });
+  };
+
+  module.exports = exports['default'];
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  /* WEBPACK VAR INJECTION */(function(global) {'use strict';
+
+  var _Object$keys = __webpack_require__(13)['default'];
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+
+  var _utils = __webpack_require__(5);
+
+  var _exception = __webpack_require__(6);
+
+  var _exception2 = _interopRequireDefault(_exception);
+
+  exports['default'] = function (instance) {
+    instance.registerHelper('each', function (context, options) {
+      if (!options) {
+        throw new _exception2['default']('Must pass iterator to #each');
+      }
+
+      var fn = options.fn,
+          inverse = options.inverse,
+          i = 0,
+          ret = '',
+          data = undefined,
+          contextPath = undefined;
 
-    instance.registerHelper('each', function(context, options) {
-      var fn = options.fn, inverse = options.inverse;
-      var i = 0, ret = "", data;
+      if (options.data && options.ids) {
+        contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
+      }
 
-      if (isFunction(context)) { context = context.call(this); }
+      if (_utils.isFunction(context)) {
+        context = context.call(this);
+      }
 
       if (options.data) {
-        data = createFrame(options.data);
+        data = _utils.createFrame(options.data);
+      }
+
+      function execIteration(field, index, last) {
+        if (data) {
+          data.key = field;
+          data.index = index;
+          data.first = index === 0;
+          data.last = !!last;
+
+          if (contextPath) {
+            data.contextPath = contextPath + field;
+          }
+        }
+
+        ret = ret + fn(context[field], {
+          data: data,
+          blockParams: _utils.blockParams([context[field], field], [contextPath + field, null])
+        });
       }
 
-      if(context && typeof context === 'object') {
-        if (isArray(context)) {
-          for(var j = context.length; i<j; i++) {
-            if (data) {
-              data.index = i;
-              data.first = (i === 0);
-              data.last  = (i === (context.length-1));
+      if (context && typeof context === 'object') {
+        if (_utils.isArray(context)) {
+          for (var j = context.length; i < j; i++) {
+            if (i in context) {
+              execIteration(i, i, i === context.length - 1);
             }
-            ret = ret + fn(context[i], { data: data });
+          }
+        } else if (global.Symbol && context[global.Symbol.iterator]) {
+          var newContext = [];
+          var iterator = context[global.Symbol.iterator]();
+          for (var it = iterator.next(); !it.done; it = iterator.next()) {
+            newContext.push(it.value);
+          }
+          context = newContext;
+          for (var j = context.length; i < j; i++) {
+            execIteration(i, i, i === context.length - 1);
           }
         } else {
-          for(var key in context) {
-            if(context.hasOwnProperty(key)) {
-              if(data) {
-                data.key = key;
-                data.index = i;
-                data.first = (i === 0);
+          (function () {
+            var priorKey = undefined;
+
+            _Object$keys(context).forEach(function (key) {
+              // We're running the iterations one step out of sync so we can detect
+              // the last iteration without have to scan the object twice and create
+              // an itermediate keys array.
+              if (priorKey !== undefined) {
+                execIteration(priorKey, i - 1);
               }
-              ret = ret + fn(context[key], {data: data});
+              priorKey = key;
               i++;
+            });
+            if (priorKey !== undefined) {
+              execIteration(priorKey, i - 1, true);
             }
-          }
+          })();
         }
       }
 
-      if(i === 0){
+      if (i === 0) {
         ret = inverse(this);
       }
 
       return ret;
     });
+  };
 
-    instance.registerHelper('if', function(conditional, options) {
-      if (isFunction(conditional)) { conditional = conditional.call(this); }
+  module.exports = exports['default'];
+  /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
 
-      // Default behavior is to render the positive path if the value is truthy and not empty.
-      // The `includeZero` option may be set to treat the condtional as purely not empty based on the
-      // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
-      if ((!options.hash.includeZero && !conditional) || Utils.isEmpty(conditional)) {
-        return options.inverse(this);
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  module.exports = { "default": __webpack_require__(14), __esModule: true };
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  __webpack_require__(15);
+  module.exports = __webpack_require__(21).Object.keys;
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  // 19.1.2.14 Object.keys(O)
+  var toObject = __webpack_require__(16);
+
+  __webpack_require__(18)('keys', function($keys){
+    return function keys(it){
+      return $keys(toObject(it));
+    };
+  });
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  // 7.1.13 ToObject(argument)
+  var defined = __webpack_require__(17);
+  module.exports = function(it){
+    return Object(defined(it));
+  };
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports) {
+
+  // 7.2.1 RequireObjectCoercible(argument)
+  module.exports = function(it){
+    if(it == undefined)throw TypeError("Can't call method on  " + it);
+    return it;
+  };
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  // most Object methods by ES6 should accept primitives
+  var $export = __webpack_require__(19)
+    , core    = __webpack_require__(21)
+    , fails   = __webpack_require__(24);
+  module.exports = function(KEY, exec){
+    var fn  = (core.Object || {})[KEY] || Object[KEY]
+      , exp = {};
+    exp[KEY] = exec(fn);
+    $export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp);
+  };
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  var global    = __webpack_require__(20)
+    , core      = __webpack_require__(21)
+    , ctx       = __webpack_require__(22)
+    , PROTOTYPE = 'prototype';
+
+  var $export = function(type, name, source){
+    var IS_FORCED = type & $export.F
+      , IS_GLOBAL = type & $export.G
+      , IS_STATIC = type & $export.S
+      , IS_PROTO  = type & $export.P
+      , IS_BIND   = type & $export.B
+      , IS_WRAP   = type & $export.W
+      , exports   = IS_GLOBAL ? core : core[name] || (core[name] = {})
+      , target    = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE]
+      , key, own, out;
+    if(IS_GLOBAL)source = name;
+    for(key in source){
+      // contains in native
+      own = !IS_FORCED && target && key in target;
+      if(own && key in exports)continue;
+      // export native or passed
+      out = own ? target[key] : source[key];
+      // prevent global pollution for namespaces
+      exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key]
+      // bind timers to global for call from export context
+      : IS_BIND && own ? ctx(out, global)
+      // wrap global constructors for prevent change them in library
+      : IS_WRAP && target[key] == out ? (function(C){
+        var F = function(param){
+          return this instanceof C ? new C(param) : C(param);
+        };
+        F[PROTOTYPE] = C[PROTOTYPE];
+        return F;
+      // make static versions for prototype methods
+      })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
+      if(IS_PROTO)(exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out;
+    }
+  };
+  // type bitmap
+  $export.F = 1;  // forced
+  $export.G = 2;  // global
+  $export.S = 4;  // static
+  $export.P = 8;  // proto
+  $export.B = 16; // bind
+  $export.W = 32; // wrap
+  module.exports = $export;
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports) {
+
+  // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
+  var global = module.exports = typeof window != 'undefined' && window.Math == Math
+    ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
+  if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports) {
+
+  var core = module.exports = {version: '1.2.6'};
+  if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef
+
+/***/ }),
+/* 22 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  // optional / simple context binding
+  var aFunction = __webpack_require__(23);
+  module.exports = function(fn, that, length){
+    aFunction(fn);
+    if(that === undefined)return fn;
+    switch(length){
+      case 1: return function(a){
+        return fn.call(that, a);
+      };
+      case 2: return function(a, b){
+        return fn.call(that, a, b);
+      };
+      case 3: return function(a, b, c){
+        return fn.call(that, a, b, c);
+      };
+    }
+    return function(/* ...args */){
+      return fn.apply(that, arguments);
+    };
+  };
+
+/***/ }),
+/* 23 */
+/***/ (function(module, exports) {
+
+  module.exports = function(it){
+    if(typeof it != 'function')throw TypeError(it + ' is not a function!');
+    return it;
+  };
+
+/***/ }),
+/* 24 */
+/***/ (function(module, exports) {
+
+  module.exports = function(exec){
+    try {
+      return !!exec();
+    } catch(e){
+      return true;
+    }
+  };
+
+/***/ }),
+/* 25 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+
+  var _exception = __webpack_require__(6);
+
+  var _exception2 = _interopRequireDefault(_exception);
+
+  exports['default'] = function (instance) {
+    instance.registerHelper('helperMissing', function () /* [args, ]options */{
+      if (arguments.length === 1) {
+        // A missing field in a {{foo}} construct.
+        return undefined;
+      } else {
+        // Someone is actually trying to call something, blow up.
+        throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"');
+      }
+    });
+  };
+
+  module.exports = exports['default'];
+
+/***/ }),
+/* 26 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+
+  var _utils = __webpack_require__(5);
+
+  var _exception = __webpack_require__(6);
+
+  var _exception2 = _interopRequireDefault(_exception);
+
+  exports['default'] = function (instance) {
+    instance.registerHelper('if', function (conditional, options) {
+      if (arguments.length != 2) {
+        throw new _exception2['default']('#if requires exactly one argument');
+      }
+      if (_utils.isFunction(conditional)) {
+        conditional = conditional.call(this);
+      }
+
+      // Default behavior is to render the positive path if the value is truthy and not empty.
+      // The `includeZero` option may be set to treat the condtional as purely not empty based on the
+      // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
+      if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) {
+        return options.inverse(this);
       } else {
         return options.fn(this);
       }
     });
 
-    instance.registerHelper('unless', function(conditional, options) {
-      return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
+    instance.registerHelper('unless', function (conditional, options) {
+      if (arguments.length != 2) {
+        throw new _exception2['default']('#unless requires exactly one argument');
+      }
+      return instance.helpers['if'].call(this, conditional, {
+        fn: options.inverse,
+        inverse: options.fn,
+        hash: options.hash
+      });
     });
+  };
+
+  module.exports = exports['default'];
+
+/***/ }),
+/* 27 */
+/***/ (function(module, exports) {
+
+  'use strict';
+
+  exports.__esModule = true;
+
+  exports['default'] = function (instance) {
+    instance.registerHelper('log', function () /* message, options */{
+      var args = [undefined],
+          options = arguments[arguments.length - 1];
+      for (var i = 0; i < arguments.length - 1; i++) {
+        args.push(arguments[i]);
+      }
 
-    instance.registerHelper('with', function(context, options) {
-      if (isFunction(context)) { context = context.call(this); }
+      var level = 1;
+      if (options.hash.level != null) {
+        level = options.hash.level;
+      } else if (options.data && options.data.level != null) {
+        level = options.data.level;
+      }
+      args[0] = level;
 
-      if (!Utils.isEmpty(context)) return options.fn(context);
+      instance.log.apply(instance, args);
     });
+  };
+
+  module.exports = exports['default'];
+
+/***/ }),
+/* 28 */
+/***/ (function(module, exports) {
 
-    instance.registerHelper('log', function(context, options) {
-      var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
-      instance.log(level, context);
+  'use strict';
+
+  exports.__esModule = true;
+
+  exports['default'] = function (instance) {
+    instance.registerHelper('lookup', function (obj, field, options) {
+      if (!obj) {
+        // Note for 5.0: Change to "obj == null" in 5.0
+        return obj;
+      }
+      return options.lookupProperty(obj, field);
     });
+  };
+
+  module.exports = exports['default'];
+
+/***/ }),
+/* 29 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+
+  var _utils = __webpack_require__(5);
+
+  var _exception = __webpack_require__(6);
+
+  var _exception2 = _interopRequireDefault(_exception);
+
+  exports['default'] = function (instance) {
+    instance.registerHelper('with', function (context, options) {
+      if (arguments.length != 2) {
+        throw new _exception2['default']('#with requires exactly one argument');
+      }
+      if (_utils.isFunction(context)) {
+        context = context.call(this);
+      }
+
+      var fn = options.fn;
+
+      if (!_utils.isEmpty(context)) {
+        var data = options.data;
+        if (options.data && options.ids) {
+          data = _utils.createFrame(options.data);
+          data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]);
+        }
+
+        return fn(context, {
+          data: data,
+          blockParams: _utils.blockParams([context], [data && data.contextPath])
+        });
+      } else {
+        return options.inverse(this);
+      }
+    });
+  };
+
+  module.exports = exports['default'];
+
+/***/ }),
+/* 30 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+  exports.registerDefaultDecorators = registerDefaultDecorators;
+
+  var _decoratorsInline = __webpack_require__(31);
+
+  var _decoratorsInline2 = _interopRequireDefault(_decoratorsInline);
+
+  function registerDefaultDecorators(instance) {
+    _decoratorsInline2['default'](instance);
   }
 
+/***/ }),
+/* 31 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  exports.__esModule = true;
+
+  var _utils = __webpack_require__(5);
+
+  exports['default'] = function (instance) {
+    instance.registerDecorator('inline', function (fn, props, container, options) {
+      var ret = fn;
+      if (!props.partials) {
+        props.partials = {};
+        ret = function (context, options) {
+          // Create a new partials stack frame prior to exec.
+          var original = container.partials;
+          container.partials = _utils.extend({}, original, props.partials);
+          var ret = fn(context, options);
+          container.partials = original;
+          return ret;
+        };
+      }
+
+      props.partials[options.args[0]] = options.fn;
+
+      return ret;
+    });
+  };
+
+  module.exports = exports['default'];
+
+/***/ }),
+/* 32 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  exports.__esModule = true;
+
+  var _utils = __webpack_require__(5);
+
   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) {
+    methodMap: ['debug', 'info', 'warn', 'error'],
+    level: 'info',
+
+    // Maps a given level value to the `methodMap` indexes above.
+    lookupLevel: function lookupLevel(level) {
+      if (typeof level === 'string') {
+        var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase());
+        if (levelMap >= 0) {
+          level = levelMap;
+        } else {
+          level = parseInt(level, 10);
+        }
+      }
+
+      return level;
+    },
+
+    // Can be overridden in the host environment
+    log: function log(level) {
+      level = logger.lookupLevel(level);
+
+      if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) {
         var method = logger.methodMap[level];
-        if (typeof console !== 'undefined' && console[method]) {
-          console[method].call(console, obj);
+        // eslint-disable-next-line no-console
+        if (!console[method]) {
+          method = 'log';
+        }
+
+        for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+          message[_key - 1] = arguments[_key];
         }
+
+        console[method].apply(console, message); // eslint-disable-line no-console
       }
     }
   };
-  __exports__.logger = logger;
-  function log(level, obj) { logger.log(level, obj); }
 
-  __exports__.log = log;var createFrame = function(object) {
-    var obj = {};
-    Utils.extend(obj, object);
-    return obj;
+  exports['default'] = logger;
+  module.exports = exports['default'];
+
+/***/ }),
+/* 33 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _Object$create = __webpack_require__(34)['default'];
+
+  var _Object$keys = __webpack_require__(13)['default'];
+
+  var _interopRequireWildcard = __webpack_require__(3)['default'];
+
+  exports.__esModule = true;
+  exports.createProtoAccessControl = createProtoAccessControl;
+  exports.resultIsAllowed = resultIsAllowed;
+  exports.resetLoggedProperties = resetLoggedProperties;
+
+  var _createNewLookupObject = __webpack_require__(36);
+
+  var _logger = __webpack_require__(32);
+
+  var logger = _interopRequireWildcard(_logger);
+
+  var loggedProperties = _Object$create(null);
+
+  function createProtoAccessControl(runtimeOptions) {
+    var defaultMethodWhiteList = _Object$create(null);
+    defaultMethodWhiteList['constructor'] = false;
+    defaultMethodWhiteList['__defineGetter__'] = false;
+    defaultMethodWhiteList['__defineSetter__'] = false;
+    defaultMethodWhiteList['__lookupGetter__'] = false;
+
+    var defaultPropertyWhiteList = _Object$create(null);
+    // eslint-disable-next-line no-proto
+    defaultPropertyWhiteList['__proto__'] = false;
+
+    return {
+      properties: {
+        whitelist: _createNewLookupObject.createNewLookupObject(defaultPropertyWhiteList, runtimeOptions.allowedProtoProperties),
+        defaultValue: runtimeOptions.allowProtoPropertiesByDefault
+      },
+      methods: {
+        whitelist: _createNewLookupObject.createNewLookupObject(defaultMethodWhiteList, runtimeOptions.allowedProtoMethods),
+        defaultValue: runtimeOptions.allowProtoMethodsByDefault
+      }
+    };
+  }
+
+  function resultIsAllowed(result, protoAccessControl, propertyName) {
+    if (typeof result === 'function') {
+      return checkWhiteList(protoAccessControl.methods, propertyName);
+    } else {
+      return checkWhiteList(protoAccessControl.properties, propertyName);
+    }
+  }
+
+  function checkWhiteList(protoAccessControlForType, propertyName) {
+    if (protoAccessControlForType.whitelist[propertyName] !== undefined) {
+      return protoAccessControlForType.whitelist[propertyName] === true;
+    }
+    if (protoAccessControlForType.defaultValue !== undefined) {
+      return protoAccessControlForType.defaultValue;
+    }
+    logUnexpecedPropertyAccessOnce(propertyName);
+    return false;
+  }
+
+  function logUnexpecedPropertyAccessOnce(propertyName) {
+    if (loggedProperties[propertyName] !== true) {
+      loggedProperties[propertyName] = true;
+      logger.log('error', 'Handlebars: Access has been denied to resolve the property "' + propertyName + '" because it is not an "own property" of its parent.\n' + 'You can add a runtime option to disable the check or this warning:\n' + 'See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details');
+    }
+  }
+
+  function resetLoggedProperties() {
+    _Object$keys(loggedProperties).forEach(function (propertyName) {
+      delete loggedProperties[propertyName];
+    });
+  }
+
+/***/ }),
+/* 34 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  module.exports = { "default": __webpack_require__(35), __esModule: true };
+
+/***/ }),
+/* 35 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  var $ = __webpack_require__(9);
+  module.exports = function create(P, D){
+    return $.create(P, D);
+  };
+
+/***/ }),
+/* 36 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _Object$create = __webpack_require__(34)['default'];
+
+  exports.__esModule = true;
+  exports.createNewLookupObject = createNewLookupObject;
+
+  var _utils = __webpack_require__(5);
+
+  /**
+   * Create a new object with "null"-prototype to avoid truthy results on prototype properties.
+   * The resulting object can be used with "object[property]" to check if a property exists
+   * @param {...object} sources a varargs parameter of source objects that will be merged
+   * @returns {object}
+   */
+
+  function createNewLookupObject() {
+    for (var _len = arguments.length, sources = Array(_len), _key = 0; _key < _len; _key++) {
+      sources[_key] = arguments[_key];
+    }
+
+    return _utils.extend.apply(undefined, [_Object$create(null)].concat(sources));
+  }
+
+/***/ }),
+/* 37 */
+/***/ (function(module, exports) {
+
+  // Build out our basic SafeString type
+  'use strict';
+
+  exports.__esModule = true;
+  function SafeString(string) {
+    this.string = string;
+  }
+
+  SafeString.prototype.toString = SafeString.prototype.toHTML = function () {
+    return '' + this.string;
+  };
+
+  exports['default'] = SafeString;
+  module.exports = exports['default'];
+
+/***/ }),
+/* 38 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _Object$seal = __webpack_require__(39)['default'];
+
+  var _Object$keys = __webpack_require__(13)['default'];
+
+  var _interopRequireWildcard = __webpack_require__(3)['default'];
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+  exports.checkRevision = checkRevision;
+  exports.template = template;
+  exports.wrapProgram = wrapProgram;
+  exports.resolvePartial = resolvePartial;
+  exports.invokePartial = invokePartial;
+  exports.noop = noop;
+
+  var _utils = __webpack_require__(5);
+
+  var Utils = _interopRequireWildcard(_utils);
+
+  var _exception = __webpack_require__(6);
+
+  var _exception2 = _interopRequireDefault(_exception);
+
+  var _base = __webpack_require__(4);
+
+  var _helpers = __webpack_require__(10);
+
+  var _internalWrapHelper = __webpack_require__(43);
+
+  var _internalProtoAccess = __webpack_require__(33);
+
+  function checkRevision(compilerInfo) {
+    var compilerRevision = compilerInfo && compilerInfo[0] || 1,
+        currentRevision = _base.COMPILER_REVISION;
+
+    if (compilerRevision >= _base.LAST_COMPATIBLE_COMPILER_REVISION && compilerRevision <= _base.COMPILER_REVISION) {
+      return;
+    }
+
+    if (compilerRevision < _base.LAST_COMPATIBLE_COMPILER_REVISION) {
+      var runtimeVersions = _base.REVISION_CHANGES[currentRevision],
+          compilerVersions = _base.REVISION_CHANGES[compilerRevision];
+      throw new _exception2['default']('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 new _exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
+    }
+  }
+
+  function template(templateSpec, env) {
+    /* istanbul ignore next */
+    if (!env) {
+      throw new _exception2['default']('No environment passed to template');
+    }
+    if (!templateSpec || !templateSpec.main) {
+      throw new _exception2['default']('Unknown template object: ' + typeof templateSpec);
+    }
+
+    templateSpec.main.decorator = templateSpec.main_d;
+
+    // Note: Using env.VM references rather than local var references throughout this section to allow
+    // for external users to override these as pseudo-supported APIs.
+    env.VM.checkRevision(templateSpec.compiler);
+
+    // backwards compatibility for precompiled templates with compiler-version 7 (<4.3.0)
+    var templateWasPrecompiledWithCompilerV7 = templateSpec.compiler && templateSpec.compiler[0] === 7;
+
+    function invokePartialWrapper(partial, context, options) {
+      if (options.hash) {
+        context = Utils.extend({}, context, options.hash);
+        if (options.ids) {
+          options.ids[0] = true;
+        }
+      }
+      partial = env.VM.resolvePartial.call(this, partial, context, options);
+
+      var extendedOptions = Utils.extend({}, options, {
+        hooks: this.hooks,
+        protoAccessControl: this.protoAccessControl
+      });
+
+      var result = env.VM.invokePartial.call(this, partial, context, extendedOptions);
+
+      if (result == null && env.compile) {
+        options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
+        result = options.partials[options.name](context, extendedOptions);
+      }
+      if (result != null) {
+        if (options.indent) {
+          var lines = result.split('\n');
+          for (var i = 0, l = lines.length; i < l; i++) {
+            if (!lines[i] && i + 1 === l) {
+              break;
+            }
+
+            lines[i] = options.indent + lines[i];
+          }
+          result = lines.join('\n');
+        }
+        return result;
+      } else {
+        throw new _exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode');
+      }
+    }
+
+    // Just add water
+    var container = {
+      strict: function strict(obj, name, loc) {
+        if (!obj || !(name in obj)) {
+          throw new _exception2['default']('"' + name + '" not defined in ' + obj, {
+            loc: loc
+          });
+        }
+        return obj[name];
+      },
+      lookupProperty: function lookupProperty(parent, propertyName) {
+        var result = parent[propertyName];
+        if (result == null) {
+          return result;
+        }
+        if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
+          return result;
+        }
+
+        if (_internalProtoAccess.resultIsAllowed(result, container.protoAccessControl, propertyName)) {
+          return result;
+        }
+        return undefined;
+      },
+      lookup: function lookup(depths, name) {
+        var len = depths.length;
+        for (var i = 0; i < len; i++) {
+          var result = depths[i] && container.lookupProperty(depths[i], name);
+          if (result != null) {
+            return depths[i][name];
+          }
+        }
+      },
+      lambda: function lambda(current, context) {
+        return typeof current === 'function' ? current.call(context) : current;
+      },
+
+      escapeExpression: Utils.escapeExpression,
+      invokePartial: invokePartialWrapper,
+
+      fn: function fn(i) {
+        var ret = templateSpec[i];
+        ret.decorator = templateSpec[i + '_d'];
+        return ret;
+      },
+
+      programs: [],
+      program: function program(i, data, declaredBlockParams, blockParams, depths) {
+        var programWrapper = this.programs[i],
+            fn = this.fn(i);
+        if (data || depths || blockParams || declaredBlockParams) {
+          programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths);
+        } else if (!programWrapper) {
+          programWrapper = this.programs[i] = wrapProgram(this, i, fn);
+        }
+        return programWrapper;
+      },
+
+      data: function data(value, depth) {
+        while (value && depth--) {
+          value = value._parent;
+        }
+        return value;
+      },
+      mergeIfNeeded: function mergeIfNeeded(param, common) {
+        var obj = param || common;
+
+        if (param && common && param !== common) {
+          obj = Utils.extend({}, common, param);
+        }
+
+        return obj;
+      },
+      // An empty object to use as replacement for null-contexts
+      nullContext: _Object$seal({}),
+
+      noop: env.VM.noop,
+      compilerInfo: templateSpec.compiler
+    };
+
+    function ret(context) {
+      var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
+
+      var data = options.data;
+
+      ret._setup(options);
+      if (!options.partial && templateSpec.useData) {
+        data = initData(context, data);
+      }
+      var depths = undefined,
+          blockParams = templateSpec.useBlockParams ? [] : undefined;
+      if (templateSpec.useDepths) {
+        if (options.depths) {
+          depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths;
+        } else {
+          depths = [context];
+        }
+      }
+
+      function main(context /*, options*/) {
+        return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths);
+      }
+
+      main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams);
+      return main(context, options);
+    }
+
+    ret.isTop = true;
+
+    ret._setup = function (options) {
+      if (!options.partial) {
+        var mergedHelpers = Utils.extend({}, env.helpers, options.helpers);
+        wrapHelpersToPassLookupProperty(mergedHelpers, container);
+        container.helpers = mergedHelpers;
+
+        if (templateSpec.usePartial) {
+          // Use mergeIfNeeded here to prevent compiling global partials multiple times
+          container.partials = container.mergeIfNeeded(options.partials, env.partials);
+        }
+        if (templateSpec.usePartial || templateSpec.useDecorators) {
+          container.decorators = Utils.extend({}, env.decorators, options.decorators);
+        }
+
+        container.hooks = {};
+        container.protoAccessControl = _internalProtoAccess.createProtoAccessControl(options);
+
+        var keepHelperInHelpers = options.allowCallsToHelperMissing || templateWasPrecompiledWithCompilerV7;
+        _helpers.moveHelperToHooks(container, 'helperMissing', keepHelperInHelpers);
+        _helpers.moveHelperToHooks(container, 'blockHelperMissing', keepHelperInHelpers);
+      } else {
+        container.protoAccessControl = options.protoAccessControl; // internal option
+        container.helpers = options.helpers;
+        container.partials = options.partials;
+        container.decorators = options.decorators;
+        container.hooks = options.hooks;
+      }
+    };
+
+    ret._child = function (i, data, blockParams, depths) {
+      if (templateSpec.useBlockParams && !blockParams) {
+        throw new _exception2['default']('must pass block params');
+      }
+      if (templateSpec.useDepths && !depths) {
+        throw new _exception2['default']('must pass parent depths');
+      }
+
+      return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths);
+    };
+    return ret;
+  }
+
+  function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) {
+    function prog(context) {
+      var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
+
+      var currentDepths = depths;
+      if (depths && context != depths[0] && !(context === container.nullContext && depths[0] === null)) {
+        currentDepths = [context].concat(depths);
+      }
+
+      return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths);
+    }
+
+    prog = executeDecorators(fn, prog, container, depths, data, blockParams);
+
+    prog.program = i;
+    prog.depth = depths ? depths.length : 0;
+    prog.blockParams = declaredBlockParams || 0;
+    return prog;
+  }
+
+  /**
+   * This is currently part of the official API, therefore implementation details should not be changed.
+   */
+
+  function resolvePartial(partial, context, options) {
+    if (!partial) {
+      if (options.name === '@partial-block') {
+        partial = options.data['partial-block'];
+      } else {
+        partial = options.partials[options.name];
+      }
+    } else if (!partial.call && !options.name) {
+      // This is a dynamic partial that returned a string
+      options.name = partial;
+      partial = options.partials[partial];
+    }
+    return partial;
+  }
+
+  function invokePartial(partial, context, options) {
+    // Use the current closure context to save the partial-block if this partial
+    var currentPartialBlock = options.data && options.data['partial-block'];
+    options.partial = true;
+    if (options.ids) {
+      options.data.contextPath = options.ids[0] || options.data.contextPath;
+    }
+
+    var partialBlock = undefined;
+    if (options.fn && options.fn !== noop) {
+      (function () {
+        options.data = _base.createFrame(options.data);
+        // Wrapper function to get access to currentPartialBlock from the closure
+        var fn = options.fn;
+        partialBlock = options.data['partial-block'] = function partialBlockWrapper(context) {
+          var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
+
+          // Restore the partial-block from the closure for the execution of the block
+          // i.e. the part inside the block of the partial call.
+          options.data = _base.createFrame(options.data);
+          options.data['partial-block'] = currentPartialBlock;
+          return fn(context, options);
+        };
+        if (fn.partials) {
+          options.partials = Utils.extend({}, options.partials, fn.partials);
+        }
+      })();
+    }
+
+    if (partial === undefined && partialBlock) {
+      partial = partialBlock;
+    }
+
+    if (partial === undefined) {
+      throw new _exception2['default']('The partial ' + options.name + ' could not be found');
+    } else if (partial instanceof Function) {
+      return partial(context, options);
+    }
+  }
+
+  function noop() {
+    return '';
+  }
+
+  function initData(context, data) {
+    if (!data || !('root' in data)) {
+      data = data ? _base.createFrame(data) : {};
+      data.root = context;
+    }
+    return data;
+  }
+
+  function executeDecorators(fn, prog, container, depths, data, blockParams) {
+    if (fn.decorator) {
+      var props = {};
+      prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths);
+      Utils.extend(prog, props);
+    }
+    return prog;
+  }
+
+  function wrapHelpersToPassLookupProperty(mergedHelpers, container) {
+    _Object$keys(mergedHelpers).forEach(function (helperName) {
+      var helper = mergedHelpers[helperName];
+      mergedHelpers[helperName] = passLookupPropertyOption(helper, container);
+    });
+  }
+
+  function passLookupPropertyOption(helper, container) {
+    var lookupProperty = container.lookupProperty;
+    return _internalWrapHelper.wrapHelper(helper, function (options) {
+      return Utils.extend({ lookupProperty: lookupProperty }, options);
+    });
+  }
+
+/***/ }),
+/* 39 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  module.exports = { "default": __webpack_require__(40), __esModule: true };
+
+/***/ }),
+/* 40 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  __webpack_require__(41);
+  module.exports = __webpack_require__(21).Object.seal;
+
+/***/ }),
+/* 41 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  // 19.1.2.17 Object.seal(O)
+  var isObject = __webpack_require__(42);
+
+  __webpack_require__(18)('seal', function($seal){
+    return function seal(it){
+      return $seal && isObject(it) ? $seal(it) : it;
+    };
+  });
+
+/***/ }),
+/* 42 */
+/***/ (function(module, exports) {
+
+  module.exports = function(it){
+    return typeof it === 'object' ? it !== null : typeof it === 'function';
+  };
+
+/***/ }),
+/* 43 */
+/***/ (function(module, exports) {
+
+  'use strict';
+
+  exports.__esModule = true;
+  exports.wrapHelper = wrapHelper;
+
+  function wrapHelper(helper, transformOptionsFn) {
+    if (typeof helper !== 'function') {
+      // This should not happen, but apparently it does in https://github.com/wycats/handlebars.js/issues/1639
+      // We try to make the wrapper least-invasive by not wrapping it, if the helper is not a function.
+      return helper;
+    }
+    var wrapper = function wrapper() /* dynamic arguments */{
+      var options = arguments[arguments.length - 1];
+      arguments[arguments.length - 1] = transformOptionsFn(options);
+      return helper.apply(this, arguments);
+    };
+    return wrapper;
+  }
+
+/***/ }),
+/* 44 */
+/***/ (function(module, exports) {
+
+  /* WEBPACK VAR INJECTION */(function(global) {'use strict';
+
+  exports.__esModule = true;
+
+  exports['default'] = function (Handlebars) {
+    /* istanbul ignore next */
+    var root = typeof global !== 'undefined' ? global : window,
+        $Handlebars = root.Handlebars;
+    /* istanbul ignore next */
+    Handlebars.noConflict = function () {
+      if (root.Handlebars === Handlebars) {
+        root.Handlebars = $Handlebars;
+      }
+      return Handlebars;
+    };
+  };
+
+  module.exports = exports['default'];
+  /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
+
+/***/ }),
+/* 45 */
+/***/ (function(module, exports) {
+
+  'use strict';
+
+  exports.__esModule = true;
+  var AST = {
+    // Public API used to evaluate derived attributes regarding AST nodes
+    helpers: {
+      // a mustache is definitely a helper if:
+      // * it is an eligible helper, and
+      // * it has at least one parameter or hash segment
+      helperExpression: function helperExpression(node) {
+        return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash);
+      },
+
+      scopedId: function scopedId(path) {
+        return (/^\.|this\b/.test(path.original)
+        );
+      },
+
+      // an ID is simple if it only has one part, and that part is not
+      // `..` or `this`.
+      simpleId: function simpleId(path) {
+        return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth;
+      }
+    }
+  };
+
+  // Must be exported as an object rather than the root of the module as the jison lexer
+  // must modify the object to operate properly.
+  exports['default'] = AST;
+  module.exports = exports['default'];
+
+/***/ }),
+/* 46 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  var _interopRequireWildcard = __webpack_require__(3)['default'];
+
+  exports.__esModule = true;
+  exports.parseWithoutProcessing = parseWithoutProcessing;
+  exports.parse = parse;
+
+  var _parser = __webpack_require__(47);
+
+  var _parser2 = _interopRequireDefault(_parser);
+
+  var _whitespaceControl = __webpack_require__(48);
+
+  var _whitespaceControl2 = _interopRequireDefault(_whitespaceControl);
+
+  var _helpers = __webpack_require__(50);
+
+  var Helpers = _interopRequireWildcard(_helpers);
+
+  var _utils = __webpack_require__(5);
+
+  exports.parser = _parser2['default'];
+
+  var yy = {};
+  _utils.extend(yy, Helpers);
+
+  function parseWithoutProcessing(input, options) {
+    // Just return if an already-compiled AST was passed in.
+    if (input.type === 'Program') {
+      return input;
+    }
+
+    _parser2['default'].yy = yy;
+
+    // Altering the shared object here, but this is ok as parser is a sync operation
+    yy.locInfo = function (locInfo) {
+      return new yy.SourceLocation(options && options.srcName, locInfo);
+    };
+
+    var ast = _parser2['default'].parse(input);
+
+    return ast;
+  }
+
+  function parse(input, options) {
+    var ast = parseWithoutProcessing(input, options);
+    var strip = new _whitespaceControl2['default'](options);
+
+    return strip.accept(ast);
+  }
+
+/***/ }),
+/* 47 */
+/***/ (function(module, exports) {
+
+  // File ignored in coverage tests via setting in .istanbul.yml
+  /* Jison generated parser */
+  "use strict";
+
+  exports.__esModule = true;
+  var handlebars = (function () {
+      var parser = { trace: function trace() {},
+          yy: {},
+          symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInver [...]
+          terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT", 18: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUM [...]
+          productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 0], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [2 [...]
+          performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
+
+              var $0 = $$.length - 1;
+              switch (yystate) {
+                  case 1:
+                      return $$[$0 - 1];
+                      break;
+                  case 2:
+                      this.$ = yy.prepareProgram($$[$0]);
+                      break;
+                  case 3:
+                      this.$ = $$[$0];
+                      break;
+                  case 4:
+                      this.$ = $$[$0];
+                      break;
+                  case 5:
+                      this.$ = $$[$0];
+                      break;
+                  case 6:
+                      this.$ = $$[$0];
+                      break;
+                  case 7:
+                      this.$ = $$[$0];
+                      break;
+                  case 8:
+                      this.$ = $$[$0];
+                      break;
+                  case 9:
+                      this.$ = {
+                          type: 'CommentStatement',
+                          value: yy.stripComment($$[$0]),
+                          strip: yy.stripFlags($$[$0], $$[$0]),
+                          loc: yy.locInfo(this._$)
+                      };
+
+                      break;
+                  case 10:
+                      this.$ = {
+                          type: 'ContentStatement',
+                          original: $$[$0],
+                          value: $$[$0],
+                          loc: yy.locInfo(this._$)
+                      };
+
+                      break;
+                  case 11:
+                      this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
+                      break;
+                  case 12:
+                      this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] };
+                      break;
+                  case 13:
+                      this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$);
+                      break;
+                  case 14:
+                      this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$);
+                      break;
+                  case 15:
+                      this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
+                      break;
+                  case 16:
+                      this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
+                      break;
+                  case 17:
+                      this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
+                      break;
+                  case 18:
+                      this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] };
+                      break;
+                  case 19:
+                      var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$),
+                          program = yy.prepareProgram([inverse], $$[$0 - 1].loc);
+                      program.chained = true;
+
+                      this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true };
+
+                      break;
+                  case 20:
+                      this.$ = $$[$0];
+                      break;
+                  case 21:
+                      this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) };
+                      break;
+                  case 22:
+                      this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
+                      break;
+                  case 23:
+                      this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
+                      break;
+                  case 24:
+                      this.$ = {
+                          type: 'PartialStatement',
+                          name: $$[$0 - 3],
+                          params: $$[$0 - 2],
+                          hash: $$[$0 - 1],
+                          indent: '',
+                          strip: yy.stripFlags($$[$0 - 4], $$[$0]),
+                          loc: yy.locInfo(this._$)
+                      };
+
+                      break;
+                  case 25:
+                      this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
+                      break;
+                  case 26:
+                      this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) };
+                      break;
+                  case 27:
+                      this.$ = $$[$0];
+                      break;
+                  case 28:
+                      this.$ = $$[$0];
+                      break;
+                  case 29:
+                      this.$ = {
+                          type: 'SubExpression',
+                          path: $$[$0 - 3],
+                          params: $$[$0 - 2],
+                          hash: $$[$0 - 1],
+                          loc: yy.locInfo(this._$)
+                      };
+
+                      break;
+                  case 30:
+                      this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) };
+                      break;
+                  case 31:
+                      this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) };
+                      break;
+                  case 32:
+                      this.$ = yy.id($$[$0 - 1]);
+                      break;
+                  case 33:
+                      this.$ = $$[$0];
+                      break;
+                  case 34:
+                      this.$ = $$[$0];
+                      break;
+                  case 35:
+                      this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) };
+                      break;
+                  case 36:
+                      this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) };
+                      break;
+                  case 37:
+                      this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) };
+                      break;
+                  case 38:
+                      this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) };
+                      break;
+                  case 39:
+                      this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) };
+                      break;
+                  case 40:
+                      this.$ = $$[$0];
+                      break;
+                  case 41:
+                      this.$ = $$[$0];
+                      break;
+                  case 42:
+                      this.$ = yy.preparePath(true, $$[$0], this._$);
+                      break;
+                  case 43:
+                      this.$ = yy.preparePath(false, $$[$0], this._$);
+                      break;
+                  case 44:
+                      $$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2];
+                      break;
+                  case 45:
+                      this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }];
+                      break;
+                  case 46:
+                      this.$ = [];
+                      break;
+                  case 47:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 48:
+                      this.$ = [];
+                      break;
+                  case 49:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 50:
+                      this.$ = [];
+                      break;
+                  case 51:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 58:
+                      this.$ = [];
+                      break;
+                  case 59:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 64:
+                      this.$ = [];
+                      break;
+                  case 65:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 70:
+                      this.$ = [];
+                      break;
+                  case 71:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 78:
+                      this.$ = [];
+                      break;
+                  case 79:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 82:
+                      this.$ = [];
+                      break;
+                  case 83:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 86:
+                      this.$ = [];
+                      break;
+                  case 87:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 90:
+                      this.$ = [];
+                      break;
+                  case 91:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 94:
+                      this.$ = [];
+                      break;
+                  case 95:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 98:
+                      this.$ = [$$[$0]];
+                      break;
+                  case 99:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+                  case 100:
+                      this.$ = [$$[$0]];
+                      break;
+                  case 101:
+                      $$[$0 - 1].push($$[$0]);
+                      break;
+              }
+          },
+          table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2 [...]
+          defaultActions: { 4: [2, 1], 54: [2, 55], 56: [2, 20], 60: [2, 57], 73: [2, 81], 82: [2, 85], 86: [2, 18], 90: [2, 89], 101: [2, 53], 104: [2, 93], 110: [2, 19], 111: [2, 77], 116: [2, 97], 119: [2, 63], 122: [2, 69], 135: [2, 75], 136: [2, 32] },
+          parseError: function parseError(str, hash) {
+              throw new Error(str);
+          },
+          parse: function parse(input) {
+              var self = this,
+                  stack = [0],
+                  vstack = [null],
+                  lstack = [],
+                  table = this.table,
+                  yytext = "",
+                  yylineno = 0,
+                  yyleng = 0,
+                  recovering = 0,
+                  TERROR = 2,
+                  EOF = 1;
+              this.lexer.setInput(input);
+              this.lexer.yy = this.yy;
+              this.yy.lexer = this.lexer;
+              this.yy.parser = this;
+              if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {};
+              var yyloc = this.lexer.yylloc;
+              lstack.push(yyloc);
+              var ranges = this.lexer.options && this.lexer.options.ranges;
+              if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError;
+              function popStack(n) {
+                  stack.length = stack.length - 2 * n;
+                  vstack.length = vstack.length - n;
+                  lstack.length = lstack.length - n;
+              }
+              function lex() {
+                  var token;
+                  token = self.lexer.lex() || 1;
+                  if (typeof token !== "number") {
+                      token = self.symbols_[token] || token;
+                  }
+                  return token;
+              }
+              var symbol,
+                  preErrorSymbol,
+                  state,
+                  action,
+                  a,
+                  r,
+                  yyval = {},
+                  p,
+                  len,
+                  newState,
+                  expected;
+              while (true) {
+                  state = stack[stack.length - 1];
+                  if (this.defaultActions[state]) {
+                      action = this.defaultActions[state];
+                  } else {
+                      if (symbol === null || typeof symbol == "undefined") {
+                          symbol = lex();
+                      }
+                      action = table[state] && table[state][symbol];
+                  }
+                  if (typeof action === "undefined" || !action.length || !action[0]) {
+                      var errStr = "";
+                      if (!recovering) {
+                          expected = [];
+                          for (p in table[state]) if (this.terminals_[p] && p > 2) {
+                              expected.push("'" + this.terminals_[p] + "'");
+                          }
+                          if (this.lexer.showPosition) {
+                              errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
+                          } else {
+                              errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
+                          }
+                          this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected });
+                      }
+                  }
+                  if (action[0] instanceof Array && action.length > 1) {
+                      throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
+                  }
+                  switch (action[0]) {
+                      case 1:
+                          stack.push(symbol);
+                          vstack.push(this.lexer.yytext);
+                          lstack.push(this.lexer.yylloc);
+                          stack.push(action[1]);
+                          symbol = null;
+                          if (!preErrorSymbol) {
+                              yyleng = this.lexer.yyleng;
+                              yytext = this.lexer.yytext;
+                              yylineno = this.lexer.yylineno;
+                              yyloc = this.lexer.yylloc;
+                              if (recovering > 0) recovering--;
+                          } else {
+                              symbol = preErrorSymbol;
+                              preErrorSymbol = null;
+                          }
+                          break;
+                      case 2:
+                          len = this.productions_[action[1]][1];
+                          yyval.$ = vstack[vstack.length - len];
+                          yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column };
+                          if (ranges) {
+                              yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
+                          }
+                          r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
+                          if (typeof r !== "undefined") {
+                              return r;
+                          }
+                          if (len) {
+                              stack = stack.slice(0, -1 * len * 2);
+                              vstack = vstack.slice(0, -1 * len);
+                              lstack = lstack.slice(0, -1 * len);
+                          }
+                          stack.push(this.productions_[action[1]][0]);
+                          vstack.push(yyval.$);
+                          lstack.push(yyval._$);
+                          newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
+                          stack.push(newState);
+                          break;
+                      case 3:
+                          return true;
+                  }
+              }
+              return true;
+          }
+      };
+      /* Jison generated lexer */
+      var lexer = (function () {
+          var lexer = { EOF: 1,
+              parseError: function parseError(str, hash) {
+                  if (this.yy.parser) {
+                      this.yy.parser.parseError(str, hash);
+                  } else {
+                      throw new Error(str);
+                  }
+              },
+              setInput: function setInput(input) {
+                  this._input = input;
+                  this._more = this._less = this.done = false;
+                  this.yylineno = this.yyleng = 0;
+                  this.yytext = this.matched = this.match = '';
+                  this.conditionStack = ['INITIAL'];
+                  this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 };
+                  if (this.options.ranges) this.yylloc.range = [0, 0];
+                  this.offset = 0;
+                  return this;
+              },
+              input: function input() {
+                  var ch = this._input[0];
+                  this.yytext += ch;
+                  this.yyleng++;
+                  this.offset++;
+                  this.match += ch;
+                  this.matched += ch;
+                  var lines = ch.match(/(?:\r\n?|\n).*/g);
+                  if (lines) {
+                      this.yylineno++;
+                      this.yylloc.last_line++;
+                  } else {
+                      this.yylloc.last_column++;
+                  }
+                  if (this.options.ranges) this.yylloc.range[1]++;
+
+                  this._input = this._input.slice(1);
+                  return ch;
+              },
+              unput: function unput(ch) {
+                  var len = ch.length;
+                  var lines = ch.split(/(?:\r\n?|\n)/g);
+
+                  this._input = ch + this._input;
+                  this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
+                  //this.yyleng -= len;
+                  this.offset -= len;
+                  var oldLines = this.match.split(/(?:\r\n?|\n)/g);
+                  this.match = this.match.substr(0, this.match.length - 1);
+                  this.matched = this.matched.substr(0, this.matched.length - 1);
+
+                  if (lines.length - 1) this.yylineno -= lines.length - 1;
+                  var r = this.yylloc.range;
+
+                  this.yylloc = { first_line: this.yylloc.first_line,
+                      last_line: this.yylineno + 1,
+                      first_column: this.yylloc.first_column,
+                      last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
+                  };
+
+                  if (this.options.ranges) {
+                      this.yylloc.range = [r[0], r[0] + this.yyleng - len];
+                  }
+                  return this;
+              },
+              more: function more() {
+                  this._more = true;
+                  return this;
+              },
+              less: function less(n) {
+                  this.unput(this.match.slice(n));
+              },
+              pastInput: function pastInput() {
+                  var past = this.matched.substr(0, this.matched.length - this.match.length);
+                  return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
+              },
+              upcomingInput: function upcomingInput() {
+                  var next = this.match;
+                  if (next.length < 20) {
+                      next += this._input.substr(0, 20 - next.length);
+                  }
+                  return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
+              },
+              showPosition: function showPosition() {
+                  var pre = this.pastInput();
+                  var c = new Array(pre.length + 1).join("-");
+                  return pre + this.upcomingInput() + "\n" + c + "^";
+              },
+              next: function next() {
+                  if (this.done) {
+                      return this.EOF;
+                  }
+                  if (!this._input) this.done = true;
+
+                  var token, match, tempMatch, index, col, lines;
+                  if (!this._more) {
+                      this.yytext = '';
+                      this.match = '';
+                  }
+                  var rules = this._currentRules();
+                  for (var i = 0; i < rules.length; i++) {
+                      tempMatch = this._input.match(this.rules[rules[i]]);
+                      if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
+                          match = tempMatch;
+                          index = i;
+                          if (!this.options.flex) break;
+                      }
+                  }
+                  if (match) {
+                      lines = match[0].match(/(?:\r\n?|\n).*/g);
+                      if (lines) this.yylineno += lines.length;
+                      this.yylloc = { first_line: this.yylloc.last_line,
+                          last_line: this.yylineno + 1,
+                          first_column: this.yylloc.last_column,
+                          last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length };
+                      this.yytext += match[0];
+                      this.match += match[0];
+                      this.matches = match;
+                      this.yyleng = this.yytext.length;
+                      if (this.options.ranges) {
+                          this.yylloc.range = [this.offset, this.offset += this.yyleng];
+                      }
+                      this._more = false;
+                      this._input = this._input.slice(match[0].length);
+                      this.matched += match[0];
+                      token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]);
+                      if (this.done && this._input) this.done = false;
+                      if (token) return token;else return;
+                  }
+                  if (this._input === "") {
+                      return this.EOF;
+                  } else {
+                      return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno });
+                  }
+              },
+              lex: function lex() {
+                  var r = this.next();
+                  if (typeof r !== 'undefined') {
+                      return r;
+                  } else {
+                      return this.lex();
+                  }
+              },
+              begin: function begin(condition) {
+                  this.conditionStack.push(condition);
+              },
+              popState: function popState() {
+                  return this.conditionStack.pop();
+              },
+              _currentRules: function _currentRules() {
+                  return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
+              },
+              topState: function topState() {
+                  return this.conditionStack[this.conditionStack.length - 2];
+              },
+              pushState: function begin(condition) {
+                  this.begin(condition);
+              } };
+          lexer.options = {};
+          lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
+
+              function strip(start, end) {
+                  return yy_.yytext = yy_.yytext.substring(start, yy_.yyleng - end + start);
+              }
+
+              var YYSTATE = YY_START;
+              switch ($avoiding_name_collisions) {
+                  case 0:
+                      if (yy_.yytext.slice(-2) === "\\\\") {
+                          strip(0, 1);
+                          this.begin("mu");
+                      } else if (yy_.yytext.slice(-1) === "\\") {
+                          strip(0, 1);
+                          this.begin("emu");
+                      } else {
+                          this.begin("mu");
+                      }
+                      if (yy_.yytext) return 15;
+
+                      break;
+                  case 1:
+                      return 15;
+                      break;
+                  case 2:
+                      this.popState();
+                      return 15;
+
+                      break;
+                  case 3:
+                      this.begin('raw');return 15;
+                      break;
+                  case 4:
+                      this.popState();
+                      // Should be using `this.topState()` below, but it currently
+                      // returns the second top instead of the first top. Opened an
+                      // issue about it at https://github.com/zaach/jison/issues/291
+                      if (this.conditionStack[this.conditionStack.length - 1] === 'raw') {
+                          return 15;
+                      } else {
+                          strip(5, 9);
+                          return 'END_RAW_BLOCK';
+                      }
+
+                      break;
+                  case 5:
+                      return 15;
+                      break;
+                  case 6:
+                      this.popState();
+                      return 14;
+
+                      break;
+                  case 7:
+                      return 65;
+                      break;
+                  case 8:
+                      return 68;
+                      break;
+                  case 9:
+                      return 19;
+                      break;
+                  case 10:
+                      this.popState();
+                      this.begin('raw');
+                      return 23;
+
+                      break;
+                  case 11:
+                      return 55;
+                      break;
+                  case 12:
+                      return 60;
+                      break;
+                  case 13:
+                      return 29;
+                      break;
+                  case 14:
+                      return 47;
+                      break;
+                  case 15:
+                      this.popState();return 44;
+                      break;
+                  case 16:
+                      this.popState();return 44;
+                      break;
+                  case 17:
+                      return 34;
+                      break;
+                  case 18:
+                      return 39;
+                      break;
+                  case 19:
+                      return 51;
+                      break;
+                  case 20:
+                      return 48;
+                      break;
+                  case 21:
+                      this.unput(yy_.yytext);
+                      this.popState();
+                      this.begin('com');
+
+                      break;
+                  case 22:
+                      this.popState();
+                      return 14;
+
+                      break;
+                  case 23:
+                      return 48;
+                      break;
+                  case 24:
+                      return 73;
+                      break;
+                  case 25:
+                      return 72;
+                      break;
+                  case 26:
+                      return 72;
+                      break;
+                  case 27:
+                      return 87;
+                      break;
+                  case 28:
+                      // ignore whitespace
+                      break;
+                  case 29:
+                      this.popState();return 54;
+                      break;
+                  case 30:
+                      this.popState();return 33;
+                      break;
+                  case 31:
+                      yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80;
+                      break;
+                  case 32:
+                      yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80;
+                      break;
+                  case 33:
+                      return 85;
+                      break;
+                  case 34:
+                      return 82;
+                      break;
+                  case 35:
+                      return 82;
+                      break;
+                  case 36:
+                      return 83;
+                      break;
+                  case 37:
+                      return 84;
+                      break;
+                  case 38:
+                      return 81;
+                      break;
+                  case 39:
+                      return 75;
+                      break;
+                  case 40:
+                      return 77;
+                      break;
+                  case 41:
+                      return 72;
+                      break;
+                  case 42:
+                      yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72;
+                      break;
+                  case 43:
+                      return 'INVALID';
+                      break;
+                  case 44:
+                      return 5;
+                      break;
+              }
+          };
+          lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^\/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]+?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, / [...]
+          lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } };
+          return lexer;
+      })();
+      parser.lexer = lexer;
+      function Parser() {
+          this.yy = {};
+      }Parser.prototype = parser;parser.Parser = Parser;
+      return new Parser();
+  })();exports["default"] = handlebars;
+  module.exports = exports["default"];
+
+/***/ }),
+/* 48 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+
+  var _visitor = __webpack_require__(49);
+
+  var _visitor2 = _interopRequireDefault(_visitor);
+
+  function WhitespaceControl() {
+    var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
+
+    this.options = options;
+  }
+  WhitespaceControl.prototype = new _visitor2['default']();
+
+  WhitespaceControl.prototype.Program = function (program) {
+    var doStandalone = !this.options.ignoreStandalone;
+
+    var isRoot = !this.isRootSeen;
+    this.isRootSeen = true;
+
+    var body = program.body;
+    for (var i = 0, l = body.length; i < l; i++) {
+      var current = body[i],
+          strip = this.accept(current);
+
+      if (!strip) {
+        continue;
+      }
+
+      var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot),
+          _isNextWhitespace = isNextWhitespace(body, i, isRoot),
+          openStandalone = strip.openStandalone && _isPrevWhitespace,
+          closeStandalone = strip.closeStandalone && _isNextWhitespace,
+          inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace;
+
+      if (strip.close) {
+        omitRight(body, i, true);
+      }
+      if (strip.open) {
+        omitLeft(body, i, true);
+      }
+
+      if (doStandalone && inlineStandalone) {
+        omitRight(body, i);
+
+        if (omitLeft(body, i)) {
+          // If we are on a standalone node, save the indent info for partials
+          if (current.type === 'PartialStatement') {
+            // Pull out the whitespace from the final line
+            current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1];
+          }
+        }
+      }
+      if (doStandalone && openStandalone) {
+        omitRight((current.program || current.inverse).body);
+
+        // Strip out the previous content node if it's whitespace only
+        omitLeft(body, i);
+      }
+      if (doStandalone && closeStandalone) {
+        // Always strip the next node
+        omitRight(body, i);
+
+        omitLeft((current.inverse || current.program).body);
+      }
+    }
+
+    return program;
   };
-  __exports__.createFrame = createFrame;
-  return __exports__;
-})(__module3__, __module5__);
 
-// handlebars/runtime.js
-var __module6__ = (function(__dependency1__, __dependency2__, __dependency3__) {
-  "use strict";
-  var __exports__ = {};
-  var Utils = __dependency1__;
-  var Exception = __dependency2__;
-  var COMPILER_REVISION = __dependency3__.COMPILER_REVISION;
-  var REVISION_CHANGES = __dependency3__.REVISION_CHANGES;
+  WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) {
+    this.accept(block.program);
+    this.accept(block.inverse);
 
-  function checkRevision(compilerInfo) {
-    var compilerRevision = compilerInfo && compilerInfo[0] || 1,
-        currentRevision = COMPILER_REVISION;
-
-    if (compilerRevision !== currentRevision) {
-      if (compilerRevision < currentRevision) {
-        var runtimeVersions = REVISION_CHANGES[currentRevision],
-            compilerVersions = REVISION_CHANGES[compilerRevision];
-        throw new Exception("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 new Exception("Template was precompiled with a newer version of Handlebars than the current runtime. "+
-              "Please update your runtime to a newer version ("+compilerInfo[1]+").");
-      }
-    }
-  }
+    // Find the inverse program that is involed with whitespace stripping.
+    var program = block.program || block.inverse,
+        inverse = block.program && block.inverse,
+        firstInverse = inverse,
+        lastInverse = inverse;
 
-  __exports__.checkRevision = checkRevision;// TODO: Remove this line and break up compilePartial
+    if (inverse && inverse.chained) {
+      firstInverse = inverse.body[0].program;
 
-  function template(templateSpec, env) {
-    if (!env) {
-      throw new Exception("No environment passed to template");
+      // Walk the inverse chain to find the last inverse that is actually in the chain.
+      while (lastInverse.chained) {
+        lastInverse = lastInverse.body[lastInverse.body.length - 1].program;
+      }
     }
 
-    // Note: Using env.VM references rather than local var references throughout this section to allow
-    // for external users to override these as psuedo-supported APIs.
-    var invokePartialWrapper = function(partial, name, context, helpers, partials, data) {
-      var result = env.VM.invokePartial.apply(this, arguments);
-      if (result != null) { return result; }
-
-      if (env.compile) {
-        var options = { helpers: helpers, partials: partials, data: data };
-        partials[name] = env.compile(partial, { data: data !== undefined }, env);
-        return partials[name](context, options);
-      } else {
-        throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
-      }
+    var strip = {
+      open: block.openStrip.open,
+      close: block.closeStrip.close,
+
+      // Determine the standalone candiacy. Basically flag our content as being possibly standalone
+      // so our parent can determine if we actually are standalone
+      openStandalone: isNextWhitespace(program.body),
+      closeStandalone: isPrevWhitespace((firstInverse || program).body)
     };
 
-    // Just add water
-    var container = {
-      escapeExpression: Utils.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);
-        }
-        return programWrapper;
-      },
-      merge: function(param, common) {
-        var ret = param || common;
+    if (block.openStrip.close) {
+      omitRight(program.body, null, true);
+    }
 
-        if (param && common && (param !== common)) {
-          ret = {};
-          Utils.extend(ret, common);
-          Utils.extend(ret, param);
-        }
-        return ret;
-      },
-      programWithDepth: env.VM.programWithDepth,
-      noop: env.VM.noop,
-      compilerInfo: null
-    };
+    if (inverse) {
+      var inverseStrip = block.inverseStrip;
 
-    return function(context, options) {
-      options = options || {};
-      var namespace = options.partial ? options : env,
-          helpers,
-          partials;
+      if (inverseStrip.open) {
+        omitLeft(program.body, null, true);
+      }
 
-      if (!options.partial) {
-        helpers = options.helpers;
-        partials = options.partials;
+      if (inverseStrip.close) {
+        omitRight(firstInverse.body, null, true);
+      }
+      if (block.closeStrip.open) {
+        omitLeft(lastInverse.body, null, true);
       }
-      var result = templateSpec.call(
-            container,
-            namespace, context,
-            helpers,
-            partials,
-            options.data);
 
-      if (!options.partial) {
-        env.VM.checkRevision(container.compilerInfo);
+      // Find standalone else statments
+      if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) {
+        omitLeft(program.body);
+        omitRight(firstInverse.body);
       }
+    } else if (block.closeStrip.open) {
+      omitLeft(program.body, null, true);
+    }
 
-      return result;
+    return strip;
+  };
+
+  WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) {
+    return mustache.strip;
+  };
+
+  WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) {
+    /* istanbul ignore next */
+    var strip = node.strip || {};
+    return {
+      inlineStandalone: true,
+      open: strip.open,
+      close: strip.close
     };
-  }
+  };
 
-  __exports__.template = template;function programWithDepth(i, fn, data /*, $depth */) {
-    var args = Array.prototype.slice.call(arguments, 3);
+  function isPrevWhitespace(body, i, isRoot) {
+    if (i === undefined) {
+      i = body.length;
+    }
 
-    var prog = function(context, options) {
-      options = options || {};
+    // Nodes that end with newlines are considered whitespace (but are special
+    // cased for strip operations)
+    var prev = body[i - 1],
+        sibling = body[i - 2];
+    if (!prev) {
+      return isRoot;
+    }
 
-      return fn.apply(this, [context, options.data || data].concat(args));
-    };
-    prog.program = i;
-    prog.depth = args.length;
-    return prog;
+    if (prev.type === 'ContentStatement') {
+      return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original);
+    }
   }
+  function isNextWhitespace(body, i, isRoot) {
+    if (i === undefined) {
+      i = -1;
+    }
 
-  __exports__.programWithDepth = programWithDepth;function program(i, fn, data) {
-    var prog = function(context, options) {
-      options = options || {};
+    var next = body[i + 1],
+        sibling = body[i + 2];
+    if (!next) {
+      return isRoot;
+    }
 
-      return fn(context, options.data || data);
-    };
-    prog.program = i;
-    prog.depth = 0;
-    return prog;
+    if (next.type === 'ContentStatement') {
+      return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original);
+    }
   }
 
-  __exports__.program = program;function invokePartial(partial, name, context, helpers, partials, data) {
-    var options = { partial: true, helpers: helpers, partials: partials, data: data };
+  // Marks the node to the right of the position as omitted.
+  // I.e. {{foo}}' ' will mark the ' ' node as omitted.
+  //
+  // If i is undefined, then the first child will be marked as such.
+  //
+  // If mulitple is truthy then all whitespace will be stripped out until non-whitespace
+  // content is met.
+  function omitRight(body, i, multiple) {
+    var current = body[i == null ? 0 : i + 1];
+    if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) {
+      return;
+    }
 
-    if(partial === undefined) {
-      throw new Exception("The partial " + name + " could not be found");
-    } else if(partial instanceof Function) {
-      return partial(context, options);
+    var original = current.value;
+    current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, '');
+    current.rightStripped = current.value !== original;
+  }
+
+  // Marks the node to the left of the position as omitted.
+  // I.e. ' '{{foo}} will mark the ' ' node as omitted.
+  //
+  // If i is undefined then the last child will be marked as such.
+  //
+  // If mulitple is truthy then all whitespace will be stripped out until non-whitespace
+  // content is met.
+  function omitLeft(body, i, multiple) {
+    var current = body[i == null ? body.length - 1 : i - 1];
+    if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) {
+      return;
     }
+
+    // We omit the last node if it's whitespace only and not preceded by a non-content node.
+    var original = current.value;
+    current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, '');
+    current.leftStripped = current.value !== original;
+    return current.leftStripped;
   }
 
-  __exports__.invokePartial = invokePartial;function noop() { return ""; }
+  exports['default'] = WhitespaceControl;
+  module.exports = exports['default'];
 
-  __exports__.noop = noop;
-  return __exports__;
-})(__module3__, __module5__, __module2__);
+/***/ }),
+/* 49 */
+/***/ (function(module, exports, __webpack_require__) {
 
-// handlebars.runtime.js
-var __module1__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
-  "use strict";
-  var __exports__;
-  /*globals Handlebars: true */
-  var base = __dependency1__;
+  'use strict';
 
-  // Each of these augment the Handlebars object. No need to setup here.
-  // (This is done to easily share code between commonjs and browse envs)
-  var SafeString = __dependency2__;
-  var Exception = __dependency3__;
-  var Utils = __dependency4__;
-  var runtime = __dependency5__;
+  var _interopRequireDefault = __webpack_require__(1)['default'];
 
-  // For compatibility and usage outside of module systems, make the Handlebars object a namespace
-  var create = function() {
-    var hb = new base.HandlebarsEnvironment();
+  exports.__esModule = true;
 
-    Utils.extend(hb, base);
-    hb.SafeString = SafeString;
-    hb.Exception = Exception;
-    hb.Utils = Utils;
+  var _exception = __webpack_require__(6);
 
-    hb.VM = runtime;
-    hb.template = function(spec) {
-      return runtime.template(spec, hb);
-    };
+  var _exception2 = _interopRequireDefault(_exception);
 
-    return hb;
-  };
+  function Visitor() {
+    this.parents = [];
+  }
 
-  var Handlebars = create();
-  Handlebars.create = create;
+  Visitor.prototype = {
+    constructor: Visitor,
+    mutating: false,
+
+    // Visits a given value. If mutating, will replace the value if necessary.
+    acceptKey: function acceptKey(node, name) {
+      var value = this.accept(node[name]);
+      if (this.mutating) {
+        // Hacky sanity check: This may have a few false positives for type for the helper
+        // methods but will generally do the right thing without a lot of overhead.
+        if (value && !Visitor.prototype[value.type]) {
+          throw new _exception2['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
+        }
+        node[name] = value;
+      }
+    },
 
-  __exports__ = Handlebars;
-  return __exports__;
-})(__module2__, __module4__, __module5__, __module3__, __module6__);
+    // Performs an accept operation with added sanity check to ensure
+    // required keys are not removed.
+    acceptRequired: function acceptRequired(node, name) {
+      this.acceptKey(node, name);
 
-// handlebars/compiler/ast.js
-var __module7__ = (function(__dependency1__) {
-  "use strict";
-  var __exports__;
-  var Exception = __dependency1__;
+      if (!node[name]) {
+        throw new _exception2['default'](node.type + ' requires ' + name);
+      }
+    },
 
-  function LocationInfo(locInfo){
-    locInfo = locInfo || {};
-    this.firstLine   = locInfo.first_line;
-    this.firstColumn = locInfo.first_column;
-    this.lastColumn  = locInfo.last_column;
-    this.lastLine    = locInfo.last_line;
-  }
+    // Traverses a given array. If mutating, empty respnses will be removed
+    // for child elements.
+    acceptArray: function acceptArray(array) {
+      for (var i = 0, l = array.length; i < l; i++) {
+        this.acceptKey(array, i);
 
-  var AST = {
-    ProgramNode: function(statements, inverseStrip, inverse, locInfo) {
-      var inverseLocationInfo, firstInverseNode;
-      if (arguments.length === 3) {
-        locInfo = inverse;
-        inverse = null;
-      } else if (arguments.length === 2) {
-        locInfo = inverseStrip;
-        inverseStrip = null;
-      }
-
-      LocationInfo.call(this, locInfo);
-      this.type = "program";
-      this.statements = statements;
-      this.strip = {};
-
-      if(inverse) {
-        firstInverseNode = inverse[0];
-        if (firstInverseNode) {
-          inverseLocationInfo = {
-            first_line: firstInverseNode.firstLine,
-            last_line: firstInverseNode.lastLine,
-            last_column: firstInverseNode.lastColumn,
-            first_column: firstInverseNode.firstColumn
-          };
-          this.inverse = new AST.ProgramNode(inverse, inverseStrip, inverseLocationInfo);
-        } else {
-          this.inverse = new AST.ProgramNode(inverse, inverseStrip);
+        if (!array[i]) {
+          array.splice(i, 1);
+          i--;
+          l--;
         }
-        this.strip.right = inverseStrip.left;
-      } else if (inverseStrip) {
-        this.strip.left = inverseStrip.right;
       }
     },
 
-    MustacheNode: function(rawParams, hash, open, strip, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type = "mustache";
-      this.strip = strip;
+    accept: function accept(object) {
+      if (!object) {
+        return;
+      }
 
-      // Open may be a string parsed from the parser or a passed boolean flag
-      if (open != null && open.charAt) {
-        // Must use charAt to support IE pre-10
-        var escapeFlag = open.charAt(3) || open.charAt(2);
-        this.escaped = escapeFlag !== '{' && escapeFlag !== '&';
-      } else {
-        this.escaped = !!open;
+      /* istanbul ignore next: Sanity code */
+      if (!this[object.type]) {
+        throw new _exception2['default']('Unknown type: ' + object.type, object);
       }
 
-      if (rawParams instanceof AST.SexprNode) {
-        this.sexpr = rawParams;
-      } else {
-        // Support old AST API
-        this.sexpr = new AST.SexprNode(rawParams, hash);
+      if (this.current) {
+        this.parents.unshift(this.current);
       }
+      this.current = object;
 
-      this.sexpr.isRoot = true;
+      var ret = this[object.type](object);
 
-      // Support old AST API that stored this info in MustacheNode
-      this.id = this.sexpr.id;
-      this.params = this.sexpr.params;
-      this.hash = this.sexpr.hash;
-      this.eligibleHelper = this.sexpr.eligibleHelper;
-      this.isHelper = this.sexpr.isHelper;
-    },
+      this.current = this.parents.shift();
 
-    SexprNode: function(rawParams, hash, locInfo) {
-      LocationInfo.call(this, locInfo);
+      if (!this.mutating || ret) {
+        return ret;
+      } else if (ret !== false) {
+        return object;
+      }
+    },
 
-      this.type = "sexpr";
-      this.hash = hash;
+    Program: function Program(program) {
+      this.acceptArray(program.body);
+    },
 
-      var id = this.id = rawParams[0];
-      var params = this.params = rawParams.slice(1);
+    MustacheStatement: visitSubExpression,
+    Decorator: visitSubExpression,
 
-      // a mustache is an eligible helper if:
-      // * its id is simple (a single part, not `this` or `..`)
-      var eligibleHelper = this.eligibleHelper = id.isSimple;
+    BlockStatement: visitBlock,
+    DecoratorBlock: visitBlock,
 
-      // a mustache is definitely a helper if:
-      // * it is an eligible helper, and
-      // * it has at least one parameter or hash segment
-      this.isHelper = eligibleHelper && (params.length || hash);
+    PartialStatement: visitPartial,
+    PartialBlockStatement: function PartialBlockStatement(partial) {
+      visitPartial.call(this, partial);
 
-      // 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.
+      this.acceptKey(partial, 'program');
     },
 
-    PartialNode: function(partialName, context, strip, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type         = "partial";
-      this.partialName  = partialName;
-      this.context      = context;
-      this.strip = strip;
+    ContentStatement: function ContentStatement() /* content */{},
+    CommentStatement: function CommentStatement() /* comment */{},
+
+    SubExpression: visitSubExpression,
+
+    PathExpression: function PathExpression() /* path */{},
+
+    StringLiteral: function StringLiteral() /* string */{},
+    NumberLiteral: function NumberLiteral() /* number */{},
+    BooleanLiteral: function BooleanLiteral() /* bool */{},
+    UndefinedLiteral: function UndefinedLiteral() /* literal */{},
+    NullLiteral: function NullLiteral() /* literal */{},
+
+    Hash: function Hash(hash) {
+      this.acceptArray(hash.pairs);
     },
+    HashPair: function HashPair(pair) {
+      this.acceptRequired(pair, 'value');
+    }
+  };
 
-    BlockNode: function(mustache, program, inverse, close, locInfo) {
-      LocationInfo.call(this, locInfo);
+  function visitSubExpression(mustache) {
+    this.acceptRequired(mustache, 'path');
+    this.acceptArray(mustache.params);
+    this.acceptKey(mustache, 'hash');
+  }
+  function visitBlock(block) {
+    visitSubExpression.call(this, block);
 
-      if(mustache.sexpr.id.original !== close.path.original) {
-        throw new Exception(mustache.sexpr.id.original + " doesn't match " + close.path.original, this);
-      }
+    this.acceptKey(block, 'program');
+    this.acceptKey(block, 'inverse');
+  }
+  function visitPartial(partial) {
+    this.acceptRequired(partial, 'name');
+    this.acceptArray(partial.params);
+    this.acceptKey(partial, 'hash');
+  }
 
-      this.type = 'block';
-      this.mustache = mustache;
-      this.program  = program;
-      this.inverse  = inverse;
+  exports['default'] = Visitor;
+  module.exports = exports['default'];
 
-      this.strip = {
-        left: mustache.strip.left,
-        right: close.strip.right
-      };
+/***/ }),
+/* 50 */
+/***/ (function(module, exports, __webpack_require__) {
 
-      (program || inverse).strip.left = mustache.strip.right;
-      (inverse || program).strip.right = close.strip.left;
+  'use strict';
 
-      if (inverse && !program) {
-        this.isInverse = true;
-      }
-    },
+  var _interopRequireDefault = __webpack_require__(1)['default'];
 
-    ContentNode: function(string, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type = "content";
-      this.string = string;
-    },
+  exports.__esModule = true;
+  exports.SourceLocation = SourceLocation;
+  exports.id = id;
+  exports.stripFlags = stripFlags;
+  exports.stripComment = stripComment;
+  exports.preparePath = preparePath;
+  exports.prepareMustache = prepareMustache;
+  exports.prepareRawBlock = prepareRawBlock;
+  exports.prepareBlock = prepareBlock;
+  exports.prepareProgram = prepareProgram;
+  exports.preparePartialBlock = preparePartialBlock;
 
-    HashNode: function(pairs, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type = "hash";
-      this.pairs = pairs;
-    },
+  var _exception = __webpack_require__(6);
 
-    IdNode: function(parts, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type = "ID";
+  var _exception2 = _interopRequireDefault(_exception);
 
-      var original = "",
-          dig = [],
-          depth = 0;
+  function validateClose(open, close) {
+    close = close.path ? close.path.original : close;
 
-      for(var i=0,l=parts.length; i<l; i++) {
-        var part = parts[i].part;
-        original += (parts[i].separator || '') + part;
+    if (open.path.original !== close) {
+      var errorNode = { loc: open.path.loc };
 
-        if (part === ".." || part === "." || part === "this") {
-          if (dig.length > 0) {
-            throw new Exception("Invalid path: " + original, this);
-          } else if (part === "..") {
-            depth++;
-          } else {
-            this.isScoped = true;
-          }
-        } else {
-          dig.push(part);
+      throw new _exception2['default'](open.path.original + " doesn't match " + close, errorNode);
+    }
+  }
+
+  function SourceLocation(source, locInfo) {
+    this.source = source;
+    this.start = {
+      line: locInfo.first_line,
+      column: locInfo.first_column
+    };
+    this.end = {
+      line: locInfo.last_line,
+      column: locInfo.last_column
+    };
+  }
+
+  function id(token) {
+    if (/^\[.*\]$/.test(token)) {
+      return token.substring(1, token.length - 1);
+    } else {
+      return token;
+    }
+  }
+
+  function stripFlags(open, close) {
+    return {
+      open: open.charAt(2) === '~',
+      close: close.charAt(close.length - 3) === '~'
+    };
+  }
+
+  function stripComment(comment) {
+    return comment.replace(/^\{\{~?!-?-?/, '').replace(/-?-?~?\}\}$/, '');
+  }
+
+  function preparePath(data, parts, loc) {
+    loc = this.locInfo(loc);
+
+    var original = data ? '@' : '',
+        dig = [],
+        depth = 0;
+
+    for (var i = 0, l = parts.length; i < l; i++) {
+      var part = parts[i].part,
+
+      // If we have [] syntax then we do not treat path references as operators,
+      // i.e. foo.[this] resolves to approximately context.foo['this']
+      isLiteral = parts[i].original !== part;
+      original += (parts[i].separator || '') + part;
+
+      if (!isLiteral && (part === '..' || part === '.' || part === 'this')) {
+        if (dig.length > 0) {
+          throw new _exception2['default']('Invalid path: ' + original, { loc: loc });
+        } else if (part === '..') {
+          depth++;
         }
+      } else {
+        dig.push(part);
       }
+    }
 
-      this.original = original;
-      this.parts    = dig;
-      this.string   = dig.join('.');
-      this.depth    = depth;
+    return {
+      type: 'PathExpression',
+      data: data,
+      depth: depth,
+      parts: dig,
+      original: original,
+      loc: loc
+    };
+  }
 
-      // an ID is simple if it only has one part, and that part is not
-      // `..` or `this`.
-      this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
+  function prepareMustache(path, params, hash, open, strip, locInfo) {
+    // Must use charAt to support IE pre-10
+    var escapeFlag = open.charAt(3) || open.charAt(2),
+        escaped = escapeFlag !== '{' && escapeFlag !== '&';
 
-      this.stringModeValue = this.string;
-    },
+    var decorator = /\*/.test(open);
+    return {
+      type: decorator ? 'Decorator' : 'MustacheStatement',
+      path: path,
+      params: params,
+      hash: hash,
+      escaped: escaped,
+      strip: strip,
+      loc: this.locInfo(locInfo)
+    };
+  }
 
-    PartialNameNode: function(name, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type = "PARTIAL_NAME";
-      this.name = name.original;
-    },
+  function prepareRawBlock(openRawBlock, contents, close, locInfo) {
+    validateClose(openRawBlock, close);
 
-    DataNode: function(id, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type = "DATA";
-      this.id = id;
-    },
+    locInfo = this.locInfo(locInfo);
+    var program = {
+      type: 'Program',
+      body: contents,
+      strip: {},
+      loc: locInfo
+    };
 
-    StringNode: function(string, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type = "STRING";
-      this.original =
-        this.string =
-        this.stringModeValue = string;
-    },
+    return {
+      type: 'BlockStatement',
+      path: openRawBlock.path,
+      params: openRawBlock.params,
+      hash: openRawBlock.hash,
+      program: program,
+      openStrip: {},
+      inverseStrip: {},
+      closeStrip: {},
+      loc: locInfo
+    };
+  }
 
-    IntegerNode: function(integer, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type = "INTEGER";
-      this.original =
-        this.integer = integer;
-      this.stringModeValue = Number(integer);
-    },
+  function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
+    if (close && close.path) {
+      validateClose(openBlock, close);
+    }
 
-    BooleanNode: function(bool, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type = "BOOLEAN";
-      this.bool = bool;
-      this.stringModeValue = bool === "true";
-    },
+    var decorator = /\*/.test(openBlock.open);
 
-    CommentNode: function(comment, locInfo) {
-      LocationInfo.call(this, locInfo);
-      this.type = "comment";
-      this.comment = comment;
-    }
-  };
+    program.blockParams = openBlock.blockParams;
 
-  // Must be exported as an object rather than the root of the module as the jison lexer
-  // most modify the object to operate properly.
-  __exports__ = AST;
-  return __exports__;
-})(__module5__);
+    var inverse = undefined,
+        inverseStrip = undefined;
 
-// handlebars/compiler/parser.js
-var __module9__ = (function() {
-  "use strict";
-  var __exports__;
-  /* jshint ignore:start */
-  /* Jison generated parser */
-  var handlebars = (function(){
-  var parser = {trace: function trace() { },
-  yy: {},
-  symbols_: {"error":2,"root":3,"statements":4,"EOF":5,"program":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"sexpr":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"CLOSE_UNESCAPED":24,"OPEN_PARTIAL":25,"partialName":26,"partial_option0":27,"sexpr_repetition0":28,"sexpr_option0":29,"dataName":30,"param":31,"STRING":32,"INTEGER":33,"BOOLEAN" [...]
-  terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"CLOSE_UNESCAPED",25:"OPEN_PARTIAL",32:"STRING",33:"INTEGER",34:"BOOLEAN",35:"OPEN_SEXPR",36:"CLOSE_SEXPR",40:"ID",41:"EQUALS",42:"DATA",44:"SEP"},
-  productions_: [0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,4],[7,2],[17,3],[17,1],[31,1],[31,1],[31,1],[31,1],[31,1],[31,3],[37,1],[39,3],[26,1],[26,1],[26,1],[30,2],[21,1],[43,3],[43,1],[27,0],[27,1],[28,0],[28,2],[29,0],[29,1],[38,1],[38,2]],
-  performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
-
-  var $0 = $$.length - 1;
-  switch (yystate) {
-  case 1: return new yy.ProgramNode($$[$0-1], this._$);
-  break;
-  case 2: return new yy.ProgramNode([], this._$);
-  break;
-  case 3:this.$ = new yy.ProgramNode([], $$[$0-1], $$[$0], this._$);
-  break;
-  case 4:this.$ = new yy.ProgramNode($$[$0-2], $$[$0-1], $$[$0], this._$);
-  break;
-  case 5:this.$ = new yy.ProgramNode($$[$0-1], $$[$0], [], this._$);
-  break;
-  case 6:this.$ = new yy.ProgramNode($$[$0], this._$);
-  break;
-  case 7:this.$ = new yy.ProgramNode([], this._$);
-  break;
-  case 8:this.$ = new yy.ProgramNode([], this._$);
-  break;
-  case 9:this.$ = [$$[$0]];
-  break;
-  case 10: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
-  break;
-  case 11:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0], this._$);
-  break;
-  case 12:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0], this._$);
-  break;
-  case 13:this.$ = $$[$0];
-  break;
-  case 14:this.$ = $$[$0];
-  break;
-  case 15:this.$ = new yy.ContentNode($$[$0], this._$);
-  break;
-  case 16:this.$ = new yy.CommentNode($$[$0], this._$);
-  break;
-  case 17:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
-  break;
-  case 18:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
-  break;
-  case 19:this.$ = {path: $$[$0-1], strip: stripFlags($$[$0-2], $$[$0])};
-  break;
-  case 20:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
-  break;
-  case 21:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
-  break;
-  case 22:this.$ = new yy.PartialNode($$[$0-2], $$[$0-1], stripFlags($$[$0-3], $$[$0]), this._$);
-  break;
-  case 23:this.$ = stripFlags($$[$0-1], $$[$0]);
-  break;
-  case 24:this.$ = new yy.SexprNode([$$[$0-2]].concat($$[$0-1]), $$[$0], this._$);
-  break;
-  case 25:this.$ = new yy.SexprNode([$$[$0]], null, this._$);
-  break;
-  case 26:this.$ = $$[$0];
-  break;
-  case 27:this.$ = new yy.StringNode($$[$0], this._$);
-  break;
-  case 28:this.$ = new yy.IntegerNode($$[$0], this._$);
-  break;
-  case 29:this.$ = new yy.BooleanNode($$[$0], this._$);
-  break;
-  case 30:this.$ = $$[$0];
-  break;
-  case 31:$$[$0-1].isHelper = true; this.$ = $$[$0-1];
-  break;
-  case 32:this.$ = new yy.HashNode($$[$0], this._$);
-  break;
-  case 33:this.$ = [$$[$0-2], $$[$0]];
-  break;
-  case 34:this.$ = new yy.PartialNameNode($$[$0], this._$);
-  break;
-  case 35:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0], this._$), this._$);
-  break;
-  case 36:this.$ = new yy.PartialNameNode(new yy.IntegerNode($$[$0], this._$));
-  break;
-  case 37:this.$ = new yy.DataNode($$[$0], this._$);
-  break;
-  case 38:this.$ = new yy.IdNode($$[$0], this._$);
-  break;
-  case 39: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2];
-  break;
-  case 40:this.$ = [{part: $$[$0]}];
-  break;
-  case 43:this.$ = [];
-  break;
-  case 44:$$[$0-1].push($$[$0]);
-  break;
-  case 47:this.$ = [$$[$0]];
-  break;
-  case 48:$$[$0-1].push($$[$0]);
-  break;
-  }
-  },
-  table: [{3:1,4:2,5:[1,3],8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[3]},{5:[1,16],8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[2,2]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{4:20,6:18,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{4:20,6:22,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15 [...]
-  defaultActions: {3:[2,2],16:[2,1],50:[2,42]},
-  parseError: function parseError(str, hash) {
-      throw new Error(str);
-  },
-  parse: function parse(input) {
-      var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
-      this.lexer.setInput(input);
-      this.lexer.yy = this.yy;
-      this.yy.lexer = this.lexer;
-      this.yy.parser = this;
-      if (typeof this.lexer.yylloc == "undefined")
-          this.lexer.yylloc = {};
-      var yyloc = this.lexer.yylloc;
-      lstack.push(yyloc);
-      var ranges = this.lexer.options && this.lexer.options.ranges;
-      if (typeof this.yy.parseError === "function")
-          this.parseError = this.yy.parseError;
-      function popStack(n) {
-          stack.length = stack.length - 2 * n;
-          vstack.length = vstack.length - n;
-          lstack.length = lstack.length - n;
-      }
-      function lex() {
-          var token;
-          token = self.lexer.lex() || 1;
-          if (typeof token !== "number") {
-              token = self.symbols_[token] || token;
-          }
-          return token;
+    if (inverseAndProgram) {
+      if (decorator) {
+        throw new _exception2['default']('Unexpected inverse block on decorator', inverseAndProgram);
       }
-      var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
-      while (true) {
-          state = stack[stack.length - 1];
-          if (this.defaultActions[state]) {
-              action = this.defaultActions[state];
-          } else {
-              if (symbol === null || typeof symbol == "undefined") {
-                  symbol = lex();
-              }
-              action = table[state] && table[state][symbol];
-          }
-          if (typeof action === "undefined" || !action.length || !action[0]) {
-              var errStr = "";
-              if (!recovering) {
-                  expected = [];
-                  for (p in table[state])
-                      if (this.terminals_[p] && p > 2) {
-                          expected.push("'" + this.terminals_[p] + "'");
-                      }
-                  if (this.lexer.showPosition) {
-                      errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
-                  } else {
-                      errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'");
-                  }
-                  this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
-              }
-          }
-          if (action[0] instanceof Array && action.length > 1) {
-              throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
-          }
-          switch (action[0]) {
-          case 1:
-              stack.push(symbol);
-              vstack.push(this.lexer.yytext);
-              lstack.push(this.lexer.yylloc);
-              stack.push(action[1]);
-              symbol = null;
-              if (!preErrorSymbol) {
-                  yyleng = this.lexer.yyleng;
-                  yytext = this.lexer.yytext;
-                  yylineno = this.lexer.yylineno;
-                  yyloc = this.lexer.yylloc;
-                  if (recovering > 0)
-                      recovering--;
-              } else {
-                  symbol = preErrorSymbol;
-                  preErrorSymbol = null;
-              }
-              break;
-          case 2:
-              len = this.productions_[action[1]][1];
-              yyval.$ = vstack[vstack.length - len];
-              yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};
-              if (ranges) {
-                  yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
-              }
-              r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
-              if (typeof r !== "undefined") {
-                  return r;
-              }
-              if (len) {
-                  stack = stack.slice(0, -1 * len * 2);
-                  vstack = vstack.slice(0, -1 * len);
-                  lstack = lstack.slice(0, -1 * len);
-              }
-              stack.push(this.productions_[action[1]][0]);
-              vstack.push(yyval.$);
-              lstack.push(yyval._$);
-              newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
-              stack.push(newState);
-              break;
-          case 3:
-              return true;
-          }
+
+      if (inverseAndProgram.chain) {
+        inverseAndProgram.program.body[0].closeStrip = close.strip;
       }
-      return true;
-  }
-  };
 
+      inverseStrip = inverseAndProgram.strip;
+      inverse = inverseAndProgram.program;
+    }
+
+    if (inverted) {
+      inverted = inverse;
+      inverse = program;
+      program = inverted;
+    }
 
-  function stripFlags(open, close) {
     return {
-      left: open.charAt(2) === '~',
-      right: close.charAt(0) === '~' || close.charAt(1) === '~'
+      type: decorator ? 'DecoratorBlock' : 'BlockStatement',
+      path: openBlock.path,
+      params: openBlock.params,
+      hash: openBlock.hash,
+      program: program,
+      inverse: inverse,
+      openStrip: openBlock.strip,
+      inverseStrip: inverseStrip,
+      closeStrip: close && close.strip,
+      loc: this.locInfo(locInfo)
     };
   }
 
-  /* Jison generated lexer */
-  var lexer = (function(){
-  var lexer = ({EOF:1,
-  parseError:function parseError(str, hash) {
-          if (this.yy.parser) {
-              this.yy.parser.parseError(str, hash);
-          } else {
-              throw new Error(str);
+  function prepareProgram(statements, loc) {
+    if (!loc && statements.length) {
+      var firstLoc = statements[0].loc,
+          lastLoc = statements[statements.length - 1].loc;
+
+      /* istanbul ignore else */
+      if (firstLoc && lastLoc) {
+        loc = {
+          source: firstLoc.source,
+          start: {
+            line: firstLoc.start.line,
+            column: firstLoc.start.column
+          },
+          end: {
+            line: lastLoc.end.line,
+            column: lastLoc.end.column
           }
-      },
-  setInput:function (input) {
-          this._input = input;
-          this._more = this._less = this.done = false;
-          this.yylineno = this.yyleng = 0;
-          this.yytext = this.matched = this.match = '';
-          this.conditionStack = ['INITIAL'];
-          this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
-          if (this.options.ranges) this.yylloc.range = [0,0];
-          this.offset = 0;
-          return this;
-      },
-  input:function () {
-          var ch = this._input[0];
-          this.yytext += ch;
-          this.yyleng++;
-          this.offset++;
-          this.match += ch;
-          this.matched += ch;
-          var lines = ch.match(/(?:\r\n?|\n).*/g);
-          if (lines) {
-              this.yylineno++;
-              this.yylloc.last_line++;
-          } else {
-              this.yylloc.last_column++;
-          }
-          if (this.options.ranges) this.yylloc.range[1]++;
+        };
+      }
+    }
 
-          this._input = this._input.slice(1);
-          return ch;
-      },
-  unput:function (ch) {
-          var len = ch.length;
-          var lines = ch.split(/(?:\r\n?|\n)/g);
-
-          this._input = ch + this._input;
-          this.yytext = this.yytext.substr(0, this.yytext.length-len-1);
-          //this.yyleng -= len;
-          this.offset -= len;
-          var oldLines = this.match.split(/(?:\r\n?|\n)/g);
-          this.match = this.match.substr(0, this.match.length-1);
-          this.matched = this.matched.substr(0, this.matched.length-1);
-
-          if (lines.length-1) this.yylineno -= lines.length-1;
-          var r = this.yylloc.range;
-
-          this.yylloc = {first_line: this.yylloc.first_line,
-            last_line: this.yylineno+1,
-            first_column: this.yylloc.first_column,
-            last_column: lines ?
-                (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length:
-                this.yylloc.first_column - len
-            };
-
-          if (this.options.ranges) {
-              this.yylloc.range = [r[0], r[0] + this.yyleng - len];
-          }
-          return this;
-      },
-  more:function () {
-          this._more = true;
-          return this;
-      },
-  less:function (n) {
-          this.unput(this.match.slice(n));
-      },
-  pastInput:function () {
-          var past = this.matched.substr(0, this.matched.length - this.match.length);
-          return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
-      },
-  upcomingInput:function () {
-          var next = this.match;
-          if (next.length < 20) {
-              next += this._input.substr(0, 20-next.length);
-          }
-          return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
-      },
-  showPosition:function () {
-          var pre = this.pastInput();
-          var c = new Array(pre.length + 1).join("-");
-          return pre + this.upcomingInput() + "\n" + c+"^";
-      },
-  next:function () {
-          if (this.done) {
-              return this.EOF;
-          }
-          if (!this._input) this.done = true;
-
-          var token,
-              match,
-              tempMatch,
-              index,
-              col,
-              lines;
-          if (!this._more) {
-              this.yytext = '';
-              this.match = '';
-          }
-          var rules = this._currentRules();
-          for (var i=0;i < rules.length; i++) {
-              tempMatch = this._input.match(this.rules[rules[i]]);
-              if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
-                  match = tempMatch;
-                  index = i;
-                  if (!this.options.flex) break;
-              }
-          }
-          if (match) {
-              lines = match[0].match(/(?:\r\n?|\n).*/g);
-              if (lines) this.yylineno += lines.length;
-              this.yylloc = {first_line: this.yylloc.last_line,
-                             last_line: this.yylineno+1,
-                             first_column: this.yylloc.last_column,
-                             last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length};
-              this.yytext += match[0];
-              this.match += match[0];
-              this.matches = match;
-              this.yyleng = this.yytext.length;
-              if (this.options.ranges) {
-                  this.yylloc.range = [this.offset, this.offset += this.yyleng];
-              }
-              this._more = false;
-              this._input = this._input.slice(match[0].length);
-              this.matched += match[0];
-              token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
-              if (this.done && this._input) this.done = false;
-              if (token) return token;
-              else return;
-          }
-          if (this._input === "") {
-              return this.EOF;
-          } else {
-              return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
-                      {text: "", token: null, line: this.yylineno});
-          }
-      },
-  lex:function lex() {
-          var r = this.next();
-          if (typeof r !== 'undefined') {
-              return r;
-          } else {
-              return this.lex();
-          }
-      },
-  begin:function begin(condition) {
-          this.conditionStack.push(condition);
-      },
-  popState:function popState() {
-          return this.conditionStack.pop();
-      },
-  _currentRules:function _currentRules() {
-          return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
-      },
-  topState:function () {
-          return this.conditionStack[this.conditionStack.length-2];
-      },
-  pushState:function begin(condition) {
-          this.begin(condition);
-      }});
-  lexer.options = {};
-  lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
-
-
-  function strip(start, end) {
-    return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng-end);
-  }
-
-
-  var YYSTATE=YY_START
-  switch($avoiding_name_collisions) {
-  case 0:
-                                     if(yy_.yytext.slice(-2) === "\\\\") {
-                                       strip(0,1);
-                                       this.begin("mu");
-                                     } else if(yy_.yytext.slice(-1) === "\\") {
-                                       strip(0,1);
-                                       this.begin("emu");
-                                     } else {
-                                       this.begin("mu");
-                                     }
-                                     if(yy_.yytext) return 14;
-
-  break;
-  case 1:return 14;
-  break;
-  case 2:
-                                     this.popState();
-                                     return 14;
-
-  break;
-  case 3:strip(0,4); this.popState(); return 15;
-  break;
-  case 4:return 35;
-  break;
-  case 5:return 36;
-  break;
-  case 6:return 25;
-  break;
-  case 7:return 16;
-  break;
-  case 8:return 20;
-  break;
-  case 9:return 19;
-  break;
-  case 10:return 19;
-  break;
-  case 11:return 23;
-  break;
-  case 12:return 22;
-  break;
-  case 13:this.popState(); this.begin('com');
-  break;
-  case 14:strip(3,5); this.popState(); return 15;
-  break;
-  case 15:return 22;
-  break;
-  case 16:return 41;
-  break;
-  case 17:return 40;
-  break;
-  case 18:return 40;
-  break;
-  case 19:return 44;
-  break;
-  case 20:// ignore whitespace
-  break;
-  case 21:this.popState(); return 24;
-  break;
-  case 22:this.popState(); return 18;
-  break;
-  case 23:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 32;
-  break;
-  case 24:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 32;
-  break;
-  case 25:return 42;
-  break;
-  case 26:return 34;
-  break;
-  case 27:return 34;
-  break;
-  case 28:return 33;
-  break;
-  case 29:return 40;
-  break;
-  case 30:yy_.yytext = strip(1,2); return 40;
-  break;
-  case 31:return 'INVALID';
-  break;
-  case 32:return 5;
-  break;
+    return {
+      type: 'Program',
+      body: statements,
+      strip: {},
+      loc: loc
+    };
   }
-  };
-  lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(? [...]
-  lexer.conditions = {"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"INITIAL":{"rules":[0,1,32],"inclusive":true}};
-  return lexer;})()
-  parser.lexer = lexer;
-  function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
-  return new Parser;
-  })();__exports__ = handlebars;
-  /* jshint ignore:end */
-  return __exports__;
-})();
-
-// handlebars/compiler/base.js
-var __module8__ = (function(__dependency1__, __dependency2__) {
-  "use strict";
-  var __exports__ = {};
-  var parser = __dependency1__;
-  var AST = __dependency2__;
 
-  __exports__.parser = parser;
+  function preparePartialBlock(open, program, close, locInfo) {
+    validateClose(open, close);
 
-  function parse(input) {
-    // Just return if an already-compile AST was passed in.
-    if(input.constructor === AST.ProgramNode) { return input; }
-
-    parser.yy = AST;
-    return parser.parse(input);
+    return {
+      type: 'PartialBlockStatement',
+      name: open.path,
+      params: open.params,
+      hash: open.hash,
+      program: program,
+      openStrip: open.strip,
+      closeStrip: close && close.strip,
+      loc: this.locInfo(locInfo)
+    };
   }
 
-  __exports__.parse = parse;
-  return __exports__;
-})(__module9__, __module7__);
+/***/ }),
+/* 51 */
+/***/ (function(module, exports, __webpack_require__) {
 
-// handlebars/compiler/compiler.js
-var __module10__ = (function(__dependency1__) {
-  "use strict";
-  var __exports__ = {};
-  var Exception = __dependency1__;
+  /* eslint-disable new-cap */
+
+  'use strict';
+
+  var _Object$create = __webpack_require__(34)['default'];
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+  exports.Compiler = Compiler;
+  exports.precompile = precompile;
+  exports.compile = compile;
+
+  var _exception = __webpack_require__(6);
+
+  var _exception2 = _interopRequireDefault(_exception);
+
+  var _utils = __webpack_require__(5);
+
+  var _ast = __webpack_require__(45);
+
+  var _ast2 = _interopRequireDefault(_ast);
+
+  var slice = [].slice;
 
   function Compiler() {}
 
-  __exports__.Compiler = Compiler;// the foundHelper register will disambiguate helper lookup from finding a
+  // the foundHelper register will disambiguate helper lookup from finding a
   // function in a context. This is necessary for mustache compatibility, which
   // requires that context functions in blocks are evaluated by blockHelperMissing,
   // and then proceed as if the resulting value was provided to blockHelperMissing.
@@ -1295,31 +3334,7 @@ var __module10__ = (function(__dependency1__) {
   Compiler.prototype = {
     compiler: Compiler,
 
-    disassemble: function() {
-      var opcodes = this.opcodes, opcode, out = [], params, param;
-
-      for (var i=0, l=opcodes.length; i<l; i++) {
-        opcode = opcodes[i];
-
-        if (opcode.opcode === 'DECLARE') {
-          out.push("DECLARE " + opcode.name + "=" + opcode.value);
-        } else {
-          params = [];
-          for (var j=0; j<opcode.args.length; j++) {
-            param = opcode.args[j];
-            if (typeof param === "string") {
-              param = "\"" + param.replace("\n", "\\n") + "\"";
-            }
-            params.push(param);
-          }
-          out.push(opcode.opcode + " " + params.join(" "));
-        }
-      }
-
-      return out.join("\n");
-    },
-
-    equals: function(other) {
+    equals: function equals(other) {
       var len = this.opcodes.length;
       if (other.opcodes.length !== len) {
         return false;
@@ -1328,21 +3343,15 @@ var __module10__ = (function(__dependency1__) {
       for (var i = 0; i < len; i++) {
         var opcode = this.opcodes[i],
             otherOpcode = other.opcodes[i];
-        if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
-          return false;
-        }
-        for (var j = 0; j < opcode.args.length; j++) {
-          if (opcode.args[j] !== otherOpcode.args[j]) {
-            return false;
-          }
+        if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) {
+          return false;
         }
       }
 
+      // We know that length is the same between the two arrays because they are directly tied
+      // to the opcode behavior above.
       len = this.children.length;
-      if (other.children.length !== len) {
-        return false;
-      }
-      for (i = 0; i < len; i++) {
+      for (var i = 0; i < len; i++) {
         if (!this.children[i].equals(other.children[i])) {
           return false;
         }
@@ -1353,110 +3362,97 @@ var __module10__ = (function(__dependency1__) {
 
     guid: 0,
 
-    compile: function(program, options) {
+    compile: function compile(program, options) {
+      this.sourceNode = [];
       this.opcodes = [];
       this.children = [];
-      this.depths = {list: []};
       this.options = options;
+      this.stringParams = options.stringParams;
+      this.trackIds = options.trackIds;
 
-      // These changes will propagate to the other compiler components
-      var knownHelpers = this.options.knownHelpers;
-      this.options.knownHelpers = {
-        'helperMissing': true,
-        'blockHelperMissing': true,
-        'each': true,
+      options.blockParams = options.blockParams || [];
+
+      options.knownHelpers = _utils.extend(_Object$create(null), {
+        helperMissing: true,
+        blockHelperMissing: true,
+        each: true,
         'if': true,
-        'unless': true,
+        unless: true,
         'with': true,
-        'log': true
-      };
-      if (knownHelpers) {
-        for (var name in knownHelpers) {
-          this.options.knownHelpers[name] = knownHelpers[name];
-        }
-      }
+        log: true,
+        lookup: true
+      }, options.knownHelpers);
 
       return this.accept(program);
     },
 
-    accept: function(node) {
-      var strip = node.strip || {},
-          ret;
-      if (strip.left) {
-        this.opcode('strip');
-      }
+    compileProgram: function compileProgram(program) {
+      var childCompiler = new this.compiler(),
+          // eslint-disable-line new-cap
+      result = childCompiler.compile(program, this.options),
+          guid = this.guid++;
 
-      ret = this[node.type](node);
+      this.usePartial = this.usePartial || result.usePartial;
 
-      if (strip.right) {
-        this.opcode('strip');
-      }
+      this.children[guid] = result;
+      this.useDepths = this.useDepths || result.useDepths;
 
-      return ret;
+      return guid;
     },
 
-    program: function(program) {
-      var statements = program.statements;
-
-      for(var i=0, l=statements.length; i<l; i++) {
-        this.accept(statements[i]);
+    accept: function accept(node) {
+      /* istanbul ignore next: Sanity code */
+      if (!this[node.type]) {
+        throw new _exception2['default']('Unknown type: ' + node.type, node);
       }
-      this.isSimple = l === 1;
-
-      this.depths.list = this.depths.list.sort(function(a, b) {
-        return a - b;
-      });
 
-      return this;
+      this.sourceNode.unshift(node);
+      var ret = this[node.type](node);
+      this.sourceNode.shift();
+      return ret;
     },
 
-    compileProgram: function(program) {
-      var result = new this.compiler().compile(program, this.options);
-      var guid = this.guid++, depth;
-
-      this.usePartial = this.usePartial || result.usePartial;
+    Program: function Program(program) {
+      this.options.blockParams.unshift(program.blockParams);
 
-      this.children[guid] = result;
+      var body = program.body,
+          bodyLength = body.length;
+      for (var i = 0; i < bodyLength; i++) {
+        this.accept(body[i]);
+      }
 
-      for(var i=0, l=result.depths.list.length; i<l; i++) {
-        depth = result.depths.list[i];
+      this.options.blockParams.shift();
 
-        if(depth < 2) { continue; }
-        else { this.addDepth(depth - 1); }
-      }
+      this.isSimple = bodyLength === 1;
+      this.blockParams = program.blockParams ? program.blockParams.length : 0;
 
-      return guid;
+      return this;
     },
 
-    block: function(block) {
-      var mustache = block.mustache,
-          program = block.program,
-          inverse = block.inverse;
+    BlockStatement: function BlockStatement(block) {
+      transformLiteralToPath(block);
 
-      if (program) {
-        program = this.compileProgram(program);
-      }
+      var program = block.program,
+          inverse = block.inverse;
 
-      if (inverse) {
-        inverse = this.compileProgram(inverse);
-      }
+      program = program && this.compileProgram(program);
+      inverse = inverse && this.compileProgram(inverse);
 
-      var sexpr = mustache.sexpr;
-      var type = this.classifySexpr(sexpr);
+      var type = this.classifySexpr(block);
 
-      if (type === "helper") {
-        this.helperSexpr(sexpr, program, inverse);
-      } else if (type === "simple") {
-        this.simpleSexpr(sexpr);
+      if (type === 'helper') {
+        this.helperSexpr(block, program, inverse);
+      } else if (type === 'simple') {
+        this.simpleSexpr(block);
 
         // now that the simple mustache is resolved, we need to
         // evaluate it by executing `blockHelperMissing`
         this.opcode('pushProgram', program);
         this.opcode('pushProgram', inverse);
         this.opcode('emptyHash');
-        this.opcode('blockValue');
+        this.opcode('blockValue', block.path.original);
       } else {
-        this.ambiguousSexpr(sexpr, program, inverse);
+        this.ambiguousSexpr(block, program, inverse);
 
         // now that the simple mustache is resolved, we need to
         // evaluate it by executing `blockHelperMissing`
@@ -1469,227 +3465,286 @@ var __module10__ = (function(__dependency1__) {
       this.opcode('append');
     },
 
-    hash: function(hash) {
-      var pairs = hash.pairs, pair, val;
+    DecoratorBlock: function DecoratorBlock(decorator) {
+      var program = decorator.program && this.compileProgram(decorator.program);
+      var params = this.setupFullMustacheParams(decorator, program, undefined),
+          path = decorator.path;
 
-      this.opcode('pushHash');
+      this.useDecorators = true;
+      this.opcode('registerDecorator', params.length, path.original);
+    },
 
-      for(var i=0, l=pairs.length; i<l; i++) {
-        pair = pairs[i];
-        val  = pair[1];
+    PartialStatement: function PartialStatement(partial) {
+      this.usePartial = true;
 
-        if (this.options.stringParams) {
-          if(val.depth) {
-            this.addDepth(val.depth);
-          }
-          this.opcode('getContext', val.depth || 0);
-          this.opcode('pushStringParam', val.stringModeValue, val.type);
+      var program = partial.program;
+      if (program) {
+        program = this.compileProgram(partial.program);
+      }
 
-          if (val.type === 'sexpr') {
-            // Subexpressions get evaluated and passed in
-            // in string params mode.
-            this.sexpr(val);
-          }
+      var params = partial.params;
+      if (params.length > 1) {
+        throw new _exception2['default']('Unsupported number of partial arguments: ' + params.length, partial);
+      } else if (!params.length) {
+        if (this.options.explicitPartialContext) {
+          this.opcode('pushLiteral', 'undefined');
         } else {
-          this.accept(val);
+          params.push({ type: 'PathExpression', parts: [], depth: 0 });
         }
+      }
 
-        this.opcode('assignToHash', pair[0]);
+      var partialName = partial.name.original,
+          isDynamic = partial.name.type === 'SubExpression';
+      if (isDynamic) {
+        this.accept(partial.name);
       }
-      this.opcode('popHash');
-    },
 
-    partial: function(partial) {
-      var partialName = partial.partialName;
-      this.usePartial = true;
+      this.setupFullMustacheParams(partial, program, undefined, true);
 
-      if(partial.context) {
-        this.ID(partial.context);
-      } else {
-        this.opcode('push', 'depth0');
+      var indent = partial.indent || '';
+      if (this.options.preventIndent && indent) {
+        this.opcode('appendContent', indent);
+        indent = '';
       }
 
-      this.opcode('invokePartial', partialName.name);
+      this.opcode('invokePartial', isDynamic, partialName, indent);
       this.opcode('append');
     },
-
-    content: function(content) {
-      this.opcode('appendContent', content.string);
+    PartialBlockStatement: function PartialBlockStatement(partialBlock) {
+      this.PartialStatement(partialBlock);
     },
 
-    mustache: function(mustache) {
-      this.sexpr(mustache.sexpr);
+    MustacheStatement: function MustacheStatement(mustache) {
+      this.SubExpression(mustache);
 
-      if(mustache.escaped && !this.options.noEscape) {
+      if (mustache.escaped && !this.options.noEscape) {
         this.opcode('appendEscaped');
       } else {
         this.opcode('append');
       }
     },
+    Decorator: function Decorator(decorator) {
+      this.DecoratorBlock(decorator);
+    },
+
+    ContentStatement: function ContentStatement(content) {
+      if (content.value) {
+        this.opcode('appendContent', content.value);
+      }
+    },
+
+    CommentStatement: function CommentStatement() {},
 
-    ambiguousSexpr: function(sexpr, program, inverse) {
-      var id = sexpr.id,
-          name = id.parts[0],
+    SubExpression: function SubExpression(sexpr) {
+      transformLiteralToPath(sexpr);
+      var type = this.classifySexpr(sexpr);
+
+      if (type === 'simple') {
+        this.simpleSexpr(sexpr);
+      } else if (type === 'helper') {
+        this.helperSexpr(sexpr);
+      } else {
+        this.ambiguousSexpr(sexpr);
+      }
+    },
+    ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) {
+      var path = sexpr.path,
+          name = path.parts[0],
           isBlock = program != null || inverse != null;
 
-      this.opcode('getContext', id.depth);
+      this.opcode('getContext', path.depth);
 
       this.opcode('pushProgram', program);
       this.opcode('pushProgram', inverse);
 
+      path.strict = true;
+      this.accept(path);
+
       this.opcode('invokeAmbiguous', name, isBlock);
     },
 
-    simpleSexpr: function(sexpr) {
-      var id = sexpr.id;
-
-      if (id.type === 'DATA') {
-        this.DATA(id);
-      } else if (id.parts.length) {
-        this.ID(id);
-      } else {
-        // Simplified ID for `this`
-        this.addDepth(id.depth);
-        this.opcode('getContext', id.depth);
-        this.opcode('pushContext');
-      }
-
+    simpleSexpr: function simpleSexpr(sexpr) {
+      var path = sexpr.path;
+      path.strict = true;
+      this.accept(path);
       this.opcode('resolvePossibleLambda');
     },
 
-    helperSexpr: function(sexpr, program, inverse) {
+    helperSexpr: function helperSexpr(sexpr, program, inverse) {
       var params = this.setupFullMustacheParams(sexpr, program, inverse),
-          name = sexpr.id.parts[0];
+          path = sexpr.path,
+          name = path.parts[0];
 
       if (this.options.knownHelpers[name]) {
         this.opcode('invokeKnownHelper', params.length, name);
       } else if (this.options.knownHelpersOnly) {
-        throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
+        throw new _exception2['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr);
       } else {
-        this.opcode('invokeHelper', params.length, name, sexpr.isRoot);
-      }
-    },
+        path.strict = true;
+        path.falsy = true;
 
-    sexpr: function(sexpr) {
-      var type = this.classifySexpr(sexpr);
-
-      if (type === "simple") {
-        this.simpleSexpr(sexpr);
-      } else if (type === "helper") {
-        this.helperSexpr(sexpr);
-      } else {
-        this.ambiguousSexpr(sexpr);
+        this.accept(path);
+        this.opcode('invokeHelper', params.length, path.original, _ast2['default'].helpers.simpleId(path));
       }
     },
 
-    ID: function(id) {
-      this.addDepth(id.depth);
-      this.opcode('getContext', id.depth);
+    PathExpression: function PathExpression(path) {
+      this.addDepth(path.depth);
+      this.opcode('getContext', path.depth);
 
-      var name = id.parts[0];
-      if (!name) {
+      var name = path.parts[0],
+          scoped = _ast2['default'].helpers.scopedId(path),
+          blockParamId = !path.depth && !scoped && this.blockParamIndex(name);
+
+      if (blockParamId) {
+        this.opcode('lookupBlockParam', blockParamId, path.parts);
+      } else if (!name) {
+        // Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
         this.opcode('pushContext');
+      } else if (path.data) {
+        this.options.data = true;
+        this.opcode('lookupData', path.depth, path.parts, path.strict);
       } else {
-        this.opcode('lookupOnContext', id.parts[0]);
-      }
-
-      for(var i=1, l=id.parts.length; i<l; i++) {
-        this.opcode('lookup', id.parts[i]);
+        this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped);
       }
     },
 
-    DATA: function(data) {
-      this.options.data = true;
-      if (data.id.isScoped || data.id.depth) {
-        throw new Exception('Scoped data references are not supported: ' + data.original, data);
-      }
+    StringLiteral: function StringLiteral(string) {
+      this.opcode('pushString', string.value);
+    },
 
-      this.opcode('lookupData');
-      var parts = data.id.parts;
-      for(var i=0, l=parts.length; i<l; i++) {
-        this.opcode('lookup', parts[i]);
-      }
+    NumberLiteral: function NumberLiteral(number) {
+      this.opcode('pushLiteral', number.value);
     },
 
-    STRING: function(string) {
-      this.opcode('pushString', string.string);
+    BooleanLiteral: function BooleanLiteral(bool) {
+      this.opcode('pushLiteral', bool.value);
     },
 
-    INTEGER: function(integer) {
-      this.opcode('pushLiteral', integer.integer);
+    UndefinedLiteral: function UndefinedLiteral() {
+      this.opcode('pushLiteral', 'undefined');
     },
 
-    BOOLEAN: function(bool) {
-      this.opcode('pushLiteral', bool.bool);
+    NullLiteral: function NullLiteral() {
+      this.opcode('pushLiteral', 'null');
     },
 
-    comment: function() {},
+    Hash: function Hash(hash) {
+      var pairs = hash.pairs,
+          i = 0,
+          l = pairs.length;
 
-    // HELPERS
-    opcode: function(name) {
-      this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) });
-    },
+      this.opcode('pushHash');
 
-    declare: function(name, value) {
-      this.opcodes.push({ opcode: 'DECLARE', name: name, value: value });
+      for (; i < l; i++) {
+        this.pushParam(pairs[i].value);
+      }
+      while (i--) {
+        this.opcode('assignToHash', pairs[i].key);
+      }
+      this.opcode('popHash');
     },
 
-    addDepth: function(depth) {
-      if(depth === 0) { return; }
+    // HELPERS
+    opcode: function opcode(name) {
+      this.opcodes.push({
+        opcode: name,
+        args: slice.call(arguments, 1),
+        loc: this.sourceNode[0].loc
+      });
+    },
 
-      if(!this.depths[depth]) {
-        this.depths[depth] = true;
-        this.depths.list.push(depth);
+    addDepth: function addDepth(depth) {
+      if (!depth) {
+        return;
       }
+
+      this.useDepths = true;
     },
 
-    classifySexpr: function(sexpr) {
-      var isHelper   = sexpr.isHelper;
-      var isEligible = sexpr.eligibleHelper;
-      var options    = this.options;
+    classifySexpr: function classifySexpr(sexpr) {
+      var isSimple = _ast2['default'].helpers.simpleId(sexpr.path);
+
+      var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);
+
+      // a mustache is an eligible helper if:
+      // * its id is simple (a single part, not `this` or `..`)
+      var isHelper = !isBlockParam && _ast2['default'].helpers.helperExpression(sexpr);
+
+      // 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.
+      var isEligible = !isBlockParam && (isHelper || isSimple);
 
       // if ambiguous, we can possibly resolve the ambiguity now
+      // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc.
       if (isEligible && !isHelper) {
-        var name = sexpr.id.parts[0];
-
-        if (options.knownHelpers[name]) {
+        var _name = sexpr.path.parts[0],
+            options = this.options;
+        if (options.knownHelpers[_name]) {
           isHelper = true;
         } else if (options.knownHelpersOnly) {
           isEligible = false;
         }
       }
 
-      if (isHelper) { return "helper"; }
-      else if (isEligible) { return "ambiguous"; }
-      else { return "simple"; }
+      if (isHelper) {
+        return 'helper';
+      } else if (isEligible) {
+        return 'ambiguous';
+      } else {
+        return 'simple';
+      }
     },
 
-    pushParams: function(params) {
-      var i = params.length, param;
+    pushParams: function pushParams(params) {
+      for (var i = 0, l = params.length; i < l; i++) {
+        this.pushParam(params[i]);
+      }
+    },
 
-      while(i--) {
-        param = params[i];
+    pushParam: function pushParam(val) {
+      var value = val.value != null ? val.value : val.original || '';
 
-        if(this.options.stringParams) {
-          if(param.depth) {
-            this.addDepth(param.depth);
-          }
+      if (this.stringParams) {
+        if (value.replace) {
+          value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.');
+        }
 
-          this.opcode('getContext', param.depth || 0);
-          this.opcode('pushStringParam', param.stringModeValue, param.type);
+        if (val.depth) {
+          this.addDepth(val.depth);
+        }
+        this.opcode('getContext', val.depth || 0);
+        this.opcode('pushStringParam', value, val.type);
 
-          if (param.type === 'sexpr') {
-            // Subexpressions get evaluated and passed in
-            // in string params mode.
-            this.sexpr(param);
+        if (val.type === 'SubExpression') {
+          // SubExpressions get evaluated and passed in
+          // in string params mode.
+          this.accept(val);
+        }
+      } else {
+        if (this.trackIds) {
+          var blockParamIndex = undefined;
+          if (val.parts && !_ast2['default'].helpers.scopedId(val) && !val.depth) {
+            blockParamIndex = this.blockParamIndex(val.parts[0]);
+          }
+          if (blockParamIndex) {
+            var blockParamChild = val.parts.slice(1).join('.');
+            this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
+          } else {
+            value = val.original || value;
+            if (value.replace) {
+              value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, '');
+            }
+
+            this.opcode('pushId', val.type, value);
           }
-        } else {
-          this[param.type](param);
         }
+        this.accept(val);
       }
     },
 
-    setupFullMustacheParams: function(sexpr, program, inverse) {
+    setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) {
       var params = sexpr.params;
       this.pushParams(params);
 
@@ -1697,71 +3752,143 @@ var __module10__ = (function(__dependency1__) {
       this.opcode('pushProgram', inverse);
 
       if (sexpr.hash) {
-        this.hash(sexpr.hash);
+        this.accept(sexpr.hash);
       } else {
-        this.opcode('emptyHash');
+        this.opcode('emptyHash', omitEmpty);
       }
 
       return params;
+    },
+
+    blockParamIndex: function blockParamIndex(name) {
+      for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
+        var blockParams = this.options.blockParams[depth],
+            param = blockParams && _utils.indexOf(blockParams, name);
+        if (blockParams && param >= 0) {
+          return [depth, param];
+        }
+      }
     }
   };
 
   function precompile(input, options, env) {
-    if (input == null || (typeof input !== 'string' && input.constructor !== env.AST.ProgramNode)) {
-      throw new Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
+    if (input == null || typeof input !== 'string' && input.type !== 'Program') {
+      throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input);
     }
 
     options = options || {};
     if (!('data' in options)) {
       options.data = true;
     }
+    if (options.compat) {
+      options.useDepths = true;
+    }
 
-    var ast = env.parse(input);
-    var environment = new env.Compiler().compile(ast, options);
+    var ast = env.parse(input, options),
+        environment = new env.Compiler().compile(ast, options);
     return new env.JavaScriptCompiler().compile(environment, options);
   }
 
-  __exports__.precompile = precompile;function compile(input, options, env) {
-    if (input == null || (typeof input !== 'string' && input.constructor !== env.AST.ProgramNode)) {
-      throw new Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
-    }
+  function compile(input, options, env) {
+    if (options === undefined) options = {};
 
-    options = options || {};
+    if (input == null || typeof input !== 'string' && input.type !== 'Program') {
+      throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input);
+    }
 
+    options = _utils.extend({}, options);
     if (!('data' in options)) {
       options.data = true;
     }
+    if (options.compat) {
+      options.useDepths = true;
+    }
 
-    var compiled;
+    var compiled = undefined;
 
     function compileInput() {
-      var ast = env.parse(input);
-      var environment = new env.Compiler().compile(ast, options);
-      var templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
+      var ast = env.parse(input, options),
+          environment = new env.Compiler().compile(ast, options),
+          templateSpec = new env.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) {
+    function ret(context, execOptions) {
+      if (!compiled) {
+        compiled = compileInput();
+      }
+      return compiled.call(this, context, execOptions);
+    }
+    ret._setup = function (setupOptions) {
       if (!compiled) {
         compiled = compileInput();
       }
-      return compiled.call(this, context, options);
+      return compiled._setup(setupOptions);
     };
+    ret._child = function (i, data, blockParams, depths) {
+      if (!compiled) {
+        compiled = compileInput();
+      }
+      return compiled._child(i, data, blockParams, depths);
+    };
+    return ret;
   }
 
-  __exports__.compile = compile;
-  return __exports__;
-})(__module5__);
+  function argEquals(a, b) {
+    if (a === b) {
+      return true;
+    }
 
-// handlebars/compiler/javascript-compiler.js
-var __module11__ = (function(__dependency1__, __dependency2__) {
-  "use strict";
-  var __exports__;
-  var COMPILER_REVISION = __dependency1__.COMPILER_REVISION;
-  var REVISION_CHANGES = __dependency1__.REVISION_CHANGES;
-  var log = __dependency1__.log;
-  var Exception = __dependency2__;
+    if (_utils.isArray(a) && _utils.isArray(b) && a.length === b.length) {
+      for (var i = 0; i < a.length; i++) {
+        if (!argEquals(a[i], b[i])) {
+          return false;
+        }
+      }
+      return true;
+    }
+  }
+
+  function transformLiteralToPath(sexpr) {
+    if (!sexpr.path.parts) {
+      var literal = sexpr.path;
+      // Casting to string here to make false and 0 literal values play nicely with the rest
+      // of the system.
+      sexpr.path = {
+        type: 'PathExpression',
+        data: false,
+        depth: 0,
+        parts: [literal.original + ''],
+        original: literal.original + '',
+        loc: literal.loc
+      };
+    }
+  }
+
+/***/ }),
+/* 52 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  'use strict';
+
+  var _Object$keys = __webpack_require__(13)['default'];
+
+  var _interopRequireDefault = __webpack_require__(1)['default'];
+
+  exports.__esModule = true;
+
+  var _base = __webpack_require__(4);
+
+  var _exception = __webpack_require__(6);
+
+  var _exception2 = _interopRequireDefault(_exception);
+
+  var _utils = __webpack_require__(5);
+
+  var _codeGen = __webpack_require__(53);
+
+  var _codeGen2 = _interopRequireDefault(_codeGen);
 
   function Literal(value) {
     this.value = value;
@@ -1772,208 +3899,304 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
   JavaScriptCompiler.prototype = {
     // PUBLIC API: You can override these methods in a subclass to provide
     // alternative compiled forms for name lookup and buffering semantics
-    nameLookup: function(parent, name /* , type*/) {
-      var wrap,
-          ret;
-      if (parent.indexOf('depth') === 0) {
-        wrap = true;
-      }
-
-      if (/^[0-9]+$/.test(name)) {
-        ret = parent + "[" + name + "]";
-      } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
-        ret = parent + "." + name;
-      }
-      else {
-        ret = parent + "['" + name + "']";
-      }
-
-      if (wrap) {
-        return '(' + parent + ' && ' + ret + ')';
-      } else {
-        return ret;
-      }
+    nameLookup: function nameLookup(parent, name /*,  type */) {
+      return this.internalNameLookup(parent, name);
+    },
+    depthedLookup: function depthedLookup(name) {
+      return [this.aliasable('container.lookup'), '(depths, "', name, '")'];
     },
 
-    compilerInfo: function() {
-      var revision = COMPILER_REVISION,
-          versions = REVISION_CHANGES[revision];
-      return "this.compilerInfo = ["+revision+",'"+versions+"'];\n";
+    compilerInfo: function compilerInfo() {
+      var revision = _base.COMPILER_REVISION,
+          versions = _base.REVISION_CHANGES[revision];
+      return [revision, versions];
     },
 
-    appendToBuffer: function(string) {
+    appendToBuffer: function appendToBuffer(source, location, explicit) {
+      // Force a source as this simplifies the merge logic.
+      if (!_utils.isArray(source)) {
+        source = [source];
+      }
+      source = this.source.wrap(source, location);
+
       if (this.environment.isSimple) {
-        return "return " + string + ";";
+        return ['return ', source, ';'];
+      } else if (explicit) {
+        // This is a case where the buffer operation occurs as a child of another
+        // construct, generally braces. We have to explicitly output these buffer
+        // operations to ensure that the emitted code goes in the correct location.
+        return ['buffer += ', source, ';'];
       } else {
-        return {
-          appendToBuffer: true,
-          content: string,
-          toString: function() { return "buffer += " + string + ";"; }
-        };
+        source.appendToBuffer = true;
+        return source;
       }
     },
 
-    initializeBuffer: function() {
-      return this.quotedString("");
+    initializeBuffer: function initializeBuffer() {
+      return this.quotedString('');
     },
-
-    namespace: "Handlebars",
     // END PUBLIC API
+    internalNameLookup: function internalNameLookup(parent, name) {
+      this.lookupPropertyFunctionIsUsed = true;
+      return ['lookupProperty(', parent, ',', JSON.stringify(name), ')'];
+    },
 
-    compile: function(environment, options, context, asObject) {
-      this.environment = environment;
-      this.options = options || {};
+    lookupPropertyFunctionIsUsed: false,
 
-      log('debug', this.environment.disassemble() + "\n\n");
+    compile: function compile(environment, options, context, asObject) {
+      this.environment = environment;
+      this.options = options;
+      this.stringParams = this.options.stringParams;
+      this.trackIds = this.options.trackIds;
+      this.precompile = !asObject;
 
       this.name = this.environment.name;
       this.isChild = !!context;
       this.context = context || {
+        decorators: [],
         programs: [],
-        environments: [],
-        aliases: { }
+        environments: []
       };
 
       this.preamble();
 
       this.stackSlot = 0;
       this.stackVars = [];
+      this.aliases = {};
       this.registers = { list: [] };
       this.hashes = [];
       this.compileStack = [];
       this.inlineStack = [];
+      this.blockParams = [];
 
       this.compileChildren(environment, options);
 
-      var opcodes = environment.opcodes, opcode;
-
-      this.i = 0;
+      this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat;
+      this.useBlockParams = this.useBlockParams || environment.useBlockParams;
 
-      for(var l=opcodes.length; this.i<l; this.i++) {
-        opcode = opcodes[this.i];
+      var opcodes = environment.opcodes,
+          opcode = undefined,
+          firstLoc = undefined,
+          i = undefined,
+          l = undefined;
 
-        if(opcode.opcode === 'DECLARE') {
-          this[opcode.name] = opcode.value;
-        } else {
-          this[opcode.opcode].apply(this, opcode.args);
-        }
+      for (i = 0, l = opcodes.length; i < l; i++) {
+        opcode = opcodes[i];
 
-        // Reset the stripNext flag if it was not set by this operation.
-        if (opcode.opcode !== this.stripNext) {
-          this.stripNext = false;
-        }
+        this.source.currentLocation = opcode.loc;
+        firstLoc = firstLoc || opcode.loc;
+        this[opcode.opcode].apply(this, opcode.args);
       }
 
       // Flush any trailing content that might be pending.
+      this.source.currentLocation = firstLoc;
       this.pushSource('');
 
+      /* istanbul ignore next */
       if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
-        throw new Exception('Compile completed with content left on stack');
+        throw new _exception2['default']('Compile completed with content left on stack');
       }
 
-      return this.createFunctionContext(asObject);
-    },
-
-    preamble: function() {
-      var out = [];
+      if (!this.decorators.isEmpty()) {
+        this.useDecorators = true;
 
-      if (!this.isChild) {
-        var namespace = this.namespace;
+        this.decorators.prepend(['var decorators = container.decorators, ', this.lookupPropertyFunctionVarDeclaration(), ';\n']);
+        this.decorators.push('return fn;');
 
-        var copies = "helpers = this.merge(helpers, " + namespace + ".helpers);";
-        if (this.environment.usePartial) { copies = copies + " partials = this.merge(partials, " + namespace + ".partials);"; }
-        if (this.options.data) { copies = copies + " data = data || {};"; }
-        out.push(copies);
+        if (asObject) {
+          this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]);
+        } else {
+          this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n');
+          this.decorators.push('}\n');
+          this.decorators = this.decorators.merge();
+        }
       } else {
-        out.push('');
+        this.decorators = undefined;
       }
 
-      if (!this.environment.isSimple) {
-        out.push(", buffer = " + this.initializeBuffer());
+      var fn = this.createFunctionContext(asObject);
+      if (!this.isChild) {
+        var ret = {
+          compiler: this.compilerInfo(),
+          main: fn
+        };
+
+        if (this.decorators) {
+          ret.main_d = this.decorators; // eslint-disable-line camelcase
+          ret.useDecorators = true;
+        }
+
+        var _context = this.context;
+        var programs = _context.programs;
+        var decorators = _context.decorators;
+
+        for (i = 0, l = programs.length; i < l; i++) {
+          if (programs[i]) {
+            ret[i] = programs[i];
+            if (decorators[i]) {
+              ret[i + '_d'] = decorators[i];
+              ret.useDecorators = true;
+            }
+          }
+        }
+
+        if (this.environment.usePartial) {
+          ret.usePartial = true;
+        }
+        if (this.options.data) {
+          ret.useData = true;
+        }
+        if (this.useDepths) {
+          ret.useDepths = true;
+        }
+        if (this.useBlockParams) {
+          ret.useBlockParams = true;
+        }
+        if (this.options.compat) {
+          ret.compat = true;
+        }
+
+        if (!asObject) {
+          ret.compiler = JSON.stringify(ret.compiler);
+
+          this.source.currentLocation = { start: { line: 1, column: 0 } };
+          ret = this.objectLiteral(ret);
+
+          if (options.srcName) {
+            ret = ret.toStringWithSourceMap({ file: options.destName });
+            ret.map = ret.map && ret.map.toString();
+          } else {
+            ret = ret.toString();
+          }
+        } else {
+          ret.compilerOptions = this.options;
+        }
+
+        return ret;
       } else {
-        out.push("");
+        return fn;
       }
+    },
 
+    preamble: function preamble() {
       // track the last context pushed into place to allow skipping the
       // getContext opcode when it would be a noop
       this.lastContext = 0;
-      this.source = out;
+      this.source = new _codeGen2['default'](this.options.srcName);
+      this.decorators = new _codeGen2['default'](this.options.srcName);
     },
 
-    createFunctionContext: function(asObject) {
-      var locals = this.stackVars.concat(this.registers.list);
+    createFunctionContext: function createFunctionContext(asObject) {
+      // istanbul ignore next
+
+      var _this = this;
 
-      if(locals.length > 0) {
-        this.source[1] = this.source[1] + ", " + locals.join(", ");
+      var varDeclarations = '';
+
+      var locals = this.stackVars.concat(this.registers.list);
+      if (locals.length > 0) {
+        varDeclarations += ', ' + locals.join(', ');
       }
 
       // Generate minimizer alias mappings
-      if (!this.isChild) {
-        for (var alias in this.context.aliases) {
-          if (this.context.aliases.hasOwnProperty(alias)) {
-            this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
-          }
+      //
+      // When using true SourceNodes, this will update all references to the given alias
+      // as the source nodes are reused in situ. For the non-source node compilation mode,
+      // aliases will not be used, but this case is already being run on the client and
+      // we aren't concern about minimizing the template size.
+      var aliasCount = 0;
+      _Object$keys(this.aliases).forEach(function (alias) {
+        var node = _this.aliases[alias];
+        if (node.children && node.referenceCount > 1) {
+          varDeclarations += ', alias' + ++aliasCount + '=' + alias;
+          node.children[0] = 'alias' + aliasCount;
         }
-      }
+      });
 
-      if (this.source[1]) {
-        this.source[1] = "var " + this.source[1].substring(2) + ";";
+      if (this.lookupPropertyFunctionIsUsed) {
+        varDeclarations += ', ' + this.lookupPropertyFunctionVarDeclaration();
       }
 
-      // Merge children
-      if (!this.isChild) {
-        this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
-      }
+      var params = ['container', 'depth0', 'helpers', 'partials', 'data'];
 
-      if (!this.environment.isSimple) {
-        this.pushSource("return buffer;");
+      if (this.useBlockParams || this.useDepths) {
+        params.push('blockParams');
       }
-
-      var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];
-
-      for(var i=0, l=this.environment.depths.list.length; i<l; i++) {
-        params.push("depth" + this.environment.depths.list[i]);
+      if (this.useDepths) {
+        params.push('depths');
       }
 
       // Perform a second pass over the output to merge content when possible
-      var source = this.mergeSource();
-
-      if (!this.isChild) {
-        source = this.compilerInfo()+source;
-      }
+      var source = this.mergeSource(varDeclarations);
 
       if (asObject) {
         params.push(source);
 
         return Function.apply(this, params);
       } else {
-        var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n  ' + source + '}';
-        log('debug', functionSource + "\n\n");
-        return functionSource;
+        return this.source.wrap(['function(', params.join(','), ') {\n  ', source, '}']);
       }
     },
-    mergeSource: function() {
-      // WARN: We are not handling the case where buffer is still populated as the source should
-      // not have buffer append operations as their final action.
-      var source = '',
-          buffer;
-      for (var i = 0, len = this.source.length; i < len; i++) {
-        var line = this.source[i];
+    mergeSource: function mergeSource(varDeclarations) {
+      var isSimple = this.environment.isSimple,
+          appendOnly = !this.forceBuffer,
+          appendFirst = undefined,
+          sourceSeen = undefined,
+          bufferStart = undefined,
+          bufferEnd = undefined;
+      this.source.each(function (line) {
         if (line.appendToBuffer) {
-          if (buffer) {
-            buffer = buffer + '\n    + ' + line.content;
+          if (bufferStart) {
+            line.prepend('  + ');
           } else {
-            buffer = line.content;
+            bufferStart = line;
           }
+          bufferEnd = line;
         } else {
-          if (buffer) {
-            source += 'buffer += ' + buffer + ';\n  ';
-            buffer = undefined;
+          if (bufferStart) {
+            if (!sourceSeen) {
+              appendFirst = true;
+            } else {
+              bufferStart.prepend('buffer += ');
+            }
+            bufferEnd.add(';');
+            bufferStart = bufferEnd = undefined;
+          }
+
+          sourceSeen = true;
+          if (!isSimple) {
+            appendOnly = false;
           }
-          source += line + '\n  ';
+        }
+      });
+
+      if (appendOnly) {
+        if (bufferStart) {
+          bufferStart.prepend('return ');
+          bufferEnd.add(';');
+        } else if (!sourceSeen) {
+          this.source.push('return "";');
+        }
+      } else {
+        varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer());
+
+        if (bufferStart) {
+          bufferStart.prepend('return buffer + ');
+          bufferEnd.add(';');
+        } else {
+          this.source.push('return buffer;');
         }
       }
-      return source;
+
+      if (varDeclarations) {
+        this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n'));
+      }
+
+      return this.source.merge();
+    },
+
+    lookupPropertyFunctionVarDeclaration: function lookupPropertyFunctionVarDeclaration() {
+      return '\n      lookupProperty = container.lookupProperty || function(parent, propertyName) {\n        if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {\n          return parent[propertyName];\n        }\n        return undefined\n    }\n    '.trim();
     },
 
     // [blockValue]
@@ -1982,19 +4205,18 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // On stack, after: return value of blockHelperMissing
     //
     // The purpose of this opcode is to take a block of the form
-    // `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
+    // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and
     // replace it on the stack with the result of properly
     // invoking blockHelperMissing.
-    blockValue: function() {
-      this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
+    blockValue: function blockValue(name) {
+      var blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
+          params = [this.contextName(0)];
+      this.setupHelperArgs(name, 0, params);
 
-      var params = ["depth0"];
-      this.setupParams(0, params);
+      var blockName = this.popStack();
+      params.splice(1, 0, blockName);
 
-      this.replaceStack(function(current) {
-        params.splice(1, 0, current);
-        return "blockHelperMissing.call(" + params.join(", ") + ")";
-      });
+      this.push(this.source.functionCall(blockHelperMissing, 'call', params));
     },
 
     // [ambiguousBlockValue]
@@ -2003,47 +4225,34 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // Compiler value, before: lastHelper=value of last found helper, if any
     // On stack, after, if no lastHelper: same as [blockValue]
     // On stack, after, if lastHelper: value
-    ambiguousBlockValue: function() {
-      this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
+    ambiguousBlockValue: function ambiguousBlockValue() {
+      // We're being a bit cheeky and reusing the options value from the prior exec
+      var blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
+          params = [this.contextName(0)];
+      this.setupHelperArgs('', 0, params, true);
 
-      var params = ["depth0"];
-      this.setupParams(0, params);
+      this.flushInline();
 
       var current = this.topStack();
-      params.splice(1, 0, current);
-
-      this.pushSource("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
-    },
-
-    // [appendContent]
-    //
-    // On stack, before: ...
-    // On stack, after: ...
-    //
-    // Appends the string value of `content` to the current buffer
-    appendContent: function(content) {
-      if (this.pendingContent) {
-        content = this.pendingContent + content;
-      }
-      if (this.stripNext) {
-        content = content.replace(/^\s+/, '');
-      }
+      params.splice(1, 0, current);
 
-      this.pendingContent = content;
+      this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']);
     },
 
-    // [strip]
+    // [appendContent]
     //
     // On stack, before: ...
     // On stack, after: ...
     //
-    // Removes any trailing whitespace from the prior content node and flags
-    // the next operation for stripping if it is a content node.
-    strip: function() {
+    // Appends the string value of `content` to the current buffer
+    appendContent: function appendContent(content) {
       if (this.pendingContent) {
-        this.pendingContent = this.pendingContent.replace(/\s+$/, '');
+        content = this.pendingContent + content;
+      } else {
+        this.pendingLocation = this.source.currentLocation;
       }
-      this.stripNext = 'strip';
+
+      this.pendingContent = content;
     },
 
     // [append]
@@ -2055,14 +4264,19 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     //
     // If `value` is truthy, or 0, it is coerced into a string and appended
     // Otherwise, the empty string is appended
-    append: function() {
-      // Force anything that is inlined onto the stack so we don't have duplication
-      // when we examine local
-      this.flushInline();
-      var local = this.popStack();
-      this.pushSource("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
-      if (this.environment.isSimple) {
-        this.pushSource("else { " + this.appendToBuffer("''") + " }");
+    append: function append() {
+      if (this.isInline()) {
+        this.replaceStack(function (current) {
+          return [' != null ? ', current, ' : ""'];
+        });
+
+        this.pushSource(this.appendToBuffer(this.popStack()));
+      } else {
+        var local = this.popStack();
+        this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']);
+        if (this.environment.isSimple) {
+          this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']);
+        }
       }
     },
 
@@ -2072,10 +4286,8 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // On stack, after: ...
     //
     // Escape `value` and append it to the buffer
-    appendEscaped: function() {
-      this.context.aliases.escapeExpression = 'this.escapeExpression';
-
-      this.pushSource(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
+    appendEscaped: function appendEscaped() {
+      this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')']));
     },
 
     // [getContext]
@@ -2085,21 +4297,8 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // Compiler value, after: lastContext=depth
     //
     // Set the value of the `lastContext` compiler value to the depth
-    getContext: function(depth) {
-      if(this.lastContext !== depth) {
-        this.lastContext = depth;
-      }
-    },
-
-    // [lookupOnContext]
-    //
-    // On stack, before: ...
-    // On stack, after: currentContext[name], ...
-    //
-    // Looks up the value of `name` on the current context and pushes
-    // it onto the stack.
-    lookupOnContext: function(name) {
-      this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
+    getContext: function getContext(depth) {
+      this.lastContext = depth;
     },
 
     // [pushContext]
@@ -2108,36 +4307,43 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // On stack, after: currentContext, ...
     //
     // Pushes the value of the current context onto the stack.
-    pushContext: function() {
-      this.pushStackLiteral('depth' + this.lastContext);
+    pushContext: function pushContext() {
+      this.pushStackLiteral(this.contextName(this.lastContext));
     },
 
-    // [resolvePossibleLambda]
+    // [lookupOnContext]
     //
-    // On stack, before: value, ...
-    // On stack, after: resolved value, ...
+    // On stack, before: ...
+    // On stack, after: currentContext[name], ...
     //
-    // If the `value` is a lambda, replace it on the stack by
-    // the return value of the lambda
-    resolvePossibleLambda: function() {
-      this.context.aliases.functionType = '"function"';
+    // Looks up the value of `name` on the current context and pushes
+    // it onto the stack.
+    lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) {
+      var i = 0;
 
-      this.replaceStack(function(current) {
-        return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current;
-      });
+      if (!scoped && this.options.compat && !this.lastContext) {
+        // The depthed query is expected to handle the undefined logic for the root level that
+        // is implemented below, so we evaluate that directly in compat mode
+        this.push(this.depthedLookup(parts[i++]));
+      } else {
+        this.pushContext();
+      }
+
+      this.resolvePath('context', parts, i, falsy, strict);
     },
 
-    // [lookup]
+    // [lookupBlockParam]
     //
-    // On stack, before: value, ...
-    // On stack, after: value[name], ...
+    // On stack, before: ...
+    // On stack, after: blockParam[name], ...
     //
-    // Replace the value on the stack with the result of looking
-    // up `name` on `value`
-    lookup: function(name) {
-      this.replaceStack(function(current) {
-        return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
-      });
+    // Looks up the value of `parts` on the given block param and pushes
+    // it onto the stack.
+    lookupBlockParam: function lookupBlockParam(blockParamId, parts) {
+      this.useBlockParams = true;
+
+      this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']);
+      this.resolvePath('context', parts, 1);
     },
 
     // [lookupData]
@@ -2146,8 +4352,53 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // On stack, after: data, ...
     //
     // Push the data lookup operator
-    lookupData: function() {
-      this.pushStackLiteral('data');
+    lookupData: function lookupData(depth, parts, strict) {
+      if (!depth) {
+        this.pushStackLiteral('data');
+      } else {
+        this.pushStackLiteral('container.data(data, ' + depth + ')');
+      }
+
+      this.resolvePath('data', parts, 0, true, strict);
+    },
+
+    resolvePath: function resolvePath(type, parts, i, falsy, strict) {
+      // istanbul ignore next
+
+      var _this2 = this;
+
+      if (this.options.strict || this.options.assumeObjects) {
+        this.push(strictLookup(this.options.strict && strict, this, parts, type));
+        return;
+      }
+
+      var len = parts.length;
+      for (; i < len; i++) {
+        /* eslint-disable no-loop-func */
+        this.replaceStack(function (current) {
+          var lookup = _this2.nameLookup(current, parts[i], type);
+          // We want to ensure that zero and false are handled properly if the context (falsy flag)
+          // needs to have the special handling for these values.
+          if (!falsy) {
+            return [' != null ? ', lookup, ' : ', current];
+          } else {
+            // Otherwise we can use generic falsy handling
+            return [' && ', lookup];
+          }
+        });
+        /* eslint-enable no-loop-func */
+      }
+    },
+
+    // [resolvePossibleLambda]
+    //
+    // On stack, before: value, ...
+    // On stack, after: resolved value, ...
+    //
+    // If the `value` is a lambda, replace it on the stack by
+    // the return value of the lambda
+    resolvePossibleLambda: function resolvePossibleLambda() {
+      this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']);
     },
 
     // [pushStringParam]
@@ -2158,14 +4409,13 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // This opcode is designed for use in string mode, which
     // provides the string value of a parameter along with its
     // depth rather than resolving it immediately.
-    pushStringParam: function(string, type) {
-      this.pushStackLiteral('depth' + this.lastContext);
-
+    pushStringParam: function pushStringParam(string, type) {
+      this.pushContext();
       this.pushString(type);
 
       // If it's a subexpression, the string result
       // will be pushed after this opcode.
-      if (type !== 'sexpr') {
+      if (type !== 'SubExpression') {
         if (typeof string === 'string') {
           this.pushString(string);
         } else {
@@ -2174,30 +4424,35 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
       }
     },
 
-    emptyHash: function() {
-      this.pushStackLiteral('{}');
-
-      if (this.options.stringParams) {
+    emptyHash: function emptyHash(omitEmpty) {
+      if (this.trackIds) {
+        this.push('{}'); // hashIds
+      }
+      if (this.stringParams) {
         this.push('{}'); // hashContexts
         this.push('{}'); // hashTypes
       }
+      this.pushStackLiteral(omitEmpty ? 'undefined' : '{}');
     },
-    pushHash: function() {
+    pushHash: function pushHash() {
       if (this.hash) {
         this.hashes.push(this.hash);
       }
-      this.hash = {values: [], types: [], contexts: []};
+      this.hash = { values: {}, types: [], contexts: [], ids: [] };
     },
-    popHash: function() {
+    popHash: function popHash() {
       var hash = this.hash;
       this.hash = this.hashes.pop();
 
-      if (this.options.stringParams) {
-        this.push('{' + hash.contexts.join(',') + '}');
-        this.push('{' + hash.types.join(',') + '}');
+      if (this.trackIds) {
+        this.push(this.objectLiteral(hash.ids));
+      }
+      if (this.stringParams) {
+        this.push(this.objectLiteral(hash.contexts));
+        this.push(this.objectLiteral(hash.types));
       }
 
-      this.push('{\n    ' + hash.values.join(',\n    ') + '\n  }');
+      this.push(this.objectLiteral(hash.values));
     },
 
     // [pushString]
@@ -2206,21 +4461,10 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // On stack, after: quotedString(string), ...
     //
     // Push a quoted version of `string` onto the stack
-    pushString: function(string) {
+    pushString: function pushString(string) {
       this.pushStackLiteral(this.quotedString(string));
     },
 
-    // [push]
-    //
-    // On stack, before: ...
-    // On stack, after: expr, ...
-    //
-    // Push an expression onto the stack
-    push: function(expr) {
-      this.inlineStack.push(expr);
-      return expr;
-    },
-
     // [pushLiteral]
     //
     // On stack, before: ...
@@ -2229,7 +4473,7 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // Pushes a value onto the stack. This operation prevents
     // the compiler from creating a temporary variable to hold
     // it.
-    pushLiteral: function(value) {
+    pushLiteral: function pushLiteral(value) {
       this.pushStackLiteral(value);
     },
 
@@ -2241,7 +4485,7 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // Push a program expression onto the stack. This takes
     // a compile-time guid and converts it into a runtime-accessible
     // expression.
-    pushProgram: function(guid) {
+    pushProgram: function pushProgram(guid) {
       if (guid != null) {
         this.pushStackLiteral(this.programExpression(guid));
       } else {
@@ -2249,6 +4493,20 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
       }
     },
 
+    // [registerDecorator]
+    //
+    // On stack, before: hash, program, params..., ...
+    // On stack, after: ...
+    //
+    // Pops off the decorator's parameters, invokes the decorator,
+    // and inserts the decorator into the decorators list.
+    registerDecorator: function registerDecorator(paramSize, name) {
+      var foundDecorator = this.nameLookup('decorators', name, 'decorator'),
+          options = this.setupHelperArgs(name, paramSize);
+
+      this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']);
+    },
+
     // [invokeHelper]
     //
     // On stack, before: hash, inverse, program, params..., ...
@@ -2258,33 +4516,35 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // and pushes the helper's return value onto the stack.
     //
     // If the helper is not found, `helperMissing` is called.
-    invokeHelper: function(paramSize, name, isRoot) {
-      this.context.aliases.helperMissing = 'helpers.helperMissing';
-      this.useRegister('helper');
+    invokeHelper: function invokeHelper(paramSize, name, isSimple) {
+      var nonHelper = this.popStack(),
+          helper = this.setupHelper(paramSize, name);
 
-      var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
-      var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
+      var possibleFunctionCalls = [];
 
-      var lookup = 'helper = ' + helper.name + ' || ' + nonHelper;
-      if (helper.paramsInit) {
-        lookup += ',' + helper.paramsInit;
+      if (isSimple) {
+        // direct call to helper
+        possibleFunctionCalls.push(helper.name);
+      }
+      // call a function from the input object
+      possibleFunctionCalls.push(nonHelper);
+      if (!this.options.strict) {
+        possibleFunctionCalls.push(this.aliasable('container.hooks.helperMissing'));
       }
 
-      this.push(
-        '('
-          + lookup
-          + ',helper '
-            + '? helper.call(' + helper.callParams + ') '
-            + ': helperMissing.call(' + helper.helperMissingParams + '))');
+      var functionLookupCode = ['(', this.itemsSeparatedBy(possibleFunctionCalls, '||'), ')'];
+      var functionCall = this.source.functionCall(functionLookupCode, 'call', helper.callParams);
+      this.push(functionCall);
+    },
 
-      // Always flush subexpressions. This is both to prevent the compounding size issue that
-      // occurs when the code has to be duplicated for inlining and also to prevent errors
-      // due to the incorrect options object being passed due to the shared register.
-      if (!isRoot) {
-        this.flushInline();
+    itemsSeparatedBy: function itemsSeparatedBy(items, separator) {
+      var result = [];
+      result.push(items[0]);
+      for (var i = 1; i < items.length; i++) {
+        result.push(separator, items[i]);
       }
+      return result;
     },
-
     // [invokeKnownHelper]
     //
     // On stack, before: hash, inverse, program, params..., ...
@@ -2292,9 +4552,9 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     //
     // This operation is used when the helper is known to exist,
     // so a `helperMissing` fallback is not required.
-    invokeKnownHelper: function(paramSize, name) {
+    invokeKnownHelper: function invokeKnownHelper(paramSize, name) {
       var helper = this.setupHelper(paramSize, name);
-      this.push(helper.name + ".call(" + helper.callParams + ")");
+      this.push(this.source.functionCall(helper.name, 'call', helper.callParams));
     },
 
     // [invokeAmbiguous]
@@ -2309,23 +4569,23 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     // This operation emits more code than the other options,
     // and can be avoided by passing the `knownHelpers` and
     // `knownHelpersOnly` flags at compile-time.
-    invokeAmbiguous: function(name, helperCall) {
-      this.context.aliases.functionType = '"function"';
+    invokeAmbiguous: function invokeAmbiguous(name, helperCall) {
       this.useRegister('helper');
 
+      var nonHelper = this.popStack();
+
       this.emptyHash();
       var helper = this.setupHelper(0, name, helperCall);
 
       var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
 
-      var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
-      var nextStack = this.nextStack();
-
-      if (helper.paramsInit) {
-        this.pushSource(helper.paramsInit);
+      var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')'];
+      if (!this.options.strict) {
+        lookup[0] = '(helper = ';
+        lookup.push(' != null ? helper : ', this.aliasable('container.hooks.helperMissing'));
       }
-      this.pushSource('if (helper = ' + helperName + ') { ' + nextStack + ' = helper.call(' + helper.callParams + '); }');
-      this.pushSource('else { helper = ' + nonHelper + '; ' + nextStack + ' = typeof helper === functionType ? helper.call(' + helper.callParams + ') : helper; }');
+
+      this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']);
     },
 
     // [invokePartial]
@@ -2335,120 +4595,165 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
     //
     // This operation pops off a context, invokes a partial with that context,
     // and pushes the result of the invocation back.
-    invokePartial: function(name) {
-      var params = [this.nameLookup('partials', name, 'partial'), "'" + name + "'", this.popStack(), "helpers", "partials"];
+    invokePartial: function invokePartial(isDynamic, name, indent) {
+      var params = [],
+          options = this.setupParams(name, 1, params);
 
-      if (this.options.data) {
-        params.push("data");
+      if (isDynamic) {
+        name = this.popStack();
+        delete options.name;
+      }
+
+      if (indent) {
+        options.indent = JSON.stringify(indent);
+      }
+      options.helpers = 'helpers';
+      options.partials = 'partials';
+      options.decorators = 'container.decorators';
+
+      if (!isDynamic) {
+        params.unshift(this.nameLookup('partials', name, 'partial'));
+      } else {
+        params.unshift(name);
       }
 
-      this.context.aliases.self = "this";
-      this.push("self.invokePartial(" + params.join(", ") + ")");
+      if (this.options.compat) {
+        options.depths = 'depths';
+      }
+      options = this.objectLiteral(options);
+      params.push(options);
+
+      this.push(this.source.functionCall('container.invokePartial', '', params));
     },
 
     // [assignToHash]
     //
-    // On stack, before: value, hash, ...
-    // On stack, after: hash, ...
+    // On stack, before: value, ..., hash, ...
+    // On stack, after: ..., hash, ...
     //
-    // Pops a value and hash off the stack, assigns `hash[key] = value`
-    // and pushes the hash back onto the stack.
-    assignToHash: function(key) {
+    // Pops a value off the stack and assigns it to the current hash
+    assignToHash: function assignToHash(key) {
       var value = this.popStack(),
-          context,
-          type;
+          context = undefined,
+          type = undefined,
+          id = undefined;
 
-      if (this.options.stringParams) {
+      if (this.trackIds) {
+        id = this.popStack();
+      }
+      if (this.stringParams) {
         type = this.popStack();
         context = this.popStack();
       }
 
       var hash = this.hash;
       if (context) {
-        hash.contexts.push("'" + key + "': " + context);
+        hash.contexts[key] = context;
       }
       if (type) {
-        hash.types.push("'" + key + "': " + type);
+        hash.types[key] = type;
+      }
+      if (id) {
+        hash.ids[key] = id;
+      }
+      hash.values[key] = value;
+    },
+
+    pushId: function pushId(type, name, child) {
+      if (type === 'BlockParam') {
+        this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : ''));
+      } else if (type === 'PathExpression') {
+        this.pushString(name);
+      } else if (type === 'SubExpression') {
+        this.pushStackLiteral('true');
+      } else {
+        this.pushStackLiteral('null');
       }
-      hash.values.push("'" + key + "': (" + value + ")");
     },
 
     // HELPERS
 
     compiler: JavaScriptCompiler,
 
-    compileChildren: function(environment, options) {
-      var children = environment.children, child, compiler;
+    compileChildren: function compileChildren(environment, options) {
+      var children = environment.children,
+          child = undefined,
+          compiler = undefined;
 
-      for(var i=0, l=children.length; i<l; i++) {
+      for (var i = 0, l = children.length; i < l; i++) {
         child = children[i];
-        compiler = new this.compiler();
+        compiler = new this.compiler(); // eslint-disable-line new-cap
 
-        var index = this.matchExistingProgram(child);
+        var existing = this.matchExistingProgram(child);
 
-        if (index == null) {
-          this.context.programs.push('');     // Placeholder to prevent name conflicts for nested children
-          index = this.context.programs.length;
+        if (existing == null) {
+          this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
+          var index = this.context.programs.length;
           child.index = index;
           child.name = 'program' + index;
-          this.context.programs[index] = compiler.compile(child, options, this.context);
+          this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile);
+          this.context.decorators[index] = compiler.decorators;
           this.context.environments[index] = child;
+
+          this.useDepths = this.useDepths || compiler.useDepths;
+          this.useBlockParams = this.useBlockParams || compiler.useBlockParams;
+          child.useDepths = this.useDepths;
+          child.useBlockParams = this.useBlockParams;
         } else {
-          child.index = index;
-          child.name = 'program' + index;
+          child.index = existing.index;
+          child.name = 'program' + existing.index;
+
+          this.useDepths = this.useDepths || existing.useDepths;
+          this.useBlockParams = this.useBlockParams || existing.useBlockParams;
         }
       }
     },
-    matchExistingProgram: function(child) {
+    matchExistingProgram: function matchExistingProgram(child) {
       for (var i = 0, len = this.context.environments.length; i < len; i++) {
         var environment = this.context.environments[i];
         if (environment && environment.equals(child)) {
-          return i;
+          return environment;
         }
       }
     },
 
-    programExpression: function(guid) {
-      this.context.aliases.self = "this";
-
-      if(guid == null) {
-        return "self.noop";
-      }
-
+    programExpression: function programExpression(guid) {
       var child = this.environment.children[guid],
-          depths = child.depths.list, depth;
-
-      var programParams = [child.index, child.name, "data"];
+          programParams = [child.index, 'data', child.blockParams];
 
-      for(var i=0, l = depths.length; i<l; i++) {
-        depth = depths[i];
-
-        if(depth === 1) { programParams.push("depth0"); }
-        else { programParams.push("depth" + (depth - 1)); }
+      if (this.useBlockParams || this.useDepths) {
+        programParams.push('blockParams');
+      }
+      if (this.useDepths) {
+        programParams.push('depths');
       }
 
-      return (depths.length === 0 ? "self.program(" : "self.programWithDepth(") + programParams.join(", ") + ")";
-    },
-
-    register: function(name, val) {
-      this.useRegister(name);
-      this.pushSource(name + " = " + val + ";");
+      return 'container.program(' + programParams.join(', ') + ')';
     },
 
-    useRegister: function(name) {
-      if(!this.registers[name]) {
+    useRegister: function useRegister(name) {
+      if (!this.registers[name]) {
         this.registers[name] = true;
         this.registers.list.push(name);
       }
     },
 
-    pushStackLiteral: function(item) {
-      return this.push(new Literal(item));
+    push: function push(expr) {
+      if (!(expr instanceof Literal)) {
+        expr = this.source.wrap(expr);
+      }
+
+      this.inlineStack.push(expr);
+      return expr;
+    },
+
+    pushStackLiteral: function pushStackLiteral(item) {
+      this.push(new Literal(item));
     },
 
-    pushSource: function(source) {
+    pushSource: function pushSource(source) {
       if (this.pendingContent) {
-        this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent)));
+        this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation));
         this.pendingContent = undefined;
       }
 
@@ -2457,106 +4762,85 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
       }
     },
 
-    pushStack: function(item) {
-      this.flushInline();
+    replaceStack: function replaceStack(callback) {
+      var prefix = ['('],
+          stack = undefined,
+          createdStack = undefined,
+          usedLiteral = undefined;
 
-      var stack = this.incrStack();
-      if (item) {
-        this.pushSource(stack + " = " + item + ";");
+      /* istanbul ignore next */
+      if (!this.isInline()) {
+        throw new _exception2['default']('replaceStack on non-inline');
       }
-      this.compileStack.push(stack);
-      return stack;
-    },
-
-    replaceStack: function(callback) {
-      var prefix = '',
-          inline = this.isInline(),
-          stack,
-          createdStack,
-          usedLiteral;
 
-      // If we are currently inline then we want to merge the inline statement into the
-      // replacement statement via ','
-      if (inline) {
-        var top = this.popStack(true);
-
-        if (top instanceof Literal) {
-          // Literals do not need to be inlined
-          stack = top.value;
-          usedLiteral = true;
-        } else {
-          // Get or create the current stack name for use by the inline
-          createdStack = !this.stackSlot;
-          var name = !createdStack ? this.topStackName() : this.incrStack();
+      // We want to merge the inline statement into the replacement statement via ','
+      var top = this.popStack(true);
 
-          prefix = '(' + this.push(name) + ' = ' + top + '),';
-          stack = this.topStack();
-        }
+      if (top instanceof Literal) {
+        // Literals do not need to be inlined
+        stack = [top.value];
+        prefix = ['(', stack];
+        usedLiteral = true;
       } else {
+        // Get or create the current stack name for use by the inline
+        createdStack = true;
+        var _name = this.incrStack();
+
+        prefix = ['((', this.push(_name), ' = ', top, ')'];
         stack = this.topStack();
       }
 
       var item = callback.call(this, stack);
 
-      if (inline) {
-        if (!usedLiteral) {
-          this.popStack();
-        }
-        if (createdStack) {
-          this.stackSlot--;
-        }
-        this.push('(' + prefix + item + ')');
-      } else {
-        // Prevent modification of the context depth variable. Through replaceStack
-        if (!/^stack/.test(stack)) {
-          stack = this.nextStack();
-        }
-
-        this.pushSource(stack + " = (" + prefix + item + ");");
+      if (!usedLiteral) {
+        this.popStack();
       }
-      return stack;
-    },
-
-    nextStack: function() {
-      return this.pushStack();
+      if (createdStack) {
+        this.stackSlot--;
+      }
+      this.push(prefix.concat(item, ')'));
     },
 
-    incrStack: function() {
+    incrStack: function incrStack() {
       this.stackSlot++;
-      if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
+      if (this.stackSlot > this.stackVars.length) {
+        this.stackVars.push('stack' + this.stackSlot);
+      }
       return this.topStackName();
     },
-    topStackName: function() {
-      return "stack" + this.stackSlot;
+    topStackName: function topStackName() {
+      return 'stack' + this.stackSlot;
     },
-    flushInline: function() {
+    flushInline: function flushInline() {
       var inlineStack = this.inlineStack;
-      if (inlineStack.length) {
-        this.inlineStack = [];
-        for (var i = 0, len = inlineStack.length; i < len; i++) {
-          var entry = inlineStack[i];
-          if (entry instanceof Literal) {
-            this.compileStack.push(entry);
-          } else {
-            this.pushStack(entry);
-          }
+      this.inlineStack = [];
+      for (var i = 0, len = inlineStack.length; i < len; i++) {
+        var entry = inlineStack[i];
+        /* istanbul ignore if */
+        if (entry instanceof Literal) {
+          this.compileStack.push(entry);
+        } else {
+          var stack = this.incrStack();
+          this.pushSource([stack, ' = ', entry, ';']);
+          this.compileStack.push(stack);
         }
       }
     },
-    isInline: function() {
+    isInline: function isInline() {
       return this.inlineStack.length;
     },
 
-    popStack: function(wrapped) {
+    popStack: function popStack(wrapped) {
       var inline = this.isInline(),
           item = (inline ? this.inlineStack : this.compileStack).pop();
 
-      if (!wrapped && (item instanceof Literal)) {
+      if (!wrapped && item instanceof Literal) {
         return item.value;
       } else {
         if (!inline) {
+          /* istanbul ignore next */
           if (!this.stackSlot) {
-            throw new Exception('Invalid stack pop');
+            throw new _exception2['default']('Invalid stack pop');
           }
           this.stackSlot--;
         }
@@ -2564,189 +4848,363 @@ var __module11__ = (function(__dependency1__, __dependency2__) {
       }
     },
 
-    topStack: function(wrapped) {
-      var stack = (this.isInline() ? this.inlineStack : this.compileStack),
+    topStack: function topStack() {
+      var stack = this.isInline() ? this.inlineStack : this.compileStack,
           item = stack[stack.length - 1];
 
-      if (!wrapped && (item instanceof Literal)) {
+      /* istanbul ignore if */
+      if (item instanceof Literal) {
         return item.value;
       } else {
         return item;
       }
     },
 
-    quotedString: function(str) {
-      return '"' + str
-        .replace(/\\/g, '\\\\')
-        .replace(/"/g, '\\"')
-        .replace(/\n/g, '\\n')
-        .replace(/\r/g, '\\r')
-        .replace(/\u2028/g, '\\u2028')   // Per Ecma-262 7.3 + 7.8.4
-        .replace(/\u2029/g, '\\u2029') + '"';
+    contextName: function contextName(context) {
+      if (this.useDepths && context) {
+        return 'depths[' + context + ']';
+      } else {
+        return 'depth' + context;
+      }
+    },
+
+    quotedString: function quotedString(str) {
+      return this.source.quotedString(str);
+    },
+
+    objectLiteral: function objectLiteral(obj) {
+      return this.source.objectLiteral(obj);
+    },
+
+    aliasable: function aliasable(name) {
+      var ret = this.aliases[name];
+      if (ret) {
+        ret.referenceCount++;
+        return ret;
+      }
+
+      ret = this.aliases[name] = this.source.wrap(name);
+      ret.aliasable = true;
+      ret.referenceCount = 1;
+
+      return ret;
     },
 
-    setupHelper: function(paramSize, name, missingParams) {
+    setupHelper: function setupHelper(paramSize, name, blockHelper) {
       var params = [],
-          paramsInit = this.setupParams(paramSize, params, missingParams);
-      var foundHelper = this.nameLookup('helpers', name, 'helper');
+          paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
+      var foundHelper = this.nameLookup('helpers', name, 'helper'),
+          callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : (container.nullContext || {})');
 
       return {
         params: params,
         paramsInit: paramsInit,
         name: foundHelper,
-        callParams: ["depth0"].concat(params).join(", "),
-        helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ")
+        callParams: [callContext].concat(params)
       };
     },
 
-    setupOptions: function(paramSize, params) {
-      var options = [], contexts = [], types = [], param, inverse, program;
+    setupParams: function setupParams(helper, paramSize, params) {
+      var options = {},
+          contexts = [],
+          types = [],
+          ids = [],
+          objectArgs = !params,
+          param = undefined;
+
+      if (objectArgs) {
+        params = [];
+      }
 
-      options.push("hash:" + this.popStack());
+      options.name = this.quotedString(helper);
+      options.hash = this.popStack();
 
-      if (this.options.stringParams) {
-        options.push("hashTypes:" + this.popStack());
-        options.push("hashContexts:" + this.popStack());
+      if (this.trackIds) {
+        options.hashIds = this.popStack();
+      }
+      if (this.stringParams) {
+        options.hashTypes = this.popStack();
+        options.hashContexts = this.popStack();
       }
 
-      inverse = this.popStack();
-      program = this.popStack();
+      var inverse = this.popStack(),
+          program = this.popStack();
 
       // Avoid setting fn and inverse if neither are set. This allows
       // helpers to do a check for `if (options.fn)`
       if (program || inverse) {
-        if (!program) {
-          this.context.aliases.self = "this";
-          program = "self.noop";
-        }
-
-        if (!inverse) {
-          this.context.aliases.self = "this";
-          inverse = "self.noop";
-        }
-
-        options.push("inverse:" + inverse);
-        options.push("fn:" + program);
+        options.fn = program || 'container.noop';
+        options.inverse = inverse || 'container.noop';
       }
 
-      for(var i=0; i<paramSize; i++) {
+      // The parameters go on to the stack in order (making sure that they are evaluated in order)
+      // so we need to pop them off the stack in reverse order
+      var i = paramSize;
+      while (i--) {
         param = this.popStack();
-        params.push(param);
+        params[i] = param;
 
-        if(this.options.stringParams) {
-          types.push(this.popStack());
-          contexts.push(this.popStack());
+        if (this.trackIds) {
+          ids[i] = this.popStack();
+        }
+        if (this.stringParams) {
+          types[i] = this.popStack();
+          contexts[i] = this.popStack();
         }
       }
 
-      if (this.options.stringParams) {
-        options.push("contexts:[" + contexts.join(",") + "]");
-        options.push("types:[" + types.join(",") + "]");
+      if (objectArgs) {
+        options.args = this.source.generateArray(params);
       }
 
-      if(this.options.data) {
-        options.push("data:data");
+      if (this.trackIds) {
+        options.ids = this.source.generateArray(ids);
+      }
+      if (this.stringParams) {
+        options.types = this.source.generateArray(types);
+        options.contexts = this.source.generateArray(contexts);
       }
 
+      if (this.options.data) {
+        options.data = 'data';
+      }
+      if (this.useBlockParams) {
+        options.blockParams = 'blockParams';
+      }
       return options;
     },
 
-    // the params and contexts arguments are passed in arrays
-    // to fill in
-    setupParams: function(paramSize, params, useRegister) {
-      var options = '{' + this.setupOptions(paramSize, params).join(',') + '}';
-
+    setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) {
+      var options = this.setupParams(helper, paramSize, params);
+      options.loc = JSON.stringify(this.source.currentLocation);
+      options = this.objectLiteral(options);
       if (useRegister) {
         this.useRegister('options');
         params.push('options');
-        return 'options=' + options;
-      } else {
+        return ['options=', options];
+      } else if (params) {
         params.push(options);
         return '';
+      } else {
+        return options;
       }
     }
   };
 
-  var reservedWords = (
-    "break else new var" +
-    " case finally return void" +
-    " catch for switch while" +
-    " continue function this with" +
-    " default if throw" +
-    " delete in try" +
-    " do instanceof typeof" +
-    " abstract enum int short" +
-    " boolean export interface static" +
-    " byte extends long super" +
-    " char final native synchronized" +
-    " class float package throws" +
-    " const goto private transient" +
-    " debugger implements protected volatile" +
-    " double import public let yield"
-  ).split(" ");
-
-  var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
-
-  for(var i=0, l=reservedWords.length; i<l; i++) {
-    compilerWords[reservedWords[i]] = true;
-  }
-
-  JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
-    if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) {
-      return true;
+  (function () {
+    var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' n [...]
+
+    var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
+
+    for (var i = 0, l = reservedWords.length; i < l; i++) {
+      compilerWords[reservedWords[i]] = true;
     }
-    return false;
+  })();
+
+  /**
+   * @deprecated May be removed in the next major version
+   */
+  JavaScriptCompiler.isValidJavaScriptVariableName = function (name) {
+    return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name);
   };
 
-  __exports__ = JavaScriptCompiler;
-  return __exports__;
-})(__module2__, __module5__);
+  function strictLookup(requireTerminal, compiler, parts, type) {
+    var stack = compiler.popStack(),
+        i = 0,
+        len = parts.length;
+    if (requireTerminal) {
+      len--;
+    }
 
-// handlebars.js
-var __module0__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
-  "use strict";
-  var __exports__;
-  /*globals Handlebars: true */
-  var Handlebars = __dependency1__;
+    for (; i < len; i++) {
+      stack = compiler.nameLookup(stack, parts[i], type);
+    }
 
-  // Compiler imports
-  var AST = __dependency2__;
-  var Parser = __dependency3__.parser;
-  var parse = __dependency3__.parse;
-  var Compiler = __dependency4__.Compiler;
-  var compile = __dependency4__.compile;
-  var precompile = __dependency4__.precompile;
-  var JavaScriptCompiler = __dependency5__;
-
-  var _create = Handlebars.create;
-  var create = function() {
-    var hb = _create();
+    if (requireTerminal) {
+      return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ', ', JSON.stringify(compiler.source.currentLocation), ' )'];
+    } else {
+      return stack;
+    }
+  }
+
+  exports['default'] = JavaScriptCompiler;
+  module.exports = exports['default'];
+
+/***/ }),
+/* 53 */
+/***/ (function(module, exports, __webpack_require__) {
+
+  /* global define */
+  'use strict';
+
+  var _Object$keys = __webpack_require__(13)['default'];
+
+  exports.__esModule = true;
 
-    hb.compile = function(input, options) {
-      return compile(input, options, hb);
+  var _utils = __webpack_require__(5);
+
+  var SourceNode = undefined;
+
+  try {
+    /* istanbul ignore next */
+    if (false) {
+      // We don't support this in AMD environments. For these environments, we asusme that
+      // they are running on the browser and thus have no need for the source-map library.
+      var SourceMap = require('source-map');
+      SourceNode = SourceMap.SourceNode;
+    }
+  } catch (err) {}
+  /* NOP */
+
+  /* istanbul ignore if: tested but not covered in istanbul due to dist build  */
+  if (!SourceNode) {
+    SourceNode = function (line, column, srcFile, chunks) {
+      this.src = '';
+      if (chunks) {
+        this.add(chunks);
+      }
     };
-    hb.precompile = function (input, options) {
-      return precompile(input, options, hb);
+    /* istanbul ignore next */
+    SourceNode.prototype = {
+      add: function add(chunks) {
+        if (_utils.isArray(chunks)) {
+          chunks = chunks.join('');
+        }
+        this.src += chunks;
+      },
+      prepend: function prepend(chunks) {
+        if (_utils.isArray(chunks)) {
+          chunks = chunks.join('');
+        }
+        this.src = chunks + this.src;
+      },
+      toStringWithSourceMap: function toStringWithSourceMap() {
+        return { code: this.toString() };
+      },
+      toString: function toString() {
+        return this.src;
+      }
     };
+  }
 
-    hb.AST = AST;
-    hb.Compiler = Compiler;
-    hb.JavaScriptCompiler = JavaScriptCompiler;
-    hb.Parser = Parser;
-    hb.parse = parse;
+  function castChunk(chunk, codeGen, loc) {
+    if (_utils.isArray(chunk)) {
+      var ret = [];
 
-    return hb;
-  };
+      for (var i = 0, len = chunk.length; i < len; i++) {
+        ret.push(codeGen.wrap(chunk[i], loc));
+      }
+      return ret;
+    } else if (typeof chunk === 'boolean' || typeof chunk === 'number') {
+      // Handle primitives that the SourceNode will throw up on
+      return chunk + '';
+    }
+    return chunk;
+  }
+
+  function CodeGen(srcFile) {
+    this.srcFile = srcFile;
+    this.source = [];
+  }
+
+  CodeGen.prototype = {
+    isEmpty: function isEmpty() {
+      return !this.source.length;
+    },
+    prepend: function prepend(source, loc) {
+      this.source.unshift(this.wrap(source, loc));
+    },
+    push: function push(source, loc) {
+      this.source.push(this.wrap(source, loc));
+    },
+
+    merge: function merge() {
+      var source = this.empty();
+      this.each(function (line) {
+        source.add(['  ', line, '\n']);
+      });
+      return source;
+    },
+
+    each: function each(iter) {
+      for (var i = 0, len = this.source.length; i < len; i++) {
+        iter(this.source[i]);
+      }
+    },
 
-  Handlebars = create();
-  Handlebars.create = create;
+    empty: function empty() {
+      var loc = this.currentLocation || { start: {} };
+      return new SourceNode(loc.start.line, loc.start.column, this.srcFile);
+    },
+    wrap: function wrap(chunk) {
+      var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1];
+
+      if (chunk instanceof SourceNode) {
+        return chunk;
+      }
+
+      chunk = castChunk(chunk, this, loc);
+
+      return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk);
+    },
+
+    functionCall: function functionCall(fn, type, params) {
+      params = this.generateList(params);
+      return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']);
+    },
+
+    quotedString: function quotedString(str) {
+      return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
+      .replace(/\u2029/g, '\\u2029') + '"';
+    },
+
+    objectLiteral: function objectLiteral(obj) {
+      // istanbul ignore next
+
+      var _this = this;
+
+      var pairs = [];
+
+      _Object$keys(obj).forEach(function (key) {
+        var value = castChunk(obj[key], _this);
+        if (value !== 'undefined') {
+          pairs.push([_this.quotedString(key), ':', value]);
+        }
+      });
+
+      var ret = this.generateList(pairs);
+      ret.prepend('{');
+      ret.add('}');
+      return ret;
+    },
+
+    generateList: function generateList(entries) {
+      var ret = this.empty();
+
+      for (var i = 0, len = entries.length; i < len; i++) {
+        if (i) {
+          ret.add(',');
+        }
+
+        ret.add(castChunk(entries[i], this));
+      }
+
+      return ret;
+    },
+
+    generateArray: function generateArray(entries) {
+      var ret = this.generateList(entries);
+      ret.prepend('[');
+      ret.add(']');
+
+      return ret;
+    }
+  };
 
-  __exports__ = Handlebars;
-  return __exports__;
-})(__module1__, __module7__, __module8__, __module10__, __module11__);
+  exports['default'] = CodeGen;
+  module.exports = exports['default'];
 
-  return __module0__;
-})();
-// Begin AMD Wrapper
-return Handlebars; });
-// End AMD Wrapper
+/***/ })
+/******/ ])
+});
+;
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/hbs.js b/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/hbs.js
index a40eb98..661a59c 100644
--- a/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/hbs.js
+++ b/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/hbs.js
@@ -1,5 +1,5 @@
 /**
- * @license handlebars hbs 0.4.0 - Alex Sexton, but Handlebars has it's own licensing junk
+ * @license Handlebars hbs 2.0.0 - Alex Sexton, but Handlebars has its own licensing junk
  *
  * Available via the MIT or new BSD license.
  * see: http://github.com/jrburke/require-cs for details on the plugin this was based off of
@@ -9,450 +9,645 @@
 /*jslint evil: true, strict: false, plusplus: false, regexp: false */
 /*global require: false, XMLHttpRequest: false, ActiveXObject: false,
 define: false, process: false, window: false */
-define([
-//>>excludeStart('excludeHbs', pragmas.excludeHbs)
-'handlebars', 'underscore', 'i18nprecompile'
-//>>excludeEnd('excludeHbs')
-], function (
-//>>excludeStart('excludeHbs', pragmas.excludeHbs)
- Handlebars, _, precompile
-//>>excludeEnd('excludeHbs')
-) {
-//>>excludeStart('excludeHbs', pragmas.excludeHbs)
-  var fs, getXhr,
-        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
-        fetchText = function () {
-            throw new Error('Environment unsupported.');
-        },
-        buildMap = [],
-        filecode = "w+",
-        templateExtension = "hbs",
-        customNameExtension = "@hbs",
-        devStyleDirectory = "/styles/",
-        buildStyleDirectory = "/demo-build/styles/",
-        helperDirectory = "template/helpers/",
-        i18nDirectory = "template/i18n/",
-        buildCSSFileName = "screen.build.css";
-
-    if (typeof window !== "undefined" && window.navigator && window.document && !window.navigator.userAgent.match(/Node.js/)) {
-        // Browser action
-        getXhr = function () {
-            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
-            var xhr, i, progId;
-            if (typeof XMLHttpRequest !== "undefined") {
-                return new XMLHttpRequest();
-            } else {
-                for (i = 0; i < 3; i++) {
-                    progId = progIds[i];
-                    try {
-                        xhr = new ActiveXObject(progId);
-                    } catch (e) {}
-
-                    if (xhr) {
-                        progIds = [progId];  // so faster next time
-                        break;
-                    }
-                }
-            }
+define(['handlebars', 'underscore'], function (Handlebars, _) {
+  function precompile(string, _unused, options) {
+    var ast, environment;
 
-            if (!xhr) {
-                throw new Error("getXhr(): XMLHttpRequest not available");
-            }
+    options = options || {};
 
-            return xhr;
-        };
-
-        fetchText = function (url, callback) {
-            var xhr = getXhr();
-            xhr.open('GET', url, true);
-            xhr.onreadystatechange = function (evt) {
-                //Do not explicitly handle errors, those should be
-                //visible via console output in the browser.
-                if (xhr.readyState === 4) {
-                    callback(xhr.responseText);
-                }
-            };
-            xhr.send(null);
-        };
+    if (!('data' in options)) {
+      options.data = true;
+    }
 
-    } else if (typeof process !== "undefined" &&
-               process.versions &&
-               !!process.versions.node) {
-        //Using special require.nodeRequire, something added by r.js.
-        fs = require.nodeRequire('fs');
-        fetchText = function ( path, callback ) {
-            var body = fs.readFileSync(path, 'utf8') || "";
-            // we need to remove BOM stuff from the file content
-            body = body.replace(/^\uFEFF/, '');
-            callback(body);
-        };
-    } else if (typeof java !== "undefined" && typeof java.io !== "undefined") {
-        fetchText = function(path, callback) {
-            var f = new java.io.File(path);
-            var is = new java.io.FileReader(f);
-            var reader = new java.io.BufferedReader(is);
-            var line;
-            var text = "";
-            while ((line = reader.readLine()) !== null) {
-                text += new String(line) + "\n";
-            }
-            reader.close();
-            callback(text);
-        };
+    if (options.compat) {
+      options.useDepths = true;
     }
 
-    var cache = {};
-    var fetchOrGetCached = function ( path, callback ){
-      if ( cache[path] ){
-        callback(cache[path]);
+    ast = Handlebars.parse(string);
+
+    environment = new Handlebars.Compiler().compile(ast, options);
+    return new Handlebars.JavaScriptCompiler().compile(environment, options);
+  }
+
+  var fs;
+  var getXhr;
+  var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
+  var fetchText = function () {
+      throw new Error('Environment unsupported.');
+  };
+  var buildMap = [];
+  var filecode = 'w+';
+  var templateExtension = 'hbs';
+  var customNameExtension = '@hbs';
+  var devStyleDirectory = '/styles/';
+  var buildStyleDirectory = '/demo-build/styles/';
+  var helperDirectory = 'templates/helpers/';
+  var buildCSSFileName = 'screen.build.css';
+  var onHbsReadMethod = "onHbsRead";
+
+  Handlebars.registerHelper('$', function() {
+    //placeholder for translation helper
+  });
+
+  if (typeof window !== 'undefined' && window.navigator && window.document && !window.navigator.userAgent.match(/Node.js/)) {
+    // Browser action
+    getXhr = function () {
+      // Would love to dump the ActiveX crap in here. Need IE 6 to die first.
+      var xhr;
+      var i;
+      var progId;
+      if (typeof XMLHttpRequest !== 'undefined') {
+        return ((arguments[0] === true)) ? new XDomainRequest() : new XMLHttpRequest();
       }
       else {
-        fetchText(path, function(data){
-          cache[path] = data;
-          callback.call(this, data);
-        });
+        for (i = 0; i < 3; i++) {
+          progId = progIds[i];
+          try {
+            xhr = new ActiveXObject(progId);
+          }
+          catch (e) {}
+
+          if (xhr) {
+            // Faster next time
+            progIds = [progId];
+            break;
+          }
+        }
+      }
+
+      if (!xhr) {
+          throw new Error('getXhr(): XMLHttpRequest not available');
       }
+
+      return xhr;
     };
-    var styleList = [], styleMap = {};
-//>>excludeEnd('excludeHbs')
 
-      return {
+    // Returns the version of Windows Internet Explorer or a -1
+    // (indicating the use of another browser).
+    // Note: this is only for development mode. Does not run in production.
+    getIEVersion = function(){
+      // Return value assumes failure.
+      var rv = -1;
+      if (navigator.appName == 'Microsoft Internet Explorer') {
+        var ua = navigator.userAgent;
+        var re = new RegExp('MSIE ([0-9]{1,}[\.0-9]{0,})');
+        if (re.exec(ua) != null) {
+          rv = parseFloat( RegExp.$1 );
+        }
+      }
+      return rv;
+    };
 
-        get: function () {
-            return Handlebars;
-        },
+    fetchText = function (url, callback) {
+      var xdm = false;
+      // If url is a fully qualified URL, it might be a cross domain request. Check for that.
+      // IF url is a relative url, it cannot be cross domain.
+      if (url.indexOf('http') != 0 ){
+          xdm = false;
+      }else{
+          var uidx = (url.substr(0,5) === 'https') ? 8 : 7;
+          var hidx = (window.location.href.substr(0,5) === 'https') ? 8 : 7;
+          var dom = url.substr(uidx).split('/').shift();
+          var msie = getIEVersion();
+              xdm = ( dom != window.location.href.substr(hidx).split('/').shift() ) && (msie >= 7);
+      }
 
-        write: function (pluginName, name, write) {
+      if ( xdm ) {
+         var xdr = getXhr(true);
+        xdr.open('GET', url);
+        xdr.onload = function() {
+          callback(xdr.responseText, url);
+        };
+        xdr.onprogress = function(){};
+        xdr.ontimeout = function(){};
+        xdr.onerror = function(){};
+        setTimeout(function(){
+          xdr.send();
+        }, 0);
+      }
+      else {
+        var xhr = getXhr();
+        xhr.open('GET', url, true);
+        xhr.onreadystatechange = function (evt) {
+          //Do not explicitly handle errors, those should be
+          //visible via console output in the browser.
+          if (xhr.readyState === 4) {
+            callback(xhr.responseText, url);
+          }
+        };
+        xhr.send(null);
+      }
+    };
 
-            if ( (name + customNameExtension ) in buildMap) {
-                var text = buildMap[name + customNameExtension];
-                write.asModule(pluginName + "!" + name, text);
-            }
-        },
+  }
+  else if (
+    typeof process !== 'undefined' &&
+    process.versions &&
+    !!process.versions.node
+  ) {
+    //Using special require.nodeRequire, something added by r.js.
+    fs = require.nodeRequire('fs');
+    fetchText = function ( path, callback ) {
+      var body = fs.readFileSync(path, 'utf8') || '';
+      // we need to remove BOM stuff from the file content
+      body = body.replace(/^\uFEFF/, '');
+      callback(body, path);
+    };
+  }
+  else if (typeof java !== 'undefined' && typeof java.io !== 'undefined') {
+    fetchText = function(path, callback) {
+      var fis = new java.io.FileInputStream(path);
+      var streamReader = new java.io.InputStreamReader(fis, "UTF-8");
+      var reader = new java.io.BufferedReader(streamReader);
+      var line;
+      var text = '';
+      while ((line = reader.readLine()) !== null) {
+        text += new String(line) + '\n';
+      }
+      reader.close();
+      callback(text, path);
+    };
+  }
 
-        version: '0.4.0',
+  var cache = {};
+  var fetchOrGetCached = function ( path, callback ){
+    if ( cache[path] ){
+      callback(cache[path]);
+    }
+    else {
+      fetchText(path, function(data, path){
+        cache[path] = data;
+        callback.call(this, data);
+      });
+    }
+  };
+  var styleList = [];
+  var styleMap = {};
 
-        load: function (name, parentRequire, load, config) {
-          //>>excludeStart('excludeHbs', pragmas.excludeHbs)
+  var config;
+  var filesToRemove = [];
 
-            var compiledName = name + customNameExtension,
-                disableI18n = (config.hbs && config.hbs.disableI18n),
-                partialDeps = [];
+  return {
 
-            function recursiveNodeSearch( statements, res ) {
-              _(statements).forEach(function ( statement ) {
-                if ( statement && statement.type && statement.type === 'partial' ) {
-                    res.push(statement.id.string);
-                }
-                if ( statement && statement.program && statement.program.statements ) {
-                  recursiveNodeSearch( statement.program.statements, res );
-                }
-                if ( statement && statement.program && statement.program.inverse && statement.program.inverse.statements ) {
-                  recursiveNodeSearch( statement.program.inverse.statements, res );
-                }
-              });
-              return res;
-            }
+    get: function () {
+      return Handlebars;
+    },
 
-            // TODO :: use the parser to do this!
-            function findPartialDeps( nodes ) {
-              var res   = [];
-              if ( nodes && nodes.statements ) {
-                res = recursiveNodeSearch( nodes.statements, [] );
-              }
-              return _(res).unique();
-            }
+    write: function (pluginName, name, write) {
+      if ( (name + customNameExtension ) in buildMap) {
+        var text = buildMap[name + customNameExtension];
+        write.asModule(pluginName + '!' + name, text);
+      }
+    },
 
-            // See if the first item is a comment that's json
-            function getMetaData( nodes ) {
-              var statement, res, test;
-              if ( nodes && nodes.statements ) {
-                statement = nodes.statements[0];
-                if ( statement && statement.type === "comment" ) {
-                  try {
-                    res = ( statement.comment ).replace(new RegExp('^[\\s]+|[\\s]+$', 'g'), '');
-                    test = JSON.parse(res);
-                    return res;
-                  }
-                  catch (e) {
-                    return "{}";
-                  }
-                }
-              }
-              return "{}";
+    version: '3.0.3',
+
+    load: function (name, parentRequire, load, _config) {
+      config = config || _config;
+
+      var compiledName = name + customNameExtension;
+      config.hbs = config.hbs || {};
+      var disableHelpers = (config.hbs.helpers == false); // be default we enable helpers unless config.hbs.helpers is false
+      var partialsUrl = '';
+      if(config.hbs.partialsUrl) {
+        partialsUrl = config.hbs.partialsUrl;
+        if(!partialsUrl.match(/\/$/)) partialsUrl += '/';
+      }
+
+      // Let redefine default fetchText
+      if(config.hbs.fetchText) {
+          fetchText = config.hbs.fetchText;
+      }
+
+      var partialDeps = [];
+
+      function recursiveNodeSearch( statements, res ) {
+        _(statements).forEach(function ( statement ) {
+          if ( statement && statement.type && statement.type === 'PartialStatement' ) {
+          //Don't register dynamic partials as undefined
+            if(statement.name.type !== "SubExpression"){
+              res.push(statement.name.original);
             }
-            function composeParts ( parts ) {
-              if ( !parts ) {
-                return [];
-              }
-              var res = [parts[0]],
-                  cur = parts[0],
-                  i;
-
-              for (i = 1; i < parts.length; ++i) {
-                if ( parts.hasOwnProperty(i) ) {
-                  cur += "." + parts[i];
-                  res.push( cur );
-                }
-              }
+          }
+          if ( statement && statement.program && statement.program.body ) {
+            recursiveNodeSearch( statement.program.body, res );
+          }
+          if ( statement && statement.inverse && statement.inverse.body ) {
+            recursiveNodeSearch( statement.inverse.body, res );
+          }
+        });
+        return res;
+      }
+
+      // TODO :: use the parser to do this!
+      function findPartialDeps( nodes , metaObj) {
+        var res = [];
+        if ( nodes && nodes.body ) {
+          res = recursiveNodeSearch( nodes.body, [] );
+        }
+
+        if(metaObj && metaObj.partials && metaObj.partials.length){
+          _(metaObj.partials).forEach(function ( partial ) {
+            res.push(partial);
+          });
+        }
+
+        return _.unique(res);
+      }
+
+      // See if the first item is a comment that's json
+      function getMetaData( nodes ) {
+        var statement, res, test;
+        if ( nodes && nodes.body ) {
+          statement = nodes.body[0];
+          if ( statement && statement.type === 'CommentStatement' ) {
+            try {
+              res = ( statement.value ).replace(new RegExp('^[\\s]+|[\\s]+$', 'g'), '');
+              test = JSON.parse(res);
               return res;
             }
+            catch (e) {
+              return JSON.stringify({
+                description: res
+              });
+            }
+          }
+        }
+        return '{}';
+      }
 
-            function recursiveVarSearch( statements, res, prefix, helpersres ) {
-              prefix = prefix ? prefix+"." : "";
+      function composeParts ( parts ) {
+        if ( !parts ) {
+          return [];
+        }
+        var res = [parts[0]];
+        var cur = parts[0];
+        var i;
+
+        for (i = 1; i < parts.length; ++i) {
+          if ( parts.hasOwnProperty(i) ) {
+            cur += '.' + parts[i];
+            res.push( cur );
+          }
+        }
+        return res;
+      }
 
-              var  newprefix = "", flag = false;
+      //Taken from Handlebar.AST.helpers.helperExpression with slight modification
+      function isHelper(statement){
+        return !!(statement.type === 'SubExpression' || (statement.params && statement.params.length) || statement.hash);
+      }
 
-              // loop through each statement
-              _(statements).forEach(function ( statement ) {
-                var parts, part, sideways;
+      function checkStatementForHelpers(statement, helpersres){
 
-                // if it's a mustache block
-                if ( statement && statement.type && statement.type === 'mustache' ) {
+        if(isHelper(statement)){
+          if(typeof statement.path !== 'undefined'){
+            registerHelper(statement.path.original,helpersres);
+          }
+        }
 
-                  // If it has params, the first part is a helper or something
-                  if ( !statement.params || ! statement.params.length ) {
-                    parts = composeParts( statement.id.parts );
-                    for( part in parts ) {
-                      if ( parts[ part ] ) {
-                        newprefix = parts[ part ] || newprefix;
-                        res.push( prefix + parts[ part ] );
-                      }
-                    }
-                    res.push(prefix + statement.id.string);
-                  }
+        if(statement && statement.params){
+          statement.params.forEach(function (param) {
+            checkStatementForHelpers(param, helpersres);
+          });
+        }
 
-                  var paramsWithoutParts = ['this', '.', '..', './..', '../..', '../../..'];
+        if(statement && statement.hash && statement.hash.pairs){
+          _(statement.hash.pairs).forEach(function(pair) {
+            checkStatementForHelpers(pair.value, helpersres);
+          });
+        }
+      }
 
-                  // grab the params
-                  if ( statement.params ) {
-                    _(statement.params).forEach(function(param) {
-                      if ( _(paramsWithoutParts).contains(param.original) ) {
-                        helpersres.push(statement.id.string);
-                      }
+      function registerHelper(helperName,helpersres){
+        if(typeof Handlebars.helpers[helperName] === 'undefined'){
+          helpersres.push(helperName);
+        }
+      }
 
-                      parts = composeParts( param.parts );
+      function recursiveVarSearch( statements, res, prefix, helpersres ) {
+        prefix = prefix ? prefix + '.' : '';
+
+        var  newprefix = '';
+        var flag = false;
+
+        // loop through each statement
+        _(statements).forEach(function(statement) {
+          var parts;
+          var part;
+          var sideways;
+
+          //Its a helper or a mustache statement
+          if (isHelper(statement) || statement.type === 'MustacheStatement') {
+            checkStatementForHelpers(statement, helpersres);
+          }
+
+          // If it's a meta block, not sure what this is. It should probably never happen
+          if ( statement && statement.mustache  ) {
+            recursiveVarSearch( [statement.mustache], res, prefix + newprefix, helpersres );
+          }
+
+          // if it's a whole new program
+          if ( statement && statement.program && statement.program.body ) {
+            sideways = recursiveVarSearch([statement.path],[], '', helpersres)[0] || '';
+            if ( statement.inverse && statement.inverse.body ) {
+             recursiveVarSearch( statement.inverse.body, res, prefix + newprefix + (sideways ? (prefix+newprefix) ? '.'+sideways : sideways : ''), helpersres);
+            }
+            recursiveVarSearch( statement.program.body, res, prefix + newprefix + (sideways ? (prefix+newprefix) ? '.'+sideways : sideways : ''), helpersres);
+          }
+        });
+        return res;
+      }
 
-                      for(var part in parts ) {
-                        if ( parts[ part ] ) {
-                          newprefix = parts[part] || newprefix;
-                          helpersres.push(statement.id.string);
-                          res.push( prefix + parts[ part ] );
-                        }
-                      }
-                    });
-                  }
-                }
+      // This finds the Helper dependencies since it's soooo similar
+      function getExternalDeps( nodes ) {
+        var res   = [];
+        var helpersres = [];
 
-                // If it's a meta block
-                if ( statement && statement.mustache  ) {
-                  recursiveVarSearch( [statement.mustache], res, prefix + newprefix, helpersres );
-                }
+        if ( nodes && nodes.body ) {
+          res = recursiveVarSearch( nodes.body, [], undefined, helpersres );
+        }
 
-                // if it's a whole new program
-                if ( statement && statement.program && statement.program.statements ) {
-                  sideways = recursiveVarSearch([statement.mustache],[], "", helpersres)[0] || "";
-                  if ( statement.program.inverse && statement.program.inverse.statements ) {
-                    recursiveVarSearch( statement.program.inverse.statements, res, prefix + newprefix + (sideways ? (prefix+newprefix) ? "."+sideways : sideways : ""), helpersres);
-                  }
-                  recursiveVarSearch( statement.program.statements, res, prefix + newprefix + (sideways ? (prefix+newprefix) ? "."+sideways : sideways : ""), helpersres);
-                }
-              });
-              return res;
+        var defaultHelpers = [
+          'helperMissing',
+          'blockHelperMissing',
+          'each',
+          'if',
+          'unless',
+          'with',
+          'log',
+          'lookup'
+        ];
+
+        return {
+          vars: _(res).chain().unique().map(function(e) {
+            if ( e === '' ) {
+              return '.';
             }
+            if ( e.length && e[e.length-1] === '.' ) {
+              return e.substr(0,e.length-1) + '[]';
+            }
+            return e;
+          }).value(),
 
-            // This finds the Helper dependencies since it's soooo similar
-            function getExternalDeps( nodes ) {
-              var res   = [];
-              var helpersres = [];
+          helpers: _(helpersres).chain().unique().map(function(e){
+            if ( _(defaultHelpers).contains(e) ) {
+              return undefined;
+            }
+            return e;
+          }).compact().value()
+        };
+      }
 
-              if ( nodes && nodes.statements ) {
-                res = recursiveVarSearch( nodes.statements, [], undefined, helpersres );
-              }
+      function cleanPath(path) {
+        var tokens = path.split('/');
+        for(var i=0;i<tokens.length; i++) {
+          if(tokens[i] === '..') {
+            delete tokens[i-1];
+            delete tokens[i];
+          } else if (tokens[i] === '.') {
+            delete tokens[i];
+          }
+        }
+        return tokens.join('/').replace(/\/\/+/g,'/');
+      }
 
-              var defaultHelpers = ["helperMissing", "blockHelperMissing", "each", "if", "unless", "with"];
-
-              return {
-                vars : _(res).chain().unique().map(function(e){
-                  if ( e === "" ) {
-                    return '.';
-                  }
-                  if ( e.length && e[e.length-1] === '.' ) {
-                    return e.substr(0,e.length-1) + '[]';
-                  }
-                  return e;
-                }).value(),
-                helpers : _(helpersres).chain().unique().map(function(e){
-                  if ( _(defaultHelpers).contains(e) ) {
-                    return undefined;
-                  }
-                  return e;
-                }).compact().value()
-              };
+      function fetchAndRegister(langMap) {
+        fetchText(path, function(text, path) {
+
+          var readCallback = (config.isBuild && config[onHbsReadMethod]) ? config[onHbsReadMethod]:  function(name,path,text){return text} ;
+          // for some reason it doesn't include hbs _first_ when i don't add it here...
+          var nodes = Handlebars.parse( readCallback(name, path, text));
+          var meta = getMetaData( nodes );
+          var extDeps = getExternalDeps( nodes );
+          var vars = extDeps.vars;
+          var helps = (extDeps.helpers || []);
+          var debugOutputStart = '';
+          var debugOutputEnd   = '';
+          var debugProperties = '';
+          var deps = [];
+          var depStr, helpDepStr, metaObj, head, linkElem;
+          var baseDir = name.substr(0,name.lastIndexOf('/')+1);
+
+          if(meta !== '{}') {
+            try {
+              metaObj = JSON.parse(meta);
+            } catch(e) {
+              console.log('couldn\'t parse meta for %s', path);
             }
+          }
+          var partials = findPartialDeps( nodes,metaObj );
+          config.hbs = config.hbs || {};
+          config.hbs._partials = config.hbs._partials || {};
+
+          for ( var i in partials ) {
+            if ( partials.hasOwnProperty(i) && typeof partials[i] === 'string') {  // make sure string, because we're iterating over all props
+              var partialReference = partials[i];
+
+              var partialPath;
+              if(partialReference.match(/^(\.|\/)+/)) {
+                // relative path
+                partialPath = cleanPath(baseDir + partialReference);
+              }
+              else {
+                // absolute path relative to config.hbs.partialsUrl if defined
+                partialPath = cleanPath(partialsUrl + partialReference);
+              }
 
-            function fetchAndRegister(langMap){
-              fetchText(path, function (text) {
-                  // for some reason it doesn't include hbs _first_ when i don't add it here...
-                  var nodes = Handlebars.parse(text),
-                      deps = findPartialDeps( nodes ),
-                      meta = getMetaData( nodes ),
-                      extDeps = getExternalDeps( nodes ),
-                      vars = extDeps.vars,
-                      helps = extDeps.helpers || [],
-                      depStr = deps.join("', 'hbs!").replace(/_/g, '/'),
-                      helpDepStr = config.hbs && config.hbs.disableHelpers ?
-                      "" : (function (){
-                        var i, paths = [],
-                            pathGetter = config.hbs && config.hbs.helperPathCallback
-                              ? config.hbs.helperPathCallback
-                              : function (name){return (config.hbs && config.hbs.helperDirectory ? config.hbs.helperDirectory : helperDirectory) + name;};
-
-                        for ( i = 0; i < helps.length; i++ ) {
-                          paths[i] = "'" + pathGetter(helps[i]) + "'"
-                        }
-                        return paths;
-                      })().join(','),
-                      debugOutputStart = "",
-                      debugOutputEnd   = "",
-                      debugProperties = "",
-                      metaObj, head, linkElem;
-
-                  if ( depStr ) {
-                    depStr = ",'hbs!" + depStr + "'";
-                  }
-                  if ( helpDepStr ) {
-                    helpDepStr = "," + helpDepStr;
-                  }
-
-                  if ( meta !== "{}" ) {
-                    try {
-                      metaObj = JSON.parse(meta);
-                      if ( metaObj && metaObj.styles ) {
-                        styleList = _.union(styleList, metaObj.styles);
-
-                        // In dev mode in the browser
-                        if ( require.isBrowser && ! config.isBuild ) {
-                          head = document.head || document.getElementsByTagName('head')[0];
-                          _(metaObj.styles).forEach(function (style) {
-                            if ( !styleMap[style] ) {
-                              linkElem = document.createElement('link');
-                              linkElem.href = config.baseUrl + devStyleDirectory + style + '.css';
-                              linkElem.media = 'all';
-                              linkElem.rel = 'stylesheet';
-                              linkElem.type = 'text/css';
-                              head.appendChild(linkElem);
-                              styleMap[style] = linkElem;
-                            }
-                          });
-                        }
-                        else if ( config.isBuild ) {
-                          (function(){
-                            var fs  = require.nodeRequire('fs'),
-                                str = _(metaObj.styles).map(function (style) {
-                                  if (!styleMap[style]) {
-                                    styleMap[style] = true;
-                                    return "@import url("+style+".css);\n";
-                                  }
-                                  return "";
-                                }).join("\n");
-
-                            // I write out my import statements to a file in order to help me build stuff.
-                            // Then I use a tool to inline my import statements afterwards. (you can run r.js on it too)
-                            fs.open(__dirname + buildStyleDirectory + buildCSSFileName, filecode, '0666', function( e, id ) {
-                              fs.writeSync(id, str, null, encoding='utf8');
-                              fs.close(id);
-                            });
-                            filecode = "a";
-                          })();
-                        }
-                      }
-                    }
-                    catch(e){
-                      console.log('error injecting styles');
-                    }
-                  }
-
-                  if ( ! config.isBuild && ! config.serverRender ) {
-                    debugOutputStart = "<!-- START - " + name + " -->";
-                    debugOutputEnd = "<!-- END - " + name + " -->";
-                    debugProperties = "t.meta = " + meta + ";\n" +
-                                      "t.helpers = " + JSON.stringify(helps) + ";\n" +
-                                      "t.deps = " + JSON.stringify(deps) + ";\n" +
-                                      "t.vars = " + JSON.stringify(vars) + ";\n";
-                  }
-
-                  var mapping = disableI18n? false : _.extend( langMap, config.localeMapping ),
-                      prec = precompile( text, mapping, { originalKeyFallback: (config.hbs || {}).originalKeyFallback });
-
-                  text = "/* START_TEMPLATE */\n" +
-                         "define(['hbs','handlebars'"+depStr+helpDepStr+"], function( hbs, Handlebars ){ \n" +
-                           "var t = Handlebars.template(" + prec + ");\n" +
-                           "Handlebars.registerPartial('" + name.replace( /\//g , '_') + "', t);\n" +
-                           debugProperties +
-                           "return t;\n" +
-                         "});\n" +
-                         "/* END_TEMPLATE */\n";
-
-                  //Hold on to the transformed text if a build.
-                  if (config.isBuild) {
-                      buildMap[compiledName] = text;
-                  }
-
-                  //IE with conditional comments on cannot handle the
-                  //sourceURL trick, so skip it if enabled.
-                  /*@if (@_jscript) @else @*/
-                  if (!config.isBuild) {
-                      text += "\r\n//@ sourceURL=" + path;
-                  }
-                  /*@end@*/
-
-                  for ( var i in deps ) {
-                    if ( deps.hasOwnProperty(i) ) {
-                      deps[ i ] = 'hbs!' + deps[ i ].replace(/_/g, '/');
+              // check for recursive partials
+              if (omitExtension) {
+                if(path === parentRequire.toUrl(partialPath)) {
+                  continue;
+                }
+              } else {
+                if(path === parentRequire.toUrl(partialPath +'.'+ (config.hbs && config.hbs.templateExtension ? config.hbs.templateExtension : templateExtension))) {
+                  continue;
+                }
+              }
+
+              config.hbs._partials[partialPath] = config.hbs._partials[partialPath] || [];
+
+              // we can reference a same template with different paths (with absolute or relative)
+              config.hbs._partials[partialPath].references = config.hbs._partials[partialPath].references || [];
+              config.hbs._partials[partialPath].references.push(partialReference);
+
+              config.hbs._loadedDeps = config.hbs._loadedDeps || {};
+
+              deps[i] = "hbs!"+partialPath;
+            }
+          }
+
+          depStr = deps.join("', '");
+
+          helps = helps.concat((metaObj && metaObj.helpers) ? metaObj.helpers : []);
+          helpDepStr = disableHelpers ?
+            '' : (function (){
+              var i;
+              var paths = [];
+              var pathGetter = config.hbs && config.hbs.helperPathCallback
+                ? config.hbs.helperPathCallback
+                : function (name){
+                  return (config.hbs && config.hbs.helperDirectory ? config.hbs.helperDirectory : helperDirectory) + name;
+                };
+
+              for ( i = 0; i < helps.length; i++ ) {
+                paths[i] = "'" + pathGetter(helps[i], path) + "'"
+              }
+              return paths;
+            })().join(',');
+
+          if ( helpDepStr ) {
+            helpDepStr = ',' + helpDepStr;
+          }
+
+          if (metaObj) {
+            try {
+              if (metaObj.styles) {
+                styleList = _.union(styleList, metaObj.styles);
+
+                // In dev mode in the browser
+                if ( require.isBrowser && ! config.isBuild ) {
+                  head = document.head || document.getElementsByTagName('head')[0];
+                  _(metaObj.styles).forEach(function (style) {
+                    if ( !styleMap[style] ) {
+                      linkElem = document.createElement('link');
+                      linkElem.href = config.baseUrl + devStyleDirectory + style + '.css';
+                      linkElem.media = 'all';
+                      linkElem.rel = 'stylesheet';
+                      linkElem.type = 'text/css';
+                      head.appendChild(linkElem);
+                      styleMap[style] = linkElem;
                     }
-                  }
-
-                  if ( !config.isBuild ) {
-                    require( deps, function (){
-                      load.fromText(text);
-
-                      //Give result to load. Need to wait until the module
-                      //is fully parse, which will happen after this
-                      //execution.
-                      parentRequire([name], function (value) {
-                        load(value);
-                      });
-                    });
-                  }
-                  else {
-                    load.fromText(text);
-
-                    //Give result to load. Need to wait until the module
-                    //is fully parse, which will happen after this
-                    //execution.
-                    parentRequire([name], function (value) {
-                      load(value);
+                  });
+                }
+                else if ( config.isBuild ) {
+                  (function(){
+                    var fs  = require.nodeRequire('fs');
+                    var str = _(metaObj.styles).map(function (style) {
+                      if (!styleMap[style]) {
+                        styleMap[style] = true;
+                        return '@import url('+style+'.css);\n';
+                      }
+                      return '';
+                    }).join('\n');
+
+                    // I write out my import statements to a file in order to help me build stuff.
+                    // Then I use a tool to inline my import statements afterwards. (you can run r.js on it too)
+                    fs.open(__dirname + buildStyleDirectory + buildCSSFileName, filecode, '0666', function( e, id ) {
+                      fs.writeSync(id, str, null, encoding='utf8');
+                      fs.close(id);
                     });
-                  }
-
-                  if ( config.removeCombined ) {
-                    fs.unlinkSync(path);
-                  }
-              });
+                    filecode = 'a';
+                  })();
+                }
+              }
+            }
+            catch(e){
+              console.log('error injecting styles');
             }
+          }
+
+          if ( ! config.isBuild && ! config.serverRender ) {
+            debugOutputStart = '<!-- START - ' + name + ' -->';
+            debugOutputEnd = '<!-- END - ' + name + ' -->';
+            debugProperties = 't.meta = ' + meta + ';\n' +
+                              't.helpers = ' + JSON.stringify(helps) + ';\n' +
+                              't.deps = ' + JSON.stringify(deps) + ';\n' +
+                              't.vars = ' + JSON.stringify(vars) + ';\n';
+          }
+
+          var mapping = false;
+          var configHbs = config.hbs || {};
+          var options = _.extend(configHbs.compileOptions || {}, { originalKeyFallback: configHbs.originalKeyFallback });
+          var prec = precompile( text, mapping, options);
+          var tmplName = "'hbs!" + name + "',";
+
+          if(depStr) depStr = ", '"+depStr+"'";
+
+          var partialReferences = [];
+          if(config.hbs._partials[name])
+            partialReferences = config.hbs._partials[name].references;
+
+          var handlebarsPath = (config.hbs && config.hbs.handlebarsPath) ? config.hbs.handlebarsPath : 'handlebars';
+
+          text = '/* START_TEMPLATE */\n' +
+                 'define('+tmplName+"['"+handlebarsPath+"'"+depStr+helpDepStr+'], function( Handlebars ){ \n' +
+                   'var t = Handlebars.template(' + prec + ');\n' +
+                   "Handlebars.registerPartial('" + name + "', t);\n";
+
+          for(var i=0; i<partialReferences.length;i++)
+            text += "Handlebars.registerPartial('" + partialReferences[i] + "', t);\n";
+
+          text += debugProperties +
+                   'return t;\n' +
+                 '});\n' +
+                 '/* END_TEMPLATE */\n';
+
+          //Hold on to the transformed text if a build.
+          if (config.isBuild) {
+            buildMap[compiledName] = text;
+          }
+
+          //IE with conditional comments on cannot handle the
+          //sourceURL trick, so skip it if enabled.
+          /*@if (@_jscript) @else @*/
+          if (!config.isBuild) {
+            text += '\r\n//# sourceURL=' + path;
+          }
+          /*@end@*/
+
+          if ( !config.isBuild ) {
+            parentRequire( deps, function (){
+              load.fromText(text);
+
+              //Give result to load. Need to wait until the module
+              //is fully parse, which will happen after this
+              //execution.
+              parentRequire([name], function (value) {
+                load(value);
+              });
+            });
+          }
+          else {
+            load.fromText(name, text);
+
+            //Give result to load. Need to wait until the module
+            //is fully parse, which will happen after this
+            //execution.
+            parentRequire([name], function (value) {
+              load(value);
+            });
+          }
+
+          if ( config.removeCombined && path ) {
+            filesToRemove.push(path);
+          }
+
+        });
+      }
 
-            var path = parentRequire.toUrl(name +'.'+ (config.hbs && config.hbs.templateExtension? config.hbs.templateExtension : templateExtension));
+      var path;
+      var omitExtension = config.hbs && config.hbs.templateExtension === false;
 
-            if (disableI18n){
-                fetchAndRegister(false);
-            } else {
-                fetchOrGetCached(parentRequire.toUrl((config.hbs && config.hbs.i18nDirectory ? config.hbs.i18nDirectory : i18nDirectory) + (config.locale || "en_us") + '.json'), function (langMap) {
-                  fetchAndRegister(JSON.parse(langMap));
-                });
-            }
-          //>>excludeEnd('excludeHbs')
-        }
-      };
+      if (omitExtension) {
+        path = parentRequire.toUrl(name);
+      }
+      else {
+        path = parentRequire.toUrl(name +'.'+ (config.hbs && config.hbs.templateExtension ? config.hbs.templateExtension : templateExtension));
+      }
+
+      fetchAndRegister(false);
+    },
+
+    onLayerEnd: function () {
+      if (config.removeCombined && fs) {
+        filesToRemove.forEach(function (path) {
+          if (fs.existsSync(path)) {
+            fs.unlinkSync(path);
+          }
+        });
+      }
+    }
+  };
 });
-/* END_hbs_PLUGIN */
+/* END_hbs_PLUGIN */
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/i18nprecompile.js b/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/i18nprecompile.js
deleted file mode 100644
index 22b4133..0000000
--- a/security-admin/src/main/webapp/libs/bower/require-handlebars-plugin/js/i18nprecompile.js
+++ /dev/null
@@ -1,45 +0,0 @@
-//>>excludeStart('excludeAfterBuild', pragmas.excludeAfterBuild)
-define(['handlebars', "underscore"], function ( Handlebars, _ ) {
-
-  function replaceLocaleStrings ( ast, mapping, options ) {
-    options = options || {};
-    mapping = mapping || {};
-    // Base set of things
-    if ( ast && ast.type === "program" && ast.statements ) {
-      _(ast.statements).forEach(function(statement, i){
-        var newString = "<!-- i18n error -->";
-        // If it's a translation node
-        if ( statement.type === "mustache" && statement.id && statement.id.original === "$" ) {
-
-          if ( statement.params.length && statement.params[0].string ) {
-            var key = statement.params[0].string;
-            newString = mapping[ key ] || (options.originalKeyFallback ? key : newString);
-          }
-          ast.statements[i] = new Handlebars.AST.ContentNode(newString);
-        }
-        // If we need to recurse
-        else if ( statement.program ) {
-          statement.program = replaceLocaleStrings( statement.program, mapping, options );
-        }
-      });
-      // Also cover the else blocks
-      if (ast.inverse) {
-        replaceLocaleStrings(ast.inverse, mapping, options);
-      }
-    }
-    return ast;
-  }
-
-  return function(string, mapping, options) {
-    options = options || {};
-    var ast, environment;
-    ast = Handlebars.parse(string);
-    // avoid replacing locale if mapping is `false`
-    if (mapping !== false) {
-        ast = replaceLocaleStrings(ast, mapping, options);
-    }
-    environment = new Handlebars.Compiler().compile(ast, options);
-    return new Handlebars.JavaScriptCompiler().compile(environment, options);
-  };
-});
-//>>excludeEnd('excludeAfterBuild')
diff --git a/security-admin/src/main/webapp/templates/common/ServiceManagerLayout_tmpl.html b/security-admin/src/main/webapp/templates/common/ServiceManagerLayout_tmpl.html
index 7b20877..f23d812 100644
--- a/security-admin/src/main/webapp/templates/common/ServiceManagerLayout_tmpl.html
+++ b/security-admin/src/main/webapp/templates/common/ServiceManagerLayout_tmpl.html
@@ -69,7 +69,7 @@
                                                     <a href="javascript:void(0)" title="Import" data-id="uploadBtnOnServices" data-servicetype="{{./this.attributes.name}}" class=" btn-right importbtn text-decoration">
                                                         <i class="fa-fw fa fa-rotate-180 fa-fw fa fa-external-link-square"> </i>
                                                     </a>
-                                                    {{#if ../../isServiceManager}}
+                                                    {{#if ../isServiceManager}}
                                                         <a href="#!/service/{{./this.id}}/create" class="pull-right text-decoration" title="Add New Service" style="margin-right: 2px;"> <i class="fa-fw fa fa-plus"></i></a>
                                                     {{else}}
                                                         <a href="javascript:void(0)" class="pull-right text-decoration disabled add-service" title="Services cannot be added while filtering Security Zones"> <i class="fa-fw fa fa-plus"></i></a>
diff --git a/security-admin/src/main/webapp/templates/common/ServiceManagerSidebarLayout_tmpl.html b/security-admin/src/main/webapp/templates/common/ServiceManagerSidebarLayout_tmpl.html
index 7907834..b61dd45 100644
--- a/security-admin/src/main/webapp/templates/common/ServiceManagerSidebarLayout_tmpl.html
+++ b/security-admin/src/main/webapp/templates/common/ServiceManagerSidebarLayout_tmpl.html
@@ -63,7 +63,7 @@
                                         {{{handleServiceDefIcon ./this.attributes.name}}}
                                         <span class="capitalizes">{{./this.attributes.displayName}}</span>
                                         {{#if ../operation}}
-                                            {{#if ../../isServiceManager}}
+                                            {{#if ../isServiceManager}}
                                                 <span class="components-header">
                                                     <a href="#!/service/{{./this.id}}/create" class="pull-right text-decoration" title="Add New Service" style="margin-right: 2px;"> <i class="fa-fw fa fa-plus"></i></a>
                                                 </span>
diff --git a/security-admin/src/main/webapp/templates/policies/RangerPolicyRO_tmpl.html b/security-admin/src/main/webapp/templates/policies/RangerPolicyRO_tmpl.html
index 14b3757..8eab654 100644
--- a/security-admin/src/main/webapp/templates/policies/RangerPolicyRO_tmpl.html
+++ b/security-admin/src/main/webapp/templates/policies/RangerPolicyRO_tmpl.html
@@ -269,14 +269,14 @@
 	  </table>
 	</div>
   {{#compare "Exclude from Allow Conditions" "eq" this.title}}
-    {{#if ../../isDenyAllElse}}
+    {{#if ../isDenyAllElse}}
       <div class="deny-all-else">
         <tr>
           <td>
             <b>{{tt 'lbl.isDenyAllElse'}} : </b>
           </td>
           <td>
-            <span class="badge badge-dark">{{ ../../../  PolicyDetails.isDenyAllElse}}</span>
+            <span class="badge badge-dark">{{ ../PolicyDetails.isDenyAllElse}}</span>
           </td>
         </tr>
       </div>
diff --git a/security-admin/src/main/webapp/templates/policies/RangerPolicyTableLayout_tmpl.html b/security-admin/src/main/webapp/templates/policies/RangerPolicyTableLayout_tmpl.html
index 5a22597..d1ca2a9 100644
--- a/security-admin/src/main/webapp/templates/policies/RangerPolicyTableLayout_tmpl.html
+++ b/security-admin/src/main/webapp/templates/policies/RangerPolicyTableLayout_tmpl.html
@@ -17,30 +17,30 @@
 <div data-id="policyTypeTab">
     <ul class="nav nav-tabs">
         {{#if isRenderAccessTab}}
-        <li data-tab="access" class="nav-item active">
-            <a class="nav-link" data-toggle="tab" href="#access">Access</a>
-        </li>
+            <li data-tab="access" class="nav-item active">
+                <a class="nav-link" data-toggle="tab" href="#access">Access</a>
+            </li>
         {{/if}}
         {{#showMaskingTab .}}
-        <li data-tab="masking" class="nav-item">
-            <a class="nav-link" data-toggle="tab" href="#masking">Masking</a>
-        </li>
+            <li data-tab="masking" class="nav-item">
+                <a class="nav-link" data-toggle="tab" href="#masking">Masking</a>
+            </li>
         {{/showMaskingTab}}
         {{#showRowLevelTab .}}
-        <li data-tab="rowLevelFilter" class="nav-item">
-            <a class="nav-link" data-toggle="tab" href="#rowLevelFilter">Row Level Filter</a>
-        </li>
+            <li data-tab="rowLevelFilter" class="nav-item">
+                <a class="nav-link" data-toggle="tab" href="#rowLevelFilter">Row Level Filter</a>
+            </li>
         {{/showRowLevelTab}}
     </ul>
 </div>
 {{#if setNewUi}}
 <div class="list-header">
-    {{#if ../isNotUser}}
-    {{#if ../isNotAuditorOrKMSAuditor}}
-    <button type="button" title="" data-name="deleteService" class=" btn btn-mini btn-right"> <i class="fa-fw fa fa-trash"></i> Service Delete</button>
-    <button type="button" title="" data-name="serviceEdit" class=" btn btn-mini btn-right"> <i class="fa-fw fa fa-edit"></i> Service Edit</button>
-    {{/if}}
-    <button type="button" title="" data-name="serviceDetails" class=" btn btn-mini btn-right"> <i class="fa-fw fa fa-eye"></i> Service Details</button>
+    {{#if isNotUser}}
+        {{#if isNotAuditorOrKMSAuditor}}
+            <button type="button" title="" data-name="deleteService" class=" btn btn-mini btn-right"> <i class="fa-fw fa fa-trash"></i> Service Delete</button>
+            <button type="button" title="" data-name="serviceEdit" class=" btn btn-mini btn-right"> <i class="fa-fw fa fa-edit"></i> Service Edit</button>
+        {{/if}}
+        <button type="button" title="" data-name="serviceDetails" class=" btn btn-mini btn-right"> <i class="fa-fw fa fa-eye"></i> Service Details</button>
     {{/if}}
 </div>
 {{/if}}
diff --git a/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyDeleteDiff_tmpl.html b/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyDeleteDiff_tmpl.html
index 456e194..6b58d9b 100644
--- a/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyDeleteDiff_tmpl.html
+++ b/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyDeleteDiff_tmpl.html
@@ -15,399 +15,402 @@
   limitations under the License.
 --}}
 <div class="diff-content">
-	<b>Policy ID:</b><label class="badge badge-ranger"> {{objectId}}</div>
-	<div class="no-margin label-size13-weightbold">Policy Name: {{policyName}}</div>
+    <b>Policy ID:</b><label class="badge badge-ranger"> {{objectId}}</div>
+    <div class="no-margin label-size13-weightbold">Policy Name: {{policyName}}</div>
     {{#if zoneName}}
         <div class="no-margin label-size13-weightbold">Zone Name: {{zoneName}}</div>
     {{/if}}
-	<div class="no-margin label-size13-weightbold">Deleted Date: {{objectCreatedDate}}</div>
-	<div class="no-margin label-size13-weightbold">Deleted By: {{userName}}</div>
+    <div class="no-margin label-size13-weightbold">Deleted Date: {{objectCreatedDate}}</div>
+    <div class="no-margin label-size13-weightbold">Deleted By: {{userName}}</div>
 
-{{#if collection.length}}
-	<h5 class="bold wrap-header m-t-sm">Policy Details:</h5>
-	<div class="diff">
-		<div class="diff-left">
-			<h3>Fields</h3>
-			<ol class="attr">
-			{{#each collection}}
-				<li class="change-row">{{./this.attributes.attributeName}}</li>
-			{{/each}}	
-			</ol>
-		</div>
-	 	<div class="diff-left">
-			<h3>Old Value</h3>
-			<ol class="list-unstyled data">
-			{{#each collection}}
-					<li class="change-row">{{./this.attributes.previousValue}}</li>
-			{{/each}}	
-			</ol>
-		</div>  
-	</div>
-{{/if}}	
-
-{{#if oldPolicyValidityPeriod}}
-    <h5 class="bold wrap-header m-t-sm">Validity Period:</h5>
-    <div class="diff validityPeriod" >
-        <div class="diff-right diff-list" data-id="diff">
-            <h3>Old Value</h3>
-            {{#each oldPolicyValidityPeriod}}
+    {{#if collection.length}}
+        <h5 class="bold wrap-header m-t-sm">Policy Details:</h5>
+        <div class="diff">
+            <div class="diff-left">
+                <h3>Fields</h3>
+                <ol class="attr">
+                    {{#each collection}}
+                        <li class="change-row">{{./this.attributes.attributeName}}</li>
+                    {{/each}}
+                </ol>
+            </div>
+            <div class="diff-left">
+                <h3>Old Value</h3>
                 <ol class="list-unstyled data">
-                    <li class="change-row"><i>Start Date</i>:
-                        {{#if this.startTime}}
-                            <span class="startTime">{{this.startTime}}</span><span>,</span>
-                        {{else}}
-                            --
-                        {{/if}}
-                    </li>
-                    <li class="change-row"><i>End Date</i>:
-                        {{#if this.endTime}}
-                            <span class="endTime">{{this.endTime}}</span><span>,</span>
+                    {{#each collection}}
+                        {{#compare ./this.attributes.previousValue "eq" ''}}
+                            <li>--</li>
                         {{else}}
-                            --
-                        {{/if}}
-                    </li>
-                    <li class="change-row"><i>Time Zone</i>:
-                        {{#if this.timeZone}}
-                            <span class="timeZone">{{this.timeZone}}</span><span>,</span>
+                            <li class="change-row">{{./this.attributes.previousValue}}</li>
+                        {{/compare}}
+                    {{/each}}
+                </ol>
+            </div>
+        </div>
+    {{/if}} 
+
+    {{#if oldPolicyValidityPeriod}}
+        <h5 class="bold wrap-header m-t-sm">Validity Period:</h5>
+        <div class="diff validityPeriod" >
+            <div class="diff-right diff-list" data-id="diff">
+                <h3>Old Value</h3>
+                {{#each oldPolicyValidityPeriod}}
+                    <ol class="list-unstyled data">
+                        <li class="change-row"><i>Start Date</i>:
+                            {{#if this.startTime}}
+                                <span class="startTime">{{this.startTime}}</span><span>,</span>
+                            {{else}}
+                                --
+                            {{/if}}
+                        </li>
+                        <li class="change-row"><i>End Date</i>:
+                            {{#if this.endTime}}
+                                <span class="endTime">{{this.endTime}}</span><span>,</span>
+                            {{else}}
+                                --
+                            {{/if}}
+                        </li>
+                        <li class="change-row"><i>Time Zone</i>:
+                            {{#if this.timeZone}}
+                                <span class="timeZone">{{this.timeZone}}</span><span>,</span>
+                            {{else}}
+                                --
+                            {{/if}}
+                        </li>
+                    </ol><br/>
+                {{/each}}
+            </div>
+        </div>
+    {{/if}}
+
+    {{#if oldPolicyCondition}}
+        <h5 class="bold wrap-header m-t-sm">Policy Conditions:</h5>
+        <div class="diff diff-perms" >
+            <div class="diff-right diff-list" data-id="diff">
+                <h3>Old Value</h3>
+                {{#each oldPolicyCondition}}
+                    <li class="change-row">
+                        {{#if this.type}}
+                            {{this.type}} : [{{this.values}}]
                         {{else}}
                             --
                         {{/if}}
                     </li>
-                </ol><br/>
-            {{/each}}
+                {{/each}}
+            </div>
         </div>
-    </div>
-{{/if}}
+    {{/if}}
 
-{{#if oldPolicyCondition}}
-    <h5 class="bold wrap-header m-t-sm">Policy Conditions:</h5>
-    <div class="diff diff-perms" >
-        <div class="diff-right diff-list" data-id="diff">
-            <h3>Old Value</h3>
-            {{#each oldPolicyCondition}}
-                <li class="change-row">
-                    {{#if this.type}}
-                        {{this.type}} : [{{this.values}}]
-                    {{else}}
-                        --
-                    {{/if}}
-                </li>
-            {{/each}}
+    {{#if oldPolicyItems}}
+        <h5 class="bold wrap-header m-t-sm">Allow PolicyItems:</h5>
+        <div class="diff diff-perms">
+            <div class="diff-right" data-id="diff">
+                <h3>Old Value</h3>
+                {{#each oldPolicyItems}}
+                    <ol class="list-unstyled data">
+                        <li class="change-row"><i>Roles</i>:
+                            {{#if_eq this.roles compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.roles}}
+                                    <span class="rolename">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Groups</i>:
+                            {{#if_eq this.groups compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.groups}}
+                                    <span class="groupname">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Users</i>:
+                            {{#if_eq this.users compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.users}}
+                                    <span class="username">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Permissions</i>:
+                            {{#each this.permissions}}
+                                <span class="perm">{{this}}</span> <span>,</span>
+                            {{/each}}
+                        </li>
+                        {{#if this.conditions}}
+                            <li class="change-row">
+                                <i>Conditions</i>:
+                                {{#each this.conditions}}
+                                    <span class="condition">{{this.type}} : [{{this.values}}]</span><span>,</span>
+                                {{/each}}
+                            </li>
+                        {{/if}}
+                        <li class="change-row"><i>Delegate Admin</i>: {{this.delegateAdmin}}</li>
+                    </ol><br/>
+                {{/each}}
+            </div>
         </div>
-    </div>
-{{/if}}
-
-{{#if oldPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Allow PolicyItems:</h5>
-	<div class="diff diff-perms">
-		<div class="diff-right" data-id="diff">
-			<h3>Old Value</h3>
-			{{#each oldPolicyItems}}
-				<ol class="list-unstyled data">
-                                                        <li class="change-row"><i>Roles</i>:
-                                                                {{#if_eq this.roles compare=0}}
-                                                                        &lt;empty&gt;
-                                                                {{else}}
-                                                                        {{#each this.roles}}
-                                                                                <span class="rolename">{{this}}</span><span>,</span>
-                                                                        {{/each}}
-                                                                {{/if_eq}}
-                                                        </li>
-							<li class="change-row"><i>Groups</i>:
-								{{#if_eq this.groups compare=0}}
-									&lt;empty&gt; 
-								{{else}}
-									{{#each this.groups}}  
-											<span class="groupname">{{this}}</span><span>,</span>
-									{{/each}}
-								{{/if_eq}}
-							</li>
-							<li class="change-row"><i>Users</i>:
-								{{#if_eq this.users compare=0}}
-									&lt;empty&gt;	 
-								{{else}}
-									{{#each this.users}}  
-											<span class="username">{{this}}</span><span>,</span>
-									{{/each}}
-								{{/if_eq}}
-							</li>
-							<li class="change-row"><i>Permissions</i>:
-								{{#each this.permissions}}
-									<span class="perm">{{this}}</span> <span>,</span>
-								{{/each}}
-							</li>
-							{{#if this.conditions}}
-								<li class="change-row">
-									<i>Conditions</i>:
-										{{#each this.conditions}}
-											<span class="condition">{{this.type}} : [{{this.values}}]</span><span>,</span>
-										{{/each}}
-								</li>
-							{{/if}}	
-							<li class="change-row"><i>Delegate Admin</i>: {{this.delegateAdmin}}</li>
-					</ol><br/>
-		{{/each}}
-		</div>
-	</div>
-{{/if}}
-<!-- Masking Policy Items -->
-{{#if oldMaskPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Masking Policy Items:</h5>
-	<div class="diff diff-perms" >
-		<div class="diff-right diff-list" data-id="diff">
-			<h3>old Value</h3>
-				{{#each oldMaskPolicyItems}}
-					<ol class="list-unstyled data">
-                                                <li class="change-row"><i>Roles</i>:
-                                                        {{#if_eq this.roles compare=0}}
-                                                                &lt;empty&gt;
-                                                        {{else}}
-                                                                {{#each this.roles}}
-                                                                        <span class="rolename">{{this}}</span><span>,</span>
-                                                                {{/each}}
-                                                        {{/if_eq}}
-                                                </li>
-						<li class="change-row">Groups:
-							{{#if_eq this.groups compare=0}}
-								&lt;empty&gt;
-							{{else}}
-								{{this.groups}}
-							{{/if_eq}}
-						</li>
-					<li class="change-row">Users:
-						{{#if_eq this.users compare=0}}
-								&lt;empty&gt;
-						{{else}}
-							{{this.users}}
-						{{/if_eq}}
-					</li>
-					<li class="change-row">Accesses:
-						{{#each this.accesses}}
-							{{this.type}} <span>,</span>
-						{{/each}}
-					</li>
-					{{#if this.dataMaskInfo}}
-					<li class="change-row">
-					Data Mask Types:
-					  <i>
-					  	{{this.dataMaskInfo.dataMaskType}}
-					  </i>
-					</li>
-					{{/if}}
-				</ol><br/>
-			{{/each}}
-		</div>
-	</div>
-{{/if}}
-
-<!--  Row Filter Policy Items-->
-{{#if oldRowFilterPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Row Level Filter Policy Items :</h5>
-	<div class="diff diff-perms" >
-		<div class="diff-right diff-list" data-id="diff">
-			<h3>Old Value</h3>
-			{{#each oldRowFilterPolicyItems}}
-				<ol class="list-unstyled data">
-                                                <li class="change-row"><i>Roles</i>:
-                                                        {{#if_eq this.roles compare=0}}
-                                                                &lt;empty&gt;
-                                                        {{else}}
-                                                                {{#each this.roles}}
-                                                                        <span class="rolename">{{this}}</span><span>,</span>
-                                                                {{/each}}
-                                                        {{/if_eq}}
-                                                </li>
-						<li class="change-row">Groups:
-							{{#if_eq this.groups compare=0}}
-								&lt;empty&gt;
-							{{else}}
-								{{this.groups}}
-							{{/if_eq}}
-						</li>
-					<li class="change-row">Users:
-						{{#if_eq this.users compare=0}}
-								&lt;empty&gt;
-						{{else}}
-							{{this.users}}
-						{{/if_eq}}
-					</li>
-					<li class="change-row">Accesses:
-						{{#each this.accesses}}
-							{{this.type}} <span>,</span>
-						{{/each}}
-					</li>
-					{{#if this.rowFilterInfo}}
-					<li class="change-row">
-					Row Level Filter:
-					  {{this.rowFilterInfo.filterExpr}}
-					</li>
-					{{/if}}
-				</ol><br/>
-			{{/each}}
-		</div>
-	</div>
-{{/if}}	
+    {{/if}}
+    <!-- Masking Policy Items -->
+    {{#if oldMaskPolicyItems}}
+        <h5 class="bold wrap-header m-t-sm">Masking Policy Items:</h5>
+        <div class="diff diff-perms" >
+            <div class="diff-right diff-list" data-id="diff">
+                <h3>old Value</h3>
+                {{#each oldMaskPolicyItems}}
+                    <ol class="list-unstyled data">
+                        <li class="change-row"><i>Roles</i>:
+                            {{#if_eq this.roles compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.roles}}
+                                    <span class="rolename">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row">Groups:
+                            {{#if_eq this.groups compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{this.groups}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row">Users:
+                            {{#if_eq this.users compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{this.users}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row">Accesses:
+                            {{#each this.accesses}}
+                                {{this.type}} <span>,</span>
+                            {{/each}}
+                        </li>
+                        {{#if this.dataMaskInfo}}
+                            <li class="change-row">
+                                Data Mask Types:
+                                <i>
+                                    {{this.dataMaskInfo.dataMaskType}}
+                                </i>
+                            </li>
+                        {{/if}}
+                    </ol><br/>
+                {{/each}}
+            </div>
+        </div>
+    {{/if}}
 
-{{#if oldAllowExceptionPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Allow Exception PolicyItems:</h5>
-	<div class="diff diff-perms">
-		<div class="diff-right" data-id="diff">
-			<h3>Old Value</h3>
-			{{#each oldAllowExceptionPolicyItems}}
-				<ol class="list-unstyled data">
-                                                        <li class="change-row"><i>Roles</i>:
-                                                                {{#if_eq this.roles compare=0}}
-                                                                        &lt;empty&gt;
-                                                                {{else}}
-                                                                        {{#each this.roles}}
-                                                                                <span class="rolename">{{this}}</span><span>,</span>
-                                                                        {{/each}}
-                                                                {{/if_eq}}
-                                                        </li>
-							<li class="change-row"><i>Groups</i>:
-								{{#if_eq this.groups compare=0}}
-									&lt;empty&gt; 
-								{{else}}
-									{{#each this.groups}}  
-											<span class="groupname">{{this}}</span><span>,</span>
-									{{/each}}
-								{{/if_eq}}
-							</li>
-							<li class="change-row"><i>Users</i>:
-								{{#if_eq this.users compare=0}}
-									&lt;empty&gt;	 
-								{{else}}
-									{{#each this.users}}  
-											<span class="username">{{this}}</span><span>,</span>
-									{{/each}}
-								{{/if_eq}}
-							</li>
-							<li class="change-row"><i>Permissions</i>:
-								{{#each this.permissions}}
-									<span class="perm">{{this}}</span> <span>,</span>
-								{{/each}}
-							</li>
-							{{#if this.conditions}}
-								<li class="change-row">
-									<i>Conditions</i>:
-										{{#each this.conditions}}
-											<span class="condition">{{this.type}}: [{{this.values}}]</span><span>,</span>
-										{{/each}}
-								</li>
-							{{/if}}	
-							<li class="change-row"><i>Delegate Admin</i>: {{this.delegateAdmin}}</li>
-					</ol><br/>
-		{{/each}}
-		</div>
-	</div>
-{{/if}}
+    <!--  Row Filter Policy Items-->
+    {{#if oldRowFilterPolicyItems}}
+        <h5 class="bold wrap-header m-t-sm">Row Level Filter Policy Items :</h5>
+        <div class="diff diff-perms" >
+            <div class="diff-right diff-list" data-id="diff">
+                <h3>Old Value</h3>
+                {{#each oldRowFilterPolicyItems}}
+                    <ol class="list-unstyled data">
+                        <li class="change-row"><i>Roles</i>:
+                            {{#if_eq this.roles compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.roles}}
+                                    <span class="rolename">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row">Groups:
+                            {{#if_eq this.groups compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{this.groups}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row">Users:
+                            {{#if_eq this.users compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{this.users}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row">Accesses:
+                            {{#each this.accesses}}
+                                {{this.type}} <span>,</span>
+                            {{/each}}
+                        </li>
+                        {{#if this.rowFilterInfo}}
+                            <li class="change-row">
+                                Row Level Filter:
+                                {{this.rowFilterInfo.filterExpr}}
+                            </li>
+                        {{/if}}
+                    </ol><br/>
+                {{/each}}
+            </div>
+        </div>
+    {{/if}}
 
-{{#if oldDenyPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Deny PolicyItems:</h5>
-	<div class="diff diff-perms">
-		<div class="diff-right" data-id="diff">
-			<h3>Old Value</h3>
-			{{#each oldDenyPolicyItems}}
-				<ol class="list-unstyled data">
-                                                        <li class="change-row"><i>Roles</i>:
-                                                                {{#if_eq this.roles compare=0}}
-                                                                        &lt;empty&gt;
-                                                                {{else}}
-                                                                        {{#each this.roles}}
-                                                                                <span class="rolename">{{this}}</span><span>,</span>
-                                                                        {{/each}}
-                                                                {{/if_eq}}
-                                                        </li>
-							<li class="change-row"><i>Groups</i>:
-								{{#if_eq this.groups compare=0}}
-									&lt;empty&gt; 
-								{{else}}
-									{{#each this.groups}}  
-											<span class="groupname">{{this}}</span><span>,</span>
-									{{/each}}
-								{{/if_eq}}
-							</li>
-							<li class="change-row"><i>Users</i>:
-								{{#if_eq this.users compare=0}}
-									&lt;empty&gt;	 
-								{{else}}
-									{{#each this.users}}  
-											<span class="username">{{this}}</span><span>,</span>
-									{{/each}}
-								{{/if_eq}}
-							</li>
-							<li class="change-row"><i>Permissions</i>:
-								{{#each this.permissions}}
-									<span class="perm">{{this}}</span> <span>,</span>
-								{{/each}}
-							</li>
-							{{#if this.conditions}}
-								<li class="change-row">
-									<i>Conditions</i>:
-										{{#each this.conditions}}
-											<span class="condition">{{this.type}}: [{{this.values}}]</span><span>,</span>
-										{{/each}}
-								</li>
-							{{/if}}	
-							<li class="change-row"><i>Delegate Admin</i>: {{this.delegateAdmin}}</li>
-					</ol><br/>
-		{{/each}}
-		</div>
-	</div>
-{{/if}}
+    {{#if oldAllowExceptionPolicyItems}}
+        <h5 class="bold wrap-header m-t-sm">Allow Exception PolicyItems:</h5>
+        <div class="diff diff-perms">
+            <div class="diff-right" data-id="diff">
+                <h3>Old Value</h3>
+                {{#each oldAllowExceptionPolicyItems}}
+                    <ol class="list-unstyled data">
+                        <li class="change-row"><i>Roles</i>:
+                            {{#if_eq this.roles compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.roles}}
+                                    <span class="rolename">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Groups</i>:
+                            {{#if_eq this.groups compare=0}}
+                                &lt;empty&gt; 
+                            {{else}}
+                                {{#each this.groups}}
+                                    <span class="groupname">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Users</i>:
+                            {{#if_eq this.users compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.users}}
+                                    <span class="username">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Permissions</i>:
+                            {{#each this.permissions}}
+                                <span class="perm">{{this}}</span> <span>,</span>
+                            {{/each}}
+                        </li>
+                        {{#if this.conditions}}
+                            <li class="change-row">
+                                <i>Conditions</i>:
+                                {{#each this.conditions}}
+                                    <span class="condition">{{this.type}}: [{{this.values}}]</span><span>,</span>
+                                {{/each}}
+                            </li>
+                        {{/if}}
+                        <li class="change-row"><i>Delegate Admin</i>: {{this.delegateAdmin}}</li>
+                    </ol><br/>
+                {{/each}}
+            </div>
+        </div>
+    {{/if}}
 
-{{#if oldDenyExceptionPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Deny Exception PolicyItems:</h5>
-	<div class="diff diff-perms">
-		<div class="diff-right" data-id="diff">
-			<h3>Old Value</h3>
-			{{#each oldDenyExceptionPolicyItems}}
-				<ol class="list-unstyled data">
-                                                        <li class="change-row"><i>Roles</i>:
-                                                                {{#if_eq this.roles compare=0}}
-                                                                        &lt;empty&gt;
-                                                                {{else}}
-                                                                        {{#each this.roles}}
-                                                                                <span class="rolename">{{this}}</span><span>,</span>
-                                                                        {{/each}}
-                                                                {{/if_eq}}
-                                                        </li>
-							<li class="change-row"><i>Groups</i>:
-								{{#if_eq this.groups compare=0}}
-									&lt;empty&gt; 
-								{{else}}
-									{{#each this.groups}}  
-											<span class="groupname">{{this}}</span><span>,</span>
-									{{/each}}
-								{{/if_eq}}
-							</li>
-							<li class="change-row"><i>Users</i>:
-								{{#if_eq this.users compare=0}}
-									&lt;empty&gt;	 
-								{{else}}
-									{{#each this.users}}  
-											<span class="username">{{this}}</span><span>,</span>
-									{{/each}}
-								{{/if_eq}}
-							</li>
-							<li class="change-row"><i>Permissions</i>:
-								{{#each this.permissions}}
-									<span class="perm">{{this}}</span> <span>,</span>
-								{{/each}}
-							</li>
-							{{#if this.conditions}}
-								<li class="change-row">
-									<i>Conditions</i>:
-										{{#each this.conditions}}
-											<span class="condition">{{this.type}}: [{{this.values}}]</span><span>,</span>
-										{{/each}}
-								</li>
-							{{/if}}	
-							<li class="change-row"><i>Delegate Admin</i>: {{this.delegateAdmin}}</li>
-					</ol><br/>
-		{{/each}}
-		</div>
-	</div>
-{{/if}}
+    {{#if oldDenyPolicyItems}}
+        <h5 class="bold wrap-header m-t-sm">Deny PolicyItems:</h5>
+        <div class="diff diff-perms">
+            <div class="diff-right" data-id="diff">
+                <h3>Old Value</h3>
+                {{#each oldDenyPolicyItems}}
+                    <ol class="list-unstyled data">
+                        <li class="change-row"><i>Roles</i>:
+                            {{#if_eq this.roles compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.roles}}
+                                    <span class="rolename">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Groups</i>:
+                            {{#if_eq this.groups compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.groups}}
+                                    <span class="groupname">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Users</i>:
+                            {{#if_eq this.users compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.users}}
+                                    <span class="username">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Permissions</i>:
+                            {{#each this.permissions}}
+                                <span class="perm">{{this}}</span> <span>,</span>
+                            {{/each}}
+                        </li>
+                        {{#if this.conditions}}
+                            <li class="change-row">
+                                <i>Conditions</i>:
+                                {{#each this.conditions}}
+                                    <span class="condition">{{this.type}}: [{{this.values}}]</span><span>,</span>
+                                {{/each}}
+                            </li>
+                        {{/if}}
+                        <li class="change-row"><i>Delegate Admin</i>: {{this.delegateAdmin}}</li>
+                    </ol><br/>
+                {{/each}}
+            </div>
+        </div>
+    {{/if}}
 
-</div>
+    {{#if oldDenyExceptionPolicyItems}}
+        <h5 class="bold wrap-header m-t-sm">Deny Exception PolicyItems:</h5>
+        <div class="diff diff-perms">
+            <div class="diff-right" data-id="diff">
+                <h3>Old Value</h3>
+                {{#each oldDenyExceptionPolicyItems}}
+                    <ol class="list-unstyled data">
+                        <li class="change-row"><i>Roles</i>:
+                            {{#if_eq this.roles compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.roles}}
+                                    <span class="rolename">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Groups</i>:
+                            {{#if_eq this.groups compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.groups}}
+                                    <span class="groupname">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Users</i>:
+                            {{#if_eq this.users compare=0}}
+                                &lt;empty&gt;
+                            {{else}}
+                                {{#each this.users}}
+                                    <span class="username">{{this}}</span><span>,</span>
+                                {{/each}}
+                            {{/if_eq}}
+                        </li>
+                        <li class="change-row"><i>Permissions</i>:
+                            {{#each this.permissions}}
+                                <span class="perm">{{this}}</span> <span>,</span>
+                            {{/each}}
+                        </li>
+                        {{#if this.conditions}}
+                            <li class="change-row">
+                                <i>Conditions</i>:
+                                {{#each this.conditions}}
+                                    <span class="condition">{{this.type}}: [{{this.values}}]</span><span>,</span>
+                                {{/each}}
+                            </li>
+                        {{/if}}
+                        <li class="change-row"><i>Delegate Admin</i>: {{this.delegateAdmin}}</li>
+                    </ol><br/>
+                {{/each}}
+            </div>
+        </div>
+    {{/if}}
+</div>
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyDiff_tmpl.html b/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyDiff_tmpl.html
index be8881c..7fe4665 100644
--- a/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyDiff_tmpl.html
+++ b/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyDiff_tmpl.html
@@ -15,375 +15,379 @@
   limitations under the License.
 --}}
 <div class="diff-content">
-	<b>Policy ID :&nbsp;&nbsp;</b><label class="badge badge-ranger"> {{objectId}}</div>
-	<div class="no-margin label-size13-weightbold">Policy Name: {{policyName}}</div>
-    {{#if zoneName}}
-        <div class="no-margin label-size13-weightbold">Zone Name: {{zoneName}}</div>
-    {{/if}}
-	{{#if repositoryType}}
-	<div class="no-margin label-size13-weightbold">Repository Type: {{repositoryType}}</div>
-	{{/if}}
-	<div class="no-margin label-size13-weightbold">Created Date: {{objectCreatedDate}}</div>
-	<div class="no-margin label-size13-weightbold">Created By: {{userName}}</div>
-{{#if collection.length}}
-	<h5 class="bold wrap-header m-t-sm">Policy Details:</h5>
-	<div class="diff">
-		<div class="diff-left">
-			<h3>Fields</h3>
-			<ol class="attr">
-			{{#each collection}}
-				<li class="change-row">{{./this.attributes.attributeName}}</li>
-			{{/each}}	
-			</ol>
-		</div>
-		<div class="diff-right">
-			<h3>New Value</h3>
-			<ol class="list-unstyled data">
-			{{#each collection}}
-				<li class="change-row">{{./this.attributes.newValue}}</li>
-			{{/each}}	
-			</ol>
-		</div>
-	</div>
-{{/if}}	
-{{#if newPolicyValidityPeriod}}
-    <h5 class="bold wrap-header m-t-sm">Validity Period:</h5>
-    <div class="diff diff-perms" >
-        <div class="diff-right diff-list" data-id="diff">
-            <h3>New Value</h3>
-            {{#each newPolicyValidityPeriod}}
-                <ol class="list-unstyled data">
-                    <li class="change-row">Start Date:
-                        {{#if this.startTime}}
-                            {{this.startTime}}
-                        {{else}}
-                            --
-                        {{/if}}
-                    </li>
-                    <li class="change-row">End Date:
-                        {{#if this.endTime}}
-                            {{this.endTime}}
-                        {{else}}
-                            --
-                        {{/if}}
-                    </li>
-                    <li class="change-row">Time Zone:
-                        {{#if this.timeZone}}
-                            {{this.timeZone}}
-                        {{else}}
-                            --
-                        {{/if}}
-                    </li>
-                </ol><br/>
-            {{/each}}
-        </div>
-    </div>
-{{/if}}
-{{#if newPolicyConditions}}
-    <h5 class="bold wrap-header m-t-sm">Policy Conditions:</h5>
-    <div class="diff diff-perms" >
-        <div class="diff-right diff-list" data-id="diff">
-            <h3>New Value</h3>
-            {{#each newPolicyConditions}}
-                <li class="change-row">
-                    {{#if this.type}}
-                        {{this.type}}: [{{this.values}}]
-                    {{else}}
-                        --
-                    {{/if}}
-                </li>
-            {{/each}}
-        </div>
-    </div>
-{{/if}}
-{{#if newPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Allow PolicyItems:</h5>
-	<div class="diff diff-perms" >
-		<div class="diff-right diff-list" data-id="diff">
-			<h3>New Value</h3>
-				{{#each newPolicyItems}}
-				<ol class="list-unstyled data">
-                                        <li class="change-row">Roles:
-                                                {{#if_eq this.roles compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.roles}}
-                                                {{/if_eq}}
-                                        </li>
-                                        <li class="change-row">Groups:
-                                                {{#if_eq this.groups compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.groups}}
-                                                {{/if_eq}}
-                                        </li>
-					<li class="change-row">Users:
-						{{#if_eq this.users compare=0}}
-								&lt;empty&gt;	 
-						{{else}}
-							{{this.users}}  
-						{{/if_eq}}  
-					</li>
-					<li class="change-row">Permissions:
-						{{#each this.permissions}}
-							{{this}} <span>,</span>
-						{{/each}}
-					</li>
-					{{#if this.conditions}}
-					<li class="change-row">
-						Conditions:
-							{{#each this.conditions}}
-								{{this.type}} : [{{this.values}}]<span>,</span>
-							{{/each}}
-					</li>
-					{{/if}}
-					<li class="change-row">Delegate Admin:{{this.delegateAdmin}}</li>
-				</ol><br/>
-			{{/each}}
-		</div>
-	</div>
-{{/if}}
+    <b>Policy ID :&nbsp;&nbsp;</b><label class="badge badge-ranger"> {{objectId}}</div>
+        <div class="no-margin label-size13-weightbold">Policy Name: {{policyName}}</div>
+        {{#if zoneName}}
+            <div class="no-margin label-size13-weightbold">Zone Name: {{zoneName}}</div>
+        {{/if}}
+        {{#if repositoryType}}
+            <div class="no-margin label-size13-weightbold">Repository Type: {{repositoryType}}</div>
+        {{/if}}
+        <div class="no-margin label-size13-weightbold">Created Date: {{objectCreatedDate}}</div>
+        <div class="no-margin label-size13-weightbold">Created By: {{userName}}</div>
+        {{#if collection.length}}
+            <h5 class="bold wrap-header m-t-sm">Policy Details:</h5>
+            <div class="diff">
+                <div class="diff-left">
+                    <h3>Fields</h3>
+                    <ol class="attr">
+                        {{#each collection}}
+                            <li class="change-row">{{./this.attributes.attributeName}}</li>
+                        {{/each}}
+                    </ol>
+                </div>
+                <div class="diff-right">
+                    <h3>New Value</h3>
+                    <ol class="list-unstyled data">
+                        {{#each collection}}
+                            {{#compare ./this.attributes.newValue "eq" ''}}
+                                <li>--</li>
+                            {{else}}
+                                <li class="change-row">{{./this.attributes.newValue}}</li>
+                            {{/compare}}
+                        {{/each}}
+                    </ol>
+                </div>
+            </div>
+        {{/if}} 
+        {{#if newPolicyValidityPeriod}}
+            <h5 class="bold wrap-header m-t-sm">Validity Period:</h5>
+            <div class="diff diff-perms" >
+                <div class="diff-right diff-list" data-id="diff">
+                    <h3>New Value</h3>
+                    {{#each newPolicyValidityPeriod}}
+                        <ol class="list-unstyled data">
+                            <li class="change-row">Start Date:
+                                {{#if this.startTime}}
+                                    {{this.startTime}}
+                                {{else}}
+                                    --
+                                {{/if}}
+                            </li>
+                            <li class="change-row">End Date:
+                                {{#if this.endTime}}
+                                    {{this.endTime}}
+                                {{else}}
+                                    --
+                                {{/if}}
+                            </li>
+                            <li class="change-row">Time Zone:
+                                {{#if this.timeZone}}
+                                    {{this.timeZone}}
+                                {{else}}
+                                    --
+                                {{/if}}
+                            </li>
+                        </ol><br/>
+                    {{/each}}
+                </div>
+            </div>
+        {{/if}}
+        {{#if newPolicyConditions}}
+            <h5 class="bold wrap-header m-t-sm">Policy Conditions:</h5>
+            <div class="diff diff-perms" >
+                <div class="diff-right diff-list" data-id="diff">
+                    <h3>New Value</h3>
+                    {{#each newPolicyConditions}}
+                        <li class="change-row">
+                            {{#if this.type}}
+                                {{this.type}}: [{{this.values}}]
+                            {{else}}
+                                --
+                            {{/if}}
+                        </li>
+                    {{/each}}
+                </div>
+            </div>
+        {{/if}}
+        {{#if newPolicyItems}}
+            <h5 class="bold wrap-header m-t-sm">Allow PolicyItems:</h5>
+            <div class="diff diff-perms" >
+                <div class="diff-right diff-list" data-id="diff">
+                    <h3>New Value</h3>
+                    {{#each newPolicyItems}}
+                        <ol class="list-unstyled data">
+                            <li class="change-row">Roles:
+                                {{#if_eq this.roles compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.roles}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Groups:
+                                {{#if_eq this.groups compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.groups}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Users:
+                                {{#if_eq this.users compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.users}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Permissions:
+                                {{#each this.permissions}}
+                                    {{this}} <span>,</span>
+                                {{/each}}
+                            </li>
+                            {{#if this.conditions}}
+                            <li class="change-row">
+                                Conditions:
+                                {{#each this.conditions}}
+                                    {{this.type}} : [{{this.values}}]<span>,</span>
+                                {{/each}}
+                            </li>
+                            {{/if}}
+                            <li class="change-row">Delegate Admin:{{this.delegateAdmin}}</li>
+                        </ol><br/>
+                    {{/each}}
+                </div>
+            </div>
+        {{/if}}
 
-<!-- Allow Exceptions -->
+        <!-- Allow Exceptions -->
 
-{{#if newAllowExceptionPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Allow Exceptions:</h5>
-	<div class="diff diff-perms" >
-		<div class="diff-right diff-list" data-id="diff">
-			<h3>New Value</h3>
-				{{#each newAllowExceptionPolicyItems}}
-				<ol class="list-unstyled data">
-                                        <li class="change-row">Roles:
-                                                {{#if_eq this.roles compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.roles}}
-                                                {{/if_eq}}
-                                        </li>
-                                        <li class="change-row">Groups:
-                                                {{#if_eq this.groups compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.groups}}
-                                                {{/if_eq}}
-                                        </li>
-					<li class="change-row">Users:
-						{{#if_eq this.users compare=0}}
-								&lt;empty&gt;	 
-						{{else}}
-							{{this.users}}  
-						{{/if_eq}}  
-					</li>
-					<li class="change-row">Permissions:
-						{{#each this.permissions}}
-							{{this}} <span>,</span>
-						{{/each}}
-					</li>
-					{{#if this.conditions}}
-					<li class="change-row">
-						Conditions:
-							{{#each this.conditions}}
-								{{this.type}} : [{{this.values}}]<span>,</span>
-							{{/each}}
-					</li>
-					{{/if}}
-					<li class="change-row">Delegate Admin:{{this.delegateAdmin}}</li>
-				</ol><br/>
-			{{/each}}
-		</div>
-	</div>
-{{/if}}
+        {{#if newAllowExceptionPolicyItems}}
+            <h5 class="bold wrap-header m-t-sm">Allow Exceptions:</h5>
+            <div class="diff diff-perms" >
+                <div class="diff-right diff-list" data-id="diff">
+                    <h3>New Value</h3>
+                    {{#each newAllowExceptionPolicyItems}}
+                        <ol class="list-unstyled data">
+                            <li class="change-row">Roles:
+                                {{#if_eq this.roles compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.roles}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Groups:
+                                {{#if_eq this.groups compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.groups}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Users:
+                                {{#if_eq this.users compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.users}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Permissions:
+                                {{#each this.permissions}}
+                                    {{this}} <span>,</span>
+                                {{/each}}
+                            </li>
+                            {{#if this.conditions}}
+                                <li class="change-row">
+                                    Conditions:
+                                    {{#each this.conditions}}
+                                        {{this.type}} : [{{this.values}}]<span>,</span>
+                                    {{/each}}
+                                </li>
+                            {{/if}}
+                            <li class="change-row">Delegate Admin:{{this.delegateAdmin}}</li>
+                        </ol><br/>
+                    {{/each}}
+                </div>
+            </div>
+        {{/if}}
 
-<!-- Deny PolicyItems -->
+        <!-- Deny PolicyItems -->
 
-{{#if newDenyPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Deny PolicyItems:</h5>
-	<div class="diff diff-perms" >
-		<div class="diff-right diff-list" data-id="diff">
-			<h3>New Value</h3>
-				{{#each newDenyPolicyItems}}
-				<ol class="list-unstyled data">
-                                        <li class="change-row">Roles:
-                                                {{#if_eq this.roles compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.roles}}
-                                                {{/if_eq}}
-                                        </li>
-                                        <li class="change-row">Groups:
-                                                {{#if_eq this.groups compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.groups}}
-                                                {{/if_eq}}
-                                        </li>
-					<li class="change-row">Users:
-						{{#if_eq this.users compare=0}}
-								&lt;empty&gt;	 
-						{{else}}
-							{{this.users}}  
-						{{/if_eq}}  
-					</li>
-					<li class="change-row">Permissions:
-						{{#each this.permissions}}
-							{{this}} <span>,</span>
-						{{/each}}
-					</li>
-					{{#if this.conditions}}
-					<li class="change-row">
-						Conditions:
-							{{#each this.conditions}}
-								{{this.type}}: [{{this.values}}]<span>,</span>
-							{{/each}}
-					</li>
-					{{/if}}
-					<li class="change-row">Delegate Admin:{{this.delegateAdmin}}</li>
-				</ol><br/>
-			{{/each}}
-		</div>
-	</div>
-{{/if}}
-<!-- Deny Exception PolicyItems -->
-{{#if newDenyExceptionPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Deny Exception PolicyItems:</h5>
-	<div class="diff diff-perms">
-		<div class="diff-right diff-list" data-id="diff">
-			<h3>New Value</h3>
-				{{#each newDenyExceptionPolicyItems}}
-				<ol class="list-unstyled data">
-                                        <li class="change-row">Roles:
-                                                {{#if_eq this.roles compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.roles}}
-                                                {{/if_eq}}
-                                        </li>
-                                        <li class="change-row">Groups:
-                                                {{#if_eq this.groups compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.groups}}
-                                                {{/if_eq}}
-                                        </li>
-					<li class="change-row">Users:
-						{{#if_eq this.users compare=0}}
-								&lt;empty&gt;	 
-						{{else}}
-							{{this.users}}  
-						{{/if_eq}}  
-					</li>
-					<li class="change-row">Permissions:
-						{{#each this.permissions}}
-							{{this}} <span>,</span>
-						{{/each}}
-					</li>
-					{{#if this.conditions}}
-					<li class="change-row">
-						Conditions:
-							{{#each this.conditions}}
-								{{this.type}} : [{{this.values}}]<span>,</span>
-							{{/each}}
-					</li>
-					{{/if}}
-					<li class="change-row">Delegate Admin:{{this.delegateAdmin}}</li>
-				</ol><br/>
-			{{/each}}
-		</div>
-	</div>
-{{/if}}	
+        {{#if newDenyPolicyItems}}
+            <h5 class="bold wrap-header m-t-sm">Deny PolicyItems:</h5>
+            <div class="diff diff-perms" >
+                <div class="diff-right diff-list" data-id="diff">
+                    <h3>New Value</h3>
+                    {{#each newDenyPolicyItems}}
+                        <ol class="list-unstyled data">
+                            <li class="change-row">Roles:
+                                {{#if_eq this.roles compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.roles}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Groups:
+                                {{#if_eq this.groups compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.groups}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Users:
+                                {{#if_eq this.users compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.users}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Permissions:
+                                {{#each this.permissions}}
+                                    {{this}} <span>,</span>
+                                {{/each}}
+                            </li>
+                            {{#if this.conditions}}
+                            <li class="change-row">
+                                Conditions:
+                                {{#each this.conditions}}
+                                    {{this.type}}: [{{this.values}}]<span>,</span>
+                                {{/each}}
+                            </li>
+                            {{/if}}
+                            <li class="change-row">Delegate Admin:{{this.delegateAdmin}}</li>
+                        </ol><br/>
+                    {{/each}}
+                </div>
+            </div>
+        {{/if}}
+        <!-- Deny Exception PolicyItems -->
+        {{#if newDenyExceptionPolicyItems}}
+            <h5 class="bold wrap-header m-t-sm">Deny Exception PolicyItems:</h5>
+            <div class="diff diff-perms">
+                <div class="diff-right diff-list" data-id="diff">
+                    <h3>New Value</h3>
+                    {{#each newDenyExceptionPolicyItems}}
+                        <ol class="list-unstyled data">
+                            <li class="change-row">Roles:
+                                {{#if_eq this.roles compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.roles}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Groups:
+                                {{#if_eq this.groups compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.groups}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Users:
+                                {{#if_eq this.users compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.users}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Permissions:
+                                {{#each this.permissions}}
+                                    {{this}} <span>,</span>
+                                {{/each}}
+                            </li>
+                            {{#if this.conditions}}
+                                <li class="change-row">
+                                    Conditions:
+                                    {{#each this.conditions}}
+                                        {{this.type}} : [{{this.values}}]<span>,</span>
+                                    {{/each}}
+                                </li>
+                            {{/if}}
+                            <li class="change-row">Delegate Admin:{{this.delegateAdmin}}</li>
+                        </ol><br/>
+                    {{/each}}
+                </div>
+            </div>
+        {{/if}} 
 
-<!-- Masking Policy Items -->
-{{#if newMaskPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Masking Policy Items:</h5>
-	<div class="diff diff-perms" >
-		<div class="diff-right diff-list" data-id="diff">
-			<h3>New Value</h3>
-			{{#each newMaskPolicyItems}}
-				<ol class="list-unstyled data">
-                                        <li class="change-row">Roles:
-                                                {{#if_eq this.roles compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.roles}}
-                                                {{/if_eq}}
-                                        </li>
-                                        <li class="change-row">Groups:
-                                                {{#if_eq this.groups compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.groups}}
-                                                {{/if_eq}}
-                                        </li>
-					<li class="change-row">Users:
-						{{#if_eq this.users compare=0}}
-								&lt;empty&gt;
-						{{else}}
-							{{this.users}}
-						{{/if_eq}}
-					</li>
-					<li class="change-row">Accesses:
-						{{#each this.accesses}}
-							{{this.type}} <span>,</span>
-						{{/each}}
-					</li>
-					{{#if this.dataMaskInfo}}
-					<li class="change-row">
-					Data Mask Types:
-					  <i>
-					  	{{this.dataMaskInfo.dataMaskType}}
-					  </i>
-					</li>
-					{{/if}}
-				</ol><br/>
-			{{/each}}
-		</div>
-	</div>
-{{/if}}
+        <!-- Masking Policy Items -->
+        {{#if newMaskPolicyItems}}
+            <h5 class="bold wrap-header m-t-sm">Masking Policy Items:</h5>
+            <div class="diff diff-perms" >
+                <div class="diff-right diff-list" data-id="diff">
+                    <h3>New Value</h3>
+                    {{#each newMaskPolicyItems}}
+                        <ol class="list-unstyled data">
+                            <li class="change-row">Roles:
+                                {{#if_eq this.roles compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.roles}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Groups:
+                                {{#if_eq this.groups compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.groups}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Users:
+                                {{#if_eq this.users compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.users}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Accesses:
+                                {{#each this.accesses}}
+                                    {{this.type}} <span>,</span>
+                                {{/each}}
+                            </li>
+                            {{#if this.dataMaskInfo}}
+                                <li class="change-row">
+                                    Data Mask Types:
+                                    <i>
+                                        {{this.dataMaskInfo.dataMaskType}}
+                                    </i>
+                                </li>
+                            {{/if}}
+                        </ol><br/>
+                    {{/each}}
+                </div>
+            </div>
+        {{/if}}
 
-<!--  Row Filter Policy Items-->
-{{#if newRowFilterPolicyItems}}
-	<h5 class="bold wrap-header m-t-sm">Row Level Filter Policy Items:</h5>
-	<div class="diff diff-perms" >
-		<div class="diff-right diff-list" data-id="diff">
-			<h3>New Value</h3>
-			{{#each newRowFilterPolicyItems}}
-				<ol class="list-unstyled data">
-                                        <li class="change-row">Roles:
-                                                {{#if_eq this.roles compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.roles}}
-                                                {{/if_eq}}
-                                        </li>
-                                        <li class="change-row">Groups:
-                                                {{#if_eq this.groups compare=0}}
-                                                        &lt;empty&gt;
-                                                {{else}}
-                                                        {{this.groups}}
-                                                {{/if_eq}}
-                                        </li>
-					<li class="change-row">Users:
-						{{#if_eq this.users compare=0}}
-								&lt;empty&gt;
-						{{else}}
-							{{this.users}}
-						{{/if_eq}}
-					</li>
-					<li class="change-row">Accesses:
-						{{#each this.accesses}}
-							{{this.type}} <span>,</span>
-						{{/each}}
-					</li>
-					{{#if this.rowFilterInfo}}
-					<li class="change-row">
-					Row Level Filter:
-					  {{this.rowFilterInfo.filterExpr}}
-					</li>
-					{{/if}}
-				</ol><br/>
-			{{/each}}
-		</div>
-	</div>
-{{/if}}
+        <!--  Row Filter Policy Items-->
+        {{#if newRowFilterPolicyItems}}
+            <h5 class="bold wrap-header m-t-sm">Row Level Filter Policy Items:</h5>
+            <div class="diff diff-perms" >
+                <div class="diff-right diff-list" data-id="diff">
+                    <h3>New Value</h3>
+                    {{#each newRowFilterPolicyItems}}
+                        <ol class="list-unstyled data">
+                            <li class="change-row">Roles:
+                                {{#if_eq this.roles compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.roles}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Groups:
+                                {{#if_eq this.groups compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.groups}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Users:
+                                {{#if_eq this.users compare=0}}
+                                    &lt;empty&gt;
+                                {{else}}
+                                    {{this.users}}
+                                {{/if_eq}}
+                            </li>
+                            <li class="change-row">Accesses:
+                                {{#each this.accesses}}
+                                    {{this.type}} <span>,</span>
+                                {{/each}}
+                            </li>
+                            {{#if this.rowFilterInfo}}
+                                <li class="change-row">
+                                    Row Level Filter:
+                                    {{this.rowFilterInfo.filterExpr}}
+                                </li>
+                            {{/if}}
+                        </ol><br/>
+                    {{/each}}
+                </div>
+            </div>
+        {{/if}}
 
-</div>
+    </div>
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyUpdateDiff_tmpl.html b/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyUpdateDiff_tmpl.html
index f06c007..c9901b5 100644
--- a/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyUpdateDiff_tmpl.html
+++ b/security-admin/src/main/webapp/templates/reports/PlugableServicePolicyUpdateDiff_tmpl.html
@@ -49,7 +49,7 @@
 			<ol class="list-unstyled data">
 			{{#each collection}}
 					{{#compare ./this.attributes.previousValue "eq" ''}}
-				 			<li>--</li>		
+				 			<li>--</li>
 					{{else}}
 						<li class="change-row">{{{highlightForPlugableServiceModel ./this.attributes.newValue ./this.attributes.previousValue 'old' ./this.attributes.type}}}</li>
 					{{/compare}}
@@ -62,7 +62,7 @@
 			<ol class="list-unstyled data">
 			{{#each collection}}
 					{{#compare ./this.attributes.newValue "eq" ''}}
-				 			<li>--</li>		
+				 			<li>--</li>
 					{{else}}
 						<li class="change-row">{{{highlightForPlugableServiceModel ./this.attributes.newValue ./this.attributes.previousValue 'new' ./this.attributes.type}}}</li>
 					{{/compare}}
diff --git a/security-admin/src/main/webapp/templates/reports/UserUpdateOperationDiff_tmpl.html b/security-admin/src/main/webapp/templates/reports/UserUpdateOperationDiff_tmpl.html
index b22cea3..efab61e 100644
--- a/security-admin/src/main/webapp/templates/reports/UserUpdateOperationDiff_tmpl.html
+++ b/security-admin/src/main/webapp/templates/reports/UserUpdateOperationDiff_tmpl.html
@@ -88,23 +88,31 @@
 		<div class="diff-left" data-id="diff">
 			<h3>Old Value</h3>
 			<ol class="list-unstyled data">
-				<li class="change-row">
-					{{#each previousGroupList}}
-						{{{highlightUsersForArr ./this ../newGroupList 'old'}}}
-						<span>,</span>
-					{{/each}}
-				</li>
+				{{#ifCond previousGroupList.length '==' "0"}}
+					<li class="change-row">--</li>
+				{{else}}
+					<li class="change-row">
+						{{#each previousGroupList}}
+							{{{highlightUsersForArr ./this ../newGroupList 'old'}}}
+							<span>,</span>
+						{{/each}}
+					</li>
+				{{/ifCond}}
 			</ol>
 		</div>
 		<div class="diff-right" data-id="diff">
 			<h3>New Value</h3>
 			<ol class="list-unstyled data">
-				<li class="change-row">
-					{{#each newGroupList}}
-						{{{highlightUsersForArr ./this ../previousGroupList 'new'}}}
-						<span>,</span>
-					{{/each}}
-				</li>
+				{{#ifCond newGroupList.length '==' "0"}}
+					<li class="change-row">--</li>
+				{{else}}
+					<li class="change-row">
+						{{#each newGroupList}}
+							{{{highlightUsersForArr ./this ../previousGroupList 'new'}}}
+							<span>,</span>
+						{{/each}}
+					</li>
+				{{/ifCond}}
 			</ol>
 		</div>
 	</div>