cejs
Version:
A JavaScript module framework that is simple to use.
1,393 lines (1,220 loc) • 89.6 kB
JavaScript
/**
* @name CeL code reorganize function
* @fileoverview
* 本檔案包含了程式碼重整重構用的 functions。
* @since
*/
/**<code>
parse code
use ISO-14977: Extended Backus–Naur Form (EBNF)
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
http://blog.zhaojie.me/2010/11/narcissus-javascript-parser.html
Narcissus是一個JavaScript引擎,完全使用JavaScript編寫,不過利用了SpiderMonkey的一些擴展,因此無法直接在僅僅實現了ECMAScript 3的引擎上執行(例如各瀏覽器)。
http://en.wikipedia.org/wiki/Narcissus_%28JavaScript_engine%29
http://hax.iteye.com/blog/181358
https://github.com/mishoo/UglifyJS2
</code>
@see https://github.com/yahoo/serialize-javascript
*/
'use strict';
typeof CeL === 'function' && CeL.run(
{
// module name
name: 'data.code.reorganize',
require: 'data.code.compatibility.|data.native.|application.OS.Windows.file.read_file|application.OS.Windows.file.write_file',
// 為了方便格式化程式碼,因此將 module 函式主體另外抽出。
code: module_code
});
function module_code(library_namespace) {
// requiring
var read_file = this.r('read_file'), write_file = this.r('write_file');
var
/**
* null module constructor
* @class 程式碼重整重構相關之 functions。
* @constructor
*/
_// JSDT:_module_
= function () {
// null module constructor
};
/**
* for JSDT: 有 prototype 才會將之當作 Class
*/
_// JSDT:_module_
.prototype = {};
//class public interface ---------------------------
_// JSDT:_module_
.
/**
* 取得[script_filename].wsf中不包括自己([script_filename].js),其餘所有 .js 的code。
* @param {String}script_filename script filename
* @return
* @requires ScriptName,read_file
* @deprecated 若想在低版本中利用eval(get_all_functions(ScriptName))來補足,有時會出現奇怪的現象,還是別用好了。
* @_memberOf _module_
*/
get_all_functions = function (script_filename) {
if (!script_filename)
script_filename = ScriptName;
var t = '', i, a = read_file(script_filename + '.wsf'), l = a ? a
.match(/[^\\\/:*?"<>|'\r\n]+\.js/gi) : [script_filename + '.js'];
for (i in l)
if (l[i] != script_filename + '.js' && (a = read_file(l[i])))
t += a;
return t;
};
var JS_reserved_word = {
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',
FutureReservedWord: 'class,enum,extends,super,const,export,import',
NullLiteral: 'null',
BooleanLiteral: 'true,false'
};
/**
*<code>
var OK = add_code('alert,write_file', ['alert', 'line_separator', 'get_all_functions']);if (typeof OK == 'string') write_file('try.js', OK), alert('done'); else alert('OK:' + OK);
{
var ss = [23, 23.456, undefined, Attribute, null, Array, '567', 'abc'], l = 80, repF = 'tmp.txt', sa = ss, st = add_code('', ['ss']), t;
ss = '(reseted)'; try { eval(st); } catch (e) { } t = (sa === ss) + ': ' + typeof sa + '→' + typeof ss + '\n';
write_file(repF, t + sa + '\n→\n' + ss + '\n\n◎eval:\n' + st);
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)));
}
加入識別格式之方法:
// from function.js -------------------------------------------------------------------
//e.g.,
// [function.js](f1,f2,'string' // 'string'或"string"中包含的需要是完整的敘述句
// number var,string var,object var,date var,undefined var)
//e.g.,
// [function.js](OS,line_separator,dirSp,dirSpR,'var ScriptName=getScriptName();',ForReading,ForWriting,ForAppending,TristateUseDefault,TristateTrue,TristateFalse,WshShell,fso,args,'initialization_WScript_Objects();',initialization_WScript_Objects,setTool,JSalert,Str2Date,Date2Str,decplaces,dQuote,set_obj_value,getScriptFullName,getScriptName,'setTool();',WinEnvironment,SpecialFolder,Network,NetDrive,NetPrinter,getEnvironment,'getEnvironment();',dateUTCdiff,gDate)
//e.g.,
// [function.js]("var line_separator='\n',OS='unix',dirSp=dirSpR='/';",dQuote,setTool,product,decplaces,countS,getText,HTML_to_Unicode,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,show_popup,sPopP,sPopF,sPopInit,sPopInit,sPop,setTextT,setText)
..(inclide code)
// [function.js]End -------------------------------------------------------------------
// ↑from function.js -------------------------------------------------------------------
TODO:
.htm 加入 .replace(/\//g,'\\/')
</code>*/
_// JSDT:_module_
.
/**
* 將各 function 加入檔案中,可做成 HTML 亦可用之格式。
* @example
* add_code('複製 -backup.js');
* @param file_name file name (list)
* @param Vlist 多加添的 function/various list
* @param {String} start_string start string
* @param {String} end_string ending string
* @returns
* @request line_separator,is_file,read_file,autodetectEncode,generate_code,JSalert,setTool,*setTool();
* @_memberOf _module_
*/
add_code = function (file_name, Vlist, start_string, end_string) {
if (!start_string)
start_string = '// [' + library_namespace.Class + ']';
if (!end_string)
end_string = start_string + 'End';
//alert(is_file(FN)+'\n'+start_string+'\n'+end_string);
if (typeof file_name == 'string')
file_name = [is_file(file_name) ? file_name : start_string
+ (file_name ? '(' + file_name + ')' : '') + line_separator
+ end_string + line_separator];
if (typeof Vlist == 'string')
Vlist = [Vlist];
else if (typeof Vlist != 'object')
Vlist = [];
var i, j, F, a, A, start, end, code_head, b, c, d, f, m, OK = 0, line_separator, error,
// 「」『』【】〈〉《》〔〕{}︵︶︹︺︷︸︻︼︿﹀︽︾﹁﹂﹃﹄()「」『』‘’“”〝〞‵′
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',
end_char, req, direct_input = '*', tmpExt = '.tmp', encoding, oriC;
for (i in file_name) try {
if (a = oriC = is_file(file_name[i]) ? read_file(file_name[i],
encoding = autodetectEncode(file_name[i])) : file_name[i], !a)
continue;
A = '', dones = [], doneS = 0;
if (false) sl(a.slice(0, 200));
/**
*<code>
判斷 line_separator 這段,將三種資料作比較就能知道為何這麼搞。
~\r:
\r 123
\n 1
\r\n 2
\n-\r -120
~\n:
\r 1
\n 123
\r\n 2
\n-\r 120
~\r\n:
\r 123
\n 123
\r\n 123
\n-\r -2~2
</code>*/
line_separator = a.replace(/[^\n]+/g, '').length;
b = a.replace(/[^\r]+/g, '').length;
if (line_separator != b && line_separator && b) {
alert("There're some encoding problems in the file:\n"
+ file_name[i] + '\n\\n: ' + line_separator + '\n\\r: ' + b);
line_separator = Math.max(line_separator, b) > 10 * Math.abs(line_separator - b) ? '\r\n'
: line_separator > b ? '\n' : '\r';
} else
line_separator = line_separator ? b ? '\r\n' : '\n' : '\r';
if (false) sl(a.indexOf(start_string) + '\n' + start_string + '\n' + a.slice(0, 200));
if (false) {
// TODO:
a = a.replace(/(startReg)(.*?)(endReg)/g, function ($0, $1, $2, $3) {..return $1 + ~+$3; });
}
while ((start = a.indexOf(start_string)) != -1
// &&(end=a.indexOf(end_string,start+start_string.length))!=-1
) {
// initial reset
code_head = codeText = end_char = '';
req = [];
j = 0;
// 判斷 end index
if ((end = a.indexOf(end_string, start + start_string.length)) == -1) {
alert('add_code: There is start mark without end mark!\nend_string:\n'
+ end_string);
// 未找到格式則 skip
break;
}
// b=inner text
b = a.slice(start + start_string.length, end);
// test檔案型式:DOS or UNIX.最後一位元已被split掉
if (false) line_separator = b.indexOf('\r\n') != -1 ? '\r\n' : b.indexOf('\n') != -1 ? '\n' : '\r';
b = b.split(line_separator);
if (c = b[0].match(/^\s*([\W])/)) {
code_head += b[0].slice(0, RegExp.lastIndex);
b[0] = b[0].slice(RegExp.lastIndex);
if (s.indexOf(c = c[1]) % 2 == 0)
end_char = s.charAt(s.indexOf(c) + 1);
else
end_char = c;
}
// 移到前面:因為需要以 line_separator 作split.
//test檔案型式:DOS or UNIX.最後一位元已被split掉
if (false) line_separator = b[0].slice(-1) == '\r' ? '\r\n' : '\n';
if (false) alert('end_char=' + end_char + ',j=' + j + ',d=' + d + '\n' + b[0] + '\nline_separator:' + (line_separator == '\n' ? '\\n' : line_separator == '\r\n' ? '\\r\\n' : '\\r') + '\ncode_head:\n' + code_head);
do {
if (false) {
// 不需要d>=b[j].length
if (d == b[j].length) continue;
}
if (!j)
d = 0;
else if (b[j].slice(0, 2) != '//')
continue;
else
d = 2;
while (true) {
if (false) alert('search ' + b[j].slice(d));
if ((c = b[j].slice(d).match(/^[,\s]*([\'\"])/))
&& (f = d + RegExp.lastIndex) <= b[j].length &&
// (c=c[1], f<b[j].length)
// .search(
(c = c[1]) && f < b[j].length) {
if (false) alert(b[j].charAt(f) + '\n' + c + '\n^(.*[^\\\\])[' + c + ']');
if (b[j].charAt(f) == c) {
// '',""等
alert('add_code: 包含[' + c + c + ']:\n'
+ b[j].slice(f));
continue;
}
if (c = b[j].slice(f).match(
new RegExp('^(.+?[^\\\\])[' + c + ']'))) {
d = f + RegExp.lastIndex;
req.push(direct_input
// 改進後不需要了
// + b[j].charAt(f - 1)
+ c[1]);
continue;
}
alert('add_code: Cannot find end quota:\n' + b[j].slice(f));
}
if (false) alert(d + ',' + b[j].length + '\nsearch to ' + b[j].slice(d));
// 出現奇怪現象請加"()"
//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
if ((c = b[j].slice(d).match(/([^,\s]+)[,\s]*/)) && (d += RegExp.lastIndex) <= b[j].length) { // 不需要\s\r
//if(!/[,\n]/.test(c[2])&&d<b[j].length)break;
//alert(RegExp.index+','+d+','+b[j].length+','+end_char+'\n['+c[1]+']\n['+c[2]+']\n'+b[j].slice(d));
if (!end_char || (m = c[1].indexOf(end_char)) == -1) req.push(c[1]);
else { if (m) req.push(c[1].slice(0, m)); end_char = ''; break; }
} else break;
}
code_head += b[j] + line_separator;
//alert('output start_string:\n'+start_string+'\ncode_head:\n'+code_head);
} while (end_char && ++j < b.length);
// 不能用b=req:object是用參考的,這樣會改到req本身!
//for(j=0,b=[];j<req.length;j++)b.push(req[j]);
// 加入附加的變數
//for(j=0;j<Vlist.length;j++)b.push(Vlist[j]);
b = _.generate_code(req.concat(Vlist), line_separator, direct_input);
codeText = code_head + (arguments.callee.report ? '/* add_code @ ' + gDate('', 1) // report
+ (req.length ? line_separator + ' request variables [' + req.length + ']: ' + req : '')
+ (Vlist.length ? line_separator + ' addition lists [' + Vlist.length + ']: ' + Vlist : '')
+ (req.length && Vlist.length && b[2].length < req.length + Vlist.length ? line_separator + ' Total request [' + b[2].length + ']: ' + b[2] : '')
+ (b[4].length ? line_separator + ' really done [' + b[4].length + ']: ' + b[4] : '')
+ (b[5].length ? line_separator + ' cannot found [' + b[5].length + ']: ' + b[5] : '')
+ (b[6].length ? line_separator + ' all listed [' + b[6].length + ']: ' + b[6] : '')
//+(b[3].length?line_separator+' included function ['+b[3].length+']: '+b[3]:'')
+ line_separator + ' */' : '') + line_separator + _.reduce_code(b[0]).replace(/([};])function(\s)/g, '$1' + line_separator + 'function$2').replace(/}var(\s)/g, '}' + line_separator + 'var$1')/*.replace(/([;}])([a-z\._\d]+=)/ig,'$1'+line_separator+'$2')*/ + line_separator + b[1] + line_separator;
//alert(start+','+end+'\n'+a.length+','+end+','+end_string.length+','+(end+end_string.length)+'\n------------\n'+codeText);//+a.slice(end+end_string.length)
A += a.slice(0, start + start_string.length)
+ codeText
+ a.substr(end, end_string.length);
a = a.substr(end + end_string.length);
}
if (file_name.length == 1 && !is_file(file_name[i]))
return A;
if (A && oriC != A + a) // 有變化才寫入
if (error = write_file(file_name[i] + tmpExt, A + a, encoding))
try {
fso.DeleteFile(file_name[i] + tmpExt);
} catch (e) {
// popErr(error);popErr(e);
}
else
try {
fso.DeleteFile(file_name[i]);
fso.MoveFile(file_name[i] + tmpExt, file_name[i]);
OK++;
} catch (e) {
// popErr(e);
}
else {
//alert('add_code error:\n'+e.message);continue;
}
} catch (e) {
//popErr(e);
throw e;
}
// A:成功的最後一個檔之內容
return file_name.length == 1 && OK == 1 ? A : OK;
};
/**
* 是否加入報告
* @type Boolean
*/
_.add_code.report = false;
_// JSDT:_module_
.
/**
* add libary use
* @param {String} code script code
* @returns
* @_memberOf _module_
*/
add_use = function (code) {
// TODO: 去除 comments 中的 .use()
var _s = _.add_use, i, m = code.match(_s.pattern);
library_namespace.error('TODO');
};
_.add_use.pattern = new RegExp(library_namespace.Class
+ '\\s*.\\s*use\\((.+)\\)');
/**
*<code>
try.wsf
<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>
try.js
destory_script('WshShell=WScript.CreateObject("WScript.Shell");'+line_separator+line_separator+alert+line_separator+line_separator+'alert("資料讀取錯誤!\\n請檢查設定是否有錯!");');
</code>*/
_// JSDT:_module_
.
/**
* script 終結者…
* @param {String} code script code
* @param addFN
* @returns error NO.
* @_memberOf _module_
*/
destory_script = function (code, addFN) {
try {
// input indepent code, additional files
var SN = getScriptName(), F, a, listJs, i, len, self = SN + '.js';
if (!code) {
//SN='try';
code = '';
}
a = read_file(SN + '.wsf');
if (!a) a = '';
// 一網打盡
listJs = a.match(/[^\\\/:*?"<>|'\r\n]+\.(js|vbs|hta|[xs]?html?|txt|wsf|pac)/gi);
//listWsf=(SN+'.wsf\n'+a).match(/[^\\\/:*?"<>|'\r\n]+\.wsf/gi);
for (i = 0, F = {}; i < listJs.length; i++)
F[listJs[i]] = 1;
if (typeof addFN == 'object')
for (i in addFN)
F[addFN[i]] = 1;
else if (addFN)
F[addFN] = 1;
listJs = [];
// 避免重複
for (i in F)
listJs[listJs.length] = i;
//alert(listJs.join('\n'));
//done all .js @ .wsf & files @ additional list without self
for (i = 0; i < listJs.length; i++)
// 除了self外殺無赦
if (listJs[i] != self) try {
if (!listJs[i].match(/\.js$/i) && listJs[i] != SN + '.wsf') { try { fso.DeleteFile(listJs[i], true); } catch (e) { } continue; } // 非.js就讓他死
// 取消唯讀
if (changeAttributes(F = fso.GetFile(listJs[i]), '-ReadOnly')) throw 0;
a = add_null_code(F.size); //a=listJs[i].match(/\.js$/i)?add_null_code(F.size):''; 先確認檔案存在,再幹掉他
//alert('done '+listJs[i]+'('+F.size+')\n'+(a.length<500?a:a.slice(0,500)+'..'));
write_file(listJs[i], a);
} catch (e) {
//popErr(e);
}
//done .wsf
try {
if (changeAttributes(F = fso.GetFile(SN + '.wsf'), '-ReadOnly'))
throw 0;
a = '<package><job id="' + SN + '"><script type="text/javascript" src="' + SN + '.js"><\/script><\/job><\/package>';
//alert('done '+SN+'.wsf'+'('+F.size+')\n'+a);
//a='<package><job id="'+SN+'"><script type="text/javascript" src="function.js"><\/script><script type="text/javascript" src="'+SN+'.js"><\/script><\/job><\/package>';
write_file(SN + '.wsf', a);
} catch (e) {
//popErr(e);
}
// done self
if (listJs.length) try {
if (changeAttributes(F = fso.GetFile(self), '-ReadOnly') < 0)
throw 0;
a = (F.size - code.length) / 2;
a = add_null_code(a) + code + add_null_code(a);
if (F.Attributes % 2)
// 取消唯讀
F.Attributes--;
//alert('done '+self+'('+F.size+')\n'+(a.length<500?a:a.slice(0,500)+'..'));
//a='setTool(),destory_script();';
write_file(self, a);
} catch (e) {
//popErr(e);
}
//run self & WScript.Quit()
//return WshShell.Run('"'+getScriptFullName()+'"');
return 0;
} catch (e) {
return 1;
}
};
/** for version<5.1:因為不能用.wsf,所以需要合併成一個檔。
請將以下函數copy至.js主檔後做適當之變更
getScriptName(),merge_script(FN),preCheck(ver)
*/
// 將script所需之檔案合併
// 因為常由preCheck()呼叫,所以所有功能亦需內含。
function merge_script(FN) {
var i, n, t, SN = getScriptName(), line_separator, fso, ForReading, ForWriting, ForAppending;
if (!line_separator)
line_separator = '\r\n';
if (!fso)
fso = WScript.CreateObject("Scripting.FileSystemObject");
if (!ForReading)
ForReading = 1, ForWriting = 2, ForAppending = 8;
try {
// from .wsf
/**
*<code>
var F=fso.OpenTextFile(SN+'.wsf',ForReading)
//,R=new RegExp('src\s*=\s*["\']?(.+\.js)["\']?\s*','gi')
,a=F.ReadAll();F.Close();
</code>*/
a = read_file(SN + '.wsf');
S = fso.OpenTextFile(FN, ForWriting, true/* create */);
try {
//t=a.match(/<\s*resource\s+id=(['"].*['"])\s*>((.|\r\n)*?)<\/\s*resource\s*>/gi);
// 5.1版以下果然還是不能成功實行,因為改變regexp不能達到目的:沒能找到t。所以在下面第一次test失敗後即放棄;改用.ini設定。
var r = new RegExp("<\\s*resource\\s+id=(['\"].*['\"])\\s*>((.|\\r\\n)*?)<\\/\\s*resource\\s*>", "ig");
t = a.match(r);
S.WriteLine('// merge_script: from ' + SN + '.wsf');
S.WriteLine("function getResource(id){");
if (!t || !t.length) S.WriteLine(" return ''");
else for (i = 0; i < t.length; i++) {
//alert(i+':'+t[i]);
//n=t[i].match(/<\s*resource\s+id=(['"].*['"])\s*>((.|\r\n)*?)<\/\s*resource\s*>/i);
r = new RegExp("<\\s*resource\\s+id=(['\"].*['\"])\\s*>((.|\\r\\n)*?)<\\/\\s*resource\\s*>", "i");
n = t[i].match(r);
S.WriteLine(" " + (i ? ":" : "return ") + "id=="
+ n[1] + "?'"
+ n[2].replace(/\r?\n/g, '\\n') + "'");
}
S.WriteLine(" :'';" + line_separator + "}" + line_separator);
} catch (e) {
}
// from .js
t = a.match(/src\s*=\s*["']?(.+\.js)["']?\s*/gi);
for (i = 0; i < t.length; i++) {
//alert(i+':'+t[i].match(/src\s*=\s*["']?(.+\.js)["']?\s*/i)[1]);
//try{F=fso.OpenTextFile(n=t[i].match(/src\s*=\s*["']?(.+\.js)["']?\s*/i)[1],ForReading);}
//catch(e){continue;}
//S.WriteLine('// merge_script: from script '+n);S.WriteBlankLines(1);S.WriteLine(F.ReadAll());
//S.WriteLine('// merge_script: from script '+n+line_separator+line_separator+F.ReadAll());
//F.Close();
S.WriteLine('// merge_script: from script '
+ (n = t[i]
.match(/src\s*=\s*["']?(.+\.js)["']?\s*/i)[1])
+ line_separator + line_separator + read_file(n));
}
S.Close();
S = 0;
} catch (e) {
S = 1;
}
//fso = null;
return S;
};
/**
*<code>
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!');}
/* use for JSON (JavaScript Object Notation)
directly input: [directInput]string
輸出string1(可reduce_code),輸出string2(主要為object definition,不需reduce_code,以.replace(/\r\n/g,'')即可reduce),總共要求的變數(去掉重複),包含的函數(可能因參考而有添加),包含的變數(可能因參考而有添加),未包含的變數
未來:對Array與Object能確實設定之 尚未對應:Object遞迴/special Object(WScript,Excel.Application,內建Object等)/special function(內建函數如Math.floor與其他如WScript.CreateObject等)
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)
** 需同步更改 json()
TODO:
Object.toSource()
Array.toSource()
json http://www.json.org/json.js
UglifyJS https://github.com/mishoo/UglifyJS
XML Object
bug:
函數定義 .toString() 時無法使用。
使用 \uXXXX 使.js跨語系
含中文行
→
//turnBy 含中文行
\x..
考慮註解&執行時語系
to top BEFORE ANY FUNCTIONS:
generate_code.dLK='dependencyList'; // dependency List Key
</code>*/
_// JSDT:_module_
.
/**
* 利用[*現有的環境*]及變數設定生成code,因此並不能完全重現所有設定,也無法判別函數間的相依關係。
* @param {Array} Vlist 變數 list
* @param {String} line_separator line separator
* @param {String} direct_input 直接輸入用辨識碼
* @requires set_obj_value,dQuote
* @_memberOf _module_
*/
generate_code = function (Vlist, line_separator, direct_input) {
// vars:處理過的variables(不論是合法或非合法),c:陳述是否已完結
var _s = _.generate_code, codeText = '', afterCode = '', vars = [], vari = [], func = [], done = [], undone = [], t, i = 0, c = 0, val, vName, vType;
if (!line_separator)
line_separator = '\n';
if (!direct_input)
direct_input = _s.ddI;
if (typeof Vlist === 'string')
Vlist = Vlist.split(_s.dsp);
for (; i < Vlist.length; i++) if (!((vName = '' + Vlist[i]) in vars)) {
// c(continue)=1:var未截止,vName:要加添的變數內容
// 避免重複
vars[vName] = vari.length, vari.push(vName);
// 不加入的
if (vName.charAt(0) == '-') {
vars[vName.slice(1)] = -1;
continue;
}
// 直接輸出
if (vName.slice(0, direct_input.length) == direct_input) {
if (c)
codeText += ';' + line_separator, c = 0;
codeText += val = vName.substr(direct_input.length);
done.push('(directly input)' + val);
continue;
}
try {
// void
eval('vType=typeof(val=' + vName + ');');
} catch (e) {
// b:type,c:已起始[var ];catch b:語法錯誤等,m:未定義
// e.constructor
undone.push((vType ? '(' + vType + ')' : '') + vName
+ '(error ' + (e.number & 0xFFFF) + ':'
+ e.description + ')');
continue;
}
// or use switch-case
if (vType === 'function') {
// 加入function object成員,.prototype可用with()。加入函數相依性(dependency)
try {
eval("var j,k;for(j in "
+ vName
+ ")if(j=='"
+ _s.dLK
+ "'&&(k=typeof "
+ vName
+ "."
+ _s.dLK
+ ",k=='string'||"
+ vName
+ "."
+ _s.dLK
+ " instanceof Array)){j="
+ vName
+ "."
+ _s.dLK
+ ";if(k=='string')j=j.split(',');for(k in j)if(j[k])Vlist.push(j[k]);}else Vlist.push('"
+ vName + ".'+j);for(j in " + vName
+ ".prototype)Vlist.push('" + vName
+ ".prototype.'+j);");
} catch (e) {
undone.push('(' + vType + ')' + vName + '.[child]'
+ '(error ' + (e.number & 0xFFFF) + ':'
+ e.description + ')');
}
// function 才會產生 \r\n 問題,所以先處理掉
val = ('' + val).replace(/[\r\n]/g, line_separator);
if ((t = val.match(/^\s*function\s*\(/)) || val.match(/^\s*function\s+([\w]*)([^(]*)\(/)) // 這種判別法不好!
if (t || (t = RegExp.$1) == 'anonymous') {
func.push(vName); vType = (typeof t == 'string' ? t : 'no named') + ' ' + vType;
if (t === 'anonymous') {
// 忠於原味(笑)
// anonymous 是從new Function(文字列を使って)來的
var m = val.match(/\(([^)]*)\)\s*{/), l = RegExp.lastIndex, q = val.match(/[^}]*$/); q = RegExp.index;
if (!m) { undone.push('(anonymous function error:' + val + ')' + vName); continue; }
if (t = m[1].replace(/,/g, "','")) t = "'" + t + "',"; t = 'new Function(' + t + dQuote(_.reduce_code(val.slice(l, q - 1))) + ')';
} else t = val;
} else if (t == vName) {
// 関数(function): http://www.interq.or.jp/student/exeal/dss/ejs/1/2.html
if (c) codeText += ';' + line_separator, c = 0; func.push(vName), codeText += val + line_separator; continue;
} else if (val.indexOf('[native code]') != -1) { undone.push('(native code function error:' + val + ')' + vName); continue; } // 內建(intrinsic 或 built-in)函數:這種判別法不好!
else if (t in vars) {
// 已經登錄過了,所以就這麼下去..
done.push('(' + vType + ')' + vName), func.push(vName);
}
else {
if (c)
codeText += ';' + line_separator;
codeText += val + line_separator;
vars[t] = vari.length;
done.push('(' + vType + ')' + t);
func.push(t, vName);
c = 0;
}
else {
// unknown error
undone.push('(function error:' + val + ')' + vName);
continue;
}
} else if (vType == 'number') {
// http://msdn2.microsoft.com/zh-tw/library/y382995a(VS.80).aspx
var k = 0, m = 'MAX_VALUE,MIN_VALUE,NEGATIVE_INFINITY,POSITIVE_INFINITY,NaN'.split(',');
if (val === NaN || val === Infinity || val === -Infinity) t = '' + val;
else for (t = 0; k < m.length; k++) if (val === Number[m[k]]) { t = 'Number.' + m[k]; break; }
if (!t) {
// http://msdn2.microsoft.com/zh-tw/library/shydc6ax(VS.80).aspx
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; }
if (!t) t = (t = Math.floor(val)) == val && ('' + t).length > (t = '0x' + val.toString(16)).length ? t : val;
}
} else if (vType == 'boolean' || val === null) t = val; //String(val)//val.toString() // typeof null is 'object'
else if (vType == 'string') t = dQuote(val);
else if (vType == 'object' && typeof val.getTime == 'function' || vType == 'date') t = 'new Date(' + ((val - new Date) > 999 ? val.getTime() : '') + ')'; // date被當作object
// http://msdn2.microsoft.com/en-us/library/dww52sbt.aspx
else if (vType == 'object' && /*val.constructor==Error "[object Error]" */('' + val.constructor).indexOf('Error') != -1)
t = 'new Error' + (val.number || val.description ? '(' + (val.number || '') + (val.description ? (val.number ? ',' : '') + dQuote(val.description) : '') + ')' : '');
/**
*<code>
else if(vName=='set_obj_value.F'){ // 明白宣示在這裡就插入依存函數:不如用 set_obj_value.F,'set_obj_value();'
if(!vars['set_obj_value']||!vars['dQuote'])Vlist=Vlist.slice(0,i).concat('set_obj_value','dQuote',Vlist.slice(i));
Vlist[i--]=directInput+'var set_obj_value.F;';continue;
}
</code>*/
else if (vType == 'object' && (val.constructor == Object || val.constructor == Array)) {// instanceof
var k, T = '', T_ = '', T_2 = '', _i = 0, cmC = '\\u002c', eqC = '\\u003d', NL_ = "'" + line_separator + "+'", maxLen = 300 - NL_.length; // type;loop用,Text,間距,integer?
if (val.constructor == Object) {
t = '';
// http://fillano.blog.ithome.com.tw/post/257/59403
// ** 一些內建的物件,他的屬性可能會是[[DontEnum]],也就是不可列舉的,而自訂的物件在下一版的ECMA-262中,也可以這樣設定他的屬性。
for (k in val)
if (typeof val[k] == 'object' || typeof val[k] == 'function')
Vlist.push(vName + '.' + k); // 簡單的Object遞迴
else {
T_2 = k.replace(/,/g, cmC).replace(/=/g, eqC) + '=' + ('' + val[k]).replace(/,/g, cmC).replace(/=/g, eqC) + ',';
if (T_.length + T_2.length > maxLen) T += T_ + NL_, T_ = T_2; else T_ += T_2;
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;
}
T += T_;
} else /*if(val.constructor==Array)*/ {
var base = 16, d_, d = -1, k_, kA = [];
for (k in val)
if (typeof val[k] == 'object' || typeof val[k] == 'function') {
// 簡單的Object遞迴
Vlist.push(vName + '.' + k);
}
else {
// 因為Array中仍有可能存在非數字index
kA.push(parseInt(k) == k ? parseInt(k) : k);
}
kA.sort(), vType = 'Array', t = ',' + base;
for (k_ = 0; k_ < kA.length; k_++) {
if (!((k = kA[k_]) in val)) {
if (d_ != '*')
if (k - d == 1)
d_ += ',';
else
d_ = '*';
} else {
T_2 = (k - d == 1 ? ''
: d_ != '*' && k - d < 3/* k.toString(base).length-1 */ ? d_
: (isNaN(k) ? k.replace(/,/g, cmC)
.replace(/=/g, eqC)
: k.toString(base))
+ '=')
+ ('' + val[k]).replace(/,/g, cmC).replace(/=/g, eqC)
+ ',';
d_ = '';
if (T_.length + T_2.length > maxLen)
T += T_ + NL_, T_ = T_2;
else
T_ += T_2;
}
d = k;
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;
}
T += T_;
}
if (T) {
if (!vars['set_obj_value'] || !vars['dQuote']) {
// 假如沒有set_obj_value則須將之與其所依存之函數(dQuote)一同加入
Vlist.push('set_obj_value', 'dQuote');
if (!vars['set_obj_value.F'])
Vlist.push(direct_input + 'var set_obj_value.F;');
}
afterCode += "set_obj_value('"
+ vName
+ "','"
+ T.slice(0, -1)
+ "'"
+ (_i ? _i == 1 ? ",1" : ",.1" : t ? ",1"
: '') + t + ");" + line_separator;
t = 1;
} else {
//new Object(), new Array()
t = vType == 'Object' ? '{}' : '[]';
}
} else if (vType == 'object' && val.constructor == RegExp)
t = val;
else if (vType == 'undefined')
// 有定義(var)但沒設定值,可計算undefined數目
t = 1;
else if (t = 1, vType != 'unknown')
if (('' + val).match(/^\s*\[[Oo]bject\s*(\w+)\]\s*$/)) {
// 僅對Math有效?
t = RegExp.$1;
}
else vType = 'unknown type: ' + vType + ' (constructor: ' + val.constructor + ')', alert(vName + ': ' + vType + ', please contract me!\n' + val); // 未知
else {
// unknown
alert('The type of ' + vName + ' is "' + vType + '"!');
}
if (typeof t != 'undefined') {
if (vName.indexOf('.') == -1) {
//alert(codeText.substr(codeText.length-200));
codeText += (c ? ',' : 'var ') + vName + (t === 1 && vType != 'number' ? '' : '=' + t), c = 1;
}
else if (t !== 1 || vType == 'number')
codeText += (c ? ';' : '') + vName + '=' + t + ';',
c = 0;
}
done.push('(' + vType + ')' + vName);
}
if (c) {
codeText += ';' + line_separator;
//c=0;//alert(codeText.substr(codeText.length-200));//alert(afterCode);
}
return [codeText, afterCode, vari, func, done, undone, Vlist];
};
/**
* default direct input symbol
* @type String
* @_memberOf _module_
*/
_.generate_code.ddI = '*';
/**
* default separator
* @type String
* @_memberOf _module_
*/
_.generate_code.dsp = ',';
// null code series
//write_file('try.js',add_null_code(50000));
// 處理null_code的變數暫存,null_code_data[變數名]=變數值,null_code_data_length=length,add_null_codeD:add_null_code data,因為每次都重新執行null_code()很費時間
var null_code_data, null_code_data_length, add_null_codeD;
// 為了基底才能加入function而作
function add_null_code(len, type) {
var s = '', t, l, i, j; if (typeof add_null_codeD != 'object') add_null_codeD = []; qq = 0;
while (s.length < len) {
/* t=Math.random()<.5?'function':'';
s+=len-s.length>9?null_code((len/2>999?999:len/2)+'-'+len,t):null_code(len,t);*/
l = len - s.length > 9 ? len > 2e3 ? 999 : len / 2 : len;
j = 0; for (i in add_null_codeD) if (i > l) break; else j = i;
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]; }
s += j && len - s.length - j < 50 ? add_null_codeD[j]
// :(t=null_code(l),add_null_codeD[t.length]=t);
: (t = null_code(l) ? add_null_codeD[t.length] = t : '');
}
return s;
}
// variables,value
function null_code_data_add(vari, val) {
if (vari) {
if (typeof null_code_data != 'object') null_code_data = {}, null_code_dataI = [], null_code_data_length = 0;
if (!(vari in null_code_data)) null_code_dataI.push(vari), null_code_data_length++;
null_code_data[vari] = val;
}
}
/**
*<code>
var t=null_code('230-513','function');alert(t.length+'\n'+t);
</code>*/
// 其他方法(有閒情逸致時再加):/**/,//,var vari=num+-*/num,str+-str,if(typeof vari=='~'){},try{eval('~');}catch(e){},eval('try{}catch(e){}');if()WScript.Echo();
_// JSDT:_module_
.
/**
* 產生無用的垃圾碼
* @param length \d || \d-\d
* @returns {String} 無用的垃圾碼
* @see
* @_memberOf _module_
*/
null_code = function (length, type) {
// variables;up,down:長度上下限
var t = '', vari = [], u, d;
if (typeof null_code_data != 'object')
null_code_data = {}, null_code_dataI = [],
null_code_data_length = 0;
if (typeof length == 'number')
u = d = Math.floor(length);
else if (length = '' + length, (i = length.indexOf('-')) != -1)
d = parseInt(length.slice(0, i)), u = parseInt(length
.substr(i + 1));
if (u < d) {
var a = d;
d = u, u = a;
}
if (!length || !u || length < 0)
return '';
if (typeof type != 'string')
type = typeof type;
//if(type=='boolean'){return Math.random()<.5?1:0;}
if (type == 'number') {
return Math.floor(Math.random() * (u - d) + d);
}
if (type == 'n2') {
if (u < 9 && d < 9)
d = Math.pow(10, d), u = Math.pow(10, u);
return Math.floor(Math.random() * (u - d) + d);
}
if (type == 'string') {
// if(d<0&&(d=0,u<0))
if (d < 0 && u < (d = 0))
return '';
for (var i = 0, l = null_code(d + '-' + u, 0), t = []; i < l; i++)
t.push(null_code('32-128', 0));
return fromCharCode(t);
}
if (type == 'vari') {
// 變數variables
if (d) d--; u--; if (u > 32) u = 32; else if (u < 1) u = 1; // 最長變數:32
var a, i, l, c = 0;
do {
t = [], a = null_code('65-123', 0), i = 0, l = null_code(d + '-' + u, 0);
if (a > 90 && a < 97) a = 95; t.push(a);
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;
t = fromCharCode(t); try { eval('a=typeof ' + t + '!="undefined";'); } catch (e) { } // 確保是新的變數
if (c % 9 == 0 && d < u)++d;
} while (
// 不能確保是新變數的話,給個新的:繼續作。★此作法可能導致長時間的迴圈delay!因此限制最多99次。
++c < 99 && (a || (t in null_code_data)));
//if(c==99){alert('重複:['+a+']'+t);WScript.Quit();}
return t;
}
if (type == 'function') {
var i = 0, l = null_code('0-9', 0), fN = null_code('2-30', 'vari'), a = line_separator + 'function ' + fN + '(', b = line_separator + '}' + line_separator, v, D = []; // fN:函數名
// 只加入函數名
null_code_data_add(fN, 'function');
if (l) {
for (; i < l; i++)
v = null_code('2-30', 'vari'), a += v + ',', D.push(v);
a = a.slice(0, -1);
}
a += '){';
l = (a + b).length + line_separator.length;
if (u < l)
return null_code(length);
return a + (line_separator + null_code((d < l ? 0 : d - l) + '-'
+ (u - l))).replace(/\n/g, '\n ') + b;
}
// others:type=='code'
var l = null_code(length, 0);
while (t.length < l) {
var a, v, va = (Math.random() < .5 ? (va = null_code('1-6', 0))
: dQuote(va = null_code('5-'
+ (u - t.length > 50 ? 50 : u - t.length),
'string')));
if (u - t.length > 20 && Math.random() < .9) {
if (Math.random() < .7 && null_code_data_length > 9)
v = null_code_dataI[null_code(0 + '-'
+ null_code_data_length, 0)], a = v + '=' + va;
else
v = null_code('1-9', 'vari'), a = 'var ' + v
+ (Math.random() < .3 ? '' : '=' + va);
a += ';' + (Math.random() < .4 ? line_separator : '');
null_code_data_add(v, va);
} else {
a = Math.floor(Math.random() * 4);
a = a == 1 ? ' ' : a || u < t.length + line_separator.length ? ' '
: line_separator;
}
if (t.length + a.length <= u)
t += a;
}
return t;
};
// ↑null code series
/**
*<code>
bug:
當每一行都去除\n也可時方能使用!否則會出現「需要;」的錯誤!
可能會lose條件式編譯(@cc_on等)的資訊或判別錯誤!另外,尚不保證不會lose或更改程式碼!
http://www.dreamprojections.com/syntaxhighlighter/Default.aspx
TODO:
將 local various 甚至 global 依頻率縮短,合併以字串組合代替。 selectable
safer cut '\r\n'
{_exp1_;_exp2_;} → _exp1_,_exp2_;
safer cut ';' ;} → }
compress: eval("~")
(function(~){~})(~);
var fascii2ascii = (function(){
var cclass
= '['+String.fromCharCode(0xff01)+'-'+String.fromCharCode(0xff5e)+']';
var re_fullwidth = new RegExp(cclass, 'g');
var substitution = function(m){
return String.fromCharCode(m.charCodeAt(0) - 0xfee0); // 0xff00 - 0x20
};
return function(s){ return s.replace(re_fullwidth, substitution) };
})();
/*@cc_on OK
/*@ cc_on error
/* @cc_on 無效
JSlint 可以協助您檢查出有問題的程式碼。
http://www.jslint.com/
Javascript compressor
http://dean.edwards.name/packer/
http://javascriptcompressor.com/
http://www.creativyst.com/Prod/3/
http://www.radok.com/javascript-compression.html
http://alex.dojotoolkit.org/shrinksafe/
http://www.saltstorm.net/depo/esc/introduction.wbm
</code>*/
_// JSDT:_module_
.
/**
* 精簡程式碼:去掉註解與\s\n。
* use for JSON (JavaScript Object Notation)
* @param code 欲精簡之程式碼
* @param mode mode=1:''中unicode轉\uHHHH
* @returns {String} 精簡後之程式碼
* @example
* CeL.run('code.reorganize');
* CeL.reduce_code('a + v = ddd;');
* @see
* @requires
* @_memberOf _module_
*/
reduce_code = function (code, mode) {
if (!code)
//sss=0,mmm=90;
return '';
var _s = _.reduce_code, reduce_space = _s.reduce_space, A = '', a = '' + code, m, b, q, c, Begin, End;
//reduce_codeM=[''];
while (a.match(/['"\/]/)) {
with (RegExp)
Begin = index, End = lastIndex, m = lastMatch;
//alert(a);
// RegExp.$'等
if (Begin && a.charAt(Begin - 1) == '$') {
A += reduce_space(a.slice(0, Begin)) + m;
a = a.substr(End);
continue;
}
// comment
if (m == '/') if (m = a.charAt(RegExp.lastIndex), m == '*' || m == '/') {
//if(++sss>mmm-2&&alert('sss='+sss+line_separator+a),sss>mmm){alert('comment');break;}
//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);//
A += reduce_space(a.slice(0, Begin));
b = m == '*' ? '*/' : '\n';
m = End + 1;
do {
// 預防「\*/」…其實其他地方(如["'])也需要預防,但沒那精力了。
m = a.indexOf(b, m);
if (a.charAt(m - 1) == '\\')
m += 2;
else
break;
} while (m != -1);
//reduce_codeM.push('find comment: Begin='+Begin+',End='+End+',m='+m+',b='+b.replace(/\n/g,'\\n')+line_separator+(m-End>200||m==-1?a.substr(Begin,200)+'..':a.slice(Begin,m))+line_separator+line_separator+'continue:'+line_separator+a.substr(m+b.length,200)+'..');
if (m == -1)
if (b == '\n') { a = ''; break; /*return A;*/ }
else throw new Error('[/*] without [*/]!\n' + a.substr(Begin, 200));
else if (
// 7: 最起碼應該有這麼多 char 的 comment 才列入查核
7 + End < m &&
//a.substring(End+1,m-5).indexOf('@cc_on')==0 不一定只有 cc_on
/^@[cei][a-z_]+/.test(a.substring(End + 1, m - 5))
)
//alert('There is conditional compilation detected,\n you may need pay attention to:\n'+a.substring(End+1,m-5)),
// 對條件式編譯全選,預防資訊lose。僅有'/*@cc_on'才列入,\/*\s+@\s+cc_on不可!
A += a.slice(End - 1, m + b.length).replace(/\s*(\/\/[^\r\n]*)?(\r?\n)\s*/g, '$2'), a = a.slice(m + b.length);
else if (a = a.substr(m + b.length), A.match(/\w$/) && a.match(/^\s*\w/))
// 預防return /*~*/a被轉為returna
A += ' ';
} else {
// RegExp
//reduce_codeM.push('find RegExp: Begin='+Begin+line_separator+a.substr(Begin,200)+line_separator+'-'.repeat(20)+line_separator+A.substr(A.length-200)+'..');
b = a.slice(0, Begin), m = 1; //c=Begin,q=End
if (b.match(/(^|[(;+=!{}&|:\\\?,])\s*$/))
// RegExp:以起頭的'/'前面的字元作判別,前面是這些則為RegExp
m = 1;
else if (b.match(/[\w)\]]\s*$/))
// 前面是這些則為op
m = 0;
else
// 需再加強前兩項判別之處
throw new Error(
'Unknown [/]! Please check it and add rules!\n'
+ b + '\n-------------\n'
+ a.slice(0, End + 80)
// +'\n-------------\n'+A
);
if (!m)
// 應該是op之類
//if(!m)A+=a.slice(0,q),a=a.substr(q);
A += reduce_space(a.slice(0, End)),
a = a.substr(End);
else {
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;//
//if(++sss>mmm-2&&alert('sss='+sss+'\n'+a),sss>mmm){alert('reg');break;}
while (m = a.substr(c).match(/([^\\]|[\\]{2,})([[\/\n])/)) { // 去掉[]
//reduce_codeM.push('find RegExp [ or / or \\n :'+line_separator+a.substr(c+RegExp.index+1,20));
if (m[1].length > 1 && m[1].length % 2 == 1) { c += RegExp.lastIndex - 1; continue; } // 奇數個[\]後
else if (m = m[2], m == '/') break;
if (m == '[')
while ((m = a.substr(c += RegExp.lastIndex).match(/([^\\]|[\\]{2,})\]/))) { // 不用c+=RegExp.index+1是因[]中一定得有字元
if (m[1].length > 1 && m[1].length % 2 == 1) { c += RegExp.lastIndex - 1; continue; } // 奇數個[\]後
c += RegExp.lastIndex - 1; m = 1; break; // -1:因為偵測'['時需要前一個字元
//if(++sss>mmm-2&&alert('sss='+sss+'\nc='+c+'\n'+a.substr(c)),sss>mmm){alert('reg 2');break;}
}
if (m != 1) throw new Error('RegExp error!\nbegin with:\n' + a.substr(Begin, 200));
}
//reduce_codeM.push('find RegExp 2:'+line_separator+a.slice(0,c+RegExp.lastIndex));
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;
//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);//
}
} else {
// quotation
//alert('quotation:\n'+a)
//reduce_codeM.push('find quotation:'+line_separator+a.substr(RegExp.index,200));
//if(++sss>mmm-2&&alert('sss='+sss+'\n'+a),sss>mmm){alert('quo');break;}
//c=RegExp.index,b=a.substr(RegExp.lastIndex-1).match(new RegExp('[^\\\\]('+(q=m)+'|\\n)')); 較正式
/**
*<code>
q=m; // 2009/8/16 15:59:02 FAILED
function test_quotation(){
'\'; // Error
'\\\'; // Error
'\\\\\'; // Error
'';
'n';
'\\';
'nn';
'\\n';
'n\\';
'n\\n';
'\\\\';
'\\\\n';
'n\\\\';
'n\\\\n';
'nn\\\\';
'nn\\\\n';
'nnn\\\\';
'nnn\\\\n';
}
alert(reduceCode(test_quotation));
alert(reduceCode(reduceCode));
// 找到 '\n' 為止,考慮 [\\\\]\\r?\\n
c = Begin + 1, b = '';
while ((c = a.indexOf('\n', c)) != -1) {
q = a.charAt(c - 1);
if (q == '\\' || q == '\r' && a.charAt(c - 2) == '\\') {
c++;
continue;
}
};
if (a.charAt(c - 1))
// alert('use RegExp: '+new
// RegExp('^([^\\\\\\r\\n]*|[\\\\][^\\r\\n]|[\\\\]\\r?\\n)*('+q+'|\\n)'));
b = a.slice(Begin + 1).match(
new RegExp('^([^\\\\\\r\\n]*|[\\\\][^\\r\\n]|[\\\\]\\r?\\n)*(' + q
+ '|\\n)')); // too slow!
alert('test string:\n' + a.slice(Begin + 1))
if (!b || b[2] == '\n')
throw new Error('There is a start quotation mark [' + q
+ '] without a end quotation mark!\nbegin with:\n'
+ a.substr(Begin, 200)); // 語法錯誤?
q = RegExp.lastIndex + 1;
</code>*/
// 未考慮 '\n' (不能 check error!)
c = Begin;
q = m;
// 考慮 [\\\\]\\r?\\n
while (b = a.substr(c).match(new RegExp('([^\\\\\\r]|\\\\{2,})(' + q + '|\\r?\\n)')))
if (b[1].length > 1 && b[1].length % 2 == 1)
c = RegExp.lastIndex - 1;
else
break;
if (!b || b[2] == '\n')
// 語法錯誤?
throw new Error('There is a start quotation mark ['
+ q + '] without a end quotation mark!\nget:['
+ b + ']\nbegin with:\n' + a.substr(Begin, 200));
//reduce_codeM.push('find quota ['+q+']:'+line_separator+a.substr(c,RegExp.lastIndex)+line_separator+'continue:'+line_separator+a.substr(c+RegExp.lastIndex,99));
q = RegExp.lastIndex;
//alert('q='+q+',['+b[0]+']');
//alert(b[1]);
//alert(b[2]);
b = a.substr(Begin, q).replace(/\\\r?\n/g, '');
//alert('mode='+mode);
if (mode == 1) {
m = '';
for (var i = 0; i <= q; i++)
m += b.charCodeAt(i) > 127 ? '\\u'
+ b.charCodeAt(i).toString(16) : b
.charAt(i);
}
else m = b;
//A+=a.slice(0,c+=RegExp.lastIndex),a=a.substr(c);
A += reduce_space(a.slice(0, Begin)) + m, a = a.substr(Begin + q);
//alert('A='+A);
//alert('a='+a);
// 對於 ~';{ → ~'{ 或 ~';if → ~'if 不被接受。
//if(!/^[\s\r\n]*\}/.test(a))A+=';';
}
}
// 後續處理
A += reduce_space(a);
// 這兩行在 reduce_space() 中已處理
//A=A.replace(/([^;])\s*\n+\s*/g,'$1;');
//A=A.replace(/\s*\n+\s*/g,'');//while(A.match(/\s*\n\s*/))A=A.replace(/\s*\n\s*/g,'');//
return A;
};
/**
*<code>
tech. data:
string:
['"]~$1
RegExp:
[/]~$1[a-z]*
[/]~$1[gim]*
=RegExp.[source|test(|exec(]
.match(RegExp)
.replace(RegExp,)
.search(RegExp)
op[/]:
word/word
word/=word
~:
/\\{0,2,4,6,..}$/
註解comment:
/*~* /
//~\n
符號denotation:/[+\-*=/()&^,<>|!~%\[\]?:{};]+/
+-
word:/[\w]+/
program:
((denotation|word|comment)+(string|RegExp)*)+
test:
i++ +
a+=++i+4
++a+i++==++j+ ++e
a++ += ++d
a++ + ++b
for(.*;;)
</code>*/
_// JSDT:_module_
.
/**
* 精簡程式碼部分:去掉\n,;前後的空白等,應由 reduce_code() 呼叫。
* @param code 輸入欲精簡之程式碼
* @returns {String} 精簡後之程式碼
* @see
* http://dean.edwards.name/packer/
* @_memberOf _module_
*/
reduce_code.reduce_space = function (code) {
// 比下一行快很多,但為了正確性而放棄。
//code=code.replace(/\s*\n+\s/g,'');
// 當每一行都去除\n也可時方能使用!否則會出現「需要;」的錯誤!
code = code
.replace(
/(\S?)\s*\n+\s*(\S?)/g,
function ($0, $1, $2) {
var a = $1, b = $2;
return a
+ (a && b && a.match(/\w/) && b.match(/\w/) ? ' ' : '')
+ b;
})
.trim();
//if(code.match(/\s+$/))code=code.slice(0,RegExp.index);
//if(code.match(/^\s+/))code=code.substr(RegExp.lastIndex);
// 對喜歡將\n當作;的,請使用下面的;但這可能造成失誤,例如[a=(b+c)\nif(~)]與[if(~)\nif(~)]
/**
*<code>
var m, a;
while (m = code.match(/\s*\n+\s*(.?)/))
a = RegExp.lastIndex, code = code.slice(0, RegExp.index)
+ (m[1].match(/\w/) ? ';' : '')
+ code.substr(a - (m[1] ? 1 : 0));
if (m = code.match(/\s+$/))
code = code.slice(0, RegExp.index);
if (m = code.match(/^\s+(.?)/)) {
code = code.substr(RegExp.lastIndex - 1);
if ((m[0].indexOf('\n') != -1 && m[1].match(/\w/)))
code = ';' + code;
}
</code>*/
code = code
// 最後再作
//.replace(/([^;])\s*\n+\s*/g,'$1;').replace(/\s*\n+\s*/g,'')
// 因為直接執行下行敘述會將for(~;;也變成for(~;,所以需先作處理。
//.replace(/for\s*\(([^;]*);\s*;/g,'for;#$1#')
// 在''等之中執行此行可能出問題,因此另外置此函數。
//.replace(/\s*;+\s*/g,';')
//.replace(/for;#([^#]*)#/g,'for($1;;')
//.replace(/(.)\s+([+\-]+)/g,function($0,$1,$2){return $1+($1=='+'||$1=='-'?' ':'')+$2;}).replace(/([+\-]+)\s+(.)/g,function($0,$1,$2){return $1+($2=='+'||$2=='-'?' ':'')+$2;}) // + ++ +
.replace(/([+\-])\s+([+\-])/g, '$1 $2').replace(/([^+\-])\s+([+\-])/g, '$1$2').replace(/([+\-])\s+([^+\-])/g, '$1$2') // + ++ +
.replace(/\s*([()\[\]&|^{*\/%<>,~!?:.]+)\s*/g, '$1') // .replace(/\s*([()\[\]&|{}/%,!]+)\s*/g,'$1') // 去掉'}',因為可能是=function(){};或={'ucC':1};
.replace(/([a-zA-Z])\s+([=+\-])/g, '$1$2').replace(/([=+\-])\s+([a-zA-Z])/g, '$1$2')
.replace(/\s*([+\-*\/%=!&^<>]+=)\s*/g, '$1')
//.replace(/\s*([{}+\-*/%,!]|[+\-*\/=!<>]?=|++|--)\s*/g,'$1')
// 因為直接執行下行敘述會將for(~;;也變成for(~;,所以需先作處理。
.replace(/for\(([^;]*);;/g, 'for;#$1#')
//.replace(/};+/g,'}') /*.replace(/;{2,}{/g,'{')*/.replace(/{;+/g,'{')//.replace(/;*{;*/g,'{')//在quotation作修正成效不彰
// 去掉'}',因為可能是=function(){};或={'ucC':1};
.replace(/\s*([{;]);+\s*/g, '$1')//.replace(/\s*([{};]);+\s*/g,'$1')
.replace(/for;#([^#]*)#/g, 'for($1;;')
.replace(/\s{2,}/g, ' ')
.replace(/([^)]);}/g, '$1}') // ~;while(~);} but: ~;i=(~);} , {a.b();}
;
//if(code.charAt(0)=="'")code=(code.charAt(1)=='}'?'}':code.charAt(1)==';'?'':code.charAt(1))+code.substr(2);
return code;
};