前沿拓展:
命令行選項語法錯誤
命令行的意思是按住winkey+R鍵,彈出的運行中輸入CMD,確定后跳出一個黑色窗口,這就是命令行。
命令行里有許多命令,有的是系統(tǒng)自帶,有的是下載的。你可以輸入命令/?查看如何用這個命令。
比如輸入 del/?,就會出現(xiàn)del這個命令的用法。
命令行選項語法錯誤,就是命令用錯了。彈出來關(guān)掉就好了。
本文,將實現(xiàn)命令行輸出帶有語法高亮、帶行號的JS代碼。
效果如下圖所示:
對于JS程序員而言,這個效果是有些驚喜的。
而實現(xiàn)起來,卻似乎是出乎意料的簡單。
直接上源碼:
var js_code = `
function get_copyright(){
var domain = "jshaman.com";
var from_year = 2017;
var copyright = "(c)" + from_year + "-" + (new Date).getFullYear() + "," + domain;
return copyright;
}
console.log(get_copyright());
`;
//高亮顯示代碼
const { codeFrameColumns } = require('@babel/code-frame');
const res = codeFrameColumns(js_code, {}, {
highlightCode: true,
});
console.log(res);
由代碼可見,僅僅是使用@babel/code-frame這個NodeJS模塊即可直接實現(xiàn)高亮語法。
本著“知其然,知其所以然”的理念,我們再深入探究一下實現(xiàn)語法高亮的原理。
第一,是進行語法分析,從JS代碼分離出不同的關(guān)鍵字。
在這一步,可以使用babel的parser獲得代碼的AST(抽象語法樹),再遍歷AST進行分析取詞。
例如獲得變量名、函數(shù)名的方式如下:
var parser = require('@babel/parser');
var traverse = require('@babel/traverse').default;
//獲得抽象語法樹
var ast = parser.parse(js_code);
//遍歷語法樹
traverse(ast, traverse(ast,{
//函數(shù)
"FunctionDeclaration"(path){
var fun_name = path.node.id.name;
console.log("函數(shù)名:",fun_name);
},
//變量
"VariableDeclaration"(path){
var var_name = path.node.declarations[0].id.name;
console.log("變量名:",var_name);
},
}));
console.log(js_code)
注:語法分析也有其它辦法,比如用正則等。
接著上面的思路,當獲得變量名、函數(shù)名之后,接下來即可對其進行著色。
寫著色功能之前,先來看行代碼:
console.log('u001b[31m JShaman專注于JS代碼混淆加密 u001b[0m');
它會輸出帶顏色的信息,如下圖:
為什么看似有些亂碼的console執(zhí)行時會出現(xiàn)彩色的文字呢?
解釋是這樣的:
The original specification only had 8 colors, and just gave them names. The SGR parameters 30-37 selected the foreground color, while 40-47 selected the background. Quite a few terminals implemented "bold" (SGR code 1) as a brighter color rather than a different font, thus providing 8 additional foreground colors. Usually you could not get these as background colors, though sometimes inverse video (SGR code 7) would allow that. Examples: to get black letters on white background use ESC[30;47m, to get red use ESC[31m, to get bright red use ESC[31;1m. To reset colors to their defaults, use ESC[39;49m (not supported on some terminals), or reset all attributes with ESC[0m.
大意是:“u001b”是一個特殊的轉(zhuǎn)意字符,遵從一定的規(guī)則,可以用來設(shè)置文字或背景顏色。
上面代碼中,前面的u001b[31m用于設(shè)定SGR顏色,后面的u001b[0m相當于一個封閉標簽作為前面SGR顏色的作用范圍的結(jié)束點標記。
有了這個知識儲備后,我們就可以繼續(xù)前面的工作。
當從JS代碼中進行分詞之后,將代碼用此方法進行改造,即可使語法高亮。
運行效果:
至此,便已得知了命令行語法高亮的全部秘密。
最后,奉上本示例完整源碼:
var js_code = `
function demo(){
var domain = "jshaman.com";
var from_year = 2017;
var copyright = "(c)" + from_year + "-" + (new Date).getFullYear() + "," + domain;
return copyright;
}
console.log(demo());
`;
//高亮顯示代碼
const { codeFrameColumns } = require('@babel/code-frame');
const res = codeFrameColumns(js_code, {}, {
highlightCode: true,
});
console.log(res);
var parser = require('@babel/parser');
var traverse = require('@babel/traverse').default;
//獲得抽象語法樹
var ast = parser.parse(js_code);
//遍歷語法樹
traverse(ast, traverse(ast,{
//函數(shù)
"FunctionDeclaration"(path){
var fun_name = path.node.id.name;
console.log("函數(shù)名:",fun_name);
js_code = js_code.replace(fun_name,"u001b[32m" + fun_name + "u001b[0m");
},
//變量
"VariableDeclaration"(path){
var var_name = path.node.declarations[0].id.name;
console.log("變量名:",var_name);
js_code = js_code.replace(var_name,"u001b[31m" + var_name + "u001b[0m");
},
}));
console.log(js_code)
JavaScript奇淫技巧:按鍵精靈
JavaScript奇淫技巧:收縮控制流
JavaScript奇淫技巧:變速齒輪
JavaScript奇淫技巧:隱寫術(shù)
JavaScript奇淫技巧:壓縮并加密圖片
JavaScript奇淫技巧:用try、catch實現(xiàn)JS代碼加密解密
拓展知識:
命令行選項語法錯誤
安裝時可能會遇到其他軟件占用某個安裝可能會修改或占用的程序而造成的,或者是殺毒軟件或防火墻所造成的,你只要試著在安裝時關(guān)閉其他程序再安裝一遍應(yīng)該就可以了。
原創(chuàng)文章,作者:九賢生活小編,如若轉(zhuǎn)載,請注明出處:http:///22101.html