UNPKG

lite

Version:

A cross platform template engine base on xml/html and javascript expression.

1,550 lines (1,426 loc) 478 kB
if(typeof console == 'undefined'){console = {};'log,warn,error,info,debug'.replace(/\w+/g,function(a){console[a] = print});console.dir = function(o){for(var n in o){console.log(n,o[n]);}}; console.time = console.time || function(l){this['#'+l] = +new Date}; console.timeEnd = console.timeEnd || function(l){console.log(l + (new Date-this['#'+l]));}; console.assert = console.assert || function(l){if(!l){console.error('Assert Failed!!!')}}; } function require(id){ id = id.replace(/(\/.*?)(?:\.js)?$/,'$1.js') if(id in require.module){ return require.module[id].exports; } var module = require.module[id] = {exports:{},id:id}; var dir = id.replace(/[^\/\\]+$/,''); //console.log(id) require.cached[id].call(null,function(id2){ if(id2.charAt() == '.'){ id2 = dir+id2; while(id2 != (id2 =id2.replace( /[^\/]+\/\.\.\/|(\/)?\.\//,'$1'))); } return require(id2); },module.exports,module,id,dir); return module.exports; } require.cached={} require.module={} if(typeof module == "object"){module.exports = require}; require.cached["fs"]=function (require,exports,m){ var isJavaEnv = typeof window == 'undefined' && typeof java == 'object' && typeof (java.io && java.io.File) == 'function'; if(isJavaEnv) { exports.readFileSync = function(path){ var ins = new java.io.FileInputStream(path); //Buffer return { toString:function(encoding){ var s = new java.io.InputStreamReader(ins,encoding||'utf-8') var buf = [],c; while((c = s.read())>=0){ //console.log(c) buf.push(c) } //console.log(String.fromCharCode.apply(String,buf)) return String.fromCharCode.apply(String,buf) } } }; exports.existsSync =function(path){ return new java.io.File(path).exists(); }; exports.realpathSync = function(path){ return new java.io.File(path).getAbsolutePath() } }else{ m.exports = module.require('fs'); } }; require.cached["path"]=function (require,exports,m,__filename,__dirname){ var isJavaEnv = typeof window == 'undefined' && typeof java == 'object' && typeof (java.io && java.io.File) == 'function'; if(isJavaEnv) { exports.resolve = function () { var i = 0; var file = new java.io.File(arguments[i++]); while (i < arguments.length) { file = new java.io.File(file, arguments[i++]); } return file.getAbsoluteFile().getCanonicalPath(); } }else{ m.exports = module.require('path'); } }; require.cached["lite/src/main/js/compiler.js"]=function (require,exports,module,__filename,__dirname){var ParseConfig = require('./parse/config').ParseConfig; var ParseContext = require('./parse/parse-context').ParseContext; var JSTranslator = require('./parse/js-translator').JSTranslator; var loadLiteXML = require('./parse/xml').loadLiteXML; var buildURIMatcher = require('./parse/resource').buildURIMatcher exports.getTemplateId = getTemplateId exports.LiteCompiler = LiteCompiler; function getTemplateId(path){ ////path.replace(/[^\w\_]/g,'_') return path.slice(1).replace(/[^\w\_]/g,'_'); } exports.execute = function(args){ var options = {}; var key = ''; for(var i=2;i<args.length;i++){ var arg = args[i]; if(arg.charAt() == '-'){ key = arg.substr(1) options[key] = []; }else{ options[key].push(arg) } } //console.log(options) var root = options.root && options.root[0]; var output = options.output && options.output[0]; compile(root,output,options.translator, options.includes,options.excludes) } function LiteCompiler(root,options){ options = options || {}; var path = require('path'); var root =String(path.resolve(root || './')).replace(/\\/g,'/'); var compileDir = options.compileDir; var configPath = options.configPath || path.resolve(root,'lite.xml'); if(require('fs').existsSync(configPath)){ var dom = loadLiteXML(configPath); //console.log(dom+'') this.config = new ParseConfig(root,dom); }else if(!options.configPath){ configPath = path.resolve(root,'WEB-INF/lite.xml'); if(require('fs').existsSync(configPath)){ var dom = loadLiteXML(configPath); //console.log(dom+'') this.config = new ParseConfig(root,dom); } } this.config = this.config || new ParseConfig(root,null); var waitPromise = 'waitPromise' in options?options.waitPromise:true; this.translator = new JSTranslator({ //liteImpl:liteImpl, waitPromise:waitPromise }); console.info("LiteCompiler root:",root); } LiteCompiler.prototype.createParseContext = function(path){ return new ParseContext(this.config,path); } LiteCompiler.prototype.compile=function(path){ var root = this.config.root; var context = this.createParseContext(path); var uri = context.createURI(path); context.parse(uri); //console.log("&&&",path) //console.log(context.getConfigMap(path)) var litecode = context.toList(); if(litecode.length){ //translator.liteImpl = 'liteImpl';//avoid inline jslib var functionName = getTemplateId(path); var jscode = this.translator && this.translator.translate(litecode,{name:functionName});//,params:null,defaults:null }else{//纯静态内容 var jscode = "function(){}"; } var res = context.getResources(); var config = context.getConfigMap(); var i = res.length; while(i--){ res[i] = res[i].path } return {resources:res,litecode:litecode,code:jscode,config:config,path:path}; }; //exports.compile = compile; function compile(root,output,translator,includes,excludes){ var fs = require('fs'); var path = require('path'); root = fs.realpathSync(root || './'); output = output || path.join(root,'.litecode'); if(!fs.existsSync(output))fs.mkdirSync(output); //console.log('compile lite @'+root,{}) var compiler = new LiteCompiler(root); includes = includes && includes.length && new RegExp(includes.map(buildURIMatcher).join('|')); excludes = excludes && excludes.length && new RegExp(excludes.map(buildURIMatcher).join('|')); function loadFile(dir){ var files = fs.readdirSync(dir); for(var i=0;i<files.length;i++){ var n = files[i]; var file = dir+'/'+n; //console.warn(file) var stat = fs.statSync(file); if(stat.isFile()){ var p = path.relative(root,file).replace(/^[\/\\]?|\\/g,'/'); if(excludes && excludes.test(p)){ continue; } if(includes ? includes.test(p):/\.xhtml$/.test(p)){ console.log('compile:',path.join(output,p)) var result = compiler.compile(p); var source = ['exports.template=',result.jscode,';\nexports.config = ',JSON.stringify(result.config)].join(''); var id = getTemplateId(p); fs.writeFileSync(path.join(output,id)+'.js',source); //dest.writeFile(path.join(dest,p)) } //console.log(p) }else if(n.charAt() != '.' &&stat.isDirectory() ){ loadFile(file) } } } loadFile(root); } }; require.cached["lite/src/main/js/parse/config.js"]=function (require,exports,module,__filename,__dirname){/* * 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 $ */ //add as default /** * 模板解析上下文对象实现 * [ * { * "includes":["/example\\/*.xhtml"], * "excludes":[], * "config":{ * "encoding":"utf-8", * "contentType":"text/html;charset=UTF-8" * }, * "extensions":[ * { * "namespace":"http://www.xidea.org/lite/core", * "package":"lite/parse/i18n" * } * ] * } * ] */ function ParseConfig(root,dom){ this.root = new URI(root && root.replace(/[\\\/]*$/,'/') || 'lite:///'); var json = dom && parseConfig(dom); if(json){ var result = []; var i = json.length while(i--){ var item = {}; copy(json[i],item); item.includes = new RegExp(item.includes||"^$"); item.excludes = new RegExp(item.excludes||"^$"); result[i] = item; } this._groups = result; }else{ this._groups = defaultConfig; } } function copy(source,dest){ for(var n in source){ dest[n] = source[n]; } } function findGroup(groups,path,require){ for(var i=0,len = groups.length;i<len;i++){ var g = groups[i]; if(g.includes.test(path)){ if(!g.excludes.test(path)){ return g; } } } return require && groups[groups.length-1]; } ParseConfig.prototype = { // getDecotatorPage:function(path){ // var g = findGroup(this.config,path,null) // return g && g.config['layout']; // }, getConfig:function(path){ var result = {} var g = findGroup(this._groups,path,null); if(g){ copy(g.config,result); } return result; }, getExtensionMap:function(path){ var g = findGroup(this._groups,path,null); if(g){ return g.extensionMap; } return {}; } } var defaultConfig = { "includes":/./,//"/example\\/*.xhtml" "excludes":/^$/, "config":{ //必要属性(控制xml编译) "encoding":"utf-8", //必要属性(控制xml编译) "contentType":"text/html;charset=UTF-8" }, "extensionMap":{ ////xhtml 编译不是自带的,需要自己定义 //"http://www.w3.org/1999/xhtml":["org.xidea.lite.xhtml"], //core 自行编译 //"http://firekylin.my.baidu.com/ns/2010":["org.xidea.lite.xhtml"], //"http://firekylin.my.baidu.com/ns/2010":["org.xidea.lite.xhtml"] } } if(typeof require == 'function'){ exports.ParseConfig=ParseConfig; var parseConfig = require('./config-parser').parseConfig; var URI=require('./resource').URI; } }; require.cached["lite/src/main/js/parse/config-parser.js"]=function (require,exports,module,__filename,__dirname){/* * 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; } }; require.cached["lite/src/main/js/parse/resource.js"]=function (require,exports,module,__filename,__dirname){/* * foo://example.com:8042/over/there?name=ferret#nose * \_/ \______________/\_________/ \_________/ \__/ * | | | | | * scheme authority path query fragment * | _____________________|__ * / \ / \ * urn:example:animal:ferret:nose */ var uriPattern = /^([a-zA-Z][\w\.]*)\:(?:(\/\/[^\/]*))?(\/?[^?#]*)(\?[^#]*)?(#[\s\S]*)?$/; var absURIPattern = /^[a-zA-Z][\w\.]*\:/; var uriChars = /\\|[\x22\x3c\x3e\x5c\x5e\x60\u1680\u180e\u202f\u205f\u3000]|[\x00-\x20]|[\x7b-\x7d]|[\x7f-\xa0]|[\u2000-\u200b]|[\u2028-\u2029]/g; var allEncodes = /[\x2f\x60]|[\x00-\x29]|[\x2b-\x2c]|[\x3a-\x40]|[\x5b-\x5e]|[\x7b-\uffff]/g; ///[\x22\x25\x3c\x3e\x5c\x5e\x60\u1680\u180e\u202f\u205f\u3000]|[\x00-\x20]|[\x7b-\x7d]|[\x7f-\xa0]|[\u2000-\u200b]|[\u2028-\u2029]/g; function encodeChar(i){ return "%"+(0x100+i).toString(16).substring(1) } function decodeChar(c){ var n = c.charCodeAt(); if (n < 0x80){ return encodeChar(n); }else if (n < 0x800){ return encodeChar(0xc0 | (n >>> 6))+encodeChar(0x80 | (n & 0x3f)) }else{ return encodeChar( 0xe0 | ((n >>> 12) & 0x0f))+ encodeChar(0x80 | ((n >>> 6) & 0x3f))+ encodeChar(0x80 | (n & 0x3f)) } } function uriDecode(source){ //192,224,240 for(var result = [], i=1;i<source.length;i+=3){ var c = parseInt(source.substr(i,2),16); if(c>=240){//其实无效,js无法处理超出2字节的字符 c = (c & 0x07)<<18; c += (parseInt(source.substr(i+=3,2),16) &0x3f)<<12; c += (parseInt(source.substr(i+=3,2),16) &0x3f)<<6; c += (parseInt(source.substr(i+=3,2),16) &0x3f); }else if(c>=224){ c = (c & 0x0f)<<12; c += (parseInt(source.substr(i+=3,2),16) &0x3f)<<6; c += (parseInt(source.substr(i+=3,2),16) &0x3f); }else if(c>=192){ c = (c & 0x1f)<<6; c += (parseInt(source.substr(i+=3,2),16) &0x3f); } result.push(String.fromCharCode(c)) } return result.join(''); } function uriReplace(c){ if(c == '\\'){ return '/'; }else{ return decodeChar(c); } } function URI(path){ if(path instanceof URI){ return path; } if(/^\s*[<]/i.test(path)){ path = String(path).replace(uriChars,decodeChar) return new URI("data:text/xml,"+path); }else{ path = String(path).replace(uriChars,uriReplace) } //normalize path = path.replace(/\/\.\/|\\\.\\|\\/g,'/'); if(/^\/|^[a-z]\:\//i.test(path)){ path = 'file://'+path; } while(path != (path = path.replace(/[^\/]+\/\.\.\//g,''))); var match = path.match(uriPattern); if(match){ setupURI(this,match); }else{ console.error("url must be absolute,"+path) } } function setupURI(uri,match){ uri.value = match[0]; uri.scheme = match[1]; uri.authority = match[2]; uri.path = match[3]; uri.query = match[4]; uri.fragment = match[5]; if('data' == uri.scheme){ match = uri.value uri.source = decodeURIComponent(match.substring(match.indexOf(',')+1)); } } URI.prototype = { resolve:function(path){ path = String(path); if( /^\s*[#<]/.test(path) ||absURIPattern.test(path)){ path = new URI(path.replace(/^\s+/,'')); return path; } path = path.replace(uriChars,uriReplace) if(path.charAt() != '/'){ var p = this.path; path = p.replace(/[^\/]*$/,path); } return new URI(this.scheme + ':'+(this.authority||'') + path); }, toString:function(){ return this.value; } } var btoa = this.btoa || function(bs){ var b64 = []; var bi = 0; var len = bs.length; while (bi <len) { var b0 = bs.charCodeAt(bi++); var b1 = bs.charCodeAt(bi++); var b2 = bs.charCodeAt(bi++); var data = (b0 << 16) + (b1 << 8) + (b2||0); b64.push( b64codes[(data >> 18) & 0x3F ], b64codes[(data >> 12) & 0x3F], b64codes[isNaN(b1) ? 64 : (data >> 6) & 0x3F], b64codes[isNaN(b2) ? 64 : data & 0x3F]) ; } return b64.join(''); } var b64codes = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''); function utf8Replacer(c){ var n = c.charCodeAt(); if (n < 0x800){ return String.fromCharCode( (0xc0 | (n >>> 6)), (0x80|(n & 0x3f))); }else{ return String.fromCharCode( (0xe0 | ((n >>> 12) & 0x0f)), (0x80 | ((n >>> 6) & 0x3f)), (0x80 | (n & 0x3f))); } } function base64Encode(data){ data = data && data.replace(/[\u0080-\uFFFF]/g,utf8Replacer)||'' data = btoa(data) ; return encodeURIComponent(data); } function buildURIMatcher(pattern){ var matcher = /\*+|[^\*\\\/]+?|[\\\/]/g; var buf = ["^"]; var m matcher.lastIndex = 0; while (m = matcher.exec(pattern)) { var item = m[0]; var len = item.length; var c = item.charAt(0); if (c == '*') { if (len > 1) { buf.push(".*"); } else { buf.push("[^\\\\/]*"); } } else if(len == 1 && c == '/' || c == '\\') { buf.push("[\\\\/]"); }else{ buf.push(item.replace(/[^\w]/g,quteReqExp)); } } buf.push("$"); return buf.join(''); } function quteReqExp(x){ switch(x){ case '.': return '\\.'; case '\\': return '\\\\'; default: return '\\x'+(0x100 + x.charCodeAt()).toString(16).substring(1); } } if(typeof require == 'function'){ exports.URI=URI; exports.buildURIMatcher = buildURIMatcher; exports.base64Encode=base64Encode; } }; require.cached["lite/src/main/js/parse/xml.js"]=function (require,exports,module,__filename,__dirname){function loadLiteXML(uri,root,options){ try{ if(uri instanceof URI){ if(uri.source){ return parseXMLByText(uri.source.replace(/^[\s\ufeff]*/,uri,options)) }else if(uri.scheme == 'lite'){ var path = uri.path+(uri.query||'')+(uri.fragment || ''); path = root.resolve(path.replace(/^\//,'./'))+''; }else{ var path = String(uri); } }else{ var path = String(uri); } if(/^[\s\ufeff]*[<#]/.test(path)){ return parseXMLByText(path.replace(/^[\s\ufeff]*/,''),root,options) }else{ //console.log(path,/^(?:\w+\:\/\/|\w\:\\|\/).*$/.test(path)) if(/^(?:\w+\:\/\/|\w\:\\|\/).*$/.test(path)){ var pos = path.indexOf('#')+1; var xpath = pos && path.substr(pos); var path = pos?path.substr(0,pos-1):path; var source = loadTextByPath(path.replace(/^file\:\/\/?/,'')); var doc = parseXMLByText(source,uri,options); if(xpath && doc.nodeType){ doc = selectByXPath(doc,xpath); } return doc; }else{ //文本看待 return parseXMLByText(path,options); } } }catch(e){ console.error("文档解析失败:"+uri,e) throw e; } } function txt2xml(source){ return "<c:out c:xmlns='http://www.xidea.org/lite/core'><![CDATA["+ source.replace(/^\ufeff?#.*[\r\n]*/, "").replace(/]]>/, "]]]]><![CDATA[>")+ "]]></c:out>"; } function addInst(xml,s){ var p = /^\s*<\?(\w+)\s+(.*)\?>/; var m; var first = xml.firstChild; while(m = s.match(p)){ if(m[1] == 'xml' && first.nodeType != 7){ var pi = xml.createProcessingInstruction(m[1], m[2]); xml.insertBefore(pi, first); } s = s.substring(m[0].length); } return xml; } /** * @private */ function parseXMLByText(text,path,options){ text = String(text) if(!/^[\s\ufeff]*</.test(text)){ text = txt2xml(text); } try{ options = Object.create(options||{});//errorHandler options.locator={systemId:path} options.xmlns=defaultNSMap var doc = new DOMParser(options).parseFromString(text,"text/html") if(!doc.querySelectorAll){//init querySelector var elp = doc.documentElement.constructor.prototype; elp.querySelector = querySelector; elp.querySelectorAll = querySelectorAll; elp = doc.constructor.prototype; elp.querySelector = querySelector; elp.querySelectorAll = querySelectorAll; } //return doc; return addInst(doc,text); }catch(e){ console.error("解析xml失败:",e,text); } } function loadTextByPath(path){ var fs = require('fs'); try{ var text = fs.readFileSync(path,'utf-8'); }catch(e){ return fs.readFileSync(decodeURI(path),'utf-8'); } return text; } function selectorInit(node){ var doc = node.ownerDocument||node; var nw = doc.nwmatcher; if(!nw){ nw = doc.nwmatcher = nwmatcher({document:doc}); nw.configure( { USE_QSAPI: false, VERBOSITY: true } ); } return nw; } function querySelectorAll(selector){ var nodes = selectorInit(this).select(selector,this); nodes.item = nodeListItem; return nodes; } function querySelector(selector){ return selectorInit(this).first(selector,this) } function selectByXPath(currentNode,xpath){ var nodes = xpathSelectNodes(currentNode,xpath); nodes.item = nodeListItem; return nodes; } function nodeListItem(i){ return this[i]; } function findXMLAttribute(el,key){ if(el.nodeType == 2){ return el.value; } try{ //el var required = key.charAt() == '*'; if(required){ key = key.substr(1); } for(var i=1,len = arguments.length;i<len;i++){ var an = arguments[i]; if(an == '#text'){ return el.textContent||el.text; }else{ var v = el.getAttribute(an);//ie bug: no hasAttribute if(v || (typeof el.hasAttribute != 'undefined') && el.hasAttribute(an)){//ie bug if(i>1 && key.charAt(0) != '#'){ console.warn(el.tagName+" 标准属性名为:"+key +'; 您采用的是:'+an); } return v; } } } if(required){ console.error("标记:"+el.tagName+"属性:'"+key +"' 为必要属性。"); } }catch(e){ console.error('findXMLAttribute error:',e) } return null; } function findXMLAttributeAsEL(el){ el = findXMLAttribute.apply(null,arguments); if(el != null){ var el2 = el.replace(/^\s*\$\{([\s\S]*)\}\s*$/,"$1") if(el == el2){ if(el2){ console.warn("缺少表达式括弧,文本将直接按表达式返回",el); } }else{ el2 = el2.replace(/^\s+|\s+$/g,''); if(!el2){ console.warn("表达式内容为空:",el); } el = el2; } } return el; } function getLiteTagInfo(node){ return node.lineNumber + ','+ node.columnNumber+'@'+node.ownerDocument.documentURI; } var defaultNSMap = {c:'http://www.xidea.org/lite/core',h:'http://www.xidea.org/lite/html-ext'} var nwmatcher = require('./nwmatcher'); var URI=require('./resource').URI; var DOMParser = require('xmldom').DOMParser; var xpathSelectNodes = require('xpath.js'); exports.defaultNSMap = defaultNSMap; exports.querySelector = querySelector; exports.querySelectorAll = querySelectorAll; exports.loadLiteXML=loadLiteXML; exports.selectByXPath=selectByXPath; exports.findXMLAttribute=findXMLAttribute; exports.findXMLAttributeAsEL=findXMLAttributeAsEL; exports.getLiteTagInfo = getLiteTagInfo; }; require.cached["lite/src/main/js/parse/nwmatcher.js"]=function (require,exports,module,__filename,__dirname){/* * Copyright (C) 2007-2015 Diego Perini * All rights reserved. * * nwmatcher.js - A fast CSS selector engine and matcher * * Author: Diego Perini <diego.perini at gmail com> * Version: 1.3.6 * Created: 20070722 * Release: 20150710 * * License: * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE * Download: * http://javascript.nwbox.com/NWMatcher/nwmatcher.js */ (function(global, factory) { if (typeof module == 'object' && typeof exports == 'object') { // in a Node.js environment, the nwmatcher functions will operate on // the passed "browserGlobal" and will be returned in an object module.exports = function (browserGlobal) { // passed global does not contain // references to native objects browserGlobal.console = console; browserGlobal.parseInt = parseInt; browserGlobal.Function = Function; browserGlobal.Boolean = Boolean; browserGlobal.Number = Number; browserGlobal.RegExp = RegExp; browserGlobal.String = String; browserGlobal.Object = Object; browserGlobal.Array = Array; browserGlobal.Error = Error; browserGlobal.Date = Date; browserGlobal.Math = Math; var exports = browserGlobal.Object(); factory(browserGlobal, exports); return exports; }; module.factory = factory; } else { // in a browser environment, the nwmatcher functions will operate on // the "global" loading them and be attached to "global.NW.Dom" factory(global, (global.NW || (global.NW = global.Object())) && (global.NW.Dom || (global.NW.Dom = global.Object()))); global.NW.Dom.factory = factory; } })(this, function(global, exports) { var version = 'nwmatcher-1.3.6', Dom = exports, // processing context & root element doc = global.document, root = doc.documentElement, // save utility methods references slice = global.Array.prototype.slice, string = global.Object.prototype.toString, // persist previous parsed data isSingleMatch, isSingleSelect, lastSlice, lastContext, lastPosition, lastMatcher, lastSelector, lastPartsMatch, lastPartsSelect, // accepted prefix identifiers // (id, class & pseudo-class) prefixes = '[#.:]?', // accepted attribute operators operators = '([~*^$|!]?={1})', // accepted whitespace characters whitespace = '[\\x20\\t\\n\\r\\f]*', // 4 combinators F E, F>E, F+E, F~E combinators = '[\\x20]|[>+~][^>+~]', // an+b format params for pseudo-classes pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', // CSS quoted string values quotedvalue = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"' + "|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'", // skip round brackets groups skipround = '\\([^()]+\\)|\\(.*\\)', // skip curly brackets groups skipcurly = '\\{[^{}]+\\}|\\{.*\\}', // skip square brackets groups skipsquare = '\\[[^[\\]]*\\]|\\[.*\\]', // skip [ ], ( ), { } brackets groups skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', // http://www.w3.org/TR/css3-syntax/#characters // unicode/ISO 10646 characters 161 and higher // NOTE: Safari 2.0.x crashes with escaped (\\) // Unicode ranges in regular expressions so we // use a negated character range class instead encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', // CSS identifier syntax identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', // build attribute string attrcheck = '(' + quotedvalue + '|' + identifier + ')', attributes = whitespace + '(' + encoding + '*:?' + encoding + '+)' + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), // build pseudoclass string pseudoclass = '((?:' + // an+b parameters or quoted string pseudoparms + '|' + quotedvalue + '|' + // id, class, pseudo-class selector prefixes + '|' + encoding + '+|' + // nested HTML attribute selector '\\[' + attributes + '\\]|' + // nested pseudo-class selector '\\(.+\\)|' + whitespace + '|' + // nested pseudos/separators ',)+)', // placeholder for extensions extensions = '.+', // CSS3: syntax scanner and // one pass validation only // using regular expression standardValidator = // discard start '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + // open match group '(' + //universal selector '\\*' + // id/class/tag/pseudo-class identifier '|(?:' + prefixes + identifier + ')' + // combinator selector '|' + combinators + // HTML attribute selector '|\\[' + attributes + '\\]' + // pseudo-classes parameters '|\\(' + pseudoclass + '\\)' + // dom properties selector (extension) '|\\{' + extensions + '\\}' + // selector group separator (comma) '|(?:,|' + whitespace + ')' + // close match group ')+', // validator for complex selectors in ':not()' pseudo-classes extendedValidator = standardValidator.replace(pseudoclass, '.*'), // validator for standard selectors as default reValidator = new global.RegExp(standardValidator, 'g'), // whitespace is any combination of these 5 character [\x20\t\n\r\f] // http://www.w3.org/TR/css3-selectors/#selector-syntax reTrimSpaces = new global.RegExp('^' + whitespace + '|' + whitespace + '$', 'g'), // only allow simple selectors nested in ':not()' pseudo-classes reSimpleNot = new global.RegExp('^(' + '(?!:not)' + '(' + prefixes + '|' + identifier + '|\\([^()]*\\))+' + '|\\[' + attributes + '\\]' + ')$'), // split comma groups, exclude commas from // quotes '' "" and from brackets () [] {} reSplitGroup = new global.RegExp('(' + '[^,\\\\()[\\]]+' + '|' + skipsquare + '|' + skipround + '|' + skipcurly + '|\\\\.' + ')+', 'g'), // split last, right most, selector group token reSplitToken = new global.RegExp('(' + '\\[' + attributes + '\\]|' + '\\(' + pseudoclass + '\\)|' + '\\\\.|[^\\x20\\t\\r\\n\\f>+~])+', 'g'), // for in excess whitespace removal reWhiteSpace = /[\x20\t\n\r\f]+/g, reOptimizeSelector = new global.RegExp(identifier + '|^$'), /*----------------------------- FEATURE TESTING ----------------------------*/ // detect native methods isNative = (function() { var re = / \w+\(/, isnative = String(Object.prototype.toString).replace(re, ' ('); return function(method) { return method && typeof method != 'string' && isnative == String(method).replace(re, ' ('); }; })(), // NATIVE_XXXXX true if method exist and is callable // detect if DOM methods are native in browsers NATIVE_FOCUS = isNative(doc.hasFocus), NATIVE_QSAPI = isNative(doc.querySelector), NATIVE_GEBID = isNative(doc.getElementById), NATIVE_GEBTN = isNative(root.getElementsByTagName), NATIVE_GEBCN = isNative(root.getElementsByClassName), // detect native getAttribute/hasAttribute methods, // frameworks extend these to elements, but it seems // this does not work for XML namespaced attributes, // used to check both getAttribute/hasAttribute in IE NATIVE_GET_ATTRIBUTE = isNative(root.getAttribute), NATIVE_HAS_ATTRIBUTE = isNative(root.hasAttribute), // check if slice() can convert nodelist to array // see http://yura.thinkweb2.com/cft/ NATIVE_SLICE_PROTO = (function() { var isBuggy = false; try { isBuggy = !!slice.call(doc.childNodes, 0)[0]; } catch(e) { } return isBuggy; })(), // supports the new traversal API NATIVE_TRAVERSAL_API = 'nextElementSibling' in root && 'previousElementSibling' in root, // BUGGY_XXXXX true if method is feature tested and has known bugs // detect buggy gEBID BUGGY_GEBID = NATIVE_GEBID ? (function() { var isBuggy = true, x = 'x' + global.String(+new global.Date), a = doc.createElementNS ? 'a' : '<a name="' + x + '">'; (a = doc.createElement(a)).name = x; root.insertBefore(a, root.firstChild); isBuggy = !!doc.getElementById(x); root.removeChild(a); return isBuggy; })() : true, // detect IE gEBTN comment nodes bug BUGGY_GEBTN = NATIVE_GEBTN ? (function() { var div = doc.createElement('div'); div.appendChild(doc.createComment('')); return !!div.getElementsByTagName('*')[0]; })() : true, // detect Opera gEBCN second class and/or UTF8 bugs as well as Safari 3.2 // caching class name results and not detecting when changed, // tests are based on the jQuery selector test suite BUGGY_GEBCN = NATIVE_GEBCN ? (function() { var isBuggy, div = doc.createElement('div'), test = '\u53f0\u5317'; // Opera tests div.appendChild(doc.createElement('span')). setAttribute('class', test + 'abc ' + test); div.appendChild(doc.createElement('span')). setAttribute('class', 'x'); isBuggy = !div.getElementsByClassName(test)[0]; // Safari test div.lastChild.className = test; return isBuggy || div.getElementsByClassName(test).length != 2; })() : true, // detect IE bug with dynamic attributes BUGGY_GET_ATTRIBUTE = NATIVE_GET_ATTRIBUTE ? (function() { var input = doc.createElement('input'); input.setAttribute('value', 5); return input.defaultValue != 5; })() : true, // detect IE bug with non-standard boolean attributes BUGGY_HAS_ATTRIBUTE = NATIVE_HAS_ATTRIBUTE ? (function() { var option = doc.createElement('option'); option.setAttribute('selected', 'selected'); return !option.hasAttribute('selected'); })() : true, // detect Safari bug with selected option elements BUGGY_SELECTED = (function() { var select = doc.createElement('select'); select.appendChild(doc.createElement('option')); return !select.firstChild.selected; })(), // initialized with the loading context // and reset for each different context BUGGY_QUIRKS_GEBCN, BUGGY_QUIRKS_QSAPI, QUIRKS_MODE, XML_DOCUMENT, // detect Opera browser OPERA = /opera/i.test(string.call(global.opera)), // skip simple selector optimizations for Opera >= 11 OPERA_QSAPI = OPERA && global.parseFloat(global.opera.version()) >= 11, // check Selector API implementations RE_BUGGY_QSAPI = NATIVE_QSAPI ? (function() { var pattern = new global.Array(), context, element, expect = function(selector, element, n) { var result = false; context.appendChild(element); try { result = context.querySelectorAll(selector).length == n; } catch(e) { } while (context.firstChild) { context.removeChild(context.firstChild); } return result; }; // certain bugs can only be detected in standard documents // to avoid writing a live loading document create a fake one if (doc.implementation && doc.implementation.createDocument) { // use a shadow document body as context context = doc.implementation.createDocument('', '', null). appendChild(doc.createElement('html')). appendChild(doc.createElement('head')).parentNode. appendChild(doc.createElement('body')); } else { // use an unattached div node as context context = doc.createElement('div'); } // fix for Safari 8.x and other engines that // fail querying filtered sibling combinators element = doc.createElement('div'); element.innerHTML = '<p id="a"></p><br>'; expect('p#a+*', element, 0) && pattern.push('\\w+#\\w+.*[+~]'); // ^= $= *= operators bugs with empty values (Opera 10 / IE8) element = doc.createElement('p'); element.setAttribute('class', ''); expect('[class^=""]', element, 1) && pattern.push('[*^$]=[\\x20\\t\\n\\r\\f]*(?:""|' + "'')"); // :checked bug with option elements (Firefox 3.6.x) // it wrongly includes 'selected' options elements // HTML5 rules says selected options also match element = doc.createElement('option'); element.setAttribute('selected', 'selected'); expect(':checked', element, 0) && pattern.push(':checked'); // :enabled :disabled bugs with hidden fields (Firefox 3.5) // http://www.w3.org/TR/html5/links.html#selector-enabled // http://www.w3.org/TR/css3-selectors/#enableddisabled // not supported by IE8 Query Selector element = doc.createElement('input'); element.setAttribute('type', 'hidden'); expect(':enabled', element, 0) && pattern.push(':enabled', ':disabled'); // :link bugs with hyperlinks matching (Firefox/Safari) element = doc.createElement('link'); element.setAttribute('href', 'x'); expect(':link', element, 1) || pattern.push(':link'); // avoid attribute selectors for IE QSA if (BUGGY_HAS_ATTRIBUTE) { // IE fails in reading: // - original values for input/textarea // - original boolean values for controls pattern.push('\\[[\\x20\\t\\n\\r\\f]*(?:checked|disabled|ismap|multiple|readonly|selected|value)'); } return pattern.length ? new global.RegExp(pattern.join('|')) : { 'test': function() { return false; } }; })() : true, // matches class selectors RE_CLASS = new global.RegExp('(?:\\[[\\x20\\t\\n\\r\\f]*class\\b|\\.' + identifier + ')'), // matches simple id, tag & class selectors RE_SIMPLE_SELECTOR = new global.RegExp( BUGGY_GEBTN && BUGGY_GEBCN || OPERA ? '^#?-?[_a-zA-Z]{1}' + encoding + '*$' : BUGGY_GEBTN ? '^[.#]?-?[_a-zA-Z]{1}' + encoding + '*$' : BUGGY_GEBCN ? '^(?:\\*|#-?[_a-zA-Z]{1}' + encoding + '*)$' : '^(?:\\*|[.#]?-?[_a-zA-Z]{1}' + encoding + '*)$'), /*----------------------------- LOOKUP OBJECTS -----------------------------*/ LINK_NODES = new global.Object({ 'a': 1, 'A': 1, 'area': 1, 'AREA': 1, 'link': 1, 'LINK': 1 }), // boolean attributes should return attribute name instead of true/false ATTR_BOOLEAN = new global.Object({ 'checked': 1, 'disabled': 1, 'ismap': 1, 'multiple': 1, 'readonly': 1, 'selected': 1 }), // dynamic attributes that needs to be checked against original HTML value ATTR_DEFAULT = new global.Object({ 'value': 'defaultValue', 'checked': 'defaultChecked', 'selected': 'defaultSelected' }), // attributes referencing URI data values need special treatment in IE ATTR_URIDATA = new global.Object({ 'action': 2, 'cite': 2, 'codebase': 2, 'data': 2, 'href': 2, 'longdesc': 2, 'lowsrc': 2, 'src': 2, 'usemap': 2 }), // HTML 5 draft specifications // http://www.whatwg.org/specs/web-apps/current-work/#selectors HTML_TABLE = new global.Object({ // class attribute must be treated case-insensitive in HTML quirks mode // initialized by default to Standard Mode (case-sensitive), // set dynamically by the attribute resolver 'class': 0, 'accept': 1, 'accept-charset': 1, 'align': 1, 'alink': 1, 'axis': 1, 'bgcolor': 1, 'charset': 1, 'checked': 1, 'clear': 1, 'codetype': 1, 'color': 1, 'compact': 1, 'declare': 1, 'defer': 1, 'dir': 1, 'direction': 1, 'disabled': 1, 'enctype': 1, 'face': 1, 'frame': 1, 'hreflang': 1, 'http-equiv': 1, 'lang': 1, 'language': 1, 'link': 1, 'media': 1, 'method': 1, 'multiple': 1, 'nohref': 1, 'noresize': 1, 'noshade': 1, 'nowrap': 1, 'readonly': 1, 'rel': 1, 'rev': 1, 'rules': 1, 'scope': 1, 'scrolling': 1, 'selected': 1, 'shape': 1, 'target': 1, 'text': 1, 'type': 1, 'valign': 1, 'valuetype': 1, 'vlink': 1 }), // the following attributes must be treated case-insensitive in XHTML mode // Niels Leenheer http://rakaz.nl/item/css_selector_bugs_case_sensitivity XHTML_TABLE = new global.Object({ 'accept': 1, 'accept-charset': 1, 'alink': 1, 'axis': 1, 'bgcolor': 1, 'charset': 1, 'codetype': 1, 'color': 1, 'enctype': 1, 'face': 1, 'hreflang': 1, 'http-equiv': 1, 'lang': 1, 'language': 1, 'link': 1, 'media': 1, 'rel': 1, 'rev': 1, 'target': 1, 'text': 1, 'type': 1, 'vlink': 1 }), /*-------------------------- REGULAR EXPRESSIONS ---------------------------*/ // placeholder to add functionalities Selectors = new global.Object({ // as a simple example this will check // for chars not in standard ascii table // // 'mySpecialSelector': { // 'Expression': /\u0080-\uffff/, // 'Callback': mySelectorCallback // } // // 'mySelectorCallback' will be invoked // only after passing all other standard // checks and only if none of them worked }), // attribute operators Operators = new global.Object({ '=': "n=='%m'", '^=': "n.indexOf('%m')==0", '*=': "n.indexOf('%m')>-1", '|=': "(n+'-').indexOf('%m-')==0", '~=': "(' '+n+' ').indexOf(' %m ')>-1", '$=': "n.substr(n.length-'%m'.length)=='%m'" }), // optimization expressions Optimize = new global.Object({ ID: new global.RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), TAG: new global.RegExp('^(' + encoding + '+)|' + skipgroup), CLASS: new global.RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) }), // precompiled Regular Expressions Patterns = new global.Object({ // structural pseudo-classes and child selectors spseudos: /^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\(\s*(even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\))?(.*)/i, // uistates + dynamic + negation pseudo-classes dpseudos: /^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(([^()]*|.*)\))?(.*)/i, // element attribute matcher attribute: new global.RegExp('^\\[' + attrmatcher + '\\](.*)'), // E > F children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, // E + F adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, // E ~ F relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, // E F ancestor: /^[\x20\t\n\r\f]+(.*)/, // all universal: /^\*(.*)/, // id id: new global.RegExp('^#(' + encoding + '+)(.*)'), // tag tagName: new global.RegExp('^(' + encoding + '+)(.*)'), // class className: new global.RegExp('^\\.(' + encoding + '+)(.*)') }), /*------------------------------ UTIL METHODS ------------------------------*/ // concat elements to data concatList = function(data, elements) { var i = -1, element; if (!data.length && global.Array.slice) return global.Array.slice(elements); while ((element = elements[++i])) data[data.length] = element; return data; }, // concat elements to data and callback concatCall = function(data, elements, callback) { var i = -1, element; while ((element = elements[++i])) { if (false === callback(data[data.length] = element)) { break; } } return data; }, // change context specific variables switchContext = function(from, force) { var div, oldDoc = doc; // save passed context lastContext = from; // set new context document doc = from.ownerDocument || from; if (force || oldDoc !== doc) { // set document root root = doc.documentElement; // set host environment flags XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; // In quirks mode css class names are case insensitive. // In standards mode they are case sensitive. See docs: // https://developer.mozilla.org/en/Mozilla_Quirks_Mode_Behavior // http://www.whatwg.org/specs/web-apps/current-work/#selectors QUIRKS_MODE = !XML_DOCUMENT && typeof doc.compatMode == 'string' ? doc.compatMode.indexOf('CSS') < 0 : (function() { var style = doc.createElement('div').style; return style && (style.width = 1) && style.width == '1px'; })(); div = doc.createElement('div'); div.appendChild(doc.createElement('p')).setAttribute('class', 'xXx'); div.appendChild(doc.createElement('p')).setAttribute('class', 'xxx'); // GEBCN buggy in quirks mode, match count is: // Firefox 3.0+ [xxx = 1, xXx = 1] // Opera 10.63+ [xxx = 0, xXx = 2] BUGGY_QUIRKS_GEBCN = !XML_DOCUMENT && NATIVE_GEBCN && QUIRKS_MODE && (div.getElementsByClassName('xxx').length != 2 || div.getElementsByClassName('xXx').length != 2); // QSAPI buggy in quirks mode, match count is: // At least Chrome 4+, Firefox 3.5+, Opera 10.x+, Safari 4+ [xxx = 1, xXx = 2] // Safari 3.2 QSA doesn't work with mixedcase in quirksmode [xxx = 1, xXx = 0] // https://bugs.webkit.org/show_bug.cgi?id=19047 // must test the attribute selector '[class~=xxx]' // before '.xXx' or the bug may not present itself BUGGY_QUI