| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731 | 
							- /**
 
-  * ETPL (Enterprise Template)
 
-  * Copyright 2013 Baidu Inc. All rights reserved.
 
-  * 
 
-  * @file 模板引擎
 
-  * @author errorrik(errorrik@gmail.com)
 
-  *         otakustay(otakustay@gmail.com)
 
-  */
 
- // 有的正则比较长,所以特别放开一些限制
 
- /* jshint maxdepth: 10, unused: false, white: false */
 
- // HACK: 可见的重复代码未抽取成function和var是为了gzip size,吐槽的一边去
 
- (function (root) {
 
-     /**
 
-      * 对象属性拷贝
 
-      * 
 
-      * @inner
 
-      * @param {Object} target 目标对象
 
-      * @param {Object} source 源对象
 
-      * @return {Object} 返回目标对象
 
-      */
 
-     function extend( target, source ) {
 
-         for ( var key in source ) {
 
-             if ( source.hasOwnProperty( key ) ) {
 
-                 target[ key ] = source[ key ];
 
-             }
 
-         }
 
-         return target;
 
-     }
 
-     /**
 
-      * 随手写了个栈
 
-      *
 
-      * @inner
 
-      * @constructor
 
-      */
 
-     function Stack() {
 
-         this.raw = [];
 
-         this.length = 0;
 
-     }
 
-     Stack.prototype = {
 
-         /**
 
-          * 添加元素进栈
 
-          *
 
-          * @param {*} elem 添加项
 
-          */
 
-         push: function ( elem ) {
 
-             this.raw[ this.length++ ] = elem;
 
-         },
 
-         /**
 
-          * 弹出顶部元素
 
-          *
 
-          * @return {*}
 
-          */
 
-         pop: function () {
 
-             if ( this.length > 0 ) {
 
-                 var elem = this.raw[ --this.length ];
 
-                 this.raw.length = this.length;
 
-                 return elem;
 
-             }
 
-         },
 
-         /**
 
-          * 获取顶部元素
 
-          *
 
-          * @return {*}
 
-          */
 
-         top: function () {
 
-             return this.raw[ this.length - 1 ];
 
-         },
 
-         /**
 
-          * 获取底部元素
 
-          *
 
-          * @return {*}
 
-          */
 
-         bottom: function () {
 
-             return this.raw[ 0 ];
 
-         },
 
-         /**
 
-          * 根据查询条件获取元素
 
-          * 
 
-          * @param {Function} condition 查询函数
 
-          * @return {*}
 
-          */
 
-         find: function ( condition ) {
 
-             var index = this.length;
 
-             while ( index-- ) {
 
-                 var item = this.raw[ index ];
 
-                 if ( condition( item ) ) {
 
-                     return item;
 
-                 }
 
-             }
 
-         }
 
-     };
 
-     /**
 
-      * 唯一id的起始值
 
-      * 
 
-      * @inner
 
-      * @type {number}
 
-      */
 
-     var guidIndex = 0x2B845;
 
-     /**
 
-      * 获取唯一id,用于匿名target或编译代码的变量名生成
 
-      * 
 
-      * @inner
 
-      * @return {string}
 
-      */
 
-     function generateGUID() {
 
-         return '___' + (guidIndex++);
 
-     }
 
-     /**
 
-      * 构建类之间的继承关系
 
-      * 
 
-      * @inner
 
-      * @param {Function} subClass 子类函数
 
-      * @param {Function} superClass 父类函数
 
-      */
 
-     function inherits( subClass, superClass ) {
 
-         var F = new Function();
 
-         F.prototype = superClass.prototype;
 
-         subClass.prototype = new F();
 
-         subClass.prototype.constructor = subClass;
 
-         // 由于引擎内部的使用场景都是inherits后,逐个编写子类的prototype方法
 
-         // 所以,不考虑将原有子类prototype缓存再逐个拷贝回去
 
-     }
 
-     /**
 
-      * HTML Filter替换的字符实体表
 
-      * 
 
-      * @const
 
-      * @inner
 
-      * @type {Object}
 
-      */
 
-     var HTML_ENTITY = {
 
-         '&': '&',
 
-         '<': '<',
 
-         '>': '>',
 
-         '"': '"',
 
-         "'": '''
 
-     };
 
-     /**
 
-      * HTML Filter的替换函数
 
-      * 
 
-      * @inner
 
-      * @param {string} c 替换字符
 
-      * @return {string}
 
-      */
 
-     function htmlFilterReplacer( c ) {
 
-         return HTML_ENTITY[ c ];
 
-     }
 
-     /**
 
-      * 默认filter
 
-      * 
 
-      * @inner
 
-      * @const
 
-      * @type {Object}
 
-      */
 
-     var DEFAULT_FILTERS = {
 
-         /**
 
-          * HTML转义filter
 
-          * 
 
-          * @param {string} source 源串
 
-          * @return {string}
 
-          */
 
-         html: function ( source ) {
 
-             return source.replace( /[&<>"']/g, htmlFilterReplacer );
 
-         },
 
-         /**
 
-          * URL编码filter
 
-          * 
 
-          * @param {string} source 源串
 
-          * @return {string}
 
-          */
 
-         url: encodeURIComponent,
 
-         /**
 
-          * 源串filter,用于在默认开启HTML转义时获取源串,不进行转义
 
-          * 
 
-          * @param {string} source 源串
 
-          * @return {string}
 
-          */
 
-         raw: function ( source ) {
 
-             return source;
 
-         }
 
-     };
 
-     /**
 
-      * 字符串字面化
 
-      * 
 
-      * @inner
 
-      * @param {string} source 需要字面化的字符串
 
-      * @return {string}
 
-      */
 
-     function stringLiteralize( source ) {
 
-         return '"'
 
-             + source
 
-                 .replace( /\x5C/g, '\\\\' )
 
-                 .replace( /"/g, '\\"' )
 
-                 .replace( /\x0A/g, '\\n' )
 
-                 .replace( /\x09/g, '\\t' )
 
-                 .replace( /\x0D/g, '\\r' )
 
-                 // .replace( /\x08/g, '\\b' )
 
-                 // .replace( /\x0C/g, '\\f' )
 
-             + '"';
 
-     }
 
-     /**
 
-      * 字符串格式化
 
-      * 
 
-      * @inner
 
-      * @param {string} source 目标模版字符串
 
-      * @param {...string} replacements 字符串替换项集合
 
-      * @return {string}
 
-      */
 
-     function stringFormat( source ) {
 
-         var args = arguments;
 
-         return source.replace( 
 
-             /\{([0-9]+)\}/g,
 
-             function ( match, index ) {
 
-                 return args[ index - 0 + 1 ];
 
-             } );
 
-     }
 
-     /**
 
-      * 用于render的字符串变量声明语句
 
-      * 
 
-      * @inner
 
-      * @const
 
-      * @type {string}
 
-      */
 
-     var RENDER_STRING_DECLATION = 'var r="";';
 
-     /**
 
-      * 用于render的字符串内容添加语句(起始)
 
-      * 
 
-      * @inner
 
-      * @const
 
-      * @type {string}
 
-      */
 
-     var RENDER_STRING_ADD_START = 'r+=';
 
-     /**
 
-      * 用于render的字符串内容添加语句(结束)
 
-      * 
 
-      * @inner
 
-      * @const
 
-      * @type {string}
 
-      */
 
-     var RENDER_STRING_ADD_END = ';';
 
-     /**
 
-      * 用于render的字符串内容返回语句
 
-      * 
 
-      * @inner
 
-      * @const
 
-      * @type {string}
 
-      */
 
-     var RENDER_STRING_RETURN = 'return r;';
 
-     // HACK: IE8-时,编译后的renderer使用join Array的策略进行字符串拼接
 
-     if ( typeof navigator != 'undefined' 
 
-         && /msie\s*([0-9]+)/i.test( navigator.userAgent )
 
-         && RegExp.$1 - 0 < 8
 
-     ) {
 
-         RENDER_STRING_DECLATION = 'var r=[],ri=0;';
 
-         RENDER_STRING_ADD_START = 'r[ri++]=';
 
-         RENDER_STRING_RETURN = 'return r.join("");';
 
-     }
 
-     /**
 
-      * 将访问变量名称转换成getVariable调用的编译语句
 
-      * 用于if、var等命令生成编译代码
 
-      * 
 
-      * @inner
 
-      * @param {string} name 访问变量名
 
-      * @return {string}
 
-      */
 
-     function toGetVariableLiteral( name ) {
 
-         name = name.replace( /^\s*\*/, '' );
 
-         return stringFormat(
 
-             'gv({0},["{1}"])',
 
-             stringLiteralize( name ),
 
-             name.replace(
 
-                     /\[['"]?([^'"]+)['"]?\]/g, 
 
-                     function ( match, name ) {
 
-                         return '.' + name;
 
-                     }
 
-                 )
 
-                 .split( '.' )
 
-                 .join( '","' )
 
-         );
 
-     }
 
-     /**
 
-      * 解析文本片段中以固定字符串开头和结尾的包含块
 
-      * 用于 命令串:<!-- ... --> 和 变量替换串:${...} 的解析
 
-      * 
 
-      * @inner
 
-      * @param {string} source 要解析的文本
 
-      * @param {string} open 包含块开头
 
-      * @param {string} close 包含块结束
 
-      * @param {boolean} greedy 是否贪婪匹配
 
-      * @param {function({string})} onInBlock 包含块内文本的处理函数
 
-      * @param {function({string})} onOutBlock 非包含块内文本的处理函数
 
-      */
 
-     function parseTextBlock( source, open, close, greedy, onInBlock, onOutBlock ) {
 
-         var closeLen = close.length;
 
-         var texts = source.split( open );
 
-         var level = 0;
 
-         var buf = [];
 
-         for ( var i = 0, len = texts.length; i < len; i++ ) {
 
-             var text = texts[ i ];
 
-             if ( i ) {
 
-                 var openBegin = 1;
 
-                 level++;
 
-                 while ( 1 ) {
 
-                     var closeIndex = text.indexOf( close );
 
-                     if ( closeIndex < 0 ) {
 
-                         buf.push( level > 1 && openBegin ? open : '', text );
 
-                         break;
 
-                     }
 
-                     level = greedy ? level - 1 : 0;
 
-                     buf.push( 
 
-                         level > 0 && openBegin ? open : '',
 
-                         text.slice( 0, closeIndex ),
 
-                         level > 0 ? close : ''
 
-                     );
 
-                     text = text.slice( closeIndex + closeLen );
 
-                     openBegin = 0;
 
-                     if ( level === 0 ) {
 
-                         break;
 
-                     }
 
-                 }
 
-                 if ( level === 0 ) {
 
-                     onInBlock( buf.join( '' ) );
 
-                     onOutBlock( text );
 
-                     buf = [];
 
-                 }
 
-             }
 
-             else {
 
-                 text && onOutBlock( text );
 
-             }
 
-         }
 
-         if ( level > 0 && buf.length > 0 ) {
 
-             onOutBlock( open );
 
-             onOutBlock( buf.join( '' ) );
 
-         }
 
-     }
 
-     /**
 
-      * 编译变量访问和变量替换的代码
 
-      * 用于普通文本或if、var、filter等命令生成编译代码
 
-      * 
 
-      * @inner
 
-      * @param {string} source 源代码
 
-      * @param {Engine} engine 引擎实例
 
-      * @param {boolean} forText 是否为输出文本的变量替换
 
-      * @return {string}
 
-      */
 
-     function compileVariable( source, engine, forText ) {
 
-         var code = [];
 
-         var options = engine.options;
 
-         var toStringHead = '';
 
-         var toStringFoot = '';
 
-         var wrapHead = '';
 
-         var wrapFoot = '';
 
-         // 默认的filter,当forText模式时有效
 
-         var defaultFilter;
 
-         if ( forText ) {
 
-             toStringHead = 'ts(';
 
-             toStringFoot = ')';
 
-             wrapHead = RENDER_STRING_ADD_START;
 
-             wrapFoot = RENDER_STRING_ADD_END;
 
-             defaultFilter = options.defaultFilter
 
-         }
 
-         parseTextBlock(
 
-             source, options.variableOpen, options.variableClose, 1,
 
-             function ( text ) {
 
-                 // 加入默认filter
 
-                 // 只有当处理forText时,需要加入默认filter
 
-                 // 处理if/var/use等command时,不需要加入默认filter
 
-                 if ( forText && text.indexOf( '|' ) < 0 && defaultFilter ) {
 
-                     text += '|' + defaultFilter;
 
-                 }
 
-                 // variableCode是一个gv调用,然后通过循环,在外面包filter的调用
 
-                 // 形成filter["b"](filter["a"](gv(...)))
 
-                 // 
 
-                 // 当forText模式,处理的是文本中的变量替换时
 
-                 // 传递给filter的需要是字符串形式,所以gv外需要包一层ts调用
 
-                 // 形成filter["b"](filter["a"](ts(gv(...))))
 
-                 // 
 
-                 // 当variableName以*起始时,忽略ts调用,直接传递原值给filter
 
-                 var filterCharIndex = text.indexOf( '|' );
 
-                 var variableName = (filterCharIndex > 0
 
-                     ? text.slice( 0, filterCharIndex )
 
-                     : text).replace( /^\s+/, '' ).replace( /\s+$/, '' );
 
-                 var filterSource = filterCharIndex > 0
 
-                     ? text.slice( filterCharIndex + 1 )
 
-                     : '';
 
-                 var variableRawValue = variableName.indexOf( '*' ) === 0;
 
-                 var variableCode = [
 
-                     variableRawValue ? '' : toStringHead,
 
-                     toGetVariableLiteral( variableName ),
 
-                     variableRawValue ? '' : toStringFoot
 
-                 ];
 
-                 if ( filterSource ) {
 
-                     filterSource = compileVariable( filterSource, engine );
 
-                     var filterSegs = filterSource.split( '|' );
 
-                     for ( var i = 0, len = filterSegs.length; i < len; i++ ) {
 
-                         var seg = filterSegs[ i ];
 
-                         if ( /^\s*([a-z0-9_-]+)(\((.*)\))?\s*$/i.test( seg ) ) {
 
-                             variableCode.unshift( 'fs["' + RegExp.$1 + '"](' );
 
-                             if ( RegExp.$3 ) {
 
-                                 variableCode.push( 
 
-                                     ',', 
 
-                                     RegExp.$3
 
-                                 );
 
-                             }
 
-                             variableCode.push( ')' );
 
-                         }
 
-                     }
 
-                 }
 
-                 code.push(
 
-                     wrapHead,
 
-                     variableCode.join( '' ),
 
-                     wrapFoot
 
-                 );
 
-             },
 
-             function ( text ) { 
 
-                 code.push( 
 
-                     wrapHead, 
 
-                     forText ? stringLiteralize( text ) : text, 
 
-                     wrapFoot
 
-                 );
 
-             }
 
-         );
 
-         return code.join( '' );
 
-     }
 
-     /**
 
-      * 文本节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 文本节点的内容文本
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function TextNode( value, engine ) {
 
-         this.value = value;
 
-         this.engine = engine;
 
-     }
 
-     
 
-     TextNode.prototype = {
 
-         /**
 
-          * 获取renderer body的生成代码
 
-          * 
 
-          * @return {string}
 
-          */
 
-         getRendererBody: function () {
 
-             var value = this.value;
 
-             var options = this.engine.options;
 
-             if ( !value || ( options.strip && /^\s*$/.test( value ) ) ) {
 
-                 return '';
 
-             }
 
-             return compileVariable( value, this.engine, 1 );
 
-         },
 
-         /**
 
-          * 获取内容
 
-          * 
 
-          * @return {string}
 
-          */
 
-         getContent: function () {
 
-             return this.value;
 
-         }
 
-     };
 
-     /**
 
-      * 命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function Command( value, engine ) {
 
-         this.value = value;
 
-         this.engine = engine;
 
-         this.children = [];
 
-     }
 
-     Command.prototype = {
 
-         /**
 
-          * 添加子节点
 
-          * 
 
-          * @param {TextNode|Command} node 子节点
 
-          */
 
-         addChild: function ( node ) {
 
-             this.children.push( node );
 
-         },
 
-         /**
 
-          * 节点open,解析开始
 
-          * 
 
-          * @param {Object} context 语法分析环境对象
 
-          */
 
-         open: function ( context ) {
 
-             var parent = context.stack.top();
 
-             this.parent = parent;
 
-             parent && parent.addChild( this );
 
-             context.stack.push( this );
 
-         },
 
-         /**
 
-          * 节点闭合,解析结束
 
-          * 
 
-          * @param {Object} context 语法分析环境对象
 
-          */
 
-         close: function ( context ) {
 
-             while (context.stack.pop().constructor !== this.constructor) {}
 
-         },
 
-         /**
 
-          * 添加文本节点
 
-          * 
 
-          * @param {TextNode} node 节点
 
-          */
 
-         addTextNode: function ( node ) {
 
-             this.addChild( node );
 
-         },
 
-         /**
 
-          * 获取renderer body的生成代码
 
-          * 
 
-          * @return {string}
 
-          */
 
-         getRendererBody: function () {
 
-             var buf = [];
 
-             var children = this.children;
 
-             for ( var i = 0; i < children.length; i++ ) {
 
-                 buf.push( children[ i ].getRendererBody() );
 
-             }
 
-             return buf.join( '' );
 
-         }
 
-     };
 
-     /**
 
-      * 命令自动闭合
 
-      * 
 
-      * @inner
 
-      * @param {Object} context 语法分析环境对象
 
-      * @param {Function=} CommandType 自闭合的节点类型
 
-      */
 
-     function autoCloseCommand( context, CommandType ) {
 
-         var stack = context.stack;
 
-         var closeEnd = CommandType 
 
-             ? stack.find( function ( item ) {
 
-                 return item instanceof CommandType;
 
-             } ) 
 
-             : stack.bottom();
 
-         if ( closeEnd ) {
 
-             var node;
 
-             do {
 
-                 node = stack.top();
 
-                 // 如果节点对象不包含autoClose方法
 
-                 // 则认为该节点不支持自动闭合,需要抛出错误
 
-                 // for等节点不支持自动闭合
 
-                 if ( !node.autoClose ) {
 
-                     throw new Error( node.type + ' must be closed manually: ' + node.value );
 
-                 }
 
-                 node.autoClose( context );
 
-             } while ( node !== closeEnd );
 
-         }
 
-         return closeEnd;
 
-     }
 
-     /**
 
-      * renderer body起始代码段
 
-      * 
 
-      * @inner
 
-      * @const
 
-      * @type {string}
 
-      */
 
-     var RENDERER_BODY_START = ''
 
-         + 'data=data||{};'
 
-         + 'var v={},fs=engine.filters,hg=typeof data.get=="function",'
 
-         + 'gv=function(n,ps){'
 
-         +     'var p=ps[0],d=v[p];'
 
-         +     'if(d==null){'
 
-         +         'if(hg){return data.get(n);}'
 
-         +         'd=data[p];'
 
-         +     '}'
 
-         +     'for(var i=1,l=ps.length;i<l;i++)if(d!=null)d = d[ps[i]];'
 
-         +     'return d;'
 
-         + '},'
 
-         + 'ts=function(s){'
 
-         +     'if(typeof s==="string"){return s;}'
 
-         +     'if(s==null){s="";}'
 
-         +     'return ""+s;'
 
-         + '};'
 
-     ;
 
-     // v: variables
 
-     // fs: filters
 
-     // gv: getVariable
 
-     // ts: toString
 
-     // n: name
 
-     // ps: properties
 
-     // hg: hasGetter
 
-     /**
 
-      * Target命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function TargetCommand( value, engine ) {
 
-         if ( !/^\s*([a-z0-9_-]+)\s*(\(\s*master\s*=\s*([a-z0-9_-]+)\s*\))?\s*/i.test( value ) ) {
 
-             throw new Error( 'Invalid ' + this.type + ' syntax: ' + value );
 
-         }
 
-         
 
-         this.master = RegExp.$3;
 
-         this.name = RegExp.$1;
 
-         Command.call( this, value, engine );
 
-         this.contents = {};
 
-     }
 
-     // 创建Target命令节点继承关系
 
-     inherits( TargetCommand, Command );
 
-     /**
 
-      * Master命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function MasterCommand( value, engine ) {
 
-         if ( !/^\s*([a-z0-9_-]+)\s*(\(\s*master\s*=\s*([a-z0-9_-]+)\s*\))?\s*/i.test( value ) ) {
 
-             throw new Error( 'Invalid ' + this.type + ' syntax: ' + value );
 
-         }
 
-         
 
-         this.master = RegExp.$3;
 
-         this.name = RegExp.$1;
 
-         Command.call( this, value, engine );
 
-         this.contents = {};
 
-     }
 
-     // 创建Master命令节点继承关系
 
-     inherits( MasterCommand, Command );
 
-     /**
 
-      * Content命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function ContentCommand( value, engine ) {
 
-         if ( !/^\s*([a-z0-9_-]+)\s*$/i.test( value ) ) {
 
-             throw new Error( 'Invalid ' + this.type + ' syntax: ' + value );
 
-         }
 
-         this.name = RegExp.$1;
 
-         Command.call( this, value, engine );
 
-     }
 
-     // 创建Content命令节点继承关系
 
-     inherits( ContentCommand, Command );
 
-     /**
 
-      * ContentPlaceHolder命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function ContentPlaceHolderCommand( value, engine ) {
 
-         if ( !/^\s*([a-z0-9_-]+)\s*$/i.test( value ) ) {
 
-             throw new Error( 'Invalid ' + this.type + ' syntax: ' + value );
 
-         }
 
-         this.name = RegExp.$1;
 
-         Command.call( this, value, engine );
 
-     }
 
-     // 创建ContentPlaceHolder命令节点继承关系
 
-     inherits( ContentPlaceHolderCommand, Command );
 
-     
 
-     /**
 
-      * Import命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function ImportCommand( value, engine ) {
 
-         if ( !/^\s*([a-z0-9_-]+)\s*$/i.test( value ) ) {
 
-             throw new Error( 'Invalid ' + this.type + ' syntax: ' + value );
 
-         }
 
-         this.name = RegExp.$1;
 
-         Command.call( this, value, engine );
 
-     }
 
-     // 创建Import命令节点继承关系
 
-     inherits( ImportCommand, Command );
 
-     /**
 
-      * Var命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function VarCommand( value, engine ) {
 
-         if ( !/^\s*([a-z0-9_]+)\s*=([\s\S]*)$/i.test( value ) ) {
 
-             throw new Error( 'Invalid ' + this.type + ' syntax: ' + value );
 
-         }
 
-         this.name = RegExp.$1;
 
-         this.expr = RegExp.$2;
 
-         Command.call( this, value, engine );
 
-     }
 
-     // 创建Var命令节点继承关系
 
-     inherits( VarCommand, Command );
 
-     /**
 
-      * filter命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function FilterCommand( value, engine ) {
 
-         if ( !/^\s*([a-z0-9_-]+)\s*(\(([\s\S]*)\))?\s*$/i.test( value ) ) {
 
-             throw new Error( 'Invalid ' + this.type + ' syntax: ' + value );
 
-         }
 
-         this.name = RegExp.$1;
 
-         this.args = RegExp.$3;
 
-         Command.call( this, value, engine );
 
-     }
 
-     // 创建filter命令节点继承关系
 
-     inherits( FilterCommand, Command );
 
-     /**
 
-      * Use命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function UseCommand( value, engine ) {
 
-         if ( !/^\s*([a-z0-9_-]+)\s*(\(([\s\S]*)\))?\s*$/i.test( value ) ) {
 
-             throw new Error( 'Invalid ' + this.type + ' syntax: ' + value );
 
-         }
 
-         this.name = RegExp.$1;
 
-         this.args = RegExp.$3;
 
-         Command.call( this, value, engine );
 
-     }
 
-     // 创建Use命令节点继承关系
 
-     inherits( UseCommand, Command );
 
-     /**
 
-      * for命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function ForCommand( value, engine ) {
 
-         if ( !/^\s*(\$\{[\s\S]+\})\s+as\s+\$\{([0-9a-z_]+)\}\s*(,\s*\$\{([0-9a-z_]+)\})?\s*$/i.test( value ) ) {
 
-             throw new Error( 'Invalid ' + this.type + ' syntax: ' + value );
 
-         }
 
-         
 
-         this.list = RegExp.$1;
 
-         this.item = RegExp.$2;
 
-         this.index = RegExp.$4;
 
-         Command.call( this, value, engine );
 
-     }
 
-     // 创建for命令节点继承关系
 
-     inherits( ForCommand, Command );
 
-     
 
-     /**
 
-      * if命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function IfCommand( value, engine ) {
 
-         Command.call( this, value, engine );
 
-     }
 
-     // 创建if命令节点继承关系
 
-     inherits( IfCommand, Command );
 
-     /**
 
-      * elif命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function ElifCommand( value, engine ) {
 
-         IfCommand.call( this, value, engine );
 
-     }
 
-     // 创建elif命令节点继承关系
 
-     inherits( ElifCommand, IfCommand );
 
-     /**
 
-      * else命令节点类
 
-      * 
 
-      * @inner
 
-      * @constructor
 
-      * @param {string} value 命令节点的value
 
-      * @param {Engine} engine 引擎实例
 
-      */
 
-     function ElseCommand( value, engine ) {
 
-         Command.call( this, value, engine );
 
-     }
 
-     // 创建else命令节点继承关系
 
-     inherits( ElseCommand, Command ); 
 
-     
 
-     /**
 
-      * Target和Master的节点状态
 
-      * 
 
-      * @inner
 
-      */
 
-     var TMNodeState = {
 
-         READING: 1,
 
-         READED: 2,
 
-         APPLIED: 3,
 
-         READY: 4
 
-     };
 
-     /**
 
-      * 节点闭合,解析结束
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     MasterCommand.prototype.close =
 
-     /**
 
-      * 节点闭合,解析结束。自闭合时被调用
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     MasterCommand.prototype.autoClose = 
 
-     /**
 
-      * 节点闭合,解析结束
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     TargetCommand.prototype.close =
 
-     /**
 
-      * 节点闭合,解析结束。自闭合时被调用
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     TargetCommand.prototype.autoClose = function ( context ) {
 
-         Command.prototype.close.call( this, context );
 
-         this.state = this.master ? TMNodeState.READED : TMNodeState.APPLIED;
 
-         context.targetOrMaster = null;
 
-     };
 
-     /**
 
-      * 应用其继承的母版,返回是否成功应用母版
 
-      * 
 
-      * @return {boolean}
 
-      */
 
-     TargetCommand.prototype.applyMaster = 
 
-     /**
 
-      * 应用其继承的母版,返回是否成功应用母版
 
-      * 
 
-      * @return {boolean}
 
-      */
 
-     MasterCommand.prototype.applyMaster = function () {
 
-         if ( this.state >= TMNodeState.APPLIED ) {
 
-             return 1;
 
-         }
 
-         var masterNode = this.engine.masters[ this.master ];
 
-         if ( masterNode && masterNode.applyMaster() ) {
 
-             this.children = [];
 
-             for ( var i = 0, len = masterNode.children.length; i < len; i++ ) {
 
-                 var child = masterNode.children[ i ];
 
-                 if ( child instanceof ContentPlaceHolderCommand ) {
 
-                     this.children.push.apply( 
 
-                         this.children, 
 
-                         (this.contents[ child.name ] || child).children
 
-                     );
 
-                 }
 
-                 else {
 
-                     this.children.push( child );
 
-                 }
 
-             }
 
-             this.state = TMNodeState.APPLIED;
 
-             return 1;
 
-         }
 
-     };
 
-     /**
 
-      * 判断target是否ready
 
-      * 包括是否成功应用母版,以及import和use语句依赖的target是否ready
 
-      * 
 
-      * @return {boolean}
 
-      */
 
-     TargetCommand.prototype.isReady = function () {
 
-         if ( this.state >= TMNodeState.READY ) {
 
-             return 1;
 
-         }
 
-         var engine = this.engine;
 
-         var readyState = 1;
 
-         /**
 
-          * 递归检查节点的ready状态
 
-          * 
 
-          * @inner
 
-          * @param {Command|TextNode} node 目标节点
 
-          */
 
-         function checkReadyState( node ) {
 
-             for ( var i = 0, len = node.children.length; i < len; i++ ) {
 
-                 var child = node.children[ i ];
 
-                 if ( child instanceof ImportCommand ) {
 
-                     var target = engine.targets[ child.name ];
 
-                     readyState = readyState 
 
-                         && target && target.isReady( engine );
 
-                 }
 
-                 else if ( child instanceof Command ) {
 
-                     checkReadyState( child );
 
-                 }
 
-             }
 
-         }
 
-         if ( this.applyMaster() ) {
 
-             checkReadyState( this );
 
-             readyState && (this.state = TMNodeState.READY);
 
-             return readyState;
 
-         }
 
-     };
 
-     /**
 
-      * 获取target的renderer函数
 
-      * 
 
-      * @return {function(Object):string}
 
-      */
 
-     TargetCommand.prototype.getRenderer = function () {
 
-         if ( this.renderer ) {
 
-             return this.renderer;
 
-         }
 
-         if ( this.isReady() ) {
 
-             // console.log( this.name + ' ------------------' );
 
-             // console.log(RENDERER_BODY_START +RENDER_STRING_DECLATION
 
-             //     + this.getRendererBody() 
 
-             //     + RENDER_STRING_RETURN);
 
-             var realRenderer = new Function( 
 
-                 'data', 'engine',
 
-                 [
 
-                     RENDERER_BODY_START,
 
-                     RENDER_STRING_DECLATION,
 
-                     this.getRendererBody(),
 
-                     RENDER_STRING_RETURN
 
-                 ].join( '\n' )
 
-             );
 
-             var engine = this.engine;
 
-             this.renderer = function ( data ) {
 
-                 return realRenderer( data, engine );
 
-             };
 
-             return this.renderer;
 
-         }
 
-         return null;
 
-     };
 
-     /**
 
-      * 获取内容
 
-      * 
 
-      * @return {string}
 
-      */
 
-     TargetCommand.prototype.getContent = function () {
 
-         if ( this.isReady() ) {
 
-             var buf = [];
 
-             var children = this.children;
 
-             for ( var i = 0; i < children.length; i++ ) {
 
-                 buf.push( children[ i ].getContent() );
 
-             }
 
-             return buf.join( '' );
 
-         }
 
-         return '';
 
-     };
 
-     /**
 
-      * 将target或master节点对象添加到语法分析环境中
 
-      * 
 
-      * @inner
 
-      * @param {TargetCommand|MasterCommand} targetOrMaster target或master节点对象
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     function addTargetOrMasterToContext( targetOrMaster, context ) {
 
-         context.targetOrMaster = targetOrMaster;
 
-         var engine = context.engine;
 
-         var name = targetOrMaster.name;
 
-         var isTarget = targetOrMaster instanceof TargetCommand;
 
-         var prop = isTarget ? 'targets' : 'masters';
 
-         if ( engine[ prop ][ name ] ) {
 
-             switch ( engine.options.namingConflict ) {
 
-                 case 'override':
 
-                     engine[ prop ][ name ] = targetOrMaster;
 
-                     isTarget && context.targets.push( name );
 
-                 case 'ignore':
 
-                     break;
 
-                 default:
 
-                     throw new Error( ( isTarget ? 'Target' :'Master' ) 
 
-                         + ' is exists: ' + name );
 
-             }
 
-         }
 
-         else {
 
-             engine[ prop ][ name ] = targetOrMaster;
 
-             isTarget && context.targets.push( name );
 
-         }
 
-     }
 
-     /**
 
-      * target节点open,解析开始
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     TargetCommand.prototype.open = 
 
-     /**
 
-      * master节点open,解析开始
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     MasterCommand.prototype.open = function ( context ) {
 
-         autoCloseCommand( context );
 
-         Command.prototype.open.call( this, context );
 
-         this.state = TMNodeState.READING;
 
-         addTargetOrMasterToContext( this, context );
 
-     };
 
-     /**
 
-      * Import节点open,解析开始
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     ImportCommand.prototype.open = 
 
-     /**
 
-      * Var节点open,解析开始
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     VarCommand.prototype.open = 
 
-     /**
 
-      * Use节点open,解析开始
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     UseCommand.prototype.open = function ( context ) {
 
-         var parent = context.stack.top();
 
-         this.parent = parent;
 
-         parent.addChild( this );
 
-     };
 
-     /**
 
-      * 节点open前的处理动作:节点不在target中时,自动创建匿名target
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     UseCommand.prototype.beforeOpen = 
 
-     /**
 
-      * 节点open前的处理动作:节点不在target中时,自动创建匿名target
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     ImportCommand.prototype.beforeOpen = 
 
-     /**
 
-      * 节点open前的处理动作:节点不在target中时,自动创建匿名target
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     VarCommand.prototype.beforeOpen = 
 
-     /**
 
-      * 节点open前的处理动作:节点不在target中时,自动创建匿名target
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     ForCommand.prototype.beforeOpen = 
 
-     /**
 
-      * 节点open前的处理动作:节点不在target中时,自动创建匿名target
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     FilterCommand.prototype.beforeOpen = 
 
-     /**
 
-      * 节点open前的处理动作:节点不在target中时,自动创建匿名target
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     IfCommand.prototype.beforeOpen = 
 
-     /**
 
-      * 文本节点被添加到分析环境前的处理动作:节点不在target中时,自动创建匿名target
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     TextNode.prototype.beforeAdd =  function ( context ) {
 
-         if ( context.stack.bottom() ) {
 
-             return;
 
-         }
 
-         var target = new TargetCommand( generateGUID(), context.engine );
 
-         target.open( context );
 
-     };
 
-     
 
-     /**
 
-      * 节点解析结束
 
-      * 由于use节点无需闭合,处理时不会入栈,所以将close置为空函数
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     UseCommand.prototype.close = 
 
-     /**
 
-      * 节点解析结束
 
-      * 由于import节点无需闭合,处理时不会入栈,所以将close置为空函数
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */ 
 
-     ImportCommand.prototype.close = 
 
-     /**
 
-      * 节点解析结束
 
-      * 由于else节点无需闭合,处理时不会入栈,闭合由if负责。所以将close置为空函数
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     ElseCommand.prototype.close = 
 
-     /**
 
-      * 节点解析结束
 
-      * 由于var节点无需闭合,处理时不会入栈,所以将close置为空函数
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     VarCommand.prototype.close = function () {};
 
-     /**
 
-      * 获取内容
 
-      * 
 
-      * @return {string}
 
-      */
 
-     ImportCommand.prototype.getContent = function () {
 
-         var target = this.engine.targets[ this.name ];
 
-         return target.getContent();
 
-     };
 
-     
 
-     /**
 
-      * 获取renderer body的生成代码
 
-      * 
 
-      * @return {string}
 
-      */
 
-     ImportCommand.prototype.getRendererBody = function () {
 
-         var target = this.engine.targets[ this.name ];
 
-         return target.getRendererBody();
 
-     };
 
-     /**
 
-      * 获取renderer body的生成代码
 
-      * 
 
-      * @return {string}
 
-      */
 
-     UseCommand.prototype.getRendererBody = function () {
 
-         return stringFormat(
 
-             '{0}engine.render({2},{{3}}){1}',
 
-             RENDER_STRING_ADD_START,
 
-             RENDER_STRING_ADD_END,
 
-             stringLiteralize( this.name ),
 
-             compileVariable( this.args, this.engine ).replace( 
 
-                 /(^|,)\s*([a-z0-9_]+)\s*=/ig,
 
-                 function ( match, start, argName ) {
 
-                     return (start || '') + stringLiteralize( argName ) + ':';
 
-                 }
 
-             )
 
-         );
 
-     };
 
-     
 
-     /**
 
-      * 获取renderer body的生成代码
 
-      * 
 
-      * @return {string}
 
-      */
 
-     VarCommand.prototype.getRendererBody = function () {
 
-         if ( this.expr ) {
 
-             return stringFormat( 
 
-                 'v[{0}]={1};',
 
-                 stringLiteralize( this.name ),
 
-                 compileVariable( this.expr, this.engine )
 
-             );
 
-         }
 
-         return '';
 
-     };
 
-     /**
 
-      * 获取renderer body的生成代码
 
-      * 
 
-      * @return {string}
 
-      */
 
-     IfCommand.prototype.getRendererBody = function () {
 
-         var rendererBody = stringFormat(
 
-             'if({0}){{1}}',
 
-             compileVariable( this.value, this.engine ),
 
-             Command.prototype.getRendererBody.call( this )
 
-         );
 
-         var elseCommand = this[ 'else' ];
 
-         if ( elseCommand ) {
 
-             return [
 
-                 rendererBody,
 
-                 stringFormat( 
 
-                     'else{{0}}',
 
-                     elseCommand.getRendererBody()
 
-                 )
 
-             ].join( '' );
 
-         }
 
-         return rendererBody;
 
-     };
 
-     /**
 
-      * 获取renderer body的生成代码
 
-      * 
 
-      * @return {string}
 
-      */
 
-     ForCommand.prototype.getRendererBody = function () {
 
-         return stringFormat(
 
-             ''
 
-             + 'var {0}={1};'
 
-             + 'if({0} instanceof Array)'
 
-             +     'for (var {4}=0,{5}={0}.length;{4}<{5};{4}++){v[{2}]={4};v[{3}]={0}[{4}];{6}}'
 
-             + 'else if(typeof {0}==="object")'
 
-             +     'for(var {4} in {0}){v[{2}]={4};v[{3}]={0}[{4}];{6}}',
 
-             generateGUID(),
 
-             compileVariable( this.list, this.engine ),
 
-             stringLiteralize( this.index || generateGUID() ),
 
-             stringLiteralize( this.item ),
 
-             generateGUID(),
 
-             generateGUID(),
 
-             Command.prototype.getRendererBody.call( this )
 
-         );
 
-     };
 
-     /**
 
-      * 获取renderer body的生成代码
 
-      * 
 
-      * @return {string}
 
-      */
 
-     FilterCommand.prototype.getRendererBody = function () {
 
-         var args = this.args;
 
-         return stringFormat(
 
-             '{2}fs[{5}]((function(){{0}{4}{1}})(){6}){3}',
 
-             RENDER_STRING_DECLATION,
 
-             RENDER_STRING_RETURN,
 
-             RENDER_STRING_ADD_START,
 
-             RENDER_STRING_ADD_END,
 
-             Command.prototype.getRendererBody.call( this ),
 
-             stringLiteralize( this.name ),
 
-             args ? ',' + compileVariable( args, this.engine ) : ''
 
-         );
 
-     };
 
-     /**
 
-      * content节点open,解析开始
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     ContentCommand.prototype.open = function ( context ) {
 
-         autoCloseCommand( context, ContentCommand );
 
-         Command.prototype.open.call( this, context );
 
-         context.targetOrMaster.contents[ this.name ] = this;
 
-     };
 
-     
 
-     /**
 
-      * content节点open,解析开始
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     ContentPlaceHolderCommand.prototype.open = function ( context ) {
 
-         autoCloseCommand( context, ContentPlaceHolderCommand );
 
-         Command.prototype.open.call( this, context );
 
-     };
 
-     /**
 
-      * 节点自动闭合,解析结束
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     ContentCommand.prototype.autoClose = 
 
-     /**
 
-      * 节点自动闭合,解析结束
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     IfCommand.prototype.autoClose = Command.prototype.close;
 
-     /**
 
-      * 节点自动闭合,解析结束
 
-      * contentplaceholder的自动结束逻辑为,在其开始位置后马上结束
 
-      * 所以,其自动结束时children应赋予其所属的parent,也就是master
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     ContentPlaceHolderCommand.prototype.autoClose = function ( context ) {
 
-         var parentChildren = this.parent.children;
 
-         parentChildren.push.apply( parentChildren, this.children );
 
-         this.children.length = 0;
 
-         this.close( context );
 
-     };
 
-     
 
-     /**
 
-      * 添加子节点
 
-      * 
 
-      * @param {TextNode|Command} node 子节点
 
-      */
 
-     IfCommand.prototype.addChild = function ( node ) {
 
-         var elseCommand = this[ 'else' ];
 
-         ( elseCommand 
 
-             ? elseCommand.children 
 
-             : this.children
 
-         ).push( node );
 
-     };
 
-     /**
 
-      * elif节点open,解析开始
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     ElifCommand.prototype.open = function ( context ) {
 
-         var elseCommand = new ElseCommand();
 
-         elseCommand.open( context );
 
-         var ifCommand = autoCloseCommand( context, IfCommand );
 
-         ifCommand.addChild( this );
 
-         context.stack.push( this );
 
-     };
 
-     /**
 
-      * else节点open,解析开始
 
-      * 
 
-      * @param {Object} context 语法分析环境对象
 
-      */
 
-     ElseCommand.prototype.open = function ( context ) {
 
-         var ifCommand = autoCloseCommand( context, IfCommand );
 
-         
 
-         ifCommand[ 'else' ] = this;
 
-         context.stack.push( ifCommand );
 
-     };
 
-     
 
-     /**
 
-      * 命令类型集合
 
-      * 
 
-      * @type {Object}
 
-      */
 
-     var commandTypes = {};
 
-     /**
 
-      * 添加命令类型
 
-      * 
 
-      * @inner
 
-      * @param {string} name 命令名称
 
-      * @param {Function} Type 处理命令用到的类
 
-      */
 
-     function addCommandType( name, Type ) {
 
-         commandTypes[ name ] = Type;
 
-         Type.prototype.type = name;
 
-     }
 
-     addCommandType( 'target', TargetCommand );
 
-     addCommandType( 'master', MasterCommand );
 
-     addCommandType( 'content', ContentCommand );
 
-     addCommandType( 'contentplaceholder', ContentPlaceHolderCommand );
 
-     addCommandType( 'import', ImportCommand );
 
-     addCommandType( 'use', UseCommand );
 
-     addCommandType( 'var', VarCommand );
 
-     addCommandType( 'for', ForCommand );
 
-     addCommandType( 'if', IfCommand );
 
-     addCommandType( 'elif', ElifCommand );
 
-     addCommandType( 'else', ElseCommand );
 
-     addCommandType( 'filter', FilterCommand );
 
-     
 
-     
 
-     /**
 
-      * etpl引擎类
 
-      * 
 
-      * @constructor
 
-      * @param {Object=} options 引擎参数
 
-      * @param {string=} options.commandOpen 命令语法起始串
 
-      * @param {string=} options.commandClose 命令语法结束串
 
-      * @param {string=} options.defaultFilter 默认变量替换的filter
 
-      * @param {boolean=} options.strip 是否清除命令标签前后的空白字符
 
-      * @param {string=} options.namingConflict target或master名字冲突时的处理策略
 
-      */
 
-     function Engine( options ) {
 
-         this.options = {
 
-             commandOpen: '<!--',
 
-             commandClose: '-->',
 
-             variableOpen: '${',
 
-             variableClose: '}',
 
-             defaultFilter: 'html'
 
-         };
 
-         this.config( options );
 
-         this.masters = {};
 
-         this.targets = {};
 
-         this.filters = extend({}, DEFAULT_FILTERS);
 
-     }
 
-     /**
 
-      * 配置引擎参数,设置的参数将被合并到现有参数中
 
-      * 
 
-      * @param {Object} options 参数对象
 
-      * @param {string=} options.commandOpen 命令语法起始串
 
-      * @param {string=} options.commandClose 命令语法结束串
 
-      * @param {string=} options.defaultFilter 默认变量替换的filter
 
-      * @param {boolean=} options.strip 是否清除命令标签前后的空白字符
 
-      * @param {string=} options.namingConflict target或master名字冲突时的处理策略
 
-      */
 
-     Engine.prototype.config =  function ( options ) {
 
-         extend( this.options, options );
 
-     };
 
-     /**
 
-      * 解析模板并编译,返回第一个target编译后的renderer函数。
 
-      * 
 
-      * @param {string} source 模板源代码
 
-      * @return {function(Object):string}
 
-      */
 
-     Engine.prototype.compile = 
 
-     /**
 
-      * 解析模板并编译,返回第一个target编译后的renderer函数。
 
-      * 该方法的存在为了兼容老模板引擎
 
-      * 
 
-      * @param {string} source 模板源代码
 
-      * @return {function(Object):string}
 
-      */
 
-     Engine.prototype.parse = function ( source ) {
 
-         if ( source ) {
 
-             var targetNames = parseSource( source, this );
 
-             if ( targetNames.length ) {
 
-                 return this.targets[ targetNames[ 0 ] ].getRenderer();
 
-             }
 
-         }
 
-         return new Function('return ""');
 
-     };
 
-     
 
-     /**
 
-      * 根据target名称获取编译后的renderer函数
 
-      * 
 
-      * @param {string} name target名称
 
-      * @return {function(Object):string}
 
-      */
 
-     Engine.prototype.getRenderer = function ( name ) {
 
-         var target = this.targets[ name ];
 
-         if ( target ) {
 
-             return target.getRenderer();
 
-         }
 
-     };
 
-     /**
 
-      * 根据target名称获取模板内容
 
-      * 
 
-      * @param {string} name target名称
 
-      * @return {string}
 
-      */
 
-     Engine.prototype.get = function ( name ) {
 
-         var target = this.targets[ name ];
 
-         if ( target ) {
 
-             return target.getContent();
 
-         }
 
-         return '';
 
-     };
 
-     /**
 
-      * 执行模板渲染,返回渲染后的字符串。
 
-      * 
 
-      * @param {string} name target名称
 
-      * @param {Object=} data 模板数据。
 
-      *      可以是plain object,
 
-      *      也可以是带有 {string}get({string}name) 方法的对象
 
-      * @return {string}
 
-      */
 
-     Engine.prototype.render = function ( name, data ) {
 
-         var renderer = this.getRenderer( name );
 
-         if ( renderer ) {
 
-             return renderer( data );
 
-         }
 
-         return '';
 
-     };
 
-     /**
 
-      * 增加过滤器
 
-      * 
 
-      * @param {string} name 过滤器名称
 
-      * @param {Function} filter 过滤函数
 
-      */
 
-     Engine.prototype.addFilter = function ( name, filter ) {
 
-         if ( typeof filter == 'function' ) {
 
-             this.filters[ name ] = filter;
 
-         }
 
-     };
 
-     /**
 
-      * 解析源代码
 
-      * 
 
-      * @inner
 
-      * @param {string} source 模板源代码
 
-      * @param {Engine} engine 引擎实例
 
-      * @return {Array} target名称列表
 
-      */
 
-     function parseSource( source, engine ) {
 
-         var commandOpen = engine.options.commandOpen;
 
-         var commandClose = engine.options.commandClose;
 
-         var stack = new Stack();
 
-         var analyseContext = {
 
-             engine: engine,
 
-             targets: [],
 
-             stack: stack
 
-         };
 
-         // text节点内容缓冲区,用于合并多text
 
-         var textBuf = [];
 
-         /**
 
-          * 将缓冲区中的text节点内容写入
 
-          *
 
-          * @inner
 
-          */
 
-         function flushTextBuf() {
 
-             if ( textBuf.length > 0 ) {
 
-                 var text = textBuf.join( '' );
 
-                 var textNode = new TextNode( text, engine );
 
-                 textNode.beforeAdd( analyseContext );
 
-                 stack.top().addTextNode( textNode );
 
-                 textBuf = [];
 
-                 if ( engine.options.strip 
 
-                     && analyseContext.current instanceof Command 
 
-                 ) {
 
-                     textNode.value = text.replace( /^[\x20\t\r]*\n/, '' );
 
-                 }
 
-                 analyseContext.current = textNode;
 
-             }
 
-         }
 
-         var NodeType;
 
-         /**
 
-          * 判断节点是否是NodeType类型的实例
 
-          * 用于在stack中find提供filter
 
-          * 
 
-          * @inner
 
-          * @param {Command} node 目标节点
 
-          * @return {boolean}
 
-          */
 
-         function isInstanceofNodeType( node ) {
 
-             return node instanceof NodeType;
 
-         }
 
-         parseTextBlock(
 
-             source, commandOpen, commandClose, 0,
 
-             function ( text ) { // <!--...-->内文本的处理函数
 
-                 var match = /^\s*(\/)?([a-z]+)\s*(:([\s\S]*))?$/.exec( text );
 
-                 // 符合command规则,并且存在相应的Command类,说明是合法有含义的Command
 
-                 // 否则,为不具有command含义的普通文本
 
-                 if ( match 
 
-                     && ( NodeType = commandTypes[ match[2].toLowerCase() ] )
 
-                     && typeof NodeType == 'function'
 
-                 ) {
 
-                     // 先将缓冲区中的text节点内容写入
 
-                     flushTextBuf(); 
 
-                     var currentNode = analyseContext.current;
 
-                     if ( engine.options.strip && currentNode instanceof TextNode ) {
 
-                         currentNode.value = currentNode.value
 
-                             .replace( /\r?\n[\x20\t]*$/, '\n' );
 
-                     }
 
-                     if ( match[1] ) {
 
-                         currentNode = stack.find( isInstanceofNodeType );
 
-                         currentNode && currentNode.close( analyseContext );
 
-                     }
 
-                     else {
 
-                         currentNode = new NodeType( match[4], engine );
 
-                         if ( typeof currentNode.beforeOpen == 'function' ) {
 
-                             currentNode.beforeOpen( analyseContext );
 
-                         }
 
-                         currentNode.open( analyseContext );
 
-                     }
 
-                     analyseContext.current = currentNode;
 
-                 }
 
-                 else if ( !/^\s*\/\//.test( text ) ) {
 
-                     // 如果不是模板注释,则作为普通文本,写入缓冲区
 
-                     textBuf.push( commandOpen, text, commandClose );
 
-                 }
 
-                 NodeType = null;
 
-             },
 
-             function ( text ) { // <!--...-->外,普通文本的处理函数
 
-                 // 普通文本直接写入缓冲区
 
-                 textBuf.push( text );
 
-             }
 
-         );
 
-         flushTextBuf(); // 将缓冲区中的text节点内容写入
 
-         autoCloseCommand( analyseContext );
 
-         return analyseContext.targets;
 
-     }
 
-     var etpl = new Engine();
 
-     etpl.Engine = Engine;
 
-     
 
-     if ( typeof exports == 'object' && typeof module == 'object' ) {
 
-         // For CommonJS
 
-         exports = module.exports = etpl;
 
-     }
 
-     else if ( typeof define == 'function' && define.amd ) {
 
-         // For AMD
 
-         define( etpl );
 
-     }
 
-     else {
 
-         // For <script src="..."
 
-         root.etpl = etpl;
 
-     }
 
- })(this);
 
 
  |