Node.js Color 模塊實現入門淺析

想此次 7年前發布 | 59K 次閱讀 Node.js Node.js 開發

Node.js 中有不少常用的 Color 模塊,例如 chalk colors.js cli-color 等,通過這些模塊我們輸出各種帶顏色、方面區分或者更酷的日志以及 CLI 工具提示。那么今天帶大家簡單了解一下 Color 模塊的實現。

ANSI escape code

與前端上對元素內的文字加上了 CSS 修飾一樣。terminal 中輸出的文字包含顏色也是因為文字的數據跟隨了顏色描述的數據。而要了解 terminal 上的顏色,首先需要了解 ANSI escape code

顏色修飾數據對于 terminal 而言,是跟 " \n " 類似的讓顯示出現變化的一種轉義字符。與常見的轉義字符不同,修飾顏色字符(在大部分平臺上)按照 CSI codes 的格式以 " ESC " + " [ " 字符開頭,形如: ESC[ + code1;code2;...;codeN + m 結束(其中的 code 即修飾顏色的數據)。例如:

echo -e "\033[31;42mhello"; # 控制字符[紅色文字;綠色背景結束符號hello
echo -e "\033[0m";          # 重置顏色修飾
echo -e "\033[33mworld";    # 控制字符[黃色文字結束符號world
echo -e "\033[0m";          # 重置顏色修飾

各位用戶(win除外)可以在 terminal 上嘗試一下執行效果,或者使用 Node.js (包括win)運行以下代碼試試:

console.log("\033[31;42mhello"); //  控制字符[紅色文字;綠色背景結束符號hello
console.log("\033[0m");          //  重置顏色修飾
console.log("\033[33mworld");    //  控制字符[黃色文字結束符號world
console.log("\033[0m");          //  重置顏色修飾

執行效果:

注意:ESC 轉義字符在 ASCII 碼中十進制是 27,八進制是 033,十六進制是 0x1B。所以在 Node.js 中除了 \033 之外還可以寫成 \u001b (嚴格模式強制)。

ANSI colors and styles

ANSI 的標準中,特定的 code 表示特定的含義,對于 terminal 的顏色主要有三方面的定義。分別是樣式、顏色、明亮度。

樣式

常見的字體樣式分別是(支持情況視 terminal 而定):

顏色 & 明亮

code 30 - 37 為字體顏色,91 - 97 為字體顏色的明亮版。40 - 47 為背景色,100 - 107 為背景色的明亮版。terminal 的默認字體色 code 是 39,默認背景色是 49。

完整的 code 信息參見 CSI codes 中的 SGR (Select Graphic Rendition) parameters。

Color 模塊實現

了解了 ANSI 編碼中關于顏色部分的知識之后,在 Node.js 中實現一個顏色模塊就很簡單了。

首先我們可以明確一點,跟某段輸出的內容加上顏色,其實要做的事情就是將該內容使用修飾顏色的數據包起來即可。例如輸出一段綠底紅字,相當于輸出 “綠色背景紅色文字修飾數據” + “輸出文字” + “重置修飾”。其效果可以簡單這樣寫:

function getRedTextGreenBg(text) {
  return '\033[31;42m' + text + '\033[0m';
}

console.log(getRedTextGreenBg('hello world'));

如果了解 CSI codes 的規則就會發現,對于顏色數據 ESC[ + code1;code2;...;codeN + m 的寫法其實和 ESC[ + code1 + m + ESC[ + code2 + m + ... + ESC[ + codeN + m 的效果是一樣的,目前 Node.js 中大部分 Color 模塊都是按照后者的情況來實現的。

完整一點的 styles 數據可以參考 chalk ansi-styles 。那么我這邊換個簡單的思路模仿 chalk 的調用方式來實現一版,供各位大佬圍觀:

'use strict';

// 嚴格模式要用 unicode 的十六進制不能用八進制的 \033
const styles = {
  // style:    [ style code, reset code  ]
  'bold':      ['\u001b[1m', '\u001b[22m'],
  // ...
  'black':     ['\u001b[30m', '\u001b[39m'],
  'red':       ['\u001b[31m', '\u001b[39m'],
  'green':     ['\u001b[32m', '\u001b[39m'],
  'yellow':    ['\u001b[33m', '\u001b[39m'],
  // ...
  'bgBlack':   ['\u001b[40m', '\u001b[49m'],
  'bgRed':     ['\u001b[41m', '\u001b[49m'],
  'bgGreen':   ['\u001b[42m', '\u001b[49m'],
  'bgYellow':  ['\u001b[43m', '\u001b[49m'],
  // ...
};

const color = {};

Object.keys(styles).map((key) => 
  color[key] = (text) => 
    styles[key][0] + text + styles[key][1]);

console.log(
  color.bgGreen(color.red('hello,')) + 
  color.yellow(' world!'));

執行效果:

 

來自:https://zhuanlan.zhihu.com/p/27308276

 

 本文由用戶 想此次 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!