1 2 /** 3 * @name CeL code reorganize function 4 * @fileoverview 5 * 本檔案包含了程式碼重整重構用的 functions。 6 * @since 7 */ 8 9 /* 10 parse code 11 use ISO-14977: Extended Backus–Naur Form (EBNF) 12 http://zh.wikipedia.org/wiki/%E6%89%A9%E5%B1%95%E5%B7%B4%E7%A7%91%E6%96%AF%E8%8C%83%E5%BC%8F 13 14 http://blog.zhaojie.me/2010/11/narcissus-javascript-parser.html 15 Narcissus是一個JavaScript引擎,完全使用JavaScript編寫,不過利用了SpiderMonkey的一些擴展,因此無法直接在僅僅實現了ECMAScript 3的引擎上執行(例如各瀏覽器)。 16 http://en.wikipedia.org/wiki/Narcissus_%28JavaScript_engine%29 17 http://hax.iteye.com/blog/181358 18 19 */ 20 21 if (typeof CeL === 'function') 22 CeL.setup_module('data.code.reorganize', 23 function(library_namespace, load_arguments) { 24 25 26 // nothing required 27 28 29 var 30 /** 31 * null module constructor 32 * @class 程式碼重整重構相關之 functions。 33 * @constructor 34 */ 35 CeL.data.code.reorganize 36 = function () { 37 // null module constructor 38 }; 39 40 /** 41 * for JSDT: 有 prototype 才會將之當作 Class 42 */ 43 CeL.data.code.reorganize 44 .prototype = {}; 45 46 47 48 49 //class public interface --------------------------- 50 51 CeL.data.code.reorganize 52 . 53 /** 54 * 取得[script_filename].wsf中不包括自己([script_filename].js),其餘所有 .js 的code。 55 * @param {String} script_filename script filename 56 * @return 57 * @requires ScriptName,simpleRead 58 * @deprecated 若想在低版本中利用eval(get_all_functions(ScriptName))來補足,有時會出現奇怪的現象,還是別用好了。 59 * @memberOf CeL.data.code.reorganize 60 */ 61 get_all_functions = function (script_filename) { 62 if (!script_filename) 63 script_filename = ScriptName; 64 var t = '', i, a = simpleRead(script_filename + '.wsf'), l = a ? a 65 .match(/[^\\\/:*?"<>|'\r\n]+\.js/gi) : [script_filename + '.js']; 66 67 for (i in l) 68 if (l[i] != script_filename + '.js' && (a = simpleRead(l[i]))) 69 t += a; 70 return t; 71 }; 72 73 74 var JS_reserved_word = { 75 Keyword : 'break,do,instanceof,typeof,case,else,new,var,catch,finally,return,void,continue,for,switch,while,debugger,function,this,with,default,if,throw,delete,in,try', 76 FutureReservedWord : 'class,enum,extends,super,const,export,import', 77 NullLiteral : 'null', 78 BooleanLiteral : 'true,false' 79 }; 80 81 82 //var OK = add_code('alert,simpleWrite', ['alert', 'NewLine', 'get_all_functions']);if (typeof OK == 'string') simpleWrite('try.js', OK), alert('done'); else alert('OK:' + OK); 83 /* 84 { 85 var ss = [23, 23.456, undefined, Attribute, null, Array, '567', 'abc'], l = 80, repF = 'tmp.txt', sa = ss, st = add_code('', ['ss']), t; 86 ss = '(reseted)'; try { eval(st); } catch (e) { } t = (sa === ss) + ': ' + typeof sa + '→' + typeof ss + '\n'; 87 simpleWrite(repF, t + sa + '\n→\n' + ss + '\n\n◎eval:\n' + st); 88 alert(t + (sa = '' + sa, sa.length < l ? sa : sa.slice(0, l / 2) + '\n..' + sa.slice(sa.length - l / 2)) + '\n→\n' + (ss = '' + ss, ss.length < l ? ss : ss.slice(0, l / 2) + '\n..' + ss.slice(ss.length - l / 2)) + '\n\n' + (ss = '' + st, ss.length < l ? ss : ss.slice(0, 200) + '\n..\n' + ss.slice(ss.length - 200))); 89 } 90 */ 91 92 /* 93 加入識別格式之方法: 94 95 // from function.js ------------------------------------------------------------------- 96 97 //e.g., 98 // [function.js](f1,f2,'string' // 'string'或"string"中包含的需要是完整的敘述句 99 // number var,string var,object var,date var,undefined var) 100 101 //e.g., 102 // [function.js](OS,NewLine,dirSp,dirSpR,'var ScriptName=getScriptName();',ForReading,ForWriting,ForAppending,TristateUseDefault,TristateTrue,TristateFalse,WshShell,fso,args,'initWScriptObj();',initWScriptObj,setTool,JSalert,Str2Date,Date2Str,decplaces,dQuote,set_obj_value,getScriptFullName,getScriptName,'setTool();',WinEnvironment,SpecialFolder,Network,NetDrive,NetPrinter,getEnvironment,'getEnvironment();',dateUTCdiff,gDate) 103 //e.g., 104 // [function.js]("var NewLine='\n',OS='unix',dirSp=dirSpR='/';",dQuote,setTool,product,decplaces,countS,getText,turnUnicode,trimStr_,trimStr,StrToDate,DateToStr,reducePath,getPathOnly,getFN,getFP,dBasePath,trigger,setTopP,setAstatusOS,setAstatus,setAstatusOver,setAstatusOut,doAlertResize,doAlertInit,doAlert,doAlertAccess,doAlertScroll,setCookie,getCookie,scrollTo,disableKM,setCookieS,*disabledKM=0;,scrollToXY,scrollToInterval,scrollToOK,doAlertDivName,doAlertOldScrollLocation,parse_Function,dealPopup,sPopP,sPopF,sPopInit,sPopInit,sPop,setTextT,setText) 105 106 ..(inclide code) 107 // [function.js]End ------------------------------------------------------------------- 108 // ↑from function.js ------------------------------------------------------------------- 109 110 111 TODO: 112 .htm 加入 .replace(/\//g,'\\/') 113 */ 114 CeL.data.code.reorganize 115 . 116 /** 117 * 將各 function 加入檔案中,可做成 HTML 亦可用之格式。 118 * @example 119 * add_code('複製 -backup.js'); 120 * @param file_name file name (list) 121 * @param Vlist 多加添的 function/various list 122 * @param {String} start_string start string 123 * @param {String} end_string ending string 124 * @returns 125 * @request NewLine,is_file,simpleRead,autodetectEncode,generate_code,JSalert,setTool,*setTool(); 126 * @memberOf CeL.data.code.reorganize 127 */ 128 add_code = function (file_name, Vlist, start_string, end_string) { 129 if (!start_string) 130 start_string = '// [' + library_namespace.Class + ']'; 131 if (!end_string) 132 end_string = start_string + 'End'; 133 //alert(is_file(FN)+'\n'+start_string+'\n'+end_string); 134 135 if (typeof file_name == 'string') 136 file_name = [ is_file(file_name) ? file_name : start_string 137 + (file_name ? '(' + file_name + ')' : '') + NewLine 138 + end_string + NewLine ]; 139 if (typeof Vlist == 'string') 140 Vlist = [ Vlist ]; 141 else if (typeof Vlist != 'object') 142 Vlist = []; 143 144 var i, j, F, a, A, start, end, code_head, b, c, d, f, m, OK = 0, new_line, 145 // 「」『』【】〈〉《》〔〕{}︵︶︹︺︷︸︻︼︿﹀︽︾﹁﹂﹃﹄()「」『』‘’“”〝〞‵′ 146 s = '()[]{}<>\u300c\u300d\u300e\u300f\u3010\u3011\u3008\u3009\u300a\u300b\u3014\u3015\uff5b\uff5d\ufe35\ufe36\ufe39\ufe3a\ufe37\ufe38\ufe3b\ufe3c\ufe3f\ufe40\ufe3d\ufe3e\ufe41\ufe42\ufe43\ufe44\uff08\uff09\u300c\u300d\u300e\u300f\u2018\u2019\u201c\u201d\u301d\u301e\u2035\u2032', 147 end_char, req, direct_input = '*', tmpExt = '.tmp', encoding, oriC; 148 149 150 for (i in file_name) try { 151 if (a = oriC = is_file(file_name[i]) ? simpleRead(file_name[i], 152 encoding = autodetectEncode(file_name[i])) : file_name[i], !a) 153 continue; 154 A = '', dones = [], doneS = 0; 155 //sl(a.slice(0,200)); 156 157 /* 判斷 new_line 這段,將三種資料作比較就能知道為何這麼搞。 158 159 ~\r: 160 161 \r 123 162 \n 1 163 \r\n 2 164 \n-\r -120 165 166 167 ~\n: 168 169 \r 1 170 \n 123 171 \r\n 2 172 \n-\r 120 173 174 175 ~\r\n: 176 177 \r 123 178 \n 123 179 \r\n 123 180 \n-\r -2~2 181 */ 182 new_line = a.replace(/[^\n]+/g, '').length; 183 b = a.replace(/[^\r]+/g, '').length; 184 if (new_line != b && new_line && b) { 185 alert("There're some encoding problems in the file:\n" 186 + file_name[i] + '\n\\n: ' + new_line + '\n\\r: ' + b); 187 new_line = Math.max(new_line, b) > 10 * Math.abs(new_line - b) ? '\r\n' 188 : new_line > b ? '\n' : '\r'; 189 } else 190 new_line = new_line ? b ? '\r\n' : '\n' : '\r'; 191 192 //sl(a.indexOf(start_string)+'\n'+start_string+'\n'+a.slice(0,200)); 193 // TODO: a=a.replace(/(startReg)(.*?)(endReg)/g,function($0,$1,$2,$3){.. return $1+~+$3;}); 194 while ((start = a.indexOf(start_string)) != -1 195 // &&(end=a.indexOf(end_string,start+start_string.length))!=-1 196 ) { 197 // initial reset 198 code_head = codeText = end_char = ''; 199 req = []; 200 j = 0; 201 // 判斷 end index 202 if ((end = a.indexOf(end_string, start + start_string.length)) == -1) { 203 alert('add_code: There is start mark without end mark!\nend_string:\n' 204 + end_string); 205 // 未找到格式則 skip 206 break; 207 } 208 // b=inner text 209 b = a.slice(start + start_string.length, end); 210 b = b.split(new_line); //b=b.split(new_line=b.indexOf('\r\n')!=-1?'\r\n':b.indexOf('\n')!=-1?'\n':'\r'); // test檔案型式:DOS or UNIX.最後一位元已被split掉 211 if (c = b[0].match(/^\s*([^\w])/)) { 212 code_head += b[0].slice(0, RegExp.lastIndex); 213 b[0] = b[0].slice(RegExp.lastIndex); 214 if (s.indexOf(c = c[1]) % 2 == 0) 215 end_char = s.charAt(s.indexOf(c) + 1); 216 else 217 end_char = c; 218 } 219 //new_line=b[0].slice(-1)=='\r'?'\r\n':'\n'; // 移到前面:因為需要以new_line作split test檔案型式:DOS or UNIX.最後一位元已被split掉 220 //alert('end_char='+end_char+',j='+j+',d='+d+'\n'+b[0]+'\nNewLine:'+(new_line=='\n'?'\\n':new_line=='\r\n'?'\\r\\n':'\\r')+'\ncode_head:\n'+code_head); 221 222 do { 223 // 不需要d>=b[j].length 224 //if(d==b[j].length)continue; 225 if (!j) 226 d = 0; 227 else if (b[j].slice(0, 2) != '//') 228 continue; 229 else 230 d = 2; 231 232 for (;;) { 233 //alert('search '+b[j].slice(d)); 234 if ((c = b[j].slice(d).match(/^[,\s]*([\'\"])/)) 235 && (f = d + RegExp.lastIndex) <= b[j].length && 236 // (c=c[1], f<b[j].length) 237 (c = c[1]) && f < b[j].length) { // .search( 238 // alert(b[j].charAt(f)+'\n'+c+'\n^(.*[^\\\\])['+c+']'); 239 if (b[j].charAt(f) == c) { 240 // '',""等 241 alert('add_code: 包含[' + c + c + ']:\n' 242 + b[j].slice(f)); 243 continue; 244 } 245 if (c = b[j].slice(f).match( 246 new RegExp('^(.+?[^\\\\])[' + c + ']'))) { 247 d = f + RegExp.lastIndex; 248 req.push(direct_input/* +b[j].charAt(f-1) 改進後不需要了 */ 249 + c[1]); 250 continue; 251 } 252 alert('add_code: Can not find end quota:\n' + b[j].slice(f)); 253 } 254 //alert(d+','+b[j].length+'\nsearch to '+b[j].slice(d)); 255 256 // 出現奇怪現象請加"()" 257 //if((c=b[j].slice(d).match(/([^,\s]+)([,\s]*)/))&& ( (d+=RegExp.lastIndex)==b[j].length || /[,\n]/.test(c[2])&&d<b[j].length ) ){ // 不需要\s\r 258 if ((c = b[j].slice(d).match(/([^,\s]+)[,\s]*/)) && (d += RegExp.lastIndex) <= b[j].length) { // 不需要\s\r 259 //if(!/[,\n]/.test(c[2])&&d<b[j].length)break; 260 //alert(RegExp.index+','+d+','+b[j].length+','+end_char+'\n['+c[1]+']\n['+c[2]+']\n'+b[j].slice(d)); 261 if (!end_char || (m = c[1].indexOf(end_char)) == -1) req.push(c[1]); 262 else { if (m) req.push(c[1].slice(0, m)); end_char = ''; break; } 263 } else break; 264 } 265 code_head += b[j] + new_line; 266 //alert('output start_string:\n'+start_string+'\ncode_head:\n'+code_head); 267 } while (end_char && ++j < b.length); 268 //for(j=0,b=[];j<req.length;j++)b.push(req[j]); // 不能用b=req:object是用參考的,這樣會改到req本身! 269 //for(j=0;j<Vlist.length;j++)b.push(Vlist[j]); // 加入附加的變數 270 271 b = _.generate_code(req.concat(Vlist), new_line, direct_input); 272 codeText = code_head + (arguments.callee.report ? '/* add_code @ ' + gDate('', 1) // report 273 + (req.length ? new_line + ' request variables [' + req.length + ']: ' + req : '') 274 + (Vlist.length ? new_line + ' addition lists [' + Vlist.length + ']: ' + Vlist : '') 275 + (req.length && Vlist.length && b[2].length < req.length + Vlist.length ? new_line + ' Total request [' + b[2].length + ']: ' + b[2] : '') 276 + (b[4].length ? new_line + ' really done [' + b[4].length + ']: ' + b[4] : '') 277 + (b[5].length ? new_line + ' cannot found [' + b[5].length + ']: ' + b[5] : '') 278 + (b[6].length ? new_line + ' all listed [' + b[6].length + ']: ' + b[6] : '') 279 //+(b[3].length?new_line+' included function ['+b[3].length+']: '+b[3]:'') 280 + new_line + ' */' : '') + new_line + _.reduce_code(b[0]).replace(/([};])function(\s)/g, '$1' + new_line + 'function$2').replace(/}var(\s)/g, '}' + new_line + 'var$1')/*.replace(/([;}])([a-z\._\d]+=)/ig,'$1'+new_line+'$2')*/ + new_line + b[1] + new_line; 281 //alert(start+','+end+'\n'+a.length+','+end+','+end_string.length+','+(end+end_string.length)+'\n------------\n'+codeText);//+a.slice(end+end_string.length) 282 A += a.slice(0, start + start_string.length) 283 + codeText 284 + a.substr(end, end_string.length); 285 a = a.substr(end + end_string.length); 286 } 287 288 if (file_name.length == 1 && !is_file(file_name[i])) 289 return A; 290 291 if (A && oriC != A + a) // 有變化才寫入 292 if (!simpleWrite(file_name[i] + tmpExt, A + a, encoding)) 293 try { 294 fso.DeleteFile(file_name[i]); 295 fso.MoveFile(file_name[i] + tmpExt, file_name[i]); 296 OK++; 297 } catch (e) { 298 // popErr(e); 299 } 300 else 301 try { 302 fso.DeleteFile(file_name[i] + tmpExt); 303 } catch (e) { 304 // popErr(simpleFileErr);popErr(e); 305 } 306 //else{alert('add_code error:\n'+e.message);continue;} 307 } catch (e) { 308 //popErr(e); 309 throw e; 310 } 311 312 // A:成功的最後一個檔之內容 313 return file_name.length == 1 && OK == 1 ? A : OK; 314 }; 315 316 /** 317 * 是否加入報告 318 * @type Boolean 319 */ 320 _.add_code.report = false; 321 322 323 CeL.data.code.reorganize 324 . 325 /** 326 * add libary use 327 * @param {String} code script code 328 * @returns 329 * @memberOf CeL.data.code.reorganize 330 */ 331 add_use = function (code) { 332 // TODO: 去除 comments 中的 .use() 333 var _s = _.add_use, i, m = code.match(_s.pattern); 334 335 library_namespace.err('TODO'); 336 }; 337 _.add_use.pattern = new RegExp(library_namespace.Class 338 + '\\s*.\\s*use\\((.+)\\)'); 339 340 /* 341 try.wsf 342 <package><job id="try"><script type="text/javascript" language="JScript" src="function.js"></script><script type="text/javascript" language="JScript" src="try.js"></script></job></package> 343 try.js 344 destory_script('WshShell=WScript.CreateObject("WScript.Shell");'+NewLine+NewLine+alert+NewLine+NewLine+'alert("資料讀取錯誤!\\n請檢查設定是否有錯!");'); 345 */ 346 CeL.data.code.reorganize 347 . 348 /** 349 * script 終結者… 350 * @param {String} code script code 351 * @param addFN 352 * @returns error no. 353 * @memberOf CeL.data.code.reorganize 354 */ 355 destory_script = function (code, addFN) { 356 try { 357 // input indepent code, additional files 358 var SN = getScriptName(), F, a, listJs, i, len, self = SN + '.js'; 359 if (!code) 360 code = ''; //SN='try'; 361 a = simpleRead(SN + '.wsf'); 362 if (!a) a = ''; 363 // 一網打盡 364 listJs = a.match(/[^\\\/:*?"<>|'\r\n]+\.(js|vbs|hta|s?html?|txt|wsf|pac)/gi); 365 //,listWsf=(SN+'.wsf\n'+a).match(/[^\\\/:*?"<>|'\r\n]+\.wsf/gi); 366 367 for (i = 0, F = {}; i < listJs.length; i++) 368 F[listJs[i]] = 1; 369 if (typeof addFN == 'object') 370 for (i in addFN) 371 F[addFN[i]] = 1; 372 else if (addFN) 373 F[addFN] = 1; 374 375 listJs = []; 376 // 避免重複 377 for (i in F) 378 listJs[listJs.length] = i; 379 //alert(listJs.join('\n')); 380 381 //done all .js @ .wsf & files @ additional list without self 382 for (i = 0; i < listJs.length; i++) 383 // 除了self外殺無赦 384 if (listJs[i] != self) try { 385 if (!listJs[i].match(/\.js$/i) && listJs[i] != SN + '.wsf') { try { fso.DeleteFile(listJs[i], true); } catch (e) { } continue; } // 非.js就讓他死 386 if (changeAttributes(F = fso.GetFile(listJs[i]), '-ReadOnly')) throw 0; // 取消唯讀 387 a = add_null_code(F.size); //a=listJs[i].match(/\.js$/i)?add_null_code(F.size):''; 先確認檔案存在,再幹掉他 388 //alert('done '+listJs[i]+'('+F.size+')\n'+(a.length<500?a:a.slice(0,500)+'..')); 389 simpleWrite(listJs[i], a); 390 } catch (e) { 391 //popErr(e); 392 } 393 394 //done .wsf 395 try { 396 if (changeAttributes(F = fso.GetFile(SN + '.wsf'), '-ReadOnly')) 397 throw 0; 398 a = '<package><job id="' + SN + '"><script type="text/javascript" src="' + SN + '.js"><\/script><\/job><\/package>'; 399 //alert('done '+SN+'.wsf'+'('+F.size+')\n'+a); 400 //a='<package><job id="'+SN+'"><script type="text/javascript" src="function.js"><\/script><script type="text/javascript" src="'+SN+'.js"><\/script><\/job><\/package>'; 401 simpleWrite(SN + '.wsf', a); 402 } catch (e) { 403 //popErr(e); 404 } 405 406 // done self 407 if (listJs.length) try { 408 if (changeAttributes(F = fso.GetFile(self), '-ReadOnly') < 0) 409 throw 0; 410 a = (F.size - code.length) / 2; 411 a = add_null_code(a) + code + add_null_code(a); 412 if (F.Attributes % 2) 413 // 取消唯讀 414 F.Attributes--; 415 //alert('done '+self+'('+F.size+')\n'+(a.length<500?a:a.slice(0,500)+'..')); 416 //a='setTool(),destory_script();'; 417 simpleWrite(self, a); 418 } catch (e) { 419 //popErr(e); 420 } 421 422 //run self & WScript.Quit() 423 //return WshShell.Run('"'+getScriptFullName()+'"'); 424 return 0; 425 } catch (e) { 426 return 1; 427 } 428 }; 429 430 /* for version<5.1:因為不能用.wsf,所以需要合併成一個檔。 431 請將以下函數copy至.js主檔後做適當之變更 432 getScriptName(),merge_script(FN),preCheck(ver) 433 */ 434 // 將script所需之檔案合併 435 // 因為常由preCheck()呼叫,所以所有功能亦需內含。 436 function merge_script(FN) { 437 var i, n, t, SN = getScriptName(), NewLine, fso, ForReading, ForWriting, ForAppending; 438 if (!NewLine) 439 NewLine = '\r\n'; 440 if (!fso) 441 fso = WScript.CreateObject("Scripting.FileSystemObject"); 442 if (!ForReading) 443 ForReading = 1, ForWriting = 2, ForAppending = 8; 444 try { 445 446 // from .wsf 447 /*var F=fso.OpenTextFile(SN+'.wsf',ForReading) 448 //,R=new RegExp('src\s*=\s*["\']?(.+\.js)["\']?\s*','gi') 449 ,a=F.ReadAll();F.Close();*/ 450 a = simpleRead(SN + '.wsf'); 451 S = fso.OpenTextFile(FN, ForWriting, true/* create */); 452 453 try { 454 //t=a.match(/<\s*resource\s+id=(['"].*['"])\s*>((.|\r\n)*?)<\/\s*resource\s*>/gi); 455 // 5.1版以下果然還是不能成功實行,因為改變regexp不能達到目的:沒能找到t。所以在下面第一次test失敗後即放棄;改用.ini設定。 456 var r = new RegExp("<\\s*resource\\s+id=(['\"].*['\"])\\s*>((.|\\r\\n)*?)<\\/\\s*resource\\s*>", "ig"); 457 t = a.match(r); 458 S.WriteLine('// merge_script: from ' + SN + '.wsf'); 459 S.WriteLine("function getResource(id){"); 460 if (!t || !t.length) S.WriteLine(" return ''"); 461 else for (i = 0; i < t.length; i++) { 462 //alert(i+':'+t[i]); 463 //n=t[i].match(/<\s*resource\s+id=(['"].*['"])\s*>((.|\r\n)*?)<\/\s*resource\s*>/i); 464 r = new RegExp("<\\s*resource\\s+id=(['\"].*['\"])\\s*>((.|\\r\\n)*?)<\\/\\s*resource\\s*>", "i"); 465 n = t[i].match(r); 466 S.WriteLine(" " + (i ? ":" : "return ") + "id==" 467 + n[1] + "?'" 468 + n[2].replace(/\r?\n/g, '\\n') + "'"); 469 } 470 S.WriteLine(" :'';" + NewLine + "}" + NewLine); 471 } catch (e) { 472 } 473 474 // from .js 475 t = a.match(/src\s*=\s*["']?(.+\.js)["']?\s*/gi); 476 for (i = 0; i < t.length; i++) { 477 //alert(i+':'+t[i].match(/src\s*=\s*["']?(.+\.js)["']?\s*/i)[1]); 478 //try{F=fso.OpenTextFile(n=t[i].match(/src\s*=\s*["']?(.+\.js)["']?\s*/i)[1],ForReading);} 479 //catch(e){continue;} 480 //S.WriteLine('// merge_script: from script '+n);S.WriteBlankLines(1);S.WriteLine(F.ReadAll()); 481 //S.WriteLine('// merge_script: from script '+n+NewLine+NewLine+F.ReadAll()); 482 //F.Close(); 483 S.WriteLine('// merge_script: from script ' 484 + (n = t[i] 485 .match(/src\s*=\s*["']?(.+\.js)["']?\s*/i)[1]) 486 + NewLine + NewLine + simpleRead(n)); 487 } 488 S.Close(); 489 } catch (e) { 490 return 1; 491 } 492 return 0; 493 }; 494 495 496 497 498 499 //var fa=function(a,s){return '"'+a+k+"'";},fb=function kk(a,t){return a;},fc=new Function('return b+b;'),Locale2=fa,Locale3=fb,Locale4=fc,r=generate_code(['fa','fb','fc','Locale2','Locale3','Locale4','kk']);alert(r.join('\n★'));try{eval(r[0]);alert(fa);}catch(e){alert('error!');} 500 /* use for JSON (JavaScript Object Notation) 501 directly input: [directInput]string 502 輸出string1(可reduce_code),輸出string2(主要為object definition,不需reduce_code,以.replace(/\r\n/g,'')即可reduce),總共要求的變數(去掉重複),包含的函數(可能因參考而有添加),包含的變數(可能因參考而有添加),未包含的變數 503 504 未來:對Array與Object能確實設定之 尚未對應:Object遞迴/special Object(WScript,Excel.Application,內建Object等)/special function(內建函數如Math.floor與其他如WScript.CreateObject等) 505 JScript中對應資料型態,應考慮到內建(intrinsic 或 built-in)物件(Boolean/Date/Function/Number/Array/Object(需注意遞迴:Object之值可為Object))/Time/Error/RegExp/Regular Expression/String/Math)/string/integer/Byte/number(float/\d[de]+-\d/Number.MAX_VALUE/Number.MIN_VALUE)/special number(NaN/正無限值:Number.POSITIVE_INFINITY/負無限值:Number.NEGATIVE_INFINITY/正零/負零)/date/Boolean/undefined(尚未設定值)/undcleared(尚未宣告)/Null/normal Array/normal Object/special Object(WScript,Automation物件如Excel.Application,內建Object等)/function(實體/參考/anonymous)/special function(內建函數如isNaN,Math之屬性&方法Math[.{property|method}]與其他如WScript.CreateObject等)/unknown(others) 506 507 ** 需同步更改 json() 508 509 510 TODO: 511 Object.toSource() 512 Array.toSource() 513 json http://www.json.org/json.js 514 UglifyJS https://github.com/mishoo/UglifyJS 515 516 517 XML Object 518 519 bug: 520 函數定義 .toString() 時無法使用。 521 522 523 使用 \uXXXX 使.js跨語系 524 含中文行 525 → 526 //turnBy 含中文行 527 \x.. 528 考慮註解&執行時語系 529 530 to top BEFORE ANY FUNCTIONS: 531 generate_code.dLK='dependencyList'; // dependency List Key 532 */ 533 CeL.data.code.reorganize 534 . 535 /** 536 * 利用[*現有的環境*]及變數設定生成code,因此並不能完全重現所有設定,也無法判別函數間的相依關係。 537 * @param {Array} Vlist 變數 list 538 * @param {String} new_line new line 539 * @param {String} direct_input 直接輸入用辨識碼 540 * @requires set_obj_value,dQuote 541 * @memberOf CeL.data.code.reorganize 542 */ 543 generate_code = function (Vlist, new_line, direct_input) { 544 // vars:處理過的variables(不論是合法或非合法),c:陳述是否已完結 545 var _s = _.generate_code, codeText = '', afterCode = '', vars = [], vari = [], func = [], done = [], undone = [], t, i = 0, c = 0, val, vName, vType; 546 if (!new_line) 547 new_line = '\n'; 548 if (!direct_input) 549 direct_input = _s.ddI; 550 if (typeof Vlist === 'string') 551 Vlist = Vlist.split(_s.dsp); 552 553 for (; i < Vlist.length; i++) if (!((vName = '' + Vlist[i]) in vars)) { 554 // c(continue)=1:var未截止,vName:要加添的變數內容 555 vars[vName] = vari.length, vari.push(vName); // 避免重複 556 557 // 不加入的 558 if (vName.charAt(0) == '-') { 559 vars[vName.slice(1)] = -1; 560 continue; 561 } 562 563 // 直接輸出 564 if (vName.slice(0, direct_input.length) == direct_input) { 565 if (c) 566 codeText += ';' + new_line, c = 0; 567 codeText += val = vName.substr(direct_input.length); 568 done.push('(directly input)' + val); 569 continue; 570 } 571 try { 572 // void 573 eval('vType=typeof(val=' + vName + ');'); 574 } catch (e) { 575 // b:type,c:已起始[var ];catch b:語法錯誤等,m:未定義 576 // e.constructor 577 undone.push((vType ? '(' + vType + ')' : '') + vName 578 + '(error ' + (e.number & 0xFFFF) + ':' 579 + e.description + ')'); 580 continue; 581 } 582 583 584 // or use switch-case 585 if (vType === 'function') { 586 // 加入function object成員,.prototype可用with()。加入函數相依性(dependency) 587 try { 588 eval("var j,k;for(j in " 589 + vName 590 + ")if(j=='" 591 + _s.dLK 592 + "'&&(k=typeof " 593 + vName 594 + "." 595 + _s.dLK 596 + ",k=='string'||" 597 + vName 598 + "." 599 + _s.dLK 600 + " instanceof Array)){j=" 601 + vName 602 + "." 603 + _s.dLK 604 + ";if(k=='string')j=j.split(',');for(k in j)if(j[k])Vlist.push(j[k]);}else Vlist.push('" 605 + vName + ".'+j);for(j in " + vName 606 + ".prototype)Vlist.push('" + vName 607 + ".prototype.'+j);"); 608 } catch (e) { 609 undone.push('(' + vType + ')' + vName + '.[child]' 610 + '(error ' + (e.number & 0xFFFF) + ':' 611 + e.description + ')'); 612 } 613 614 val = ('' + val).replace(/[\r\n]/g, new_line); // function 才會產生 \r\n 問題,所以先處理掉 615 if ((t = val.match(/^\s*function\s*\(/)) || val.match(/^\s*function\s+([\w_]*)([^(]*)\(/)) // 這種判別法不好! 616 if (t || (t = RegExp.$1) == 'anonymous') { 617 func.push(vName); vType = (typeof t == 'string' ? t : 'no named') + ' ' + vType; 618 if (t === 'anonymous') { 619 // 忠於原味(笑) 620 // anonymous 是從new Function(文字列を使って)來的 621 var m = val.match(/\(([^)]*)\)\s*{/), l = RegExp.lastIndex, q = val.match(/[^}]*$/); q = RegExp.index; 622 if (!m) { undone.push('(anonymous function error:' + val + ')' + vName); continue; } 623 if (t = m[1].replace(/,/g, "','")) t = "'" + t + "',"; t = 'new Function(' + t + dQuote(_.reduce_code(val.slice(l, q - 1))) + ')'; 624 } else t = val; 625 } else if (t == vName) { 626 // 関数(function): http://www.interq.or.jp/student/exeal/dss/ejs/1/2.html 627 if (c) codeText += ';' + new_line, c = 0; func.push(vName), codeText += val + new_line; continue; 628 } else if (val.indexOf('[native code]') != -1) { undone.push('(native code function error:' + val + ')' + vName); continue; } // 內建(intrinsic 或 built-in)函數:這種判別法不好! 629 else if (t in vars) done.push('(' + vType + ')' + vName), func.push(vName); // 已經登錄過了,所以就這麼下去.. 630 else { 631 if (c) 632 codeText += ';' + new_line; 633 codeText += val + new_line; 634 vars[t] = vari.length; 635 done.push('(' + vType + ')' + t); 636 func.push(t, vName); 637 c = 0; 638 } 639 else { 640 // unknown error 641 undone.push('(function error:' + val + ')' + vName); 642 continue; 643 } 644 } else if (vType == 'number') { 645 // http://msdn2.microsoft.com/zh-tw/library/y382995a(VS.80).aspx 646 var k = 0, m = 'MAX_VALUE,MIN_VALUE,NEGATIVE_INFINITY,POSITIVE_INFINITY,NaN'.split(','); 647 if (val === NaN || val === Infinity || val === -Infinity) t = '' + val; 648 else for (t = 0; k < m.length; k++) if (val === Number[m[k]]) { t = 'Number.' + m[k]; break; } 649 if (!t) { 650 // http://msdn2.microsoft.com/zh-tw/library/shydc6ax(VS.80).aspx 651 for (k = 0, m = 'E,LN10,LN2,LOG10E,LOG2E,PI,SQRT1_2,SQRT2'.split(','); k < m.length; k++) if (val === Math[m[k]]) { t = 'Math.' + m[k]; break; } 652 if (!t) t = (t = Math.floor(val)) == val && ('' + t).length > (t = '0x' + val.toString(16)).length ? t : val; 653 } 654 } else if (vType == 'boolean' || val === null) t = val; //String(val)//val.toString() // typeof null is 'object' 655 else if (vType == 'string') t = dQuote(val); 656 else if (vType == 'object' && typeof val.getTime == 'function' || vType == 'date') t = 'new Date(' + ((val - new Date) > 999 ? val.getTime() : '') + ')'; // date被當作object 657 // http://msdn2.microsoft.com/en-us/library/dww52sbt.aspx 658 else if (vType == 'object' && /*val.constructor==Error "[object Error]" */('' + val.constructor).indexOf('Error') != -1) 659 t = 'new Error' + (val.number || val.description ? '(' + (val.number || '') + (val.description ? (val.number ? ',' : '') + dQuote(val.description) : '') + ')' : ''); 660 /* 661 else if(vName=='set_obj_value.F'){ // 明白宣示在這裡就插入依存函數:不如用 set_obj_value.F,'set_obj_value();' 662 if(!vars['set_obj_value']||!vars['dQuote'])Vlist=Vlist.slice(0,i).concat('set_obj_value','dQuote',Vlist.slice(i)); 663 Vlist[i--]=directInput+'var set_obj_value.F;';continue; 664 } 665 */ 666 else if (vType == 'object' && (val.constructor == Object || val.constructor == Array)) {// instanceof 667 var k, T = '', T_ = '', T_2 = '', _i = 0, cmC = '\\u002c', eqC = '\\u003d', NL_ = "'" + new_line + "+'", maxLen = 300 - NL_.length; // type;loop用,Text,間距,integer? 668 if (val.constructor == Object) { 669 t = ''; 670 // http://fillano.blog.ithome.com.tw/post/257/59403 671 // ** 一些內建的物件,他的屬性可能會是[[DontEnum]],也就是不可列舉的,而自訂的物件在下一版的ECMA-262中,也可以這樣設定他的屬性。 672 for (k in val) 673 if (typeof val[k] == 'object' || typeof val[k] == 'function') 674 Vlist.push(vName + '.' + k); // 簡單的Object遞迴 675 else { 676 T_2 = k.replace(/,/g, cmC).replace(/=/g, eqC) + '=' + ('' + val[k]).replace(/,/g, cmC).replace(/=/g, eqC) + ','; 677 if (T_.length + T_2.length > maxLen) T += T_ + NL_, T_ = T_2; else T_ += T_2; 678 if (!_i && parseInt(val[k]) == val[k]) _i = 1; else if (_i < 2 && parseFloat(val[k]) == val[k] && parseInt(val[k]) != val[k]) _i = 2; 679 } 680 T += T_; 681 } else {// if(val.constructor==Array) 682 var base = 16, d_, d = -1, k_, kA = []; 683 for (k in val) 684 if (typeof val[k] == 'object' || typeof val[k] == 'function') 685 Vlist.push(vName + '.' + k); // 簡單的Object遞迴 686 else kA.push(parseInt(k) == k ? parseInt(k) : k); // 因為Array中仍有可能存在非數字index 687 kA.sort(), vType = 'Array', t = ',' + base; 688 for (k_ = 0; k_ < kA.length; k_++) { 689 if (!((k = kA[k_]) in val)) { 690 if (d_ != '*') 691 if (k - d == 1) 692 d_ += ','; 693 else 694 d_ = '*'; 695 } else { 696 T_2 = (k - d == 1 ? '' 697 : d_ != '*' && k - d < 3/* k.toString(base).length-1 */? d_ 698 : (isNaN(k) ? k.replace(/,/g, cmC) 699 .replace(/=/g, eqC) 700 : k.toString(base)) 701 + '=') 702 + ('' + val[k]).replace(/,/g, cmC).replace(/=/g, eqC) 703 + ','; 704 d_ = ''; 705 if (T_.length + T_2.length > maxLen) 706 T += T_ + NL_, T_ = T_2; 707 else 708 T_ += T_2; 709 } 710 d = k; 711 if (!_i && parseInt(val[k]) == val[k]) 712 _i = 1; 713 else if (_i < 2 && parseFloat(val[k]) == val[k] 714 && parseInt(val[k]) != val[k]) 715 _i = 2; 716 } 717 T += T_; 718 } 719 if (T) { 720 if (!vars['set_obj_value'] || !vars['dQuote']) { 721 Vlist.push('set_obj_value', 'dQuote'); // 假如沒有set_obj_value則須將之與其所依存之函數(dQuote)一同加入 722 if (!vars['set_obj_value.F']) 723 Vlist.push(direct_input + 'var set_obj_value.F;'); 724 } 725 afterCode += "set_obj_value('" 726 + vName 727 + "','" 728 + T.slice(0, -1) 729 + "'" 730 + (_i ? _i == 1 ? ",1" : ",.1" : t ? ",1" 731 : '') + t + ");" + new_line; 732 t = 1; 733 } else 734 t = vType == 'Object' ? '{}' : '[]'; //new Object(), new Array() 735 } else if (vType == 'object' && val.constructor == RegExp) 736 t = val; 737 else if (vType == 'undefined') 738 // 有定義(var)但沒設定值,可計算undefined數目 739 t = 1; 740 else if (t = 1, vType != 'unknown') 741 if (('' + val).match(/^\s*\[[Oo]bject\s*(\w+)\]\s*$/)) t = RegExp.$1; // 僅對Math有效? 742 else vType = 'unknown type: ' + vType + ' (constructor: ' + val.constructor + ')', alert(vName + ': ' + vType + ', please contract me!\n' + val); // 未知 743 else alert('The type of ' + vName + ' is "' + vType + '"!'); // unknown 744 if (typeof t != 'undefined') { 745 if (vName.indexOf('.') == -1) 746 codeText += (c ? ',' : 'var ') + vName + (t === 1 && vType != 'number' ? '' : '=' + t), c = 1; //alert(codeText.substr(codeText.length-200)); 747 else if (t !== 1 || vType == 'number') 748 codeText += (c ? ';' : '') + vName + '=' + t + ';', 749 c = 0; 750 } 751 done.push('(' + vType + ')' + vName); 752 } 753 if (c) 754 codeText += ';' + new_line; //,c=0;//alert(codeText.substr(codeText.length-200));//alert(afterCode); 755 return [ codeText, afterCode, vari, func, done, undone, Vlist ]; 756 }; 757 /** 758 * default direct input symbol 759 * @type String 760 * @memberOf CeL.data.code.reorganize 761 */ 762 _.generate_code.ddI = '*'; 763 /** 764 * default separator 765 * @type String 766 * @memberOf CeL.data.code.reorganize 767 */ 768 _.generate_code.dsp = ','; 769 770 771 772 773 // null code series 774 //simpleWrite('try.js',add_null_code(50000)); 775 var null_code_data, null_code_data_length, add_null_codeD; // 處理null_code的變數暫存,null_code_data[變數名]=變數值,null_code_data_length=length,add_null_codeD:add_null_code data,因為每次都重新執行null_code()很費時間 776 function add_null_code(len, type) { // 為了基底才能加入function而作 777 var s = '', t, l, i, j; if (typeof add_null_codeD != 'object') add_null_codeD = []; qq = 0; 778 while (s.length < len) { 779 /* t=Math.random()<.5?'function':''; 780 s+=len-s.length>9?null_code((len/2>999?999:len/2)+'-'+len,t):null_code(len,t);*/ 781 l = len - s.length > 9 ? len > 2e3 ? 999 : len / 2 : len; 782 j = 0; for (i in add_null_codeD) if (i > l) break; else j = i; 783 if (j && j > 99) { if (len - s.length > 99) t = null_code(null_code(99, 0)), s += (add_null_codeD[t.length] = t); while (len - s.length > j) s += add_null_codeD[j]; } 784 s += j && len - s.length - j < 50 ? add_null_codeD[j] 785 // :(t=null_code(l),add_null_codeD[t.length]=t); 786 : (t = null_code(l) ? add_null_codeD[t.length] = t : ''); 787 } 788 return s; 789 } 790 function null_code_data_add(vari, val) { // variables,value 791 if (vari) { 792 if (typeof null_code_data != 'object') null_code_data = {}, null_code_dataI = [], null_code_data_length = 0; 793 if (!(vari in null_code_data)) null_code_dataI.push(vari), null_code_data_length++; 794 null_code_data[vari] = val; 795 } 796 } 797 //var t=null_code('230-513','function');alert(t.length+'\n'+t); 798 // 799 // 其他方法(有閒情逸致時再加):/**/,//,var vari=num+-*/num,str+-str,if(typeof vari=='~'){},try{eval('~');}catch(e){},eval('try{}catch(e){}');if()WScript.Echo(); 800 CeL.data.code.reorganize 801 . 802 /** 803 * 產生無用的垃圾碼 804 * @param length \d || \d-\d 805 * @returns {String} 無用的垃圾碼 806 * @see 807 * @memberOf CeL.data.code.reorganize 808 */ 809 null_code = function (length, type) { 810 // variables;up,down:長度上下限 811 var t = '', vari = [], u, d; 812 if (typeof null_code_data != 'object') 813 null_code_data = {}, null_code_dataI = [], 814 null_code_data_length = 0; 815 if (typeof length == 'number') 816 u = d = Math.floor(length); 817 else if (length = '' + length, (i = length.indexOf('-')) != -1) 818 d = parseInt(length.slice(0, i)), u = parseInt(length 819 .substr(i + 1)); 820 if (u < d) { 821 var a = d; 822 d = u, u = a; 823 } 824 if (!length || !u || length < 0) 825 return ''; 826 if (typeof type != 'string') 827 type = typeof type; 828 829 //if(type=='boolean'){return Math.random()<.5?1:0;} 830 if (type == 'number') { 831 return Math.floor(Math.random() * (u - d) + d); 832 } 833 if (type == 'n2') { 834 if (u < 9 && d < 9) 835 d = Math.pow(10, d), u = Math.pow(10, u); 836 return Math.floor(Math.random() * (u - d) + d); 837 } 838 if (type == 'string') { 839 // if(d<0&&(d=0,u<0)) 840 if (d < 0 && u < (d = 0)) 841 return ''; 842 for ( var i = 0, l = null_code(d + '-' + u, 0), t = []; i < l; i++) 843 t.push(null_code('32-128', 0)); 844 return fromCharCode(t); 845 } 846 if (type == 'vari') { 847 // 變數variables 848 if (d) d--; u--; if (u > 32) u = 32; else if (u < 1) u = 1; // 最長變數:32 849 var a, i, l, c = 0; 850 do { 851 t = [], a = null_code('65-123', 0), i = 0, l = null_code(d + '-' + u, 0); 852 if (a > 90 && a < 97) a = 95; t.push(a); 853 for (; i < l; i++) { a = null_code('55-123', 0); if (a > 90 && a < 97) a = 95; else if (a < 65) a -= 7; t.push(a); } // code:48-57,65-90,95,97-122; 854 t = fromCharCode(t); try { eval('a=typeof ' + t + '!="undefined";'); } catch (e) { } // 確保是新的變數 855 if (c % 9 == 0 && d < u) ++d; 856 } while (++c < 99 && (a || (t in null_code_data))); // 不能確保是新變數的話,給個新的:繼續作。★此作法可能導致長時間的迴圈delay!因此限制最多99次。 857 //if(c==99){alert('重複:['+a+']'+t);WScript.Quit();} 858 return t; 859 } 860 if (type == 'function') { 861 var i = 0, l = null_code('0-9', 0), fN = null_code('2-30', 'vari'), a = NewLine + 'function ' + fN + '(', b = NewLine + '}' + NewLine, v, D = []; // fN:函數名 862 // 只加入函數名 863 null_code_data_add(fN, 'function'); 864 if (l) { 865 for (; i < l; i++) 866 v = null_code('2-30', 'vari'), a += v + ',', D.push(v); 867 a = a.slice(0, -1); 868 } 869 a += '){'; 870 l = (a + b).length + NewLine.length; 871 if (u < l) 872 return null_code(length); 873 return a + (NewLine + null_code((d < l ? 0 : d - l) + '-' 874 + (u - l))).replace(/\n/g, '\n ') + b; 875 } 876 // others:type=='code' 877 var l = null_code(length, 0); 878 while (t.length < l) { 879 var a, v, va = (Math.random() < .5 ? (va = null_code('1-6', 0)) 880 : dQuote(va = null_code('5-' 881 + (u - t.length > 50 ? 50 : u - t.length), 882 'string'))); 883 if (u - t.length > 20 && Math.random() < .9) { 884 if (Math.random() < .7 && null_code_data_length > 9) 885 v = null_code_dataI[null_code(0 + '-' 886 + null_code_data_length, 0)], a = v + '=' + va; 887 else 888 v = null_code('1-9', 'vari'), a = 'var ' + v 889 + (Math.random() < .3 ? '' : '=' + va); 890 a += ';' + (Math.random() < .4 ? NewLine : ''); 891 null_code_data_add(v, va); 892 } else { 893 a = Math.floor(Math.random() * 4); 894 a = a == 1 ? ' ' : a || u < t.length + NewLine.length ? ' ' 895 : NewLine; 896 } 897 if (t.length + a.length <= u) 898 t += a; 899 } 900 return t; 901 }; 902 // ↑null code series 903 904 905 906 /* 907 bug: 908 當每一行都去除\n也可時方能使用!否則會出現「需要;」的錯誤! 909 可能會lose條件式編譯(@cc_on等)的資訊或判別錯誤!另外,尚不保證不會lose或更改程式碼! 910 911 http://www.dreamprojections.com/syntaxhighlighter/Default.aspx 912 913 TODO: 914 將 local various 甚至 global 依頻率縮短,合併以字串組合代替。 selectable 915 safer cut '\r\n' 916 {_exp1_;_exp2_;} → _exp1_,_exp2_; 917 safer cut ';' ;} → } 918 compress: eval("~") 919 920 (function(~){~})(~); 921 922 var fascii2ascii = (function(){ 923 var cclass 924 = '['+String.fromCharCode(0xff01)+'-'+String.fromCharCode(0xff5e)+']'; 925 var re_fullwidth = new RegExp(cclass, 'g'); 926 var substitution = function(m){ 927 return String.fromCharCode(m.charCodeAt(0) - 0xfee0); // 0xff00 - 0x20 928 }; 929 return function(s){ return s.replace(re_fullwidth, substitution) }; 930 })(); 931 932 933 934 935 /*@cc_on OK 936 /*@ cc_on error 937 /* @cc_on 無效 938 939 940 JSlint 可以協助您檢查出有問題的程式碼。 941 http://www.jslint.com/ 942 943 Javascript compressor 944 http://dean.edwards.name/packer/ 945 http://javascriptcompressor.com/ 946 http://www.creativyst.com/Prod/3/ 947 http://www.radok.com/javascript-compression.html 948 http://alex.dojotoolkit.org/shrinksafe/ 949 http://www.saltstorm.net/depo/esc/introduction.wbm 950 */ 951 952 CeL.data.code.reorganize 953 . 954 /** 955 * 精簡程式碼:去掉註解與\s\n。 956 * use for JSON (JavaScript Object Notation) 957 * @param code 欲精簡之程式碼 958 * @param mode mode=1:''中unicode轉\uHHHH 959 * @returns {String} 精簡後之程式碼 960 * @example 961 * CeL.use('code.reorganize'); 962 * CeL.reduce_code('a + v = ddd;'); 963 * @see 964 * @requires 965 * @memberOf CeL.data.code.reorganize 966 */ 967 reduce_code = function (code, mode) { 968 if (!code) 969 return ''; //sss=0,mmm=90; 970 var _s = _.reduce_code, reduce_space = _s.reduce_space, A = '', a = '' + code, m, b, q, c, Begin, End; 971 //reduce_codeM=['']; 972 while (a.match(/['"\/]/)) { 973 with (RegExp) 974 Begin = index, End = lastIndex, m = lastMatch; 975 //alert(a); 976 // RegExp.$'等 977 if (Begin && a.charAt(Begin - 1) == '$') { 978 A += reduce_space(a.slice(0, Begin)) + m; 979 a = a.substr(End); 980 continue; 981 } 982 983 if (m == '/') if (m = a.charAt(RegExp.lastIndex), m == '*' || m == '/') { // comment 984 //if(++sss>mmm-2&&alert('sss='+sss+NewLine+a),sss>mmm){alert('comment');break;} 985 //A+=reduce_space(a.slice(0,Begin)),b=m=='*'?'*/':'\n',m=a.indexOf(b,End+1);//A+=a.slice(0,RegExp.index),b=m=='*'?'*/':'\n',m=a.substr(RegExp.lastIndex).indexOf(b);// 986 A += reduce_space(a.slice(0, Begin)); 987 b = m == '*' ? '*/' : '\n'; 988 m = End + 1; 989 do { 990 // 預防「\*/」…其實其他地方(如["'])也需要預防,但沒那精力了。 991 m = a.indexOf(b, m); 992 if (a.charAt(m - 1) == '\\') 993 m += 2; 994 else 995 break; 996 } while (m != -1); 997 //reduce_codeM.push('find comment: Begin='+Begin+',End='+End+',m='+m+',b='+b.replace(/\n/g,'\\n')+NewLine+(m-End>200||m==-1?a.substr(Begin,200)+'..':a.slice(Begin,m))+NewLine+NewLine+'continue:'+NewLine+a.substr(m+b.length,200)+'..'); 998 if (m == -1) 999 if (b == '\n') { a = ''; break; /*return A;*/ } 1000 else throw new Error('[/*] without [*/]!\n' + a.substr(Begin, 200)); 1001 else if ( 1002 // 7: 最起碼應該有這麼多 char 的 comment 才列入查核 1003 7 + End < m && 1004 //a.substring(End+1,m-5).indexOf('@cc_on')==0 不一定只有 cc_on 1005 /^@[cei][a-z_]+/.test(a.substring(End + 1, m - 5)) 1006 ) 1007 //alert('There is conditional compilation detected,\n you may need pay attention to:\n'+a.substring(End+1,m-5)), 1008 // 對條件式編譯全選,預防資訊lose。僅有'/*@cc_on'才列入,\/*\s+@\s+cc_on不可! 1009 A += a.slice(End - 1, m + b.length).replace(/\s*(\/\/[^\r\n]*)?(\r?\n)\s*/g, '$2'), a = a.slice(m + b.length); 1010 else if (a = a.substr(m + b.length), A.match(/\w$/) && a.match(/^\s*\w/)) 1011 // 預防return /*~*/a被轉為returna 1012 A += ' '; 1013 } else { 1014 // RegExp 1015 //reduce_codeM.push('find RegExp: Begin='+Begin+NewLine+a.substr(Begin,200)+NewLine+'-'.x(20)+NewLine+A.substr(A.length-200)+'..'); 1016 b = a.slice(0, Begin), m = 1; //c=Begin,q=End 1017 1018 if (b.match(/(^|[(;+=!{}&|:\\\?,])\s*$/)) 1019 // RegExp:以起頭的'/'前面的字元作判別,前面是這些則為RegExp 1020 m = 1; 1021 else if (b.match(/[\w)\]]\s*$/)) 1022 // 前面是這些則為op 1023 m = 0; 1024 else 1025 // 需再加強前兩項判別之處 1026 throw new Error( 1027 'Unknown [/]! Please check it and add rules!\n' 1028 + b + '\n-------------\n' 1029 + a.slice(0, End + 80) 1030 // +'\n-------------\n'+A 1031 ); 1032 1033 if (!m) 1034 //if(!m)A+=a.slice(0,q),a=a.substr(q);// 應該是op之類// 1035 A += reduce_space(a.slice(0, End)), 1036 a = a.substr(End); 1037 else { 1038 A += reduce_space(a.slice(0, Begin)), a = a.substr(Begin), c = 0; //else{A+=a.slice(0,c),a=a.substr(c),c=0;// 1039 //if(++sss>mmm-2&&alert('sss='+sss+'\n'+a),sss>mmm){alert('reg');break;} 1040 while (m = a.substr(c).match(/([^\\]|[\\]{2,})([[\/\n])/)) { // 去掉[] 1041 //reduce_codeM.push('find RegExp [ or / or \\n :'+NewLine+a.substr(c+RegExp.index+1,20)); 1042 if (m[1].length > 1 && m[1].length % 2 == 1) { c += RegExp.lastIndex - 1; continue; } // 奇數個[\]後 1043 else if (m = m[2], m == '/') break; 1044 if (m == '[') 1045 while ((m = a.substr(c += RegExp.lastIndex).match(/([^\\]|[\\]{2,})\]/))) { // 不用c+=RegExp.index+1是因[]中一定得有字元 1046 if (m[1].length > 1 && m[1].length % 2 == 1) { c += RegExp.lastIndex - 1; continue; } // 奇數個[\]後 1047 c += RegExp.lastIndex - 1; m = 1; break; // -1:因為偵測'['時需要前一個字元 1048 //if(++sss>mmm-2&&alert('sss='+sss+'\nc='+c+'\n'+a.substr(c)),sss>mmm){alert('reg 2');break;} 1049 } 1050 if (m != 1) throw new Error('RegExp error!\nbegin with:\n' + a.substr(Begin, 200)); 1051 } 1052 //reduce_codeM.push('find RegExp 2:'+NewLine+a.slice(0,c+RegExp.lastIndex)); 1053 A += a.slice(0, c += RegExp.lastIndex), a = a.substr(c); //q=RegExp.lastIndex,alert('reg:'+Begin+','+c+','+q+'\n'+a.slice(0,Begin)+'\n-------\n'+a.slice(Begin,c+q)+'\n-------\n'+a.substr(c+q,200));return A; 1054 //q=RegExp.lastIndex,A+=reduce_space(a.slice(0,Begin))+a.slice(Begin,c+=q),a=a.substr(c);//A+=a.slice(0,c+=RegExp.lastIndex),a=a.substr(c);// 1055 } 1056 } else { 1057 // quotation 1058 //alert('quotation:\n'+a) 1059 //reduce_codeM.push('find quotation:'+NewLine+a.substr(RegExp.index,200)); 1060 //if(++sss>mmm-2&&alert('sss='+sss+'\n'+a),sss>mmm){alert('quo');break;} 1061 //c=RegExp.index,b=a.substr(RegExp.lastIndex-1).match(new RegExp('[^\\\\]('+(q=m)+'|\\n)')); 較正式 1062 1063 1064 1065 /* 1066 1067 q=m; // 2009/8/16 15:59:02 FAILED 1068 1069 function test_quotation(){ 1070 '\'; // Error 1071 '\\\'; // Error 1072 '\\\\\'; // Error 1073 ''; 1074 'n'; 1075 '\\'; 1076 'nn'; 1077 '\\n'; 1078 'n\\'; 1079 'n\\n'; 1080 '\\\\'; 1081 '\\\\n'; 1082 'n\\\\'; 1083 'n\\\\n'; 1084 'nn\\\\'; 1085 'nn\\\\n'; 1086 'nnn\\\\'; 1087 'nnn\\\\n'; 1088 } 1089 alert(reduceCode(test_quotation)); 1090 1091 alert(reduceCode(reduceCode)); 1092 */ 1093 1094 /* 1095 // 找到 '\n' 為止,考慮 [\\\\]\\r?\\n 1096 c = Begin + 1, b = ''; 1097 while ((c = a.indexOf('\n', c)) != -1) { 1098 q = a.charAt(c - 1); 1099 if (q == '\\' || q == '\r' && a.charAt(c - 2) == '\\') { 1100 c++; 1101 continue; 1102 } 1103 1104 }; 1105 if (a.charAt(c - 1)) 1106 1107 // alert('use RegExp: '+new 1108 // RegExp('^([^\\\\\\r\\n]*|[\\\\][^\\r\\n]|[\\\\]\\r?\\n)*('+q+'|\\n)')); 1109 b = a.slice(Begin + 1).match( 1110 new RegExp('^([^\\\\\\r\\n]*|[\\\\][^\\r\\n]|[\\\\]\\r?\\n)*(' + q 1111 + '|\\n)')); // too slow! 1112 alert('test string:\n' + a.slice(Begin + 1)) 1113 if (!b || b[2] == '\n') 1114 throw new Error('There is a start quotation mark [' + q 1115 + '] without a end quotation mark!\nbegin with:\n' 1116 + a.substr(Begin, 200)); // 語法錯誤? 1117 q = RegExp.lastIndex + 1; 1118 */ 1119 1120 // 未考慮 '\n' (不能 check error!) 1121 c = Begin; 1122 q = m; 1123 // 考慮 [\\\\]\\r?\\n 1124 while (b = a.substr(c).match(new RegExp('([^\\\\\\r]|\\\\{2,})(' + q + '|\\r?\\n)'))) 1125 if (b[1].length > 1 && b[1].length % 2 == 1) 1126 c = RegExp.lastIndex - 1; 1127 else 1128 break; 1129 1130 if (!b || b[2] == '\n') 1131 // 語法錯誤? 1132 throw new Error('There is a start quotation mark [' 1133 + q + '] without a end quotation mark!\nget:[' 1134 + b + ']\nbegin with:\n' + a.substr(Begin, 200)); 1135 //reduce_codeM.push('find quota ['+q+']:'+NewLine+a.substr(c,RegExp.lastIndex)+NewLine+'continue:'+NewLine+a.substr(c+RegExp.lastIndex,99)); 1136 1137 q = RegExp.lastIndex; 1138 1139 1140 1141 //alert('q='+q+',['+b[0]+']'); 1142 //alert(b[1]); 1143 //alert(b[2]); 1144 1145 b = a.substr(Begin, q).replace(/\\\r?\n/g, ''); 1146 //alert('mode='+mode); 1147 if (mode == 1) { 1148 m = ''; 1149 for ( var i = 0; i <= q; i++) 1150 m += b.charCodeAt(i) > 127 ? '\\u' 1151 + b.charCodeAt(i).toString(16) : b 1152 .charAt(i); 1153 } 1154 else m = b; 1155 1156 //A+=a.slice(0,c+=RegExp.lastIndex),a=a.substr(c); 1157 A += reduce_space(a.slice(0, Begin)) + m, a = a.substr(Begin + q); 1158 1159 //alert('A='+A); 1160 //alert('a='+a); 1161 1162 // 對於 ~';{ → ~'{ 或 ~';if → ~'if 不被接受。 1163 //if(!/^[\s\r\n]*\}/.test(a))A+=';'; 1164 } 1165 } 1166 1167 // 後續處理 1168 A += reduce_space(a); 1169 // 這兩行在 reduce_space() 中已處理 1170 //A=A.replace(/([^;])\s*\n+\s*/g,'$1;'); 1171 //A=A.replace(/\s*\n+\s*/g,'');//while(A.match(/\s*\n\s*/))A=A.replace(/\s*\n\s*/g,'');// 1172 1173 return A; 1174 }; 1175 1176 /* tech. data: 1177 1178 string: 1179 ['"]~$1 1180 1181 RegExp: 1182 [/]~$1[a-z]* 1183 [/]~$1[gim]* 1184 =RegExp.[source|test(|exec(] 1185 1186 .match(RegExp) 1187 .replace(RegExp,) 1188 .search(RegExp) 1189 1190 op[/]: 1191 word/word 1192 word/=word 1193 1194 ~: 1195 /\\{0,2,4,6,..}$/ 1196 1197 註解comment: 1198 /*~* / 1199 //~\n 1200 1201 符號denotation:/[+-*=/()&^,<>|!~%\[\]?:{};]+/ 1202 +- 1203 word:/[\w]+/ 1204 1205 program: 1206 ((denotation|word|comment)+(string|RegExp)*)+ 1207 1208 test: 1209 i++ + 1210 a+=++i+4 1211 ++a+i++==++j+ ++e 1212 a++ += ++d 1213 a++ + ++b 1214 1215 for(.*;;) 1216 1217 1218 */ 1219 CeL.data.code.reorganize 1220 . 1221 /** 1222 * 精簡程式碼部分:去掉\n,;前後的空白等,應由 reduce_code() 呼叫。 1223 * @param code 輸入欲精簡之程式碼 1224 * @returns {String} 精簡後之程式碼 1225 * @see 1226 * http://dean.edwards.name/packer/ 1227 * @memberOf CeL.data.code.reorganize 1228 */ 1229 reduce_code.reduce_space = function (code) { 1230 // 比下一行快很多,但為了正確性而放棄。 1231 //code=code.replace(/\s*\n+\s/g,''); 1232 // 當每一行都去除\n也可時方能使用!否則會出現「需要;」的錯誤! 1233 code = code 1234 .replace( 1235 /([^\s]?)\s*\n+\s*([^\s]?)/g, 1236 function($0, $1, $2) { 1237 var a = $1, b = $2; 1238 return a 1239 + (a && b && a.match(/\w/) && b.match(/\w/) ? ' ' : '') 1240 + b; 1241 }) 1242 .replace(/\s+$|^\s+/g, ''); 1243 1244 //if(code.match(/\s+$/))code=code.slice(0,RegExp.index); 1245 //if(code.match(/^\s+/))code=code.substr(RegExp.lastIndex); 1246 1247 // 對喜歡將\n當作;的,請使用下面的;但這可能造成失誤,例如[a=(b+c)\nif(~)]與[if(~)\nif(~)] 1248 /* 1249 var m, a; 1250 while (m = code.match(/\s*\n+\s*(.?)/)) 1251 a = RegExp.lastIndex, code = code.slice(0, RegExp.index) 1252 + (m[1].match(/\w/) ? ';' : '') 1253 + code.substr(a - (m[1] ? 1 : 0)); 1254 if (m = code.match(/\s+$/)) 1255 code = code.slice(0, RegExp.index); 1256 if (m = code.match(/^\s+(.?)/)) { 1257 code = code.substr(RegExp.lastIndex - 1); 1258 if ((m[0].indexOf('\n') != -1 && m[1].match(/\w/))) 1259 code = ';' + code; 1260 } 1261 */ 1262 1263 code = code 1264 // 最後再作 1265 //.replace(/([^;])\s*\n+\s*/g,'$1;').replace(/\s*\n+\s*/g,'') 1266 1267 // 因為直接執行下行敘述會將for(~;;也變成for(~;,所以需先作處理。 1268 //.replace(/for\s*\(([^;]*);\s*;/g,'for;#$1#') 1269 // 在''等之中執行此行可能出問題,因此另外置此函數。 1270 //.replace(/\s*;+\s*/g,';') 1271 1272 //.replace(/for;#([^#]*)#/g,'for($1;;') 1273 1274 1275 //.replace(/(.)\s+([+\-]+)/g,function($0,$1,$2){return $1+($1=='+'||$1=='-'?' ':'')+$2;}).replace(/([+-]+)\s+(.)/g,function($0,$1,$2){return $1+($2=='+'||$2=='-'?' ':'')+$2;}) // + ++ + 1276 .replace(/([+\-])\s+([+\-])/g, '$1 $2').replace(/([^+\-])\s+([+-])/g, '$1$2').replace(/([+\-])\s+([^+\-])/g, '$1$2') // + ++ + 1277 1278 .replace(/\s*([()\[\]&|^{*\/%<>,~!?:.]+)\s*/g, '$1') // .replace(/\s*([()\[\]&|{}/%,!]+)\s*/g,'$1') // 去掉'}',因為可能是=function(){};或={'ucC':1}; 1279 .replace(/([a-zA-Z])\s+([=+\-])/g, '$1$2').replace(/([=+\-])\s+([a-zA-Z])/g, '$1$2') 1280 1281 .replace(/\s*([+\-*\/%=!&^<>]+=)\s*/g, '$1') 1282 //.replace(/\s*([{}+\-*/%,!]|[+\-*\/=!<>]?=|++|--)\s*/g,'$1') 1283 1284 1285 // 因為直接執行下行敘述會將for(~;;也變成for(~;,所以需先作處理。 1286 .replace(/for\(([^;]*);;/g, 'for;#$1#') 1287 //.replace(/};+/g,'}') /*.replace(/;{2,}{/g,'{')*/.replace(/{;+/g,'{')//.replace(/;*{;*/g,'{')//在quotation作修正成效不彰 1288 // 去掉'}',因為可能是=function(){};或={'ucC':1}; 1289 .replace(/\s*([{;]);+\s*/g, '$1')//.replace(/\s*([{};]);+\s*/g,'$1') 1290 .replace(/for;#([^#]*)#/g, 'for($1;;') 1291 1292 .replace(/\s{2,}/g, ' ') 1293 .replace(/([^)]);}/g, '$1}') // ~;while(~);} but: ~;i=(~);} , {a.b();} 1294 ; 1295 //if(code.charAt(0)=="'")code=(code.charAt(1)=='}'?'}':code.charAt(1)==';'?'':code.charAt(1))+code.substr(2); 1296 1297 return code; 1298 }; 1299 1300 1301 1302 CeL.data.code.reorganize 1303 . 1304 /** 1305 * 精簡整個檔的程式碼 1306 * …and test程式是否有語法不全處(例如沒加';') 1307 * @param original_ScriptFileName origin javascript file name 1308 * @param output_ScriptFileName target javascript file name 1309 * @param flag 1310 * flag={doTest:bool,doReport:bool,outEnc:(enc),copyOnFailed:bool,startFrom:// | '',addBefore:'',runBefore:function} 1311 * startFrom 若為 // 則應為 startAfter!! 1312 * @requires autodetectEncode,simpleRead,simpleWrite,reduce_code,is_file 1313 * @deprecated use <a href="http://closure-compiler.appspot.com/" accessdate="2009/12/3 12:13">Closure Compiler Service</a> 1314 * @memberOf CeL.data.code.reorganize 1315 */ 1316 reduce_script = function (original_ScriptFileName, output_ScriptFileName, flag) { 1317 if (!original_ScriptFileName) 1318 original_ScriptFileName = WScript.ScriptFullName; 1319 1320 if (!output_ScriptFileName) 1321 output_ScriptFileName = 1322 // getFP(original_ScriptFileName.replace(/\.ori/,''),1); 1323 original_ScriptFileName + 1324 //.compressed.js 1325 '.reduced.js'; 1326 1327 if (!flag) 1328 flag = {}; 1329 1330 if (!fso) 1331 fso = new ActiveXObject("Scripting.FileSystemObject"); 1332 1333 // 同檔名偵測(若自行把 .ori 改成標的檔等,把標的檔先 copy 成原來檔案。) 1334 if (original_ScriptFileName == output_ScriptFileName) { 1335 if (2 == WshShell.Popup('origin file and output file is the same!' 1336 + (flag.originFile ? "\nI'll try to copy it back." : ''), 0, 1337 'Copy target as origin file', 1 + 48)) 1338 return; 1339 if (!flag.originFile) 1340 return; 1341 if (is_file(original_ScriptFileName = flag.originFile)) { 1342 alert('origin file is exist! Please rename the file!'); 1343 return; 1344 } 1345 try { 1346 fso.CopyFile(output_ScriptFileName, original_ScriptFileName); 1347 } catch (e) { 1348 alert('Failed to copy file!'); 1349 return; 1350 } 1351 } 1352 1353 if (!is_file(original_ScriptFileName)) { 1354 alert("Doesn't found original javascript file!\n" + original_ScriptFileName); 1355 return; 1356 } 1357 1358 var sp = '='.x(80) + NewLine, reduce_codeM = [], enc = autodetectEncode(original_ScriptFileName), i, outenc = autodetectEncode(output_ScriptFileName); 1359 1360 if (!flag.outEnc) 1361 flag.outEnc = outenc || enc || TristateTrue; 1362 1363 try { 1364 var f = simpleRead(original_ScriptFileName, enc), 1365 ot = simpleRead(output_ScriptFileName, flag.outEnc), r = ''; 1366 if (typeof f != 'string') 1367 throw new Error("Can't read file [" + original_ScriptFileName + "]!"); 1368 t = flag.runBefore ? flag.runBefore(f) || f : f; 1369 if (flag.startFrom) 1370 if (typeof flag.startFrom == 'string') { 1371 if ((i = t.indexOf(flag.startFrom)) != -1) 1372 t = t.slice(i); 1373 } else if (flag.startFrom instanceof RegExp) 1374 t = t.replace(flag.startFrom, ''); 1375 t = reduce_code(t); 1376 t = (flag.addBefore || '') 1377 + t.replace(/([};])function(\s)/g, '$1\nfunction$2').replace( 1378 /}var(\s)/g, '}\nvar$1')/* .replace(/([;}])([a-z\._\d]+=)/ig,'$1\n$2') */ 1379 + reduce_codeM.join(NewLine + sp); 1380 // 不相同才 run 1381 if (t) 1382 if (t != ot || outenc != flag.outEnc) 1383 simpleWrite(output_ScriptFileName, t, flag.outEnc); 1384 else 1385 r = '* 欲寫入之內容(' + t.length + ' chars)與標的檔相同。檔案並未變更。\n'; 1386 1387 if (flag.doTest) 1388 // void //should use windows.eval 1389 // //if(WScript.ScriptName!=output_ScriptFileName)eval(t); 1390 eval('if(0){if(0){if(0){' + t + '}}}'); 1391 if (flag.doReport) 1392 alert('OK!\n' + r + '\n' + f.length + '→' + t.length 1393 + '(origin output: ' + ot.length + ') (' 1394 + (100 * t.length / f.length).decp(2) + '%)\n\n[' + enc 1395 + '] ' + original_ScriptFileName + '\n→\n[' + flag.outEnc 1396 + '] ' + output_ScriptFileName); 1397 } catch (e) { 1398 if (6 == alert( 1399 'reduce_script: Error occured!\nDo you want to write error message to target file?\n' 1400 + output_ScriptFileName, 0, 0, 3 + 32)) 1401 simpleWrite(output_ScriptFileName, popErr(e) + NewLine + NewLine 1402 + reduce_codeM.join(NewLine + sp), TristateTrue/* enc */, 0, 1403 true); 1404 if (flag.copyOnFailed) 1405 try { 1406 fso.CopyFile(original_ScriptFileName, output_ScriptFileName); 1407 } catch (e) { 1408 alert('Failed to copy file!'); 1409 return; 1410 } 1411 } 1412 }; 1413 1414 1415 1416 1417 /* 1418 !! arguments unfinished !! 1419 1420 usage: include code in front: 1421 // [function.js]_iF,rJS 1422 // [function.js]End 1423 1424 rJS({add:'/*\nCopyright 2008 kanashimi\n欲使用此工具功能者,請聯絡作者。\n*\/\n'}); 1425 1426 // code start 1427 1428 (main code).. 1429 1430 */ 1431 CeL.data.code.reorganize 1432 . 1433 /** 1434 * 縮減 HTML 用 .js大小+自動判別。 1435 * TODO: 1436 * 自動選擇 target 之模式(不一定是 .ori) 1437 * @param flag flag 1438 * @requires reduce_script 1439 * @since 2008/7/31 17:40:40 1440 * @memberOf CeL.data.code.reorganize 1441 */ 1442 rJS = function (flag) { 1443 if (typeof WScript == 'object') { 1444 var o = WScript, t, n; 1445 1446 if (typeof reduce_script != 'function') 1447 o.Echo('Please include function reduce_script() to generate code.'); 1448 else 1449 flag = flag || {}, 1450 n = o.ScriptFullName, 1451 t = n.replace(/\.ori/, ''), 1452 reduce_script(n, t, { 1453 doReport : 1, 1454 outEnc : 'UTF-8', 1455 startFrom : flag.cut || /^(.|\n)+code\s+start\r?\n/, 1456 addBefore : flag.add, 1457 originFile : t.replace(flag.ori || /(\.[^.]+)$/, '.ori$1') 1458 }); 1459 1460 o.Quit(); 1461 } 1462 }; 1463 1464 1465 /* 1466 try{var o;try{o=new ActiveXObject('Microsoft.XMLHTTP')}catch(e){o=new XMLHttpRequest()}with(o)open('GET',(new ActiveXObject("WScript.Shell")).RegRead('HKCU\\Software\\Colorless echo\\CeL.path'),false),send(null),eval(responseText)}catch(e){} 1467 1468 */ 1469 //(''+CeL.library_loader).replace(/^\s*function\s*\(\s*\)\s*{\s*/,'').replace(/\s*}\s*;\s*$/,''); 1470 CeL.data.code.reorganize 1471 . 1472 /** 1473 * for 引用: include library 自 registry 中的 path 1474 * @since 2009/11/25 22:59:02 1475 * @_memberOf _module_ 1476 */ 1477 library_loader_by_registry = function () { 1478 //if (typeof WScript == "object") 1479 try { 1480 var o; 1481 try { 1482 o = new ActiveXObject('Microsoft.XMLHTTP'); 1483 } catch (e) { 1484 o = new XMLHttpRequest(); 1485 } 1486 with (o) 1487 open('GET', (new ActiveXObject("WScript.Shell")).RegRead(library_namespace.env.registry_key), false), 1488 send(null), 1489 eval(responseText); 1490 } catch (e) { 1491 } 1492 }; 1493 1494 1495 1496 1497 1498 /* 1499 {var d=new Date;try1();alert(gDate(new Date-d));} 1500 function try1(){ 1501 var s='sde'.x(9999),t='',m,i=0; 1502 while(m=s.substr(i).match(/s[^s]+/))t+=s.substr(i,RegExp.index),i+=RegExp.lastIndex; // way 1:3.24,3.19,3.13 1503 //while(m=s.match(/s[^s]+/))t+=s.slice(0,RegExp.index),s=s.substr(RegExp.lastIndex); // way 2:3.52,3.24,3.29 1504 // way 1 is litter better than way 2. 1505 }*/ 1506 1507 1508 /* 1509 // TODO: 對 encodeCode/decodeCode/reduceCode 嚴厲的測試(笑) 1510 {var tr=1,c=simpleRead('function.js'),testF='try.txt',p='',range=99 ,sp='='.x(80)+NewLine,tr2=tr,i,j,t,d,d0=new Date,da,db,dc;try{simpleWrite('try.js',c=reduceCode(c),TristateTrue); 1511 do{da=new Date;t=''+encodeCode(c,p);db=new Date;d=''+decodeCode(t,p);dc=new Date;}while(--tr&&new Date-d0<2e4&&c==d); // find different 1512 //if(d)alert('['+c.length+']→['+t.length+'] ( '+(100*t.length/c.length).to_fixed(2)+' %)\n'+t.slice(0,range)+'\n..\n\ndecode →\n'+d.slice(0,range));//+'\n'+c 1513 for(i=0,j=[];i<c.length;i++)j.push((i%80?'':NewLine)+c.charCodeAt(i));c+=j; 1514 for(i=0,j=[];i<t.length;i++)j.push((i%80?'':NewLine)+t.charCodeAt(i));t+=j; 1515 for(i=0,j=[];i<d.length;i++)j.push((i%80?'':NewLine)+d.charCodeAt(i));d+=j; 1516 simpleWrite(testF,'start at '+gDate(da)+NewLine+'encode: '+gDate(db-da)+NewLine+'decode: '+gDate(dc-db)+NewLine+sp+'['+c.length+']→['+t.length+'] ( '+(100*t.length/c.length).to_fixed(2)+' %)'+NewLine+c+NewLine+NewLine+t+NewLine+sp+(typeof encodeCodeC!='undefined'?encodeCodeC+sp:'')+NewLine+d+NewLine+sp+(typeof decodeCodeC!='undefined'?decodeCodeC+sp:'')+'try '+(tr2-tr)+' times '+(c==d?'OK!':'failed @ '+(i=same(c,d))+' .'+NewLine+c.substr(i-9,range)+NewLine+'-'.x(20)+NewLine+d.substr(i-9,range))+NewLine,TristateTrue); 1517 alert('Test encodeCode over!'); 1518 }catch(e){simpleWrite(testF,popErr(e));}} */ 1519 //{a=simpleRead('function.js');for(i=0;i<encodeCodeDwordsRef.length;i++)a=a.replace(encodeCodeDwordsRef[i].replace(/([()])/g,'\\$1'),'');simpleWrite('try.txt',a);} 1520 /* 編程式碼 1521 [0-\uffff=65535] 1522 ↓ mapping to 1523 [1-10,13-29,32-127]:123個 普通char98[9,10,13,32-126], control chars25[1-8,14-29,127] 1524 [unicode control chars:ucC~ucC+5=1~5 *123^2]+unicode[*123][*1], [low unicode control chars:lucC~lucC+1=6~7]+[c]:char[0-31,127~255(最多2*122-32+127=339)], [片語char code:wordC=8]+片語index, [片語設定char code:wordSet=127]+[ (3 upper bits+) 4 len bits]+[片語index]+words 1525 尚可用char:16個[14-29](未來擴充用,如\uhhhhhhhh:19個+4chars,不夠~) 1526 ↓ mapping to 1527 char[1-9,11-12,14-127]-["\]:123個index 1528 1529 未來:unicode片語編碼 1530 1531 JavaScript五大關鍵字 - hax的技術部落格 - JavaEye技術網站 http://hax.javaeye.com/blog/380285 1532 if,this,function,return,var 1533 1534 下兩行調到檔案頭 1535 var encodeCodeCC,encodeCodeDwordsRef=['function ','return ','return','undefined','for(','var ','.length','typeof','continue;','if(','else','while(','break;','this.','try{','}catch(','true','false','eval(','new ','Array','Object','RegExp','.replace(','.match(','.push(','.pop(','.split(','isNaN(','.indexOf(','.substr(','with(']; 1536 set_obj_value('encodeCodeCC','ucC=1,lucC=6,wordC=8,wordS=127','int'); 1537 */ 1538 function encodeCode(code,K){ // code,key 1539 code=''+code;//code=reduceCode(code); 1540 if(!code)return; 1541 var ucC=encodeCodeCC.ucC,lucC=encodeCodeCC.lucC,wordC=encodeCodeCC.wordC,wordS=encodeCodeCC.wordS,rC=87 // 2<rC<ch.length! 1542 ,rc='',c,i,k=[nullCode('3-'+(code.length>rC?rC:code.length<7?7:code.length),0)],l=nullCode('1-'+rC,0),p,q,r,count,po=0 // rc:return code,k:encode key array,l:每次跳l個,c,p,q,r:tmp,po:point 1543 ,recent,words={},wordsRef=encodeCodeDwordsRef.join('\0').split('\0')//,countC=[] // 最近一次出現時間與出現頻率(次數:frequency),片語index,片語index參照(reference) 1544 ,ind=[],ch=[]; // 設定加碼chars:ind:index,用ch[(ind[]+k[])%ch.length]來取得所欲轉換成的字元 1545 while(k.length<3&&!(l%=k.length))l=nullCode('1-'+rC,0);count=l+l; // 確保多變性 1546 // 設定加碼chars 1547 /* 1548 for(i=1;i<128;i++) 1549 if(i!=10&&i!=13&&i!=34&&i!=92)ch.push(String.fromCharCode(i)); 1550 for(i=1,j=k.length;i<128;i++) 1551 if(i!=11&&i!=12&&i!=30&&i!=31){if(++j>=ch.length)j=0;ind[i]=j;} 1552 */ 1553 for(i=1,j=0;i<128;i++){ 1554 if(i!=11&&i!=12&&i!=30&&i!=31)ind[i]=j++; 1555 if(i!=10&&i!=13&&i!=34&&i!=92)ch.push(String.fromCharCode(i)); 1556 } 1557 // 設定加碼key 1558 for(i=0;i<k.length;i++)k[i]=nullCode('0-'+rC,0); 1559 if(typeof K=='string')for(i=0,p=K,K=[];i<p.length;i++)K.push(p.charCodeAt(i)%ch.length); 1560 if(K instanceof Array&&K.length)k=K.concat(k);else K=[]; // 加入自訂key:k=自訂key+亂數key 1561 //l=51,count=l+l,k=[50,22,22];alert('l='+l+'\ncount='+count+'\n'+k); // 自行初始設定key 1562 // 使用下列keyword約可減一成 1563 recent=[ch.length]; 1564 if(wordsRef.length>recent.length)wordsRef.length=recent.length;//alert(wordsRef.length+','+20*l); 1565 for(p=20*l,i=0;i<wordsRef.length;i++)recent[words[wordsRef[i]]=i]=p; // 初始優先權 1566 1567 //encodeCodeC=['wordsRef='+wordsRef+NewLine,k.length,l+NewLine].concat(k);encodeCodeC.push(NewLine,'-'.x(9),NewLine);if(K.length)encodeCodeC.push('use password['+K.length+']'+K+NewLine);var mm; 1568 // 開始壓縮與編碼charcode>127 1569 while(po<code.length){ 1570 if(126<(c=code.charCodeAt(po))||c<9||c<32&&c!=10&&c!=13) 1571 if(po++,c<340) // low unicode 1572 p=c<32?c:c-95//,mm='low unicode['+c+','+code.charAt(po-1)+'→'+p+']['+(lucC+(p<123?0:1))+','+p%123+']'//95=127-32 1573 ,c=String.fromCharCode(lucC+(p<123?0:1),p%123),q=2;//q=c.length 1574 else // unicode 1575 q=(p=(c-(r=c%123))/123)%123,p=(p-q)/123//,mm='unicode['+code.charAt(po-1)+']:[ucC+'+p+']['+q+']['+r+']' 1576 ,c=String.fromCharCode(ucC+p,q,r),q=3;//q=c.length 1577 else if(p=code.substr(po).match(/^([.};'"]?\w{2,15})([ (.;{'"])?/)){ // 片語,雖然想在找出[.};'"]時一起處理,但因過於麻煩作罷 1578 if(!isNaN(words[q=p[1]+p[2]])||!isNaN(words[q=p[1]])) // 已有此片語 1579 po+=q.length,c=String.fromCharCode(wordC,q=words[q]),recent[q]=count 1580 //,mm='已有此片語['+q+']['+wordsRef[q]+']' 1581 ,q=2;//,countC[q]++ 1582 else if(r=code.indexOf(q=p[1],po+RegExp.lastIndex),r!=-1&&r<5e3+po+RegExp.lastIndex){ // 後面還有此詞:建新片語 1583 if(p[2]&&(r+=q.length)<code.length&&code.charAt(r)==p[2])q+=p[2]; // 尋求最長片語 1584 for(r=0,i=1;i<recent.length;i++)if(!recent[i]){r=i;break;}else if(recent[i]<recent[r])r=i; // 找出最不常用的 1585 delete words[wordsRef[r]] // 別忘了刪除原值。But注意!這個delete相當於 words[wordsRef[r]]='' 如此而已!(並不更改length,用.join()仍可發現其存在!)but typeof=='undefined' 1586 ,po+=q.length,recent[words[wordsRef[r]=q]=r]=count,c=String.fromCharCode(wordS,q.length,r)+q 1587 //,mm='建新片語['+r+']['+q+']' 1588 ,q=3;//,countC[r]=1 1589 } 1590 else 1591 c=code.charAt(po++),q=0 1592 //,mm='片語['+p[1]+']→直接encode['+code.charCodeAt(po-1)+','+c+']' // 沒有就直接encode 1593 ; 1594 } 1595 else 1596 c=code.charAt(po++),q=0 1597 //,mm='直接encode['+code.charCodeAt(po-1)+','+c+']' // 都不行就直接encode 1598 ; 1599 1600 // 加碼與de-quote 1601 //for(r=[],i=0;i<c.length;i++)r.push(c.charCodeAt(i));alert('get '+mm+' ['+c.length+']'+r+'\n'+c); 1602 for(r='',i=0;i<c.length;i++)r+=ch[((i&&i<q?c.charCodeAt(i):ind[c.charCodeAt(i)])+k[count%k.length])%ch.length]; // char code(0)+control code(1-q)+char code 1603 //encodeCodeC.push(count,'next:'+po,code.charCodeAt(po)+'['+code.charAt(po)+']','control code len:'+q,'編成'+r.length+'['+r+'] '+mm+' ');for(var a,i=0;i<c.length;i++)encodeCodeC.push((i?' ':'')+'ch[('+(i&&i<q?a=c.charCodeAt(i):'ind['+(a=c.charCodeAt(i))+']='+(isNaN(a=ind[a])?'(null)':a))+' +k['+(p=count%k.length)+']='+(!isNaN(p)&&(p=k[p])?p:'(null)')+' )%'+ch.length+'='+(a=((a||0)+(p||0))%ch.length)+' ]=[ '+(!isNaN(a)&&(a=ch[a])?a.charCodeAt(0):'(null)')+' ]'+(a.charCodeAt(0)==r.charCodeAt(i)?'':'err:['+r.charCodeAt(i)+']'));encodeCodeC.push(NewLine); 1604 rc+=r,count+=l; 1605 } 1606 1607 // 組合 p:加碼組 1608 for(i=K.length,p=(i?ch[0]:'')+ch[k.length-i]+ch[l];i<k.length;i++)p+=ch[k[i]]; 1609 //alert(toCharCode(p)+'\n'+toCharCode(rc));//4,55,54,25,25 53,56,86,22,22,54,86,22 1610 return p+rc; 1611 } 1612 1613 function toCharCode(s) { 1614 s += ''; if (!s) return; var i = 0, c = []; 1615 for (; i < s.length; i++) c.push(s.charCodeAt(i)); 1616 return c; 1617 } 1618 1619 // 解程式碼 1620 function decodeCode(c,K){ // code,key 1621 if(!c)return;//c:encoded code 1622 // var ucC=encodeCodeCC.ucC,lucC=encodeCodeCC.lucC,wordC=encodeCodeCC.wordC,wordS=encodeCodeCC.wordS,words=encodeCodeDwordsRef.join('\0').split('\0') 1623 var ucC=1,lucC=6,wordC=8,wordS=127,words=['function ','return ','return','undefined','for(','var ','.length','typeof','continue;','if(','else','while(','break;','this.','try{','}catch(','true','false','eval(','new ','Array','Object','RegExp','.replace(','.match(','.push(','.pop(','.split(','isNaN(','.indexOf(','.substr(','with('] // 精簡實戰版 1624 ,i,k,l,p,q,r='',w=1,cr=[] 1625 // tr:b===''時return a之char code,其他無b時return a之index code,有b時return a-b之char set。出錯時無return 1626 ,trSet={}, 1627 tr=function(s,a,b){if(!isNaN(b)&&b){var c,t="";while(a<b)if(!isNaN(c=s.ind[s.c.charCodeAt(a++)])&&!isNaN(c=s.ch[(c+s.k[s.count%s.k.length])%s.ch.length]))t+=String.fromCharCode(c);else return;return t;}else if(!isNaN(a=s.ind[s.c.charCodeAt(a)])&&((a=(a+s.k[s.count%s.k.length])%s.ch.length),typeof b!="string"||!isNaN(a=s.ch[a])))return a;} 1628 ,ind=[],ch=[]; // 設定解碼chars:ind:index 1629 // 設定解碼chars 1630 for(i=1,p=0;i<128;i++){ 1631 if(i!=10&&i!=13&&i!=34&&i!=92)ind[i]=p++; 1632 if(i!=11&&i!=12&&i!=30&&i!=31)ch.push(i); 1633 } 1634 // 取得及設定解碼key 1635 if(!(p=ind[c.charCodeAt(q=0)])){ 1636 if(typeof K=='string')for(i=0,p=K,K=[];i<p.length;i++)K.push(ch.length-p.charCodeAt(i)%ch.length); 1637 if(K instanceof Array&&K.length)p=ind[c.charCodeAt(++q)];else return; 1638 }else K=[]; // 需要密碼 1639 for(k=[],l=ind[c.charCodeAt(++q)],p+=i=q+1;i<p;i++)k.push(ch.length-ind[c.charCodeAt(i)]); 1640 if(K.length)k=K.concat(k); 1641 trSet.c=c=c.substr(p), 1642 trSet.ind=ind,trSet.ch=ch,trSet.k=k,trSet.count=l; 1643 1644 // decodeCodeC=['words:'+words+NewLine,k.length,l+NewLine].concat(k);decodeCodeC.push(NewLine+'-'.x(9)+NewLine+'c: ');var mm;for(i=0;i<c.length;i++)decodeCodeC.push(c.charCodeAt(i));decodeCodeC.push(NewLine+'-'.x(9)+NewLine);if(K.length)decodeCodeC.push('use password['+K.length+']'+K+NewLine); 1645 i=-1;//alert('-1:'+i); 1646 // 開始解碼 1647 while((trSet.count+=l),++i<c.length){ 1648 // if((p=c.charCodeAt(i))>127)trSet.c=c=c.slice(0,)+; 1649 // decodeCodeC.push(trSet.count+' ch[(ind['+(q=c.charCodeAt(i))+']='+ind[q]+' +k['+(q=trSet.count%k.length)+']='+(q=k[q])+'('+(ch.length-q)+') )%'+ch.length+'='+(q=(ind[c.charCodeAt(i)]+q)%ch.length)+' ]=[ '+ch[q]+' ]',tr(trSet,i,'')+NewLine); 1650 // decodeCodeC.push(trSet.count+' ch[(ind['+(q=c.charCodeAt(i+1))+']='+ind[q]+' +k['+(q=trSet.count%k.length)+']='+(q=k[q])+'('+(ch.length-q)+') )%'+ch.length+'='+(q=(ind[c.charCodeAt(i+1)]+q)%ch.length)+' ]=[ '+ch[q]+' ]',tr(trSet,i+1,'')+NewLine); 1651 // decodeCodeC.push(trSet.count+' ch[(ind['+(q=c.charCodeAt(i+2))+']='+ind[q]+' +k['+(q=trSet.count%k.length)+']='+(q=k[q])+'('+(ch.length-q)+') )%'+ch.length+'='+(q=(ind[c.charCodeAt(i+2)]+q)%ch.length)+' ]=[ '+ch[q]+' ]',tr(trSet,i+2,'')+NewLine); 1652 if(isNaN(p=tr(trSet,i,''))){ 1653 alert('decodeCode filed: illegal char ('+c.charCodeAt(i)+') @ '+i+'/'+c.length+'\n'+r);for(i=0,p=String.fromCharCode(k.length,l);i<k.length;i++)p+=String.fromCharCode(k[i]);return p+','+r; 1654 return; 1655 } // illegal 1656 // [ucC|lucC]+unicode, [wordC]+片語index, [wordS]+[ (3 upper bits+) 4 len bits]+[片語index]+words 1657 if(p==wordS) 1658 q=tr(trSet,++i),p=tr(trSet,++i),r+=words[p]=tr(trSet,++i,i+q),i+=q-1 1659 // ,mm='設定片語 長'+q+'['+p+']:'+words[p] 1660 ; 1661 else if(p==wordC)r+=words[tr(trSet,++i)] 1662 // ,mm='片語'+tr(trSet,i)+'['+words[tr(trSet,i)]+']' 1663 ; 1664 else if(p==lucC||p==lucC+1) 1665 p+=tr(trSet,++i)-lucC,r+=String.fromCharCode(p<32?p:p+95) 1666 // ,mm='low unicode['+r.charCodeAt(r.length-1)+','+r.slice(-1)+'][p='+p+']' 1667 ; 1668 else if(ucC<=p&&p<ucC+5) 1669 r+=String.fromCharCode(((p-ucC)*123+tr(trSet,++i))*123+tr(trSet,++i)) 1670 // ,mm='unicode['+r.charCodeAt(r.length-1)+','+r.slice(-1)+'][p='+p+']' 1671 ; 1672 else 1673 r+=String.fromCharCode(p) 1674 // ,mm='普通char('+p+')['+String.fromCharCode(p)+']' 1675 ; // 普通char 1676 1677 // alert(mm+'\n'+r); 1678 // decodeCodeC.length--,decodeCodeC.push(' '+mm+NewLine); 1679 } 1680 1681 return r; 1682 } 1683 1684 1685 CeL.data.code.reorganize 1686 . 1687 /** 1688 * get various from code 1689 * @param {String} code 程式碼 1690 * @param {Boolean} fill_code (TODO) 不只是定義,在 .code 填入程式碼。 1691 * @return {Object} root namespace 1692 * @since 2009/12/5 15:04:42, 2009/12/20 14:33:30, 2010/7/7 10:58:22 1693 * @_memberOf _module_ 1694 */ 1695 get_various_from_code = function (code, fill_code) { 1696 //library_namespace.log(''+code.slice(0, 100)); 1697 1698 // 使用 .split(/\r?\n/) 應注意:這實際上等於 .split(/(\r?\n)+/) (??) 1699 code = code.split(/\r?\n/); 1700 1701 var i, m, last_code = [], 1702 /** 1703 * 現在所處之 line 1704 * 1705 * @inner 1706 * @ignore 1707 */ 1708 line = '', 1709 /** 1710 * code.length, 加快速度用 1711 * 1712 * @constant 1713 * @inner 1714 * @ignore 1715 */ 1716 l = code.length, 1717 /** 1718 * root namespace 1719 * 1720 * @inner 1721 * @ignore 1722 */ 1723 ns = {}, 1724 /** 1725 * 暫存 code(變數定義) 1726 * 1727 * @inner 1728 * @ignore 1729 */ 1730 tmp_code, 1731 /** 1732 * 名稱暫存變數 1733 * 1734 * @inner 1735 * @ignore 1736 */ 1737 name, 1738 /** 1739 * arguments 暫存變數<br/> 1740 * e.g., 變數 name 1741 * 1742 * @inner 1743 * @ignore 1744 */ 1745 various, 1746 /** 1747 * 本變數之 properties。<br/> 1748 * properties = { property: text contents of this property } 1749 * 1750 * @inner 1751 * @ignore 1752 */ 1753 properties, 1754 /** 1755 * 最後一次定義的變數名,用於之後若有變數需要繼承 namespace 時。 1756 * 1757 * @inner 1758 * @ignore 1759 */ 1760 latest_name, 1761 /** 1762 * 紀錄有意義的註解所在行號. 1763 * 預防需要把註解之前的也讀進來。有 bug! 1764 * 1765 * @inner 1766 * @ignore 1767 */ 1768 origin_index, 1769 new_line=library_namespace.env.new_line, 1770 /** 1771 * 將 jsdoc properties 轉換成 VSdoc(JScript IntelliSense in Visual Studio) 1772 * 1773 * @inner 1774 * @ignore 1775 * @see 1776 * http://weblogs.asp.net/bleroy/archive/2007/04/23/the-format-for-javascript-doc-comments.aspx, 1777 * http://msdn.microsoft.com/zh-tw/library/bb385682.aspx, 1778 * http://www.codeproject.com/Articles/60661/Visual-Studio-JavaScript-Intellisense-Revisited.aspx 1779 */ 1780 jsdoc_to_vsdoc = function() { 1781 var p = [ '' ], n, V, a, i, l, t_p = function(v) { 1782 //CeL.log(n + ':\n' + properties[n]); 1783 v = typeof v === 'string' ? v 1784 .replace(/^[\s\n]+|[\s\n]+$/g, '') 1785 .replace(/\r?\n\s+|\s+\r?\n/g, new_line) 1786 //.replace(/</g,'<') 1787 : ''; 1788 a = ''; 1789 1790 switch (n) { 1791 1792 case 'description': 1793 case 'summary': 1794 if (!v || /^[\s\n]*$/.test(v)) 1795 return; 1796 n = 'summary'; 1797 break; 1798 1799 case 'param': 1800 if (a = v.match(/^({([a-zA-Z_\d.$\|\s]+)}\s*)?([a-zA-Z_\d$]+|\[([a-zA-Z_\d.$]+)\])\s*(.*?)$/)){ 1801 var t = a[2].replace(/\s+/g, ''); 1802 v = a[5], a = ' name="' + (a[4] || a[3]) + '" type="' + t + '" optional="' + (!!a[4]) + '"'; 1803 1804 if (/integer/i.test(t)) 1805 a += ' integer="true"'; 1806 // from CeL.net.web 1807 if (/HTML([A-U][A-Za-z]{1,15})?Element/i.test(t)) 1808 a += ' domElement="true"'; 1809 }else 1810 a = ''; 1811 break; 1812 1813 case 'type': 1814 return; 1815 1816 case 'return': 1817 n += 's'; 1818 case 'returns': 1819 if (a = v.match(/^({([a-zA-Z_\d$.\|\s]+)})?(.*)$/)){ 1820 v = a[3].replace(/^[\s\n]+/g, ''); 1821 a = a[2].replace(/\s+/g, '') || properties.type; 1822 1823 a = a ? ' type="' + a + '"' : ''; 1824 1825 if (/integer/i.test(t)) 1826 a += ' integer="true"'; 1827 // from CeL.net.web 1828 if (/HTML([A-U][A-Za-z]{1,15})?Element/i.test(t)) 1829 a += ' domElement="true"'; 1830 }else 1831 a = ''; 1832 break; 1833 1834 default: 1835 } 1836 1837 if (v.indexOf(new_line) === -1 && a.indexOf(new_line) === -1) 1838 p.push('<' + n + a + (v ? '>' + v + '</' + n + '>' : '/>')); 1839 else{ 1840 p.push('<' + n + a + '>'); 1841 p = p.concat(v.split(new_line)); 1842 p.push('</' + n + '>'); 1843 } 1844 }; 1845 1846 for (n in properties) 1847 if (library_namespace.is_Array(V = properties[n])) 1848 for (i = 0, l = V.length; i < l; i++) 1849 t_p(V[i]); 1850 else 1851 t_p(V); 1852 1853 return p.length>1 ? p.join(new_line + ' /// ') + new_line 1854 + new_line : ''; 1855 }, 1856 /** 1857 * 從變數定義取得變數名。 1858 * 1859 * @param {String} _ 1860 * 變數定義 1861 * @inner 1862 * @ignore 1863 */ 1864 set_name = function(_) { 1865 name = properties.name; 1866 if (!name) { 1867 name = []; 1868 var i = origin_index, l; 1869 while (i > 0) 1870 if (/[;{})]\s*$/.test(l = code[--i].replace(/\/\/.*$/, ''))) 1871 if ((name = name.join(' ') 1872 // 除去註解後 1873 .replace(/\/\*(.*?)\*\//g, ' ')) 1874 // 已無註解的話 1875 .indexOf('*/') === -1){ 1876 _ = name.replace(/^\s*var(\s+|$)/, '') + _; 1877 break; 1878 } else 1879 name = [ l, name ]; 1880 else if(l) 1881 name.unshift(l); 1882 1883 //if(!i): Error! 1884 //if(_.match(/var/)) library_namespace.warn(name+'\n'+_); 1885 1886 name = properties.memberOf ? 1887 (_.replace(/[\s\n]+/g, '').indexOf(properties.memberOf + '.') === -1 ? 1888 properties.memberOf + '.' : '') 1889 + _ /* .replace(/^(.+)\./,'') */ 1890 : 'property' in properties ? 1891 latest_name ? latest_name + '.prototype.' + _.replace(/^(.+)\./, '') : '' 1892 : _; 1893 } 1894 1895 // 除去 space 1896 name = name.replace(/[\s\n]+/g, ''); 1897 }, 1898 handle_name = function() { 1899 var m = name 1900 .match(/^([a-zA-Z_$\d]+)\.[^.].+[^.]\.([a-zA-Z_$\d]+)$/); 1901 return m && m[1] === library_namespace.Class ? m[1] + '.' 1902 + m[2] + '=' + name : name; 1903 }; 1904 1905 for (i = 0; i < l; i++) { 1906 // 一行一行判斷 1907 // TODO: 提升效率 1908 line = code[origin_index = i]; 1909 1910 if (/^\s*\/\*\*/.test(line)) { 1911 // 處理 '/**' 之註解(這些是有意義的) 1912 properties = {}; 1913 // 都沒有 '@' 時,預設為 @description 1914 name = 'description'; 1915 tmp_code = []; 1916 various=[]; 1917 //library_namespace.log('' + line); 1918 while (i < l) { 1919 //library_namespace.log('' + line); 1920 tmp_code.push(line); 1921 1922 // 判別 1923 if (line.indexOf('*/') !== -1 || (m = line.match(/^\s+\*\s+@([_a-zA-Z\d\$.]+)(\s+([^\s].*)?\s*)?$/))) { 1924 // 設定 name = various 1925 various = various.join(new_line); 1926 if (name in properties) 1927 if (library_namespace.is_Array(properties[name])) 1928 properties[name].push(various); 1929 else 1930 properties[name] = [ properties[name], various ]; 1931 else 1932 properties[name] = various; 1933 1934 if (line.indexOf('*/') !== -1) 1935 break; 1936 1937 name = m[1], various = [ m[3] ]; 1938 1939 } else 1940 various.push((m = line.match(/^\s+\*\s+([^\s].+)$/)) ? m[1] : line.replace(/^(.*)\/\*\*/, '')); 1941 1942 line = code[++i]; 1943 } 1944 1945 //library_namespace.log('[' + i + ']' + '\n' + tmp_code.join('\n') + '\n' + line); 1946 if (m = line.match(/(.*?\*\/)/)) { 1947 line = line.replace(/(.*?)\*\//, ''); 1948 while (i < l 1949 && !/=\s*[^\s]|{/.test(line = line.replace( 1950 /\s*\/\/[^\n]*/g, '').replace( 1951 /\/\*((.|\n)*?)\*\//g, ''))) 1952 line += code[++i]; 1953 1954 // 初始化函式名 1955 name = ''; 1956 1957 /* 1958 * 註解處理完了,接下來是變數。先把整個定義區放到 line。 1959 * 這邊處理幾種定義法: 1960 * function name() {}; 1961 * var name = function(){}; 1962 * var name = new Function(); 1963 * var name = 123; 1964 */ 1965 while (!/^\s*function\s$/.test(line) && !/[=;,]/.test(line)) 1966 line += ' ' + code[++i]; 1967 1968 if (m = line.match(/^\s*function\s+([_a-zA-Z\d\$.]*)\s*\((.*)/)) { 1969 // function name() {}; 1970 set_name(m[1]); 1971 various = m[2]; 1972 while (i < l && various.indexOf(')') === -1) 1973 various += code[++i]; 1974 m = various.match(/^[^)]*/); 1975 tmp_code.push(handle_name() + '=function(' + m[0] + '){' 1976 + jsdoc_to_vsdoc() + '};'); 1977 1978 } else if (m = line 1979 .match(/^\s*(var\s+)?([_a-zA-Z\d\$.]+)\s*=\s*(.+)/)) { 1980 set_name(m[2]); 1981 various = m[3]; 1982 if (/^\s*function(\s+[_a-zA-Z\d\$]+)?\s*\(/.test(various)) { 1983 // var name = function(){}; 1984 while (i < l && various.indexOf(')') === -1) 1985 various += code[++i]; 1986 m = various.match(/^[^)]+\)/); 1987 tmp_code.push(handle_name() + '=' + m[0] + '{' + jsdoc_to_vsdoc() + '};'); 1988 1989 } else if (/^\s*new\s+Function\s*\(/.test(various)) { 1990 // var name = new Function(); 1991 if (m = various.match(/^\s*new\s+Function\s*\(.+\)\s*;?\s*$/)) { 1992 // TODO 1993 tmp_code.push(handle_name() + '=new Function("");'); 1994 } else 1995 tmp_code.push(handle_name() + '=new Function();'); 1996 1997 } else { 1998 // var name = 123; 1999 if (!properties.type) 2000 if (/^['"]/.test(various)) { 2001 properties.type = 'String'; 2002 } else if (!isNaN(various)) { 2003 properties.type = 'number'; 2004 } else if (/^(true|false)([\s;,]|$)/.test(various)) { 2005 properties.type = 'bool'; 2006 } else if (various.charAt(0) === '[') { 2007 properties.type = 'array'; 2008 } else if (various.charAt(0) === '{') { 2009 properties.type = 'object'; 2010 } else if (various.charAt(0) === '/') { 2011 properties.type = 'regexp'; 2012 } else if (/^regexp obj(ect)?$/.test(properties.type)) { 2013 properties.type = 'regexp'; 2014 } 2015 2016 //if (name === 'module_name'); 2017 2018 switch ((properties.type || '').toLowerCase()) { 2019 case 'string': 2020 m = various.replace(/\s*[,;]*\s*$/, ''); 2021 //library_namespace.log('['+m+']'); 2022 if (/^'[^\\']*'$/.test(m) 2023 || /^"[^\\"]*"$/.test(m)) { 2024 various = '=' + m + ';'; 2025 } else { 2026 various = '=""; // ' + various; 2027 } 2028 properties.type='String'; 2029 break; 2030 2031 case 'bool': 2032 case 'boolean': 2033 if (m = various.toLowerCase().match( 2034 /^(true|false)([\s,;]|$)/i)) { 2035 various = '=' + m[1] + ';'; 2036 } else { 2037 various = '=true; // ' + various; 2038 } 2039 properties.type='Boolean'; 2040 break; 2041 2042 case 'number': 2043 properties.type = 'Number'; 2044 case 'int': 2045 case 'integer': 2046 if (/int(eger)?/i.test(properties.type)) 2047 properties.type = 'Integer'; 2048 2049 if (!isNaN(various)) { 2050 various = '=' + various + ';'; 2051 } else { 2052 various = '=0; // ' + various; 2053 } 2054 break; 2055 2056 case 'array': 2057 various = '=' + '[];'; 2058 properties.type = 'Array'; 2059 break; 2060 2061 case 'object': 2062 if (various.charAt(0) === '{') { 2063 while (i < l) { 2064 if (various.lastIndexOf('}') !== -1) { 2065 m = various.slice(1, various.lastIndexOf('}')); 2066 if (m.lastIndexOf('/*') === -1 2067 || m.lastIndexOf('/*') < m 2068 .lastIndexOf('*/')) 2069 break; 2070 } 2071 various += '\n' + code[++i]; 2072 } 2073 m = various 2074 .replace(/\s*\/\/[^\n]*/g, '') 2075 .replace(/\/\*((.|\n)*?)\*\//g, '') 2076 .replace(/}(.*)$/,'}'); 2077 if (0 && m.length > 3) 2078 library_namespace.log(name + '\n' + m 2079 // + '\n'+v 2080 ); 2081 if (/^{([\s\n]*(('[^']*'|"[^"]*"|[_a-zA-Z\d\$.]+))[\s\n]*:('[^']*'|"[^"]*"|[\s\n\d+\-*\/()\^]+|true|false|null)+|,)*}/ 2082 .test(m)) 2083 various = '=' + various.replace(/}(.*)$/, '}') + ';'; 2084 else 2085 various = '=' + '{};'; 2086 } else 2087 various = '=' + '{};'; 2088 properties.type = 'Object'; 2089 break; 2090 2091 case 'regexp': 2092 if (/^\/.+\/$/.test(various)) 2093 various = '=' + various + ';'; 2094 else { 2095 various = '=' + '/^regexp$/; // ' + various; 2096 } 2097 properties.type = 'RegExp'; 2098 break; 2099 2100 default: 2101 // TODO: T1|T2|.. 2102 if (/^[_a-zA-Z\d\$.]/.test(various)) { 2103 // reference 2104 various = ';//' + (properties.type ? '[' + properties.type + ']' : '') 2105 + various; 2106 } else { 2107 // unknown code 2108 various = '; // ' 2109 + (properties.type ? '[' + properties.type + ']' : '') 2110 + various; 2111 } 2112 } 2113 2114 tmp_code.push((/^=/.test(various) ? '' : '//') + handle_name() + various); 2115 } 2116 } 2117 2118 if (name && !('ignore' in properties) && !('inner' in properties) && !('private' in properties)) { 2119 if (!('property' in properties)) 2120 // 定義最後一次變數名 2121 latest_name = name; 2122 2123 name = name.split(library_namespace.env.module_name_separator); 2124 2125 // 對可能的錯誤發出警告 2126 if (name[0] !== library_namespace.Class && !('deprecated' in properties)) 2127 library_namespace.warn(i + ': line [' + name.join(library_namespace.env.module_name_separator) + '] NOT initial as '+library_namespace.Class+'\n' 2128 + code.slice(i - 6, i + 6).join('\n')); 2129 2130 // 將變數定義設置到 ns 2131 var np = ns, nl = name.length - 1, n; 2132 for (m = 0; m < nl; m++) { 2133 n = name[m]; 2134 if (!(n in np)) 2135 // 初始設定 namespace 2136 np[n] = { 2137 'this': '' 2138 }; 2139 else if (!library_namespace.is_Object(np[n])) 2140 np[n] = { 2141 'this': np[n] 2142 }; 2143 np = np[n]; 2144 } 2145 2146 n = name[nl]; 2147 //if (n in np) library_namespace.log('get_various_from_code: get duplicate various: [' + name.join(library_namespace.env.module_name_separator) + ']'); 2148 2149 np[n] = tmp_code.join(new_line); 2150 } 2151 } 2152 } 2153 } 2154 2155 return ns; 2156 }; 2157 2158 2159 CeL.data.code.reorganize 2160 . 2161 /** 2162 * 把 get_various_from_code 生成的 namespace 轉成 code 2163 * @param {Object} ns root namespace 2164 * @param {String} [prefix] (TODO) prefix of root namespace 2165 * @param {Array} [code_array] inner use, please don't specify this value. 2166 * @return {String} code 2167 * @since 2009/12/20 14:51:52 2168 * @_memberOf _module_ 2169 */ 2170 get_code_from_generated_various = function (ns, prefix, code_array) { 2171 var _s = _.get_code_from_generated_various, i, return_text = 0; 2172 2173 if (!code_array) 2174 code_array = [], 2175 return_text = 1; 2176 2177 // 先處理 'this' 2178 if (prefix) { 2179 if (!/\.prototype$/.test(prefix)) 2180 if (i = ns['this']) { 2181 code_array.push(i); 2182 delete ns['this']; 2183 } else 2184 code_array.push('', 2185 '// null constructor for [' + prefix + ']', 2186 prefix + '=function(){};', 2187 prefix + '.prototype={};'); 2188 prefix += '.'; 2189 } else 2190 prefix = ''; 2191 2192 2193 for (i in ns) 2194 if (typeof ns[i] === 'string') 2195 code_array.push(ns[i]); 2196 else 2197 _s(ns[i], prefix + i, code_array); 2198 2199 return return_text ? 2200 code_array.join(library_namespace.env.new_line) 2201 //.replace(/[\r\n]+/g,library_namespace.env.new_line) 2202 : code_array; 2203 }; 2204 2205 2206 2207 2208 return ( 2209 CeL.data.code.reorganize 2210 ); 2211 } 2212 2213 2214 ); 2215 2216