聖誕節,把你的 JavaScript 程式碼都裝扮成聖誕樹吧
用開源專案將你的 JavaScript 變成聖誕樹吧!
效果的話,可以去看一下我們公司的官網(http://www.souche.com ),裡面涉及到的js程式碼在今天大部分被臨時替換成了聖誕樹,開啟每個js程式碼即可看到效果。
其實也不神奇,我們使用了自己寫的一個nodejs庫,如果您要實現這樣的效果,只需要按照下面第一章節的方法即可。當然您也可以線上壓縮程式碼:http://f2e.souche.com/cheniu/js2image.html
下面分兩章節,分別講解如何使用js2image這個庫 和 js2image這個庫的原理。
- github地址:https://github.com/xinyu198736/js2image ps:求star
- 線上轉換地址:http://f2e.souche.com/cheniu/js2image.html
js2image使用
github地址:https://github.com/xinyu198736/js2image 歡迎送上star或者follow。
js2image主要有兩個比較特殊的特性:
- 將任意js原始碼 壓縮成 用程式碼堆砌成圖形的最終程式碼。例如聖誕樹,聖誕老人,程式碼和圖片都可以自定義。
- 壓縮後的js程式碼格式雖然被破壞,但是仍然可以執行。這個是關鍵點!
壓縮後的示例可以檢視這些js(均來自搜車官網):
- http://assets.souche.com/assets/js/souche.js souche主指令碼
- http://assets.souche.com/assets/js/lib/jquery-1.7.1.min.js jquery 1.7.1
- http://assets.souche.com/assets/js/lib/mustache.js mustache
使用方式很簡單:
npm install js2image -g;
然後在存在js的資料夾中執行:
js2image -s ./resource/jquery.js
或者針對某個目錄下所有的js執行(慎用),會深度遍歷此目錄裡所有的js檔案然後壓縮出.xmas.js字尾的結果檔案。
js2image -s ./resource/
即可生成一個對應的 **.xmas.js 的檔案。
如果要將js2image整合到gulp或者其他nodes專案中,可以使用用模組的形式:
var Js2Image = require("js2image");//獲取結果的 codeJs2Image.getCode("./resource/jquery.js","./resource/tree.png", {}).then(function(code){
console.log(code);
})
更多的資訊可以參照github上的文件。
如果只是要使用這個效果,看到這裡就ok啦,下面講解這個庫的原理,有些地方可能比較繞。
js2image實現原理
js2image的實現從宏觀來說,大體只有3個要點。
- 從圖片生成字元畫,這個有現成的庫。
- 把js程式碼分割成一小塊一小塊,儘量小,然後用逐行填充的方式分別替換到上一步生成的字元畫裡去。
- js程式碼中有諸多不能分開的語法,分塊的時候要把這些語法保留在一個塊內。這個是這個庫的難點所在,也是程式碼最多最繞的地方。
稍有想法的同學估計看到這裡基本已經明白是怎麼回事了,下面一一講解這3個要點。
① 從圖片生成2值得字元畫
這裡用到了一個現成的npm包:image-to-ascii 。這個庫的作用是用指定的字元來還原一個影像。而我們用這個庫來生成一個用 ☃字元和空格 分別表示黑和白的字元畫,然後將字元畫的每一行分解成陣列的一個元素,供第二步使用,這就是我們中間生成的一個struct,程式碼見 utils/image-to-struct.js
② 分割js原始碼成儘量小的小塊。
這是非常重要的一步,js程式碼具體可以分解成多細的小塊呢?
看下面一段程式碼:
!function
(e,t
){ (
"objec"
+"t") ==
typeof
module && (
"objec"+"t")
== typeof module
.exports?module.
exports=e.document?t(e
,!0):function(e){if(!e.
document) throw new Error (
("jQuer"+"y req"+"uires"+" a wi"
+"ndow "+"with "+"a doc"+"ument") )
; return t (e)}:t(e)}( ("undef"+"ined")
!=typeof window ?window:this,function(e,t){var
這是jQuery開始的一段程式碼,可以看到,大部分運算子都允許中間插入任意多的空格或者換行,我們正是利用這一特性將js程式碼解肢,然後拼接成任意形狀的圖片。
核心程式碼其實就是一個正則,我們用這個正則把js原始碼解構成一個陣列,然後後續根據每行需要的字元數,從這個陣列裡不斷取片段出來拼接。
//分離程式碼,以可分割單位拆分成陣列。var lines = hold_code.replace(/([^a-zA-Z_0-9=!|&$])/g,"\n$1\n").split("\n");
//有了這個lines陣列之後後面就簡單了,根據第一步裡生成的struct不斷遍歷從lines抽取程式碼填充到struct裡即可生成最終的程式碼:
while(lines.length>0){
//迴圈往struct裡填充程式碼
struct.forEach(function(s){
var chars_arr = s.replace(/ +/g," ");//一行有多組分離的*****
var r = s;
chars_arr.split(/ +/).forEach(function(chars){
if(chars.length == 0){
return;
}
var char_count = chars.length;
//從lines裡取出char_count數量的程式碼來填充,不一定精準,要確保斷行正確
var l = pickFromLines(lines,char_count);
r = r.replace(chars,function(){
return l;
})
})
result += r+"\n"
})
}
③ 保留不可分割的語法
注意:到了這一步,還很早,你分解出來的程式碼是無法執行的,很多不能換行和加空格的程式碼都被你分開了,自然會報錯,那如何處理這些情況呢?
這一步,我們做的工作就是:
在執行程式碼分拆之前,提取出程式碼裡所有不可分割的語法,將他們保留在一個物件中,並且在原始碼中用佔位符替代這些語法,然後讓佔位符參與上個步驟的分離,因為佔位符是一個完整的連字元變數,所以不會被分割。在分割完成之後,我們再把這些佔位符替換回來即可。
不過,在js中哪些語法必須是連線在一起才能正常執行的呢?
這裡總結下:
- 字串不可分割 包括雙引號單引號內的內容。
- 正規表示式絕對不可分割 正則裡的轉義很難處理,這是這個演算法裡的難點。
- 運算運算子 包括2字元的3字元的 例如 以下兩種
var double_operator = ["==", ">=", "<=", "+=", "-=", "*=", "/=", "%=", "++", "--", "&&", "||", ">>", "<<"]
var three_operator = ['===', '!==']
一些固定語法,可以用正則表達,如下:
var reg_operator = [
{
start:"return",
reg:/^return[^a-zA-Z_0-1"'][a-zA-Z_0-1.]+/
// return 0.1 或者 return function 或者return aaabb
},
{
start:"return\"",
reg:/^return".*?"/ // return "d" 或者 return ""
},
{
start:"return\'",
reg:/^return'.*?'/ // return 'd' 或者 return ''
},
{
start:"throw",
reg:/^throw [a-zA-Z_0-1]+?/ //throw new 或者 throw obj
}
]
小數點語法,例如 0.01 因為之前我們用點號來分割程式碼的,但是這裡的點號不能作為分割符使用,需要保留前後數字跟點號在一行 其他語法,例如 value++ 之類的語法,變數和運算子之間不可分割。 那我們如何從原始碼中解析出這些語法,然後做處理呢?
核心程式碼均在 utils/keep-line.js
中
核心演算法,事實上是透過一個對字串的遍歷來完成的,然後在遍歷每個字元的時候都會判斷是否進入某個邏輯來跳躍處理。
例如,判斷出當前在雙引號內,則進入字串提取邏輯,一直到字串結束的時候再繼續正常的遍歷。
其他運算子和正規表示式的演算法也是類似,不過裡面很多細節需要處理,例如跳脫字元之類的。
有些比較特殊的,例如小數點語法的提取,在判斷到當前字元是點號之後,需要往前和向後迴圈查詢數字,然後把整個語法找出來。
這裡不細講,在keep-line.js 這個檔案中又一大坨程式碼做這個事情的。
④ 字串解構
做到這一步的時候,其實效果已經很不錯了,也可以保證程式碼的可執行,但是程式碼裡有些字串很長,他們總是會被被保留在一行裡,這樣就造成他會影響一些圖案的邊緣的準確性(程式碼分離原則是越細越好,就是為這個考慮)。
我們如何處理呢,那就是將字串解構,以5個為單位將字串分離成小塊。
這裡有兩個比較重要的問題需要處理;
- 字串內的跳脫字元如何處理,還有一些特殊字元,例如0x01這樣的字元,這些字元不能被分離到不同的字串裡,所以分離的時候要保留這些字串的完整性。
- 字串分離成小字串,然後用+號拼接起來,不過要注意運算子優先順序的問題,所以所有分離後的字串,都要用括號包起來,讓這個+號的優先順序永遠最高。
具體演算法見 keep-line.js 中的 splitDoubleQuot (分離雙引號字串)。
結語
至此,整個應用就完成了,可以順利完成從任意js和影像生成圖形程式碼了。
再說一遍專案開源地址:https://github.com/xinyu198736/js2image 歡迎star,順便follow下樓主就更開心了。
相關文章
- 聖誕夜,讓你的程式碼都變成聖誕樹吧!
- 聖誕節,把網站所有的js程式碼都壓縮成聖誕樹吧。網站JS
- 程式設計師的聖誕節--送她一顆聖誕樹(附原始碼)程式設計師原始碼
- 程式設計師的聖誕節–送她一顆聖誕樹(附原始碼)程式設計師原始碼
- 最美聖誕樹!用Python畫棵雪夜聖誕樹送給你Python
- 聖誕節的python豪華版聖誕樹,包括雪花彩燈文字背景Python
- 聖誕樹--pythonPython
- 聖誕節快到了,快來裝飾你的Mac電腦桌面吧!Mac
- 彩色聖誕樹 題解
- AntD 聖誕節彩蛋事件事件
- 用程式碼畫兩棵聖誕樹送給你【附詳細程式碼】
- 聖誕快樂——Keras+樹莓派:用深度學習識別聖誕老人Keras樹莓派深度學習
- 【python:turtle繪畫 聖誕樹】Python
- 分享聖誕樹+雪人+全屏動效
- 聖誕節快到啦!Mac電腦系統如何在聖誕節讓電腦螢幕下雪?Mac
- 快到聖誕節了,用python來給自己的頭像加上一頂聖誕帽Python
- 聖誕祝福程式官方漢化版!
- 聖誕郵件營銷:如何做使用者眼中的聖誕老人?
- Linux/Unix 桌面趣事:終端上的聖誕樹Linux
- 神奇的C語言輸出12天聖誕節歌詞程式碼C語言
- 聖誕小鹿?VScodeVSCode
- 聖誕裝飾的11款WordPress外掛
- Python程式設計 聖誕樹教程 (附程式碼)程式設計師的浪漫Python程式設計師
- 【Python自動戴聖誕帽】02 戴聖誕帽及抗疫彩蛋Python
- 聖誕鬧劇!阿里旗下開源專案聖誕彩蛋遭開發者狂批阿里
- 聖誕快樂: 用 GaussDB T 繪製一顆聖誕樹,兼論高斯資料庫語法相容資料庫
- YouGov:45%的美國人更喜歡人造聖誕樹Go
- Python繪圖,聖誕樹,花,愛心 | Turtle篇Python繪圖
- 如何用 C 語言畫一個“聖誕樹”?
- 聖誕節如何打造新穎的郵件營銷?
- 「趣圖」第四張圖,程式設計師的聖誕節願望清單,過於真實,聖誕老人很難辦啊程式設計師
- 一個聖誕動畫的實現動畫
- 聖誕節快樂:來自程式設計師們的問候程式設計師
- 亞馬遜:2015年聖誕節亞馬遜自主裝置銷量翻番亞馬遜
- 《真·簡單》Golang 輕量級桌面程式 wails 庫(聖誕節限定)GolangAI
- 聖誕雪花紛飛自定義ViewView
- virtono聖誕節月付0.68歐元VPS註冊教程
- 聖誕節到了!!你的桌面下雪了嗎?? - Qt趣味開發之讓你的桌面下雪QT