2013-12-03 02:15:31 +08:00
/ * !
handlebars v1 . 1.2
2013-06-07 05:50:49 +08:00
Copyright ( C ) 2011 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
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
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 .
2013-12-03 02:15:31 +08:00
@ license
2013-06-07 05:50:49 +08:00
* /
2013-12-03 02:15:31 +08:00
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 ;
}
SafeString . prototype . toString = function ( ) {
return "" + this . string ;
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ = SafeString ;
return _ _exports _ _ ;
} ) ( ) ;
// handlebars/utils.js
var _ _module3 _ _ = ( function ( _ _dependency1 _ _ ) {
"use strict" ;
var _ _exports _ _ = { } ;
var SafeString = _ _dependency1 _ _ ;
var escape = {
"&" : "&" ,
"<" : "<" ,
">" : ">" ,
'"' : """ ,
"'" : "'" ,
"`" : "`"
} ;
var badChars = /[&<>"'`]/g ;
var possible = /[&<>"'`]/ ;
function escapeChar ( chr ) {
return escape [ chr ] || "&" ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
function extend ( obj , value ) {
for ( var key in value ) {
if ( value . hasOwnProperty ( key ) ) {
obj [ key ] = value [ key ] ;
}
}
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
_ _exports _ _ . extend = extend ; var toString = Object . prototype . toString ;
_ _exports _ _ . toString = toString ;
// Sourced from lodash
// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
var isFunction = function ( value ) {
return typeof value === 'function' ;
} ;
// fallback for older versions of Chrome and Safari
if ( isFunction ( /x/ ) ) {
isFunction = function ( value ) {
return typeof value === 'function' && toString . call ( value ) === '[object Function]' ;
} ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
var isFunction ;
_ _exports _ _ . isFunction = isFunction ;
var isArray = Array . isArray || function ( value ) {
return ( value && typeof value === 'object' ) ? toString . call ( value ) === '[object Array]' : false ;
} ;
_ _exports _ _ . isArray = isArray ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
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 "" ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// 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 ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( ! possible . test ( string ) ) { return string ; }
return string . replace ( badChars , escapeChar ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . escapeExpression = escapeExpression ; function isEmpty ( value ) {
if ( ! value && value !== 0 ) {
return true ;
} else if ( isArray ( value ) && value . length === 0 ) {
return true ;
2013-06-07 05:50:49 +08:00
} else {
2013-12-03 02:15:31 +08:00
return false ;
2013-06-07 05:50:49 +08:00
}
}
2013-12-03 02:15:31 +08:00
_ _exports _ _ . isEmpty = isEmpty ;
return _ _exports _ _ ;
} ) ( _ _module4 _ _ ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// handlebars/exception.js
var _ _module5 _ _ = ( function ( ) {
"use strict" ;
var _ _exports _ _ ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
var errorProps = [ 'description' , 'fileName' , 'lineNumber' , 'message' , 'name' , 'number' , 'stack' ] ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
function Exception ( /* message */ ) {
var tmp = Error . prototype . constructor . apply ( this , arguments ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
for ( var idx = 0 ; idx < errorProps . length ; idx ++ ) {
this [ errorProps [ idx ] ] = tmp [ errorProps [ idx ] ] ;
2013-06-07 05:50:49 +08:00
}
}
2013-12-03 02:15:31 +08:00
Exception . prototype = new Error ( ) ;
_ _exports _ _ = Exception ;
return _ _exports _ _ ;
} ) ( ) ;
// handlebars/base.js
var _ _module2 _ _ = ( function ( _ _dependency1 _ _ , _ _dependency2 _ _ ) {
"use strict" ;
var _ _exports _ _ = { } ;
/*globals Exception, Utils */
var Utils = _ _dependency1 _ _ ;
var Exception = _ _dependency2 _ _ ;
var VERSION = "1.1.2" ;
_ _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'
} ;
_ _exports _ _ . REVISION _CHANGES = REVISION _CHANGES ;
var isArray = Utils . isArray ,
isFunction = Utils . isFunction ,
toString = Utils . toString ,
objectType = '[object Object]' ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
function HandlebarsEnvironment ( helpers , partials ) {
this . helpers = helpers || { } ;
this . partials = partials || { } ;
2013-07-16 07:47:13 +08:00
2013-12-03 02:15:31 +08:00
registerDefaultHelpers ( this ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
_ _exports _ _ . HandlebarsEnvironment = HandlebarsEnvironment ; HandlebarsEnvironment . prototype = {
constructor : HandlebarsEnvironment ,
logger : logger ,
log : log ,
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 ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
} ,
registerPartial : function ( name , str ) {
if ( toString . call ( name ) === objectType ) {
Utils . extend ( this . partials , name ) ;
} else {
this . partials [ name ] = str ;
2013-06-07 05:50:49 +08:00
}
}
2013-12-03 02:15:31 +08:00
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
function registerDefaultHelpers ( instance ) {
instance . registerHelper ( 'helperMissing' , function ( arg ) {
if ( arguments . length === 2 ) {
return undefined ;
} else {
throw new Error ( "Missing helper: '" + arg + "'" ) ;
}
} ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
instance . registerHelper ( 'blockHelperMissing' , function ( context , options ) {
var inverse = options . inverse || function ( ) { } , fn = options . fn ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( isFunction ( context ) ) { context = context . call ( this ) ; }
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( context === true ) {
return fn ( this ) ;
} else if ( context === false || context == null ) {
return inverse ( this ) ;
} else if ( isArray ( context ) ) {
if ( context . length > 0 ) {
return instance . helpers . each ( context , options ) ;
2013-06-07 05:50:49 +08:00
} else {
2013-12-03 02:15:31 +08:00
return inverse ( this ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
} else {
return fn ( context ) ;
}
} ) ;
instance . registerHelper ( 'each' , function ( context , options ) {
var fn = options . fn , inverse = options . inverse ;
var i = 0 , ret = "" , data ;
if ( isFunction ( context ) ) { context = context . call ( this ) ; }
if ( options . data ) {
data = createFrame ( options . data ) ;
}
if ( context && typeof context === 'object' ) {
if ( isArray ( context ) ) {
for ( var j = context . length ; i < j ; i ++ ) {
if ( data ) {
data . index = i ;
data . first = ( i === 0 )
data . last = ( i === ( context . length - 1 ) ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
ret = ret + fn ( context [ i ] , { data : data } ) ;
}
2013-06-07 05:50:49 +08:00
} else {
2013-12-03 02:15:31 +08:00
for ( var key in context ) {
if ( context . hasOwnProperty ( key ) ) {
if ( data ) { data . key = key ; }
ret = ret + fn ( context [ key ] , { data : data } ) ;
i ++ ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
}
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( i === 0 ) {
ret = inverse ( this ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return ret ;
} ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
instance . registerHelper ( 'if' , function ( conditional , options ) {
if ( isFunction ( conditional ) ) { conditional = conditional . call ( this ) ; }
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// 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 ) ;
}
} ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
instance . registerHelper ( 'unless' , function ( conditional , options ) {
return instance . helpers [ 'if' ] . call ( this , conditional , { fn : options . inverse , inverse : options . fn , hash : options . hash } ) ;
} ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
instance . registerHelper ( 'with' , function ( context , options ) {
if ( isFunction ( context ) ) { context = context . call ( this ) ; }
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( ! Utils . isEmpty ( context ) ) return options . fn ( context ) ;
} ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
instance . registerHelper ( 'log' , function ( context , options ) {
var level = options . data && options . data . level != null ? parseInt ( options . data . level , 10 ) : 1 ;
instance . log ( level , context ) ;
} ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
var logger = {
methodMap : { 0 : 'debug' , 1 : 'info' , 2 : 'warn' , 3 : 'error' } ,
// State enum
DEBUG : 0 ,
INFO : 1 ,
WARN : 2 ,
ERROR : 3 ,
level : 3 ,
// can be overridden in the host environment
log : function ( level , obj ) {
if ( logger . level <= level ) {
var method = logger . methodMap [ level ] ;
if ( typeof console !== 'undefined' && console [ method ] ) {
console [ method ] . call ( console , obj ) ;
}
2013-06-07 05:50:49 +08:00
}
}
2013-12-03 02:15:31 +08:00
} ;
_ _exports _ _ . logger = logger ;
function log ( level , obj ) { logger . log ( level , obj ) ; }
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . log = log ; var createFrame = function ( object ) {
var obj = { } ;
Utils . extend ( obj , object ) ;
return obj ;
} ;
_ _exports _ _ . createFrame = createFrame ;
return _ _exports _ _ ;
} ) ( _ _module3 _ _ , _ _module5 _ _ ) ;
// handlebars/runtime.js
var _ _module6 _ _ = ( function ( _ _dependency1 _ _ , _ _dependency2 _ _ , _ _dependency3 _ _ ) {
"use strict" ;
var _ _exports _ _ = { } ;
/*global Utils */
var Utils = _ _dependency1 _ _ ;
var Exception = _ _dependency2 _ _ ;
var COMPILER _REVISION = _ _dependency3 _ _ . COMPILER _REVISION ;
var REVISION _CHANGES = _ _dependency3 _ _ . REVISION _CHANGES ;
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 Error ( "Template was precompiled with an older version of Handlebars than the current runtime. " +
"Please update your precompiler to a newer version (" + runtimeVersions + ") or downgrade your runtime to an older version (" + compilerVersions + ")." ) ;
} else {
// Use the embedded version info since the runtime doesn't know about this revision yet
throw new Error ( "Template was precompiled with a newer version of Handlebars than the current runtime. " +
"Please update your runtime to a newer version (" + compilerInfo [ 1 ] + ")." ) ;
}
2013-06-07 05:50:49 +08:00
}
}
2013-12-03 02:15:31 +08:00
// TODO: Remove this line and break up compilePartial
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
function template ( templateSpec , env ) {
if ( ! env ) {
throw new Error ( "No environment passed to template" ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
var invokePartialWrapper ;
if ( env . compile ) {
invokePartialWrapper = function ( partial , name , context , helpers , partials , data ) {
// TODO : Check this for all inputs and the options handling (partial flag, etc). This feels
// like there should be a common exec path
var result = invokePartial . apply ( this , arguments ) ;
if ( result ) { return result ; }
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
var options = { helpers : helpers , partials : partials , data : data } ;
partials [ name ] = env . compile ( partial , { data : data !== undefined } , env ) ;
return partials [ name ] ( context , options ) ;
} ;
} else {
invokePartialWrapper = function ( partial , name /* , context, helpers, partials, data */ ) {
var result = invokePartial . apply ( this , arguments ) ;
if ( result ) { return result ; }
throw new Exception ( "The partial " + name + " could not be compiled when running in runtime-only mode" ) ;
} ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// 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 ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( param && common && ( param !== common ) ) {
ret = { } ;
Utils . extend ( ret , common ) ;
Utils . extend ( ret , param ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
return ret ;
} ,
programWithDepth : programWithDepth ,
noop : noop ,
compilerInfo : null
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return function ( context , options ) {
options = options || { } ;
var namespace = options . partial ? options : env ,
helpers ,
partials ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( ! options . partial ) {
helpers = options . helpers ;
partials = options . partials ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
var result = templateSpec . call (
container ,
namespace , context ,
helpers ,
partials ,
options . data ) ;
if ( ! options . partial ) {
checkRevision ( container . compilerInfo ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
return result ;
} ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . template = template ; function programWithDepth ( i , fn , data /*, $depth */ ) {
var args = Array . prototype . slice . call ( arguments , 3 ) ;
var prog = function ( context , options ) {
options = options || { } ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return fn . apply ( this , [ context , options . data || data ] . concat ( args ) ) ;
2013-06-07 05:50:49 +08:00
} ;
2013-12-03 02:15:31 +08:00
prog . program = i ;
prog . depth = args . length ;
return prog ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . programWithDepth = programWithDepth ; function program ( i , fn , data ) {
var prog = function ( context , options ) {
options = options || { } ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return fn ( context , options . data || data ) ;
} ;
prog . program = i ;
prog . depth = 0 ;
return prog ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . program = program ; function invokePartial ( partial , name , context , helpers , partials , data ) {
var options = { partial : true , helpers : helpers , partials : partials , data : data } ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( partial === undefined ) {
throw new Exception ( "The partial " + name + " could not be found" ) ;
} else if ( partial instanceof Function ) {
return partial ( context , options ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . invokePartial = invokePartial ; function noop ( ) { return "" ; }
_ _exports _ _ . noop = noop ;
return _ _exports _ _ ;
} ) ( _ _module3 _ _ , _ _module5 _ _ , _ _module2 _ _ ) ;
// handlebars.runtime.js
var _ _module1 _ _ = ( function ( _ _dependency1 _ _ , _ _dependency2 _ _ , _ _dependency3 _ _ , _ _dependency4 _ _ , _ _dependency5 _ _ ) {
"use strict" ;
var _ _exports _ _ ;
var base = _ _dependency1 _ _ ;
// 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 _ _ ;
// For compatibility and usage outside of module systems, make the Handlebars object a namespace
var create = function ( ) {
var hb = new base . HandlebarsEnvironment ( ) ;
Utils . extend ( hb , base ) ;
hb . SafeString = SafeString ;
hb . Exception = Exception ;
hb . Utils = Utils ;
hb . VM = runtime ;
hb . template = function ( spec ) {
return runtime . template ( spec , hb ) ;
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return hb ;
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
var Handlebars = create ( ) ;
Handlebars . create = create ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ = Handlebars ;
return _ _exports _ _ ;
} ) ( _ _module2 _ _ , _ _module4 _ _ , _ _module5 _ _ , _ _module3 _ _ , _ _module6 _ _ ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// handlebars/compiler/ast.js
var _ _module7 _ _ = ( function ( _ _dependency1 _ _ ) {
"use strict" ;
var _ _exports _ _ = { } ;
var Exception = _ _dependency1 _ _ ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
function ProgramNode ( statements , inverseStrip , inverse ) {
this . type = "program" ;
this . statements = statements ;
this . strip = { } ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( inverse ) {
this . inverse = new ProgramNode ( inverse , inverseStrip ) ;
this . strip . right = inverseStrip . left ;
} else if ( inverseStrip ) {
this . strip . left = inverseStrip . right ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . ProgramNode = ProgramNode ; function MustacheNode ( rawParams , hash , open , strip ) {
this . type = "mustache" ;
this . hash = hash ;
this . strip = strip ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
var escapeFlag = open [ 3 ] || open [ 2 ] ;
this . escaped = escapeFlag !== '{' && escapeFlag !== '&' ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
var id = this . id = rawParams [ 0 ] ;
var params = this . params = rawParams . slice ( 1 ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// a mustache is an eligible helper if:
// * its id is simple (a single part, not `this` or `..`)
var eligibleHelper = this . eligibleHelper = id . isSimple ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// 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 ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// 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.
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . MustacheNode = MustacheNode ; function PartialNode ( partialName , context , strip ) {
this . type = "partial" ;
this . partialName = partialName ;
this . context = context ;
this . strip = strip ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . PartialNode = PartialNode ; function BlockNode ( mustache , program , inverse , close ) {
if ( mustache . id . original !== close . path . original ) {
throw new Exception ( mustache . id . original + " doesn't match " + close . path . original ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
this . type = "block" ;
this . mustache = mustache ;
this . program = program ;
this . inverse = inverse ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . strip = {
left : mustache . strip . left ,
right : close . strip . right
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
( program || inverse ) . strip . left = mustache . strip . right ;
( inverse || program ) . strip . right = close . strip . left ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( inverse && ! program ) {
this . isInverse = true ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . BlockNode = BlockNode ; function ContentNode ( string ) {
this . type = "content" ;
this . string = string ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . ContentNode = ContentNode ; function HashNode ( pairs ) {
this . type = "hash" ;
this . pairs = pairs ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . HashNode = HashNode ; function IdNode ( parts ) {
this . type = "ID" ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
var original = "" ,
dig = [ ] ,
depth = 0 ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
for ( var i = 0 , l = parts . length ; i < l ; i ++ ) {
var part = parts [ i ] . part ;
original += ( parts [ i ] . separator || '' ) + part ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( part === ".." || part === "." || part === "this" ) {
if ( dig . length > 0 ) { throw new Exception ( "Invalid path: " + original ) ; }
else if ( part === ".." ) { depth ++ ; }
else { this . isScoped = true ; }
}
else { dig . push ( part ) ; }
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
this . original = original ;
this . parts = dig ;
this . string = dig . join ( '.' ) ;
this . depth = depth ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// 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 ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . stringModeValue = this . string ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . IdNode = IdNode ; function PartialNameNode ( name ) {
this . type = "PARTIAL_NAME" ;
this . name = name . original ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . PartialNameNode = PartialNameNode ; function DataNode ( id ) {
this . type = "DATA" ;
this . id = id ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . DataNode = DataNode ; function StringNode ( string ) {
this . type = "STRING" ;
this . original =
this . string =
this . stringModeValue = string ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . StringNode = StringNode ; function IntegerNode ( integer ) {
this . type = "INTEGER" ;
this . original =
this . integer = integer ;
this . stringModeValue = Number ( integer ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . IntegerNode = IntegerNode ; function BooleanNode ( bool ) {
this . type = "BOOLEAN" ;
this . bool = bool ;
this . stringModeValue = bool === "true" ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . BooleanNode = BooleanNode ; function CommentNode ( comment ) {
this . type = "comment" ;
this . comment = comment ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . CommentNode = CommentNode ;
return _ _exports _ _ ;
} ) ( _ _module5 _ _ ) ;
// handlebars/compiler/parser.js
var _ _module9 _ _ = ( function ( ) {
"use strict" ;
var _ _exports _ _ ;
/* 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 , "inMustache" : 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 , "inMustache_repetition0" : 28 , "inMustache_option0" : 29 , "dataName" : 30 , "param" : 31 , "STRING" : 32 , "INTEGER" : 33 , "BOOLEAN" : 34 , "hash" : 35 , "hash_repetition_plus0" : 36 , "hashSegment" : 37 , "ID" : 38 , "EQUALS" : 39 , "DATA" : 40 , "pathSegments" : 41 , "SEP" : 42 , "$accept" : 0 , "$end" : 1 } ,
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" , 38 : "ID" , 39 : "EQUALS" , 40 : "DATA" , 42 : "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 ] , [ 35 , 1 ] , [ 37 , 3 ] , [ 26 , 1 ] , [ 26 , 1 ] , [ 26 , 1 ] , [ 30 , 2 ] , [ 21 , 1 ] , [ 41 , 3 ] , [ 41 , 1 ] , [ 27 , 0 ] , [ 27 , 1 ] , [ 28 , 0 ] , [ 28 , 2 ] , [ 29 , 0 ] , [ 29 , 1 ] , [ 36 , 1 ] , [ 36 , 2 ] ] ,
performAction : function anonymous ( yytext , yyleng , yylineno , yy , yystate , $$ , _$ ) {
var $0 = $$ . length - 1 ;
switch ( yystate ) {
case 1 : return new yy . ProgramNode ( $$ [ $0 - 1 ] ) ;
break ;
case 2 : return new yy . ProgramNode ( [ ] ) ;
break ;
case 3 : this . $ = new yy . ProgramNode ( [ ] , $$ [ $0 - 1 ] , $$ [ $0 ] ) ;
break ;
case 4 : this . $ = new yy . ProgramNode ( $$ [ $0 - 2 ] , $$ [ $0 - 1 ] , $$ [ $0 ] ) ;
break ;
case 5 : this . $ = new yy . ProgramNode ( $$ [ $0 - 1 ] , $$ [ $0 ] , [ ] ) ;
break ;
case 6 : this . $ = new yy . ProgramNode ( $$ [ $0 ] ) ;
break ;
case 7 : this . $ = new yy . ProgramNode ( [ ] ) ;
break ;
case 8 : this . $ = new yy . ProgramNode ( [ ] ) ;
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 ] ) ;
break ;
case 12 : this . $ = new yy . BlockNode ( $$ [ $0 - 2 ] , $$ [ $0 - 1 ] , $$ [ $0 - 1 ] . inverse , $$ [ $0 ] ) ;
break ;
case 13 : this . $ = $$ [ $0 ] ;
break ;
case 14 : this . $ = $$ [ $0 ] ;
break ;
case 15 : this . $ = new yy . ContentNode ( $$ [ $0 ] ) ;
break ;
case 16 : this . $ = new yy . CommentNode ( $$ [ $0 ] ) ;
break ;
case 17 : this . $ = new yy . MustacheNode ( $$ [ $0 - 1 ] [ 0 ] , $$ [ $0 - 1 ] [ 1 ] , $$ [ $0 - 2 ] , stripFlags ( $$ [ $0 - 2 ] , $$ [ $0 ] ) ) ;
break ;
case 18 : this . $ = new yy . MustacheNode ( $$ [ $0 - 1 ] [ 0 ] , $$ [ $0 - 1 ] [ 1 ] , $$ [ $0 - 2 ] , stripFlags ( $$ [ $0 - 2 ] , $$ [ $0 ] ) ) ;
break ;
case 19 : this . $ = { path : $$ [ $0 - 1 ] , strip : stripFlags ( $$ [ $0 - 2 ] , $$ [ $0 ] ) } ;
break ;
case 20 : this . $ = new yy . MustacheNode ( $$ [ $0 - 1 ] [ 0 ] , $$ [ $0 - 1 ] [ 1 ] , $$ [ $0 - 2 ] , stripFlags ( $$ [ $0 - 2 ] , $$ [ $0 ] ) ) ;
break ;
case 21 : this . $ = new yy . MustacheNode ( $$ [ $0 - 1 ] [ 0 ] , $$ [ $0 - 1 ] [ 1 ] , $$ [ $0 - 2 ] , stripFlags ( $$ [ $0 - 2 ] , $$ [ $0 ] ) ) ;
break ;
case 22 : this . $ = new yy . PartialNode ( $$ [ $0 - 2 ] , $$ [ $0 - 1 ] , stripFlags ( $$ [ $0 - 3 ] , $$ [ $0 ] ) ) ;
break ;
case 23 : this . $ = stripFlags ( $$ [ $0 - 1 ] , $$ [ $0 ] ) ;
break ;
case 24 : this . $ = [ [ $$ [ $0 - 2 ] ] . concat ( $$ [ $0 - 1 ] ) , $$ [ $0 ] ] ;
break ;
case 25 : this . $ = [ [ $$ [ $0 ] ] , null ] ;
break ;
case 26 : this . $ = $$ [ $0 ] ;
break ;
case 27 : this . $ = new yy . StringNode ( $$ [ $0 ] ) ;
break ;
case 28 : this . $ = new yy . IntegerNode ( $$ [ $0 ] ) ;
break ;
case 29 : this . $ = new yy . BooleanNode ( $$ [ $0 ] ) ;
break ;
case 30 : this . $ = $$ [ $0 ] ;
break ;
case 31 : this . $ = new yy . HashNode ( $$ [ $0 ] ) ;
break ;
case 32 : this . $ = [ $$ [ $0 - 2 ] , $$ [ $0 ] ] ;
break ;
case 33 : this . $ = new yy . PartialNameNode ( $$ [ $0 ] ) ;
break ;
case 34 : this . $ = new yy . PartialNameNode ( new yy . StringNode ( $$ [ $0 ] ) ) ;
break ;
case 35 : this . $ = new yy . PartialNameNode ( new yy . IntegerNode ( $$ [ $0 ] ) ) ;
break ;
case 36 : this . $ = new yy . DataNode ( $$ [ $0 ] ) ;
break ;
case 37 : this . $ = new yy . IdNode ( $$ [ $0 ] ) ;
break ;
case 38 : $$ [ $0 - 2 ] . push ( { part : $$ [ $0 ] , separator : $$ [ $0 - 1 ] } ) ; this . $ = $$ [ $0 - 2 ] ;
break ;
case 39 : this . $ = [ { part : $$ [ $0 ] } ] ;
break ;
case 42 : this . $ = [ ] ;
break ;
case 43 : $$ [ $0 - 1 ] . push ( $$ [ $0 ] ) ;
break ;
case 46 : this . $ = [ $$ [ $0 ] ] ;
break ;
case 47 : $$ [ $0 - 1 ] . push ( $$ [ $0 ] ) ;
break ;
}
2013-06-07 05:50:49 +08:00
} ,
2013-12-03 02:15:31 +08:00
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 : [ 1 , 10 ] , 16 : [ 1 , 12 ] , 19 : [ 1 , 21 ] , 20 : [ 2 , 8 ] , 22 : [ 1 , 13 ] , 23 : [ 1 , 14 ] , 25 : [ 1 , 15 ] } , { 5 : [ 2 , 13 ] , 14 : [ 2 , 13 ] , 15 : [ 2 , 13 ] , 16 : [ 2 , 13 ] , 19 : [ 2 , 13 ] , 20 : [ 2 , 13 ] , 22 : [ 2 , 13 ] , 23 : [ 2 , 13 ] , 25 : [ 2 , 13 ] } , { 5 : [ 2 , 14 ] , 14 : [ 2 , 14 ] , 15 : [ 2 , 14 ] , 16 : [ 2 , 14 ] , 19 : [ 2 , 14 ] , 20 : [ 2 , 14 ] , 22 : [ 2 , 14 ] , 23 : [ 2 , 14 ] , 25 : [ 2 , 14 ] } , { 5 : [ 2 , 15 ] , 14 : [ 2 , 15 ] , 15 : [ 2 , 15 ] , 16 : [ 2 , 15 ] , 19 : [ 2 , 15 ] , 20 : [ 2 , 15 ] , 22 : [ 2 , 15 ] , 23 : [ 2 , 15 ] , 25 : [ 2 , 15 ] } , { 5 : [ 2 , 16 ] , 14 : [ 2 , 16 ] , 15 : [ 2 , 16 ] , 16 : [ 2 , 16 ] , 19 : [ 2 , 16 ] , 20 : [ 2 , 16 ] , 22 : [ 2 , 16 ] , 23 : [ 2 , 16 ] , 25 : [ 2 , 16 ] } , { 17 : 23 , 21 : 24 , 30 : 25 , 38 : [ 1 , 28 ] , 40 : [ 1 , 27 ] , 41 : 26 } , { 17 : 29 , 21 : 24 , 30 : 25 , 38 : [ 1 , 28 ] , 40 : [ 1 , 27 ] , 41 : 26 } , { 17 : 30 , 21 : 24 , 30 : 25 , 38 : [ 1 , 28 ] , 40 : [ 1 , 27 ] , 41 : 26 } , { 17 : 31 , 21 : 24 , 30 : 25 , 38 : [ 1 , 28 ] , 40 : [ 1 , 27 ] , 41 : 26 } , { 21 : 33 , 26 : 32 , 32 : [ 1 , 34 ] , 33 : [ 1 , 35 ] , 38 : [ 1 , 28 ] , 41 : 26 } , { 1 : [ 2 , 1 ] } , { 5 : [ 2 , 10 ] , 14 : [ 2 , 10 ] , 15 : [ 2 , 10 ] , 16 : [ 2 , 10 ] , 19 : [ 2 , 10 ] , 20 : [ 2 , 10 ] , 22 : [ 2 , 10 ] , 23 : [ 2 , 10 ] , 25 : [ 2 , 10 ] } , { 10 : 36 , 20 : [ 1 , 37 ] } , { 4 : 38 , 8 : 4 , 9 : 5 , 11 : 6 , 12 : 7 , 13 : 8 , 14 : [ 1 , 9 ] , 15 : [ 1 , 10 ] , 16 : [ 1 , 12 ] , 19 : [ 1 , 11 ] , 20 : [ 2 , 7 ] , 22 : [ 1 , 13 ] , 23 : [ 1 , 14 ] , 25 : [ 1 , 15 ] } , { 7 : 39 , 8 : 17 , 9 : 5 , 11 : 6 , 12 : 7 , 13 : 8 , 14 : [ 1 , 9 ] , 15 : [ 1 , 10 ] , 16 : [ 1 , 12 ] , 19 : [ 1 , 21 ] , 20 : [ 2 , 6 ] , 22 : [ 1 , 13 ] , 23 : [ 1 , 14 ] , 25 : [ 1 , 15 ] } , { 17 : 23 , 18 : [ 1 , 40 ] , 21 : 24 , 30 : 25 , 38 : [ 1 , 28 ] , 40 : [ 1 , 27 ] , 41 : 26 } , { 10 : 41 , 20 : [ 1 , 37 ] } , { 18 : [ 1 , 42 ] } , { 18 : [ 2 , 42 ] , 24 : [ 2 , 42 ] , 28 : 43 , 32 : [ 2 , 42 ] , 33 : [ 2 , 42 ] , 34 : [ 2 , 42 ] , 38 : [ 2 , 42 ] , 40 : [ 2 , 42 ] } , { 18 : [ 2 , 25 ] , 24 : [ 2 , 25 ] } , { 18 : [ 2 , 37 ] , 24 : [ 2 , 37 ] , 32 : [ 2 , 37 ] , 33 : [ 2 , 37 ] , 34 : [ 2 , 37 ] , 38 : [ 2 , 37 ] , 40 : [ 2 , 37 ] , 42 : [ 1 , 44 ] } , { 21 : 45 , 38 : [ 1 , 28 ] , 41 : 26 } , { 18 : [ 2 , 39 ] , 24 : [ 2 , 39 ] , 32 : [ 2 , 39 ] , 33 : [ 2 , 39 ] , 34 : [ 2 , 39 ] , 38 : [ 2 , 39 ] , 40 : [ 2 , 39 ] , 42 : [ 2 , 39 ] } , { 18 : [ 1 , 46 ] } , { 18 : [ 1 , 47 ] } , { 24 : [ 1 , 48 ] } , { 18 : [ 2 , 40 ] , 21 : 50 , 27 : 49 , 38 : [ 1 , 28 ] , 41 : 26 } , { 18 : [ 2 , 33 ] , 38 : [ 2 , 33 ] } , { 18 : [ 2 , 34 ] , 38 : [ 2 , 34 ] } , { 18 : [ 2 , 35 ] , 38 : [ 2 , 35 ] } , { 5 : [ 2 , 11 ] , 14 : [ 2 , 11 ] , 15 : [ 2 , 11 ] , 16 : [ 2 , 11 ] , 19 : [ 2 , 11 ] , 20 : [ 2 , 11 ] , 22 : [ 2 , 11 ] , 23 : [ 2 , 11 ] , 25 : [ 2 , 11 ] } , { 21 : 51 , 38 : [ 1 , 28 ] , 41 : 26 } , { 8 : 17 , 9 : 5 , 11 : 6 , 12 : 7 , 13 : 8 , 14 : [ 1 , 9 ] , 15 : [ 1 , 10 ] , 16 : [ 1 , 12 ] , 19 : [ 1 , 11 ] , 20 : [ 2 , 3 ] , 22 : [ 1 , 13 ] , 23 : [ 1 , 14 ] , 25 : [ 1 , 15 ] } , { 4 : 52 , 8 : 4 , 9 : 5 , 11 : 6 , 12 : 7 , 13 : 8 , 14 : [ 1 , 9 ] , 15 : [ 1 , 10 ] , 16 : [ 1 , 12 ] , 19 : [ 1 , 11 ] , 20 : [ 2 , 5 ] , 22 : [ 1 , 13 ] , 23 : [ 1 , 14 ] , 25 : [ 1 , 15 ] } , { 14 : [ 2 , 23 ] , 15 : [ 2 , 23 ] , 16 : [ 2 , 23 ] , 19 : [ 2 , 23 ] , 20 : [ 2 , 23 ] , 22 : [ 2 , 23 ] , 23 : [ 2 , 23 ] , 25 : [ 2 , 23 ] } , { 5 : [ 2 , 12 ] , 14 : [ 2 , 12 ] , 15 : [ 2 , 12 ] , 16 : [ 2 , 12 ] , 19 : [ 2 , 12 ] , 20 : [ 2 , 12 ] , 22 : [ 2 , 12 ] , 23 : [ 2 , 12 ] , 25 : [ 2 , 12 ] } , { 14 : [ 2 , 18 ] , 15 : [ 2 , 18 ] , 16 : [ 2 , 18 ] , 19 : [ 2 , 18 ] , 20 : [ 2 , 18 ] , 22 : [ 2 , 18 ] , 23 : [ 2 , 18 ] , 25 : [ 2 , 18 ] } , { 18 : [ 2 , 44 ] , 21 : 56 , 24 : [ 2 , 44 ] , 29 : 53 , 30 : 60 , 31 : 54 , 32 : [ 1 , 57 ] , 33 : [ 1 , 58 ] , 34 : [ 1 , 59 ] , 35 : 55 , 36 : 61 , 37 : 62 , 38 : [ 1 , 63 ] , 40 : [ 1 , 27 ] , 41 : 26 } , { 38 : [ 1 , 64 ] } , { 18 : [ 2 , 36 ] , 24 : [ 2 , 36 ] , 32 : [ 2 , 36 ] , 33 : [ 2 , 36 ] , 34 : [ 2 , 36 ] , 38 : [ 2 , 36 ] , 40 : [ 2 , 36 ] } , { 14 : [ 2 , 17 ] , 15 : [ 2 , 17 ] , 16 : [ 2 , 17 ] , 19 : [ 2 , 17 ] , 20 : [ 2 , 17 ] , 22 : [ 2 , 17 ] , 23 : [ 2 , 17 ] , 25 : [ 2 , 17 ] } , { 5 : [ 2 , 20 ] , 14 : [ 2 , 20 ] , 15 : [ 2 , 20 ] , 16 : [ 2 , 20 ] , 19 : [ 2 , 20 ] , 20 : [ 2 , 20 ] , 22 : [ 2 , 20 ] , 23 : [ 2 , 20 ] , 25 : [ 2 , 20 ] } , { 5 : [ 2 , 21 ] , 14 : [ 2 , 21 ] , 15 : [ 2 , 21 ] , 16 : [ 2 , 21 ] , 19 : [ 2 , 21 ] , 20 : [ 2 , 21 ] , 22 : [ 2 , 21 ] , 23 : [ 2 , 21 ] , 25 : [ 2 , 21 ] } , { 18 : [ 1 , 65 ] } , { 18 : [ 2 , 41 ] } , { 18 : [ 1 , 66 ] } , { 8 : 17 , 9 : 5 , 11 : 6 , 12 : 7 , 13 : 8 , 14 : [ 1 , 9 ] , 15 : [ 1 , 10 ] , 16 : [ 1 , 12 ] , 19 : [ 1 , 11 ] , 20 : [ 2 , 4 ] , 22 : [ 1 , 13 ] , 23 : [ 1 , 14 ] , 25 : [ 1 , 15 ] } , { 18 : [ 2 , 24 ] , 24 : [ 2 , 24 ] } , { 18 : [ 2 , 43 ] , 24 : [ 2 , 43 ] , 32 : [ 2 , 43 ] , 33 : [ 2 , 43 ] , 34 : [ 2 , 43 ] , 38 : [ 2 , 43 ] , 40 : [ 2 , 43 ] } , { 18 : [ 2 , 45 ] , 24 : [ 2 , 45 ] } , { 18 : [ 2 , 26 ] , 24 : [ 2 , 26 ] , 32 : [ 2 , 26 ] , 33 : [ 2 , 26 ] , 34 : [ 2 , 26 ] , 38 : [ 2 , 26 ] , 40 : [ 2 , 26 ] } , { 18 : [ 2 , 27 ] , 24 : [ 2 , 27 ] , 32 : [ 2 , 27 ] , 33 : [ 2 , 27 ] , 34 : [ 2 , 27 ] , 38 : [ 2 , 27 ] , 40 : [ 2 , 27 ] } , { 18 : [ 2 , 28 ] , 24 : [ 2 , 28 ] , 32 : [ 2 , 28 ] , 33 : [ 2 , 28 ] , 34 : [ 2 , 28 ] , 38 : [ 2 , 28 ] , 40 : [ 2 , 28 ] } , { 18 : [ 2 , 29 ] , 24 : [ 2 , 29 ] , 32 : [ 2 , 29 ] , 33 : [ 2 , 29 ] , 34 : [ 2 , 29 ] , 38 : [ 2 , 29 ] , 40 : [ 2 , 29 ] } , { 18 : [ 2 , 30 ] , 24 : [ 2 , 30 ] , 32 : [ 2 , 30 ] , 33 : [ 2 , 30 ] , 34 : [ 2 , 30 ] , 38 : [ 2 , 30 ] , 40 : [ 2 , 30 ] } , { 18 : [ 2 , 31 ] , 24 : [ 2 , 31 ] , 37 : 67 , 38 : [ 1 , 68 ] } , { 18 : [ 2 , 46 ] , 24 : [ 2 , 46 ] , 38 : [ 2 , 46 ] } , { 18 : [ 2 , 39 ] , 24 : [ 2 , 39 ] , 32 : [ 2 , 39 ] , 33 : [ 2 , 39 ] , 34 : [ 2 , 39 ] , 38 : [ 2 , 39 ] , 39 : [ 1 , 69 ] , 40 : [ 2 , 39 ] , 42 : [ 2 , 39 ] } , { 18 : [ 2 , 38 ] , 24 : [ 2 , 38 ] , 32 : [ 2 , 38 ] , 33 : [ 2 , 38 ] , 34 : [ 2 , 38 ] , 38 : [ 2 , 38 ] , 40 : [ 2 , 38 ] , 42 : [ 2 , 38 ] } , { 5 : [ 2 , 22 ] , 14 : [ 2 , 22 ] , 15 : [ 2 , 22 ] , 16 : [ 2 , 22 ] , 19 : [ 2 , 22 ] , 20 : [ 2 , 22 ] , 22 : [ 2 , 22 ] , 23 : [ 2 , 22 ] , 25 : [ 2 , 22 ] } , { 5 : [ 2 , 19 ] , 14 : [ 2 , 19 ] , 15 : [ 2 , 19 ] , 16 : [ 2 , 19 ] , 19 : [ 2 , 19 ] , 20 : [ 2 , 19 ] , 22 : [ 2 , 19 ] , 23 : [ 2 , 19 ] , 25 : [
defaultActions : { 3 : [ 2 , 2 ] , 16 : [ 2 , 1 ] , 50 : [ 2 , 41 ] } ,
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 ;
}
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
function stripFlags ( open , close ) {
return {
left : open [ 2 ] === '~' ,
right : close [ 0 ] === '~' || close [ 1 ] === '~'
} ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
/* 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 ( 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 ] ++ ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
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 ) {
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
function strip ( start , end ) {
return yy _ . yytext = yy _ . yytext . substr ( start , yy _ . yyleng - end ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
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 :
if ( yy _ . yytext . slice ( - 1 ) !== "\\" ) this . popState ( ) ;
if ( yy _ . yytext . slice ( - 1 ) === "\\" ) strip ( 0 , 1 ) ;
return 14 ;
break ;
case 3 : strip ( 0 , 4 ) ; this . popState ( ) ; return 15 ;
break ;
case 4 : return 25 ;
break ;
case 5 : return 16 ;
break ;
case 6 : return 20 ;
break ;
case 7 : return 19 ;
break ;
case 8 : return 19 ;
break ;
case 9 : return 23 ;
break ;
case 10 : return 22 ;
break ;
case 11 : this . popState ( ) ; this . begin ( 'com' ) ;
break ;
case 12 : strip ( 3 , 5 ) ; this . popState ( ) ; return 15 ;
break ;
case 13 : return 22 ;
break ;
case 14 : return 39 ;
break ;
case 15 : return 38 ;
break ;
case 16 : return 38 ;
break ;
case 17 : return 42 ;
break ;
case 18 : /*ignore whitespace*/
break ;
case 19 : this . popState ( ) ; return 24 ;
break ;
case 20 : this . popState ( ) ; return 18 ;
break ;
case 21 : yy _ . yytext = strip ( 1 , 2 ) . replace ( /\\"/g , '"' ) ; return 32 ;
break ;
case 22 : yy _ . yytext = strip ( 1 , 2 ) . replace ( /\\'/g , "'" ) ; return 32 ;
break ;
case 23 : return 40 ;
break ;
case 24 : return 34 ;
break ;
case 25 : return 34 ;
break ;
case 26 : return 33 ;
break ;
case 27 : return 38 ;
break ;
case 28 : yy _ . yytext = strip ( 1 , 2 ) ; return 38 ;
break ;
case 29 : return 'INVALID' ;
break ;
case 30 : return 5 ;
break ;
}
} ;
lexer . rules = [ /^(?:[^\x00]*?(?=(\{\{)))/ , /^(?:[^\x00]+)/ , /^(?:[^\x00]{2,}?(?=(\{\{|$)))/ , /^(?:[\s\S]*?--\}\})/ , /^(?:\{\{(~)?>)/ , /^(?:\{\{(~)?#)/ , /^(?:\{\{(~)?\/)/ , /^(?:\{\{(~)?\^)/ , /^(?:\{\{(~)?\s*else\b)/ , /^(?:\{\{(~)?\{)/ , /^(?:\{\{(~)?&)/ , /^(?:\{\{!--)/ , /^(?:\{\{![\s\S]*?\}\})/ , /^(?:\{\{(~)?)/ , /^(?:=)/ , /^(?:\.\.)/ , /^(?:\.(?=([=~}\s\/.])))/ , /^(?:[\/.])/ , /^(?:\s+)/ , /^(?:\}(~)?\}\})/ , /^(?:(~)?\}\})/ , /^(?:"(\\["]|[^"])*")/ , /^(?:'(\\[']|[^'])*')/ , /^(?:@)/ , /^(?:true(?=([~}\s])))/ , /^(?:false(?=([~}\s])))/ , /^(?:-?[0-9]+(?=([~}\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 ] , "inclusive" : false } , "emu" : { "rules" : [ 2 ] , "inclusive" : false } , "com" : { "rules" : [ 3 ] , "inclusive" : false } , "INITIAL" : { "rules" : [ 0 , 1 , 30 ] , "inclusive" : true } } ;
return lexer ; } ) ( )
parser . lexer = lexer ;
function Parser ( ) { this . yy = { } ; } Parser . prototype = parser ; parser . Parser = Parser ;
return new Parser ;
} ) ( ) ; _ _exports _ _ = handlebars ;
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 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 ) ;
}
_ _exports _ _ . parse = parse ;
return _ _exports _ _ ;
} ) ( _ _module9 _ _ , _ _module7 _ _ ) ;
// handlebars/compiler/javascript-compiler.js
var _ _module11 _ _ = ( function ( _ _dependency1 _ _ ) {
"use strict" ;
var _ _exports _ _ ;
var COMPILER _REVISION = _ _dependency1 _ _ . COMPILER _REVISION ;
var REVISION _CHANGES = _ _dependency1 _ _ . REVISION _CHANGES ;
var log = _ _dependency1 _ _ . log ;
function Literal ( value ) {
this . value = value ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
function JavaScriptCompiler ( ) { }
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
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 ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( /^[0-9]+$/ . test ( name ) ) {
ret = parent + "[" + name + "]" ;
} else if ( JavaScriptCompiler . isValidJavaScriptVariableName ( name ) ) {
ret = parent + "." + name ;
}
else {
ret = parent + "['" + name + "']" ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
if ( wrap ) {
return '(' + parent + ' && ' + ret + ')' ;
} else {
return ret ;
}
} ,
appendToBuffer : function ( string ) {
if ( this . environment . isSimple ) {
return "return " + string + ";" ;
} else {
return {
appendToBuffer : true ,
content : string ,
toString : function ( ) { return "buffer += " + string + ";" ; }
} ;
}
} ,
initializeBuffer : function ( ) {
return this . quotedString ( "" ) ;
} ,
namespace : "Handlebars" ,
// END PUBLIC API
compile : function ( environment , options , context , asObject ) {
this . environment = environment ;
this . options = options || { } ;
log ( 'debug' , this . environment . disassemble ( ) + "\n\n" ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . name = this . environment . name ;
this . isChild = ! ! context ;
this . context = context || {
programs : [ ] ,
environments : [ ] ,
aliases : { }
} ;
this . preamble ( ) ;
this . stackSlot = 0 ;
this . stackVars = [ ] ;
this . registers = { list : [ ] } ;
this . compileStack = [ ] ;
this . inlineStack = [ ] ;
this . compileChildren ( environment , options ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
var opcodes = environment . opcodes , opcode ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . i = 0 ;
for ( var l = opcodes . length ; this . i < l ; this . i ++ ) {
opcode = opcodes [ this . i ] ;
if ( opcode . opcode === 'DECLARE' ) {
this [ opcode . name ] = opcode . value ;
} else {
this [ opcode . opcode ] . apply ( this , opcode . args ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
// Reset the stripNext flag if it was not set by this operation.
if ( opcode . opcode !== this . stripNext ) {
this . stripNext = false ;
}
}
// Flush any trailing content that might be pending.
this . pushSource ( '' ) ;
return this . createFunctionContext ( asObject ) ;
} ,
preamble : function ( ) {
var out = [ ] ;
if ( ! this . isChild ) {
var namespace = this . namespace ;
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 ) ;
2013-06-07 05:50:49 +08:00
} else {
2013-12-03 02:15:31 +08:00
out . push ( '' ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
if ( ! this . environment . isSimple ) {
out . push ( ", buffer = " + this . initializeBuffer ( ) ) ;
} else {
out . push ( "" ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// 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 ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
createFunctionContext : function ( asObject ) {
var locals = this . stackVars . concat ( this . registers . list ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( locals . length > 0 ) {
this . source [ 1 ] = this . source [ 1 ] + ", " + locals . join ( ", " ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// 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 ] ;
}
}
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( this . source [ 1 ] ) {
this . source [ 1 ] = "var " + this . source [ 1 ] . substring ( 2 ) + ";" ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// Merge children
if ( ! this . isChild ) {
this . source [ 1 ] += '\n' + this . context . programs . join ( '\n' ) + '\n' ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( ! this . environment . isSimple ) {
this . pushSource ( "return buffer;" ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
var params = this . isChild ? [ "depth0" , "data" ] : [ "Handlebars" , "depth0" , "helpers" , "partials" , "data" ] ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
for ( var i = 0 , l = this . environment . depths . list . length ; i < l ; i ++ ) {
params . push ( "depth" + this . environment . depths . list [ i ] ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// Perform a second pass over the output to merge content when possible
var source = this . mergeSource ( ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( ! this . isChild ) {
var revision = COMPILER _REVISION ,
versions = REVISION _CHANGES [ revision ] ;
source = "this.compilerInfo = [" + revision + ",'" + versions + "'];\n" + source ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
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 ;
}
} ,
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 ] ;
if ( line . appendToBuffer ) {
if ( buffer ) {
buffer = buffer + '\n + ' + line . content ;
} else {
buffer = line . content ;
}
} else {
if ( buffer ) {
source += 'buffer += ' + buffer + ';\n ' ;
buffer = undefined ;
}
source += line + '\n ' ;
}
}
return source ;
} ,
// [blockValue]
//
// On stack, before: hash, inverse, program, value
// 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
// replace it on the stack with the result of properly
// invoking blockHelperMissing.
blockValue : function ( ) {
this . context . aliases . blockHelperMissing = 'helpers.blockHelperMissing' ;
var params = [ "depth0" ] ;
this . setupParams ( 0 , params ) ;
this . replaceStack ( function ( current ) {
params . splice ( 1 , 0 , current ) ;
return "blockHelperMissing.call(" + params . join ( ", " ) + ")" ;
} ) ;
} ,
// [ambiguousBlockValue]
//
// On stack, before: hash, inverse, program, value
// 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' ;
var params = [ "depth0" ] ;
this . setupParams ( 0 , params ) ;
var current = this . topStack ( ) ;
params . splice ( 1 , 0 , current ) ;
// Use the options value generated from the invocation
params [ params . length - 1 ] = 'options' ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . pushSource ( "if (!" + this . lastHelper + ") { " + current + " = blockHelperMissing.call(" + params . join ( ", " ) + "); }" ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// [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+/ , '' ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . pendingContent = content ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// [strip]
//
// 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 ( ) {
if ( this . pendingContent ) {
this . pendingContent = this . pendingContent . replace ( /\s+$/ , '' ) ;
}
this . stripNext = 'strip' ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// [append]
//
// On stack, before: value, ...
// On stack, after: ...
//
// Coerces `value` to a String and appends it to the current buffer.
//
// 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 ( "''" ) + " }" ) ;
}
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// [appendEscaped]
//
// On stack, before: value, ...
// On stack, after: ...
//
// Escape `value` and append it to the buffer
appendEscaped : function ( ) {
this . context . aliases . escapeExpression = 'this.escapeExpression' ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . pushSource ( this . appendToBuffer ( "escapeExpression(" + this . popStack ( ) + ")" ) ) ;
} ,
// [getContext]
//
// On stack, before: ...
// On stack, after: ...
// 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' ) ) ;
} ,
// [pushContext]
//
// On stack, before: ...
// On stack, after: currentContext, ...
//
// Pushes the value of the current context onto the stack.
pushContext : function ( ) {
this . pushStackLiteral ( 'depth' + this . lastContext ) ;
} ,
// [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 ( ) {
this . context . aliases . functionType = '"function"' ;
this . replaceStack ( function ( current ) {
return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current ;
} ) ;
} ,
// [lookup]
//
// On stack, before: value, ...
// On stack, after: value[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' ) ;
} ) ;
} ,
// [lookupData]
//
// On stack, before: ...
// On stack, after: data, ...
//
// Push the data lookup operator
lookupData : function ( ) {
this . push ( 'data' ) ;
} ,
// [pushStringParam]
//
// On stack, before: ...
// On stack, after: string, currentContext, ...
//
// 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 ) ;
this . pushString ( type ) ;
if ( typeof string === 'string' ) {
this . pushString ( string ) ;
2013-06-07 05:50:49 +08:00
} else {
2013-12-03 02:15:31 +08:00
this . pushStackLiteral ( string ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
emptyHash : function ( ) {
this . pushStackLiteral ( '{}' ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( this . options . stringParams ) {
this . register ( 'hashTypes' , '{}' ) ;
this . register ( 'hashContexts' , '{}' ) ;
}
} ,
pushHash : function ( ) {
this . hash = { values : [ ] , types : [ ] , contexts : [ ] } ;
} ,
popHash : function ( ) {
var hash = this . hash ;
this . hash = undefined ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( this . options . stringParams ) {
this . register ( 'hashContexts' , '{' + hash . contexts . join ( ',' ) + '}' ) ;
this . register ( 'hashTypes' , '{' + hash . types . join ( ',' ) + '}' ) ;
}
this . push ( '{\n ' + hash . values . join ( ',\n ' ) + '\n }' ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// [pushString]
//
// On stack, before: ...
// On stack, after: quotedString(string), ...
//
// Push a quoted version of `string` onto the stack
pushString : function ( string ) {
this . pushStackLiteral ( this . quotedString ( string ) ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// [push]
//
// On stack, before: ...
// On stack, after: expr, ...
//
// Push an expression onto the stack
push : function ( expr ) {
this . inlineStack . push ( expr ) ;
return expr ;
} ,
2013-07-16 07:47:13 +08:00
2013-12-03 02:15:31 +08:00
// [pushLiteral]
//
// On stack, before: ...
// On stack, after: value, ...
//
// Pushes a value onto the stack. This operation prevents
// the compiler from creating a temporary variable to hold
// it.
pushLiteral : function ( value ) {
this . pushStackLiteral ( value ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// [pushProgram]
//
// On stack, before: ...
// On stack, after: program(guid), ...
//
// Push a program expression onto the stack. This takes
// a compile-time guid and converts it into a runtime-accessible
// expression.
pushProgram : function ( guid ) {
if ( guid != null ) {
this . pushStackLiteral ( this . programExpression ( guid ) ) ;
} else {
this . pushStackLiteral ( null ) ;
}
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// [invokeHelper]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of helper invocation
//
// Pops off the helper's parameters, invokes the helper,
// and pushes the helper's return value onto the stack.
//
// If the helper is not found, `helperMissing` is called.
invokeHelper : function ( paramSize , name ) {
this . context . aliases . helperMissing = 'helpers.helperMissing' ;
var helper = this . lastHelper = this . setupHelper ( paramSize , name , true ) ;
var nonHelper = this . nameLookup ( 'depth' + this . lastContext , name , 'context' ) ;
this . push ( helper . name + ' || ' + nonHelper ) ;
this . replaceStack ( function ( name ) {
return name + ' ? ' + name + '.call(' +
helper . callParams + ") " + ": helperMissing.call(" +
helper . helperMissingParams + ")" ;
} ) ;
} ,
// [invokeKnownHelper]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of helper invocation
//
// This operation is used when the helper is known to exist,
// so a `helperMissing` fallback is not required.
invokeKnownHelper : function ( paramSize , name ) {
var helper = this . setupHelper ( paramSize , name ) ;
this . push ( helper . name + ".call(" + helper . callParams + ")" ) ;
} ,
// [invokeAmbiguous]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of disambiguation
//
// This operation is used when an expression like `{{foo}}`
// is provided, but we don't know at compile-time whether it
// is a helper or a path.
//
// 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"' ;
this . pushStackLiteral ( '{}' ) ; // Hash value
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 ( ) ;
this . pushSource ( 'if (' + nextStack + ' = ' + helperName + ') { ' + nextStack + ' = ' + nextStack + '.call(' + helper . callParams + '); }' ) ;
this . pushSource ( 'else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '.call(' + helper . callParams + ') : ' + nextStack + '; }' ) ;
} ,
// [invokePartial]
//
// On stack, before: context, ...
// On stack after: result of partial invocation
//
// 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" ] ;
if ( this . options . data ) {
params . push ( "data" ) ;
}
this . context . aliases . self = "this" ;
this . push ( "self.invokePartial(" + params . join ( ", " ) + ")" ) ;
} ,
// [assignToHash]
//
// 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 ) {
var value = this . popStack ( ) ,
context ,
type ;
if ( this . options . stringParams ) {
type = this . popStack ( ) ;
context = this . popStack ( ) ;
}
var hash = this . hash ;
if ( context ) {
hash . contexts . push ( "'" + key + "': " + context ) ;
}
if ( type ) {
hash . types . push ( "'" + key + "': " + type ) ;
}
hash . values . push ( "'" + key + "': (" + value + ")" ) ;
} ,
// HELPERS
compiler : JavaScriptCompiler ,
compileChildren : function ( environment , options ) {
var children = environment . children , child , compiler ;
for ( var i = 0 , l = children . length ; i < l ; i ++ ) {
child = children [ i ] ;
compiler = new this . compiler ( ) ;
var index = this . matchExistingProgram ( child ) ;
if ( index == null ) {
this . context . programs . push ( '' ) ; // Placeholder to prevent name conflicts for nested children
index = this . context . programs . length ;
child . index = index ;
child . name = 'program' + index ;
this . context . programs [ index ] = compiler . compile ( child , options , this . context ) ;
this . context . environments [ index ] = child ;
} else {
child . index = index ;
child . name = 'program' + index ;
}
}
} ,
matchExistingProgram : function ( 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 ;
}
}
} ,
programExpression : function ( guid ) {
this . context . aliases . self = "this" ;
if ( guid == null ) {
return "self.noop" ;
}
var child = this . environment . children [ guid ] ,
depths = child . depths . list , depth ;
var programParams = [ child . index , child . name , "data" ] ;
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 ) ) ; }
}
return ( depths . length === 0 ? "self.program(" : "self.programWithDepth(" ) + programParams . join ( ", " ) + ")" ;
} ,
register : function ( name , val ) {
this . useRegister ( name ) ;
this . pushSource ( name + " = " + val + ";" ) ;
} ,
useRegister : function ( name ) {
if ( ! this . registers [ name ] ) {
this . registers [ name ] = true ;
this . registers . list . push ( name ) ;
}
} ,
pushStackLiteral : function ( item ) {
return this . push ( new Literal ( item ) ) ;
} ,
pushSource : function ( source ) {
if ( this . pendingContent ) {
this . source . push ( this . appendToBuffer ( this . quotedString ( this . pendingContent ) ) ) ;
this . pendingContent = undefined ;
}
if ( source ) {
this . source . push ( source ) ;
}
} ,
pushStack : function ( item ) {
this . flushInline ( ) ;
var stack = this . incrStack ( ) ;
if ( item ) {
this . pushSource ( stack + " = " + item + ";" ) ;
}
this . compileStack . push ( stack ) ;
return stack ;
} ,
replaceStack : function ( callback ) {
var prefix = '' ,
inline = this . isInline ( ) ,
stack ;
// 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 ;
} else {
// Get or create the current stack name for use by the inline
var name = this . stackSlot ? this . topStackName ( ) : this . incrStack ( ) ;
prefix = '(' + this . push ( name ) + ' = ' + top + '),' ;
stack = this . topStack ( ) ;
}
} else {
stack = this . topStack ( ) ;
}
var item = callback . call ( this , stack ) ;
if ( inline ) {
if ( this . inlineStack . length || this . compileStack . length ) {
this . popStack ( ) ;
}
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 + ");" ) ;
}
return stack ;
} ,
nextStack : function ( ) {
return this . pushStack ( ) ;
} ,
incrStack : function ( ) {
this . stackSlot ++ ;
if ( this . stackSlot > this . stackVars . length ) { this . stackVars . push ( "stack" + this . stackSlot ) ; }
return this . topStackName ( ) ;
} ,
topStackName : function ( ) {
return "stack" + this . stackSlot ;
} ,
flushInline : function ( ) {
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 ) ;
}
}
}
} ,
isInline : function ( ) {
return this . inlineStack . length ;
} ,
popStack : function ( wrapped ) {
var inline = this . isInline ( ) ,
item = ( inline ? this . inlineStack : this . compileStack ) . pop ( ) ;
if ( ! wrapped && ( item instanceof Literal ) ) {
return item . value ;
} else {
if ( ! inline ) {
this . stackSlot -- ;
}
return item ;
}
} ,
topStack : function ( wrapped ) {
var stack = ( this . isInline ( ) ? this . inlineStack : this . compileStack ) ,
item = stack [ stack . length - 1 ] ;
if ( ! wrapped && ( 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' ) + '"' ;
} ,
setupHelper : function ( paramSize , name , missingParams ) {
var params = [ ] ;
this . setupParams ( paramSize , params , missingParams ) ;
var foundHelper = this . nameLookup ( 'helpers' , name , 'helper' ) ;
return {
params : params ,
name : foundHelper ,
callParams : [ "depth0" ] . concat ( params ) . join ( ", " ) ,
helperMissingParams : missingParams && [ "depth0" , this . quotedString ( name ) ] . concat ( params ) . join ( ", " )
} ;
} ,
// the params and contexts arguments are passed in arrays
// to fill in
setupParams : function ( paramSize , params , useRegister ) {
var options = [ ] , contexts = [ ] , types = [ ] , param , inverse , program ;
options . push ( "hash:" + this . popStack ( ) ) ;
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" ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
options . push ( "inverse:" + inverse ) ;
options . push ( "fn:" + program ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
for ( var i = 0 ; i < paramSize ; i ++ ) {
param = this . popStack ( ) ;
params . push ( param ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( this . options . stringParams ) {
types . push ( this . popStack ( ) ) ;
contexts . push ( this . popStack ( ) ) ;
2013-07-16 07:47:13 +08:00
}
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
if ( this . options . stringParams ) {
options . push ( "contexts:[" + contexts . join ( "," ) + "]" ) ;
options . push ( "types:[" + types . join ( "," ) + "]" ) ;
options . push ( "hashContexts:hashContexts" ) ;
options . push ( "hashTypes:hashTypes" ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( this . options . data ) {
options . push ( "data:data" ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
options = "{" + options . join ( "," ) + "}" ;
if ( useRegister ) {
this . register ( 'options' , options ) ;
params . push ( 'options' ) ;
} else {
params . push ( options ) ;
}
return params . join ( ", " ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
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 ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
JavaScriptCompiler . isValidJavaScriptVariableName = function ( name ) {
if ( ! JavaScriptCompiler . RESERVED _WORDS [ name ] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/ . test ( name ) ) {
return true ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
return false ;
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ = JavaScriptCompiler ;
return _ _exports _ _ ;
} ) ( _ _module2 _ _ ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// handlebars/compiler/compiler.js
var _ _module10 _ _ = ( function ( _ _dependency1 _ _ , _ _dependency2 _ _ , _ _dependency3 _ _ , _ _dependency4 _ _ ) {
"use strict" ;
var _ _exports _ _ = { } ;
var Exception = _ _dependency1 _ _ ;
var parse = _ _dependency2 _ _ . parse ;
var JavaScriptCompiler = _ _dependency3 _ _ ;
var AST = _ _dependency4 _ _ ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
function Compiler ( ) { }
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . Compiler = Compiler ; // 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.
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 ) ;
2013-06-07 05:50:49 +08:00
} else {
2013-12-03 02:15:31 +08:00
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 ( " " ) ) ;
2013-06-07 05:50:49 +08:00
}
}
2013-12-03 02:15:31 +08:00
return out . join ( "\n" ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
equals : function ( other ) {
var len = this . opcodes . length ;
if ( other . opcodes . length !== len ) {
return false ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
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 ;
}
}
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
len = this . children . length ;
if ( other . children . length !== len ) {
return false ;
}
for ( i = 0 ; i < len ; i ++ ) {
if ( ! this . children [ i ] . equals ( other . children [ i ] ) ) {
return false ;
}
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return true ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
guid : 0 ,
compile : function ( program , options ) {
this . opcodes = [ ] ;
this . children = [ ] ;
this . depths = { list : [ ] } ;
this . options = options ;
// These changes will propagate to the other compiler components
var knownHelpers = this . options . knownHelpers ;
this . options . knownHelpers = {
'helperMissing' : true ,
'blockHelperMissing' : true ,
'each' : true ,
'if' : true ,
'unless' : true ,
'with' : true ,
'log' : true
} ;
if ( knownHelpers ) {
for ( var name in knownHelpers ) {
this . options . knownHelpers [ name ] = knownHelpers [ name ] ;
}
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return this . accept ( program ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
accept : function ( node ) {
var strip = node . strip || { } ,
ret ;
if ( strip . left ) {
this . opcode ( 'strip' ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
ret = this [ node . type ] ( node ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( strip . right ) {
this . opcode ( 'strip' ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return ret ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
program : function ( program ) {
var statements = program . statements ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
for ( var i = 0 , l = statements . length ; i < l ; i ++ ) {
this . accept ( statements [ i ] ) ;
}
this . isSimple = l === 1 ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . depths . list = this . depths . list . sort ( function ( a , b ) {
return a - b ;
} ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return this ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
compileProgram : function ( program ) {
var result = new this . compiler ( ) . compile ( program , this . options ) ;
var guid = this . guid ++ , depth ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . usePartial = this . usePartial || result . usePartial ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . children [ guid ] = result ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
for ( var i = 0 , l = result . depths . list . length ; i < l ; i ++ ) {
depth = result . depths . list [ i ] ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( depth < 2 ) { continue ; }
else { this . addDepth ( depth - 1 ) ; }
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return guid ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
block : function ( block ) {
var mustache = block . mustache ,
program = block . program ,
inverse = block . inverse ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( program ) {
program = this . compileProgram ( program ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( inverse ) {
inverse = this . compileProgram ( inverse ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
var type = this . classifyMustache ( mustache ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( type === "helper" ) {
this . helperMustache ( mustache , program , inverse ) ;
} else if ( type === "simple" ) {
this . simpleMustache ( mustache ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// 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' ) ;
} else {
this . ambiguousMustache ( mustache , program , inverse ) ;
// 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 ( 'ambiguousBlockValue' ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . opcode ( 'append' ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
hash : function ( hash ) {
var pairs = hash . pairs , pair , val ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . opcode ( 'pushHash' ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
for ( var i = 0 , l = pairs . length ; i < l ; i ++ ) {
pair = pairs [ i ] ;
val = pair [ 1 ] ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( this . options . stringParams ) {
if ( val . depth ) {
this . addDepth ( val . depth ) ;
}
this . opcode ( 'getContext' , val . depth || 0 ) ;
this . opcode ( 'pushStringParam' , val . stringModeValue , val . type ) ;
} else {
this . accept ( val ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . opcode ( 'assignToHash' , pair [ 0 ] ) ;
}
this . opcode ( 'popHash' ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
partial : function ( partial ) {
var partialName = partial . partialName ;
this . usePartial = true ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( partial . context ) {
this . ID ( partial . context ) ;
2013-06-07 05:50:49 +08:00
} else {
2013-12-03 02:15:31 +08:00
this . opcode ( 'push' , 'depth0' ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
this . opcode ( 'invokePartial' , partialName . name ) ;
this . opcode ( 'append' ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
content : function ( content ) {
this . opcode ( 'appendContent' , content . string ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
mustache : function ( mustache ) {
var options = this . options ;
var type = this . classifyMustache ( mustache ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( type === "simple" ) {
this . simpleMustache ( mustache ) ;
} else if ( type === "helper" ) {
this . helperMustache ( mustache ) ;
} else {
this . ambiguousMustache ( mustache ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( mustache . escaped && ! options . noEscape ) {
this . opcode ( 'appendEscaped' ) ;
} else {
this . opcode ( 'append' ) ;
}
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
ambiguousMustache : function ( mustache , program , inverse ) {
var id = mustache . id ,
name = id . parts [ 0 ] ,
isBlock = program != null || inverse != null ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . opcode ( 'getContext' , id . depth ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . opcode ( 'pushProgram' , program ) ;
this . opcode ( 'pushProgram' , inverse ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . opcode ( 'invokeAmbiguous' , name , isBlock ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
simpleMustache : function ( mustache ) {
var id = mustache . id ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
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' ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . opcode ( 'resolvePossibleLambda' ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
helperMustache : function ( mustache , program , inverse ) {
var params = this . setupFullMustacheParams ( mustache , program , inverse ) ,
name = mustache . id . parts [ 0 ] ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( this . options . knownHelpers [ name ] ) {
this . opcode ( 'invokeKnownHelper' , params . length , name ) ;
} else if ( this . options . knownHelpersOnly ) {
throw new Error ( "You specified knownHelpersOnly, but used the unknown helper " + name ) ;
2013-06-07 05:50:49 +08:00
} else {
2013-12-03 02:15:31 +08:00
this . opcode ( 'invokeHelper' , params . length , name ) ;
}
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
ID : function ( id ) {
this . addDepth ( id . depth ) ;
this . opcode ( 'getContext' , id . depth ) ;
var name = id . parts [ 0 ] ;
if ( ! name ) {
this . opcode ( 'pushContext' ) ;
} else {
this . opcode ( 'lookupOnContext' , id . parts [ 0 ] ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
for ( var i = 1 , l = id . parts . length ; i < l ; i ++ ) {
this . opcode ( 'lookup' , id . parts [ i ] ) ;
}
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
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 ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
this . opcode ( 'lookupData' ) ;
var parts = data . id . parts ;
for ( var i = 0 , l = parts . length ; i < l ; i ++ ) {
this . opcode ( 'lookup' , parts [ i ] ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
STRING : function ( string ) {
this . opcode ( 'pushString' , string . string ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
INTEGER : function ( integer ) {
this . opcode ( 'pushLiteral' , integer . integer ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
BOOLEAN : function ( bool ) {
this . opcode ( 'pushLiteral' , bool . bool ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
comment : function ( ) { } ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// HELPERS
opcode : function ( name ) {
this . opcodes . push ( { opcode : name , args : [ ] . slice . call ( arguments , 1 ) } ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
declare : function ( name , value ) {
this . opcodes . push ( { opcode : 'DECLARE' , name : name , value : value } ) ;
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
addDepth : function ( depth ) {
if ( isNaN ( depth ) ) { throw new Error ( "EWOT" ) ; }
if ( depth === 0 ) { return ; }
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( ! this . depths [ depth ] ) {
this . depths [ depth ] = true ;
this . depths . list . push ( depth ) ;
}
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
classifyMustache : function ( mustache ) {
var isHelper = mustache . isHelper ;
var isEligible = mustache . eligibleHelper ;
var options = this . options ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// if ambiguous, we can possibly resolve the ambiguity now
if ( isEligible && ! isHelper ) {
var name = mustache . id . parts [ 0 ] ;
if ( options . knownHelpers [ name ] ) {
isHelper = true ;
} else if ( options . knownHelpersOnly ) {
isEligible = false ;
}
}
if ( isHelper ) { return "helper" ; }
else if ( isEligible ) { return "ambiguous" ; }
else { return "simple" ; }
} ,
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
pushParams : function ( params ) {
var i = params . length , param ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
while ( i -- ) {
param = params [ i ] ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( this . options . stringParams ) {
if ( param . depth ) {
this . addDepth ( param . depth ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . opcode ( 'getContext' , param . depth || 0 ) ;
this . opcode ( 'pushStringParam' , param . stringModeValue , param . type ) ;
} else {
this [ param . type ] ( param ) ;
}
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
} ,
setupMustacheParams : function ( mustache ) {
var params = mustache . params ;
this . pushParams ( params ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( mustache . hash ) {
this . hash ( mustache . hash ) ;
} else {
this . opcode ( 'emptyHash' ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
return params ;
} ,
// this will replace setupMustacheParams when we're done
setupFullMustacheParams : function ( mustache , program , inverse ) {
var params = mustache . params ;
this . pushParams ( params ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
this . opcode ( 'pushProgram' , program ) ;
this . opcode ( 'pushProgram' , inverse ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( mustache . hash ) {
this . hash ( mustache . hash ) ;
} else {
this . opcode ( 'emptyHash' ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
return params ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
function precompile ( input , options ) {
if ( input == null || ( typeof input !== 'string' && input . constructor !== AST . ProgramNode ) ) {
throw new Exception ( "You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
options = options || { } ;
if ( ! ( 'data' in options ) ) {
options . data = true ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
var ast = parse ( input ) ;
2013-06-07 05:50:49 +08:00
var environment = new Compiler ( ) . compile ( ast , options ) ;
2013-12-03 02:15:31 +08:00
return new JavaScriptCompiler ( ) . compile ( environment , options ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
_ _exports _ _ . precompile = precompile ; function compile ( input , options , env ) {
if ( input == null || ( typeof input !== 'string' && input . constructor !== AST . ProgramNode ) ) {
throw new Exception ( "You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
options = options || { } ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
if ( ! ( 'data' in options ) ) {
options . data = true ;
}
2013-07-16 07:47:13 +08:00
2013-12-03 02:15:31 +08:00
var compiled ;
function compileInput ( ) {
var ast = parse ( input ) ;
var environment = new Compiler ( ) . compile ( ast , options ) ;
var templateSpec = new JavaScriptCompiler ( ) . compile ( environment , options , undefined , true ) ;
return env . template ( templateSpec ) ;
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
// Template is only compiled on first use and cached after that point.
2013-06-07 05:50:49 +08:00
return function ( context , options ) {
2013-12-03 02:15:31 +08:00
if ( ! compiled ) {
compiled = compileInput ( ) ;
2013-06-07 05:50:49 +08:00
}
2013-12-03 02:15:31 +08:00
return compiled . call ( this , context , options ) ;
2013-06-07 05:50:49 +08:00
} ;
2013-12-03 02:15:31 +08:00
}
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ . compile = compile ;
return _ _exports _ _ ;
} ) ( _ _module5 _ _ , _ _module8 _ _ , _ _module11 _ _ , _ _module7 _ _ ) ;
// handlebars.js
var _ _module0 _ _ = ( function ( _ _dependency1 _ _ , _ _dependency2 _ _ , _ _dependency3 _ _ , _ _dependency4 _ _ , _ _dependency5 _ _ ) {
"use strict" ;
var _ _exports _ _ ;
var Handlebars = _ _dependency1 _ _ ;
// 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 ( ) ;
hb . compile = function ( input , options ) {
return compile ( input , options , hb ) ;
} ;
hb . precompile = precompile ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
hb . AST = AST ;
hb . Compiler = Compiler ;
hb . JavaScriptCompiler = JavaScriptCompiler ;
hb . Parser = Parser ;
hb . parse = parse ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return hb ;
} ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
Handlebars = create ( ) ;
Handlebars . create = create ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
_ _exports _ _ = Handlebars ;
return _ _exports _ _ ;
} ) ( _ _module1 _ _ , _ _module7 _ _ , _ _module8 _ _ , _ _module10 _ _ , _ _module11 _ _ ) ;
2013-06-07 05:50:49 +08:00
2013-12-03 02:15:31 +08:00
return _ _module0 _ _ ;
} ) ( ) ;