nl_tokens: parse #foreach
pl_tokens: function ( block ) { var ast = block [ 0 ] ; var _from = this . getLiteral ( ast . from ) ; var _block = block . slice ( 1 ) ; var _to = ast . to ; var local = { foreach : { count : 0 } } ; var ret = '' ; var guid = utils . guid ( ) ; var contextId = 'foreach:' + guid ; var type = ( { } ) . toString . call ( _from ) ; if ( ! _from || ( type !== '[object Array]' && type !== '[object Object]' ) ) { return '' ; } if ( utils . isArray ( _from ) ) { var len = _from . length ; utils . forEach ( _from , function ( val , i ) { if ( this . _state . break ) { return ; } // 构造临时变量 local [ _to ] = val ; local . foreach = { count : i + 1 , index : i , hasNext : i + 1 < len } ; local . velocityCount = i + 1 ; this . local [ contextId ] = local ; ret += this . _render ( _block , contextId ) ; } , this ) ; } else { var len = utils . keys ( _from ) . length ; utils . forEach ( utils . keys ( _from ) , function ( key , i ) { if ( this . _state . break ) { return ; } <mask> [ _to ] = _from [ key ] ; local . foreach = { count : i + 1 , index : i , hasNext : i + 1 < len } ; local . velocityCount = i + 1 ; this . local [ contextId ] = local ; ret += this . _render ( _block , contextId ) ; } , this ) ; } // if foreach items be an empty array, then this code will shift current // conditions, but not this._render call, so this will shift parent context if ( _from && _from . length ) { this . _state . break = false ; // empty current local context object this . local [ contextId ] = { } ; this . conditions . shift ( ) ; this . condition = this . conditions [ 0 ] || '' ; } return ret ; }