重新进行了设计,抛弃了所有重新定义javascript固有语法的方法,这样也就是无招胜有招 了,
而且可方便自定义标记 ,没有精力写注解和用法了.直接贴源代码(初稿)吧:(请在FF下测试,还没有调整IE的兼容性)
细心的朋友应该可以看出来,不同标记之间是可以转换的.
/**
* javascript Common Templates(jCT) 3(第3版)
* http://code.google.com/p/jsct/
*
* licensed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*
* Author achun (achun.shx at gmail.com)
* Create Date: 2008-6-23
* Last Date: 2008-6-26
* Revision:3.8.6.26
* 预定义变量:
D............用于生成函数的输入参数,表示提供给模板的数据.可以通过设置Main改变此名称
* 保留属性:有些属性的保留纯粹是为了方便调试
CTA..........SRC的模板数组形式表示
CTD..........用于保留执行(Exec)模板时候传入的参数
CTV..........在执行(Exec)模板过程当中生成结果的数组形式
Fn...........继承自jCT的几个属性和方法
MAIN.........Build模板的时候生成的主体过程数组形式
PATH.........保留模板的URL路径,由调用模板的函数提供,保留这个的目的是考虑到这个参数可能会有很多的用途。
SRC..........模板原文本,由调用模板的函数提供
TAG..........模板标签风格,来自Fn的引用
ERROR........Build异常时的错误信息.
* 保留方法:
Build........构建模板的Exec方法,参数对应属性的TAG
Clean........清理模板,参数对应属性的TAG
Exec.........执行模板
* 保留字串:
... 再使用Main时用于替换主体过程的占位符
* 调用:
var jct = jCT(txt,path,tag);
txt..........对应属性SRC
path.........对应属性PATH
tag..........对应属性TAG
*/
function jCT3(txt,path,by){
var self=function(){
return arguments.callee.Exec.apply(arguments.callee,arguments);
};
by=by||'comment';//默认的标记风格,到底是用script还是comment呢?
self.Fn={};
for (var prop in jCT3.Fn)
self.Fn[prop] = jCT3.Fn[prop];
self.SRC=txt;
self.PATH=path;
self.TAG=self.Fn[by];
self.CTA=[];
self.CTV=[];
self.CTD={};
self.Clean=function(){
this.Fn.src=this.SRC;
this.Fn.path=this.PATH;
this.Fn.clean(this.TAG.clean);
return this.Fn.src;
};
self.Build=function(){
this.Clean();
var fn=this.Fn;
this.MAIN=[];
fn.path=this.PATH;
var ext=fn.parse(this,this.MAIN);
var jctbody=this.MAIN.join('\n');
if (ext.run) window.eval(ext.run);
if (ext.main) {
var func=ext.main.replace('{...}','\n{this.CTV=[];'+jctbody+'\n}\n');
}else{
var func='function(D){if(!D) D={};this.CTD=D;with(D){this.CTV=[];'+jctbody+'}\nreturn this.CTV.join("");}';
}
try{
this.Exec = eval('false||'+func);
}catch (ex){
this.Exec = function(){return 'jCT Parse Error';};
this.ERROR={message:ex.message + '\n'+ (ex.lineNumber || ex.number),src:func};
}
return this;
};
self.Build();
return self;
}
jCT3.Fn={
clean:function(tn){
var a=[];
var p=[0,0,0,0,0];
var e=this.src.length;
while (this.slice(tn,p[4],p,e))
a.push(this.src.slice(p[0],p[1]));
a.push(this.src.slice(p[4]));
this.src = a.join('');
},
parse:function(self,jctbody){
var tag = self.TAG;
var cta = self.CTA;
var p=[0,0,0,0,0];
var e=this.src.length;
var main='';
var run='';
while (this.slice(tag.tag,p[4],p,e)){//语法分2段
var p1=[0,0,0,0,p[0]];
while (this.slice(tag.exp,p1[4],p1,p[1])){//第1段取值表达式
jctbody.push('this.CTV.push(this.CTA['+cta.length+']);');
cta.push(this.src.slice(p1[0],p1[1]));
jctbody.push('this.CTV.push('+this.src.slice(p1[2],p1[3])+');');
}
jctbody.push('this.CTV.push(this.CTA['+cta.length+']);');
cta.push(this.src.slice(p1[4],p[1]));
//处理第2段
if (this.slice(tag.ext,p[2],p1,p[3])){///*+*/处理
jctbody.push('this.CTV.push('+this.src.slice(p1[0],p1[1])+');');
var str=this.src.slice(p1[2],p1[3]);
var tmp=str.indexOf(' ');
var par='',sta='';
if (tmp>0){
par=str.slice(tmp+1);
sta=sta.slice(0,tmp);
}else
sta=str;
var foo=this.src.slice(p1[4],p[3]);
switch(sta){
case 'Main':main=foo;break;
case 'Run':run+=foo+"\n";break;
case 'Child':
var p2=[];
var child=tag.tag.begin+'/*-'+str+'*/'+tag.tag.end;
tmp = this.src.indexOf(child,p[4]);
if (tmp>0){
self[par]=jCT3(txt.slice(p[4],tmp),this.path);
p[4] = tmp + child.length;
}
break;
}
}else{
jctbody.push(this.src.slice(p[2],p[3]));
}
}
var p1=[0,0,0,0,p[4]];
while (this.slice(tag.exp,p[4],p1,e)){//第1段取值表达式
jctbody.push('this.CTV.push(this.CTA['+cta.length+']);');
cta.push(this.src.slice(p1[0],p1[1]));
jctbody.push('this.CTV.push('+this.src.slice(p1[2],p1[3])+');');
}
jctbody.push('this.CTV.push(this.CTA['+cta.length+']);');
cta.push(this.src.slice(p1[4]));
return {main:main,run:run};
},
slice:function(tn,b1,p,max){//把string第2段分成2段
var begin=tn.begin;
var end=tn.end;
var e1,b2,e2;
e1=this.src.indexOf(begin,b1);
if (e1<0 || e1>=max) return false;
b2=e1+begin.length;
if (b2<0 || b2>=max) return false;
e2=this.src.indexOf(end,b2);
if (e2<0 || e2>=max) return false;
p[0]=b1;p[1]=e1;
p[2]=b2;p[3]=e2;
p[4]=e2+end.length;
return true;
},
//下面就是几个自定义标记的配置了
comment:{//注释标记风格
tag:{begin:'<!---',end:'-->'},
exp:{begin:'+-',end:'-+'},
ext:{begin:'/*+',end:'*/'},
clean:{begin:'<!--clean-->',end:'<!--clean -->'}
},
script:{//脚本标记风格
tag:{begin:'<script type="jct">',end:'</script>'},
exp:{begin:'+-',end:'-+'},
ext:{begin:'/*+',end:'*/'},
clean:{begin:'<script type="jct" />',end:'<script type="jct" />'}
},
code:{//code标记风格
tag:{begin:'<code lang="jct">',end:'</code>'},
exp:{begin:'+-',end:'-+'},
ext:{begin:'/*+',end:'*/'},
clean:{begin:'<code lang="jct" />',end:'<code lang="jct" />'}
}
};
本文介绍了一款名为jCT3的JavaScript模板引擎的设计与实现。该引擎通过自定义标记风格来简化模板语法,支持多种标记类型如注释、脚本和code标记,并提供了构建、清理及执行模板的方法。
6840

被折叠的 条评论
为什么被折叠?



