lite
Version:
A cross platform template engine base on xml/html and javascript expression.
253 lines (247 loc) • 7.17 kB
JavaScript
/*
* List Template
* License LGPL(您可以在任何地方免费使用,但请不要吝啬您对框架本身的改进)
* http://www.xidea.org/project/lite/
* @author jindw
* @version $Id: template.js,v 1.4 2008/02/28 14:39:06 jindw Exp $
*/
/**
* 模板解析上下文对象实现
* <lite>
* <extension namespace="http://www.w3.org/1999/xhtml"
* package="org.xidea.lite.xhtml"/>
* <include>**.xhtml</include>
* <group layout="/layout.xhtml">
* <config name="javascriptCompressor"
* package="org.jside.jsi.tools.JSACompressor"/>
* <include>/example/*.xhtml</include>
* </group>
* </lite>
* ==>
* [
* {
* "includes":"^[\\\\/]example[\\\\/][^\\\\/]*\.xhtml$",
* "excludes":"",
* "config":{
* "layout":"/layout.xhtml",
* "encoding":"utf-8",
* "contentType":"text/html;charset=UTF-8",
* "javascriptCompressor":"org.jside.jsi.tools.JSACompressor"
* },
* "extensionMap":[
* {
* "namespace":"http://www.w3.org/1999/xhtml",
* "package":"org.xidea.lite.xhtml"
* }
* ]
* },
* {
* "includes":"^.*\.xhtml$",
* "excludes":"",
* "config":{
* "encoding":"utf-8",
* "contentType":"text/html;charset=UTF-8"
* },
* "extensionMap":{
* "http://www.w3.org/1999/xhtml":["org.xidea.lite.xhtml"]
* ]
* }
* ]
*/
function parseConfig(doc){
if(typeof doc == 'string'){doc = loadLiteXML(doc)}
var lites = doc.getElementsByTagName("lite");
var len = lites.length;
//console.log(new (require('xmldom').XMLSerializer)().serializeToString(doc))
if(len >= 1){
var root = new LiteGroup(lites.item(0))
if(len>1){
console.error("配置文件只允许一个lite节点","您的文档中包含"+len+"个节点,后续节点将作为第一个节点子节点解析。");
for(var i=1;i<len;i++){
root.children.push(new LiteGroup(lites[i],this));
}
}
var json = root.toJSON();
return json;
}
return null
}
function LiteGroup(node,parentConfig){
this.parentConfig = parentConfig || null
this.config = {}
this.encoding= findXMLAttribute(node,'encoding','charset');
this.type = findXMLAttribute(node,'type',"mime-type",'mimeType');
this.contentType = findXMLAttribute(node,'contentType','contextType');
this.layout = findXMLAttribute(node,'layout');
this.extensionMap = {};
this.children = [];
this.includes = [];
this.excludes = [];
var child = node.firstChild;
while(child){
if(child.nodeType == 1){
switch(child.nodeName){
case 'feature':
case 'attribute':
case 'config':
this.config[findXMLAttribute(child,'name','key','uri','url')] =
findXMLAttribute(child,'value','#text')
break;
case 'extension':
var ns = findXMLAttribute(child,'namespace','name','key','uri','url');
var p = findXMLAttribute(child,'package','impl','value','#text');
var ps = this.extensionMap[ns];
if(ps && ps instanceof Array){
appendAfter(ps,p);
}else{
this.extensionMap[ns] = [p];
}
break;
case 'include':
this.includes.push(findXMLAttribute(child,'value','#text','pattern'));
break;
case 'exclude':
this.excludes.push(findXMLAttribute(child,'value','#text','pattern'));
break;
case 'group':
this.children.push(new LiteGroup(child,this))
break;
default:
console.warn("unknow nodeName:"+child.nodeName);
}
}
child = child.nextSibling;
}
}
LiteGroup.prototype.toJSON = function(){
var result = [];
var len = this.children.length;
var json = {}
this.initialize();
for(var i=0;i<len;i++){
result.push.apply(result,this.children[i].toJSON());
}
json.includes = this.includes;
json.excludes = this.excludes;
json.config = this.config;
json.extensionMap = this.extensionMap;
result.push(json);
return result;
}
LiteGroup.prototype.initialize = function(){
this.initialize = Function.prototype;
var parentConfig = this.parentConfig
if(parentConfig){
var config = {};
copy(parentConfig.config,config);
copy(this.config,config);
this.config=config;
this.extensionMap = margeExtensionMap(parentConfig.extensionMap,this.extensionMap);
}
this.includes = compilePatterns(this.includes)
this.excludes = compilePatterns(this.excludes)
mergeContentType(this,parentConfig);
this.config["encoding"] = this.encoding;
this.config["contentType"] = this.contentType;
if(this.layout != null){
if(!this.layout || this.layout.charAt() == '/'){
this.config["layout"] = this.layout;
}else{
console.error("layout 必须为绝对地址('/'开始),你的设置为:"+this.layout);
}
}
}
function mergeContentType(thiz,parentConfig){
var type=thiz.type;
var encoding = thiz.encoding;
var contentType = thiz.contentType;//不从parent继承
/*========= init 3 vars==========*/
if(contentType!=null){
console.info("contentType 用于同时指定 type 和charset 属性,如此需求更推荐您采用type和encoding代替")
var p = contentType.indexOf('charset=');
if(p>0){
var charset = contentType.substring(p+8);
if(encoding){
if(charset.toUpperCase() != encoding.toUpperCase()){
console.info('encoding 与 contentType 不一致'+encoding+','+contentType
+"; ");
}
}else{
encoding = charset;
}
}
var contentType0 = contentType.replace(/\s*;.*$/,'');
if(type){
if(type.toUpperCase() != contentType0.toUpperCase()){
console.error('type 与 contentType 不一致'+type+','+contentType0
+';type 设置将被忽略');
}
}
type = contentType0
}
/*========== init from parent ==============*/
if(encoding == null){
encoding = parentConfig && parentConfig.encoding || 'UTF-8';
}
if(type == null){
type = parentConfig && parentConfig.type;
}
if(contentType == null){//不继承
if(type){
contentType = type+";charset="+encoding;
}
}else{
var p = contentType.indexOf('charset=');
if(p<0){
contentType +=";charset="+encoding;
}
}
thiz.type = type;
thiz.encoding = encoding;
thiz.contentType = contentType;
}
function copy(source,dest){
for(var n in source){
dest[n] = source[n];
}
}
function margeExtensionMap(parentExtMap,thisExtMap){
var result = {};
for(var n in thisExtMap){
result[n] = [].concat(thisExtMap[n]);
}
for(var n in parentExtMap){
var list = [].concat(parentExtMap[n]);
var thisExt = result[n] ;
if(thisExt){
var i = thisExt.length;
while(i--){
appendAfter(list,thisExt[i]);
}
}
result[n] = list;
}
return result;
}
function appendAfter(ps,p){
var i = ps.length;
while(i--){
if(ps[i] == p){
ps.splice(i,1)
}
}
ps.push(p);
}
function compilePatterns(ps){
var i = ps.length;
while(i--){
ps[i] = buildURIMatcher(ps[i]);
}
return ps.join('|')||null;
}
if(typeof require == 'function'){
exports.parseConfig=parseConfig;
var buildURIMatcher = require('./resource').buildURIMatcher
var loadLiteXML = require('./xml').loadLiteXML;
var findXMLAttribute=require('./xml').findXMLAttribute;
}