Node.js Color 模块实现入门浅析
<p><img src="https://simg.open-open.com/show/184f56f65e772dd4a78ec72eb67bb0be.png"></p> <p>Node.js 中有不少常用的 Color 模块,例如 <a href="/misc/goto?guid=4959749970921119703" rel="nofollow,noindex"> chalk </a> 、 <a href="/misc/goto?guid=4959749971018504154" rel="nofollow,noindex"> colors.js </a> 、 <a href="/misc/goto?guid=4959749971096479741" rel="nofollow,noindex"> cli-color </a> 等,通过这些模块我们输出各种带颜色、方面区分或者更酷的日志以及 CLI 工具提示。那么今天带大家简单了解一下 Color 模块的实现。</p> <h2><strong>ANSI escape code</strong></h2> <p>与前端上对元素内的文字加上了 CSS 修饰一样。terminal 中输出的文字包含颜色也是因为文字的数据跟随了颜色描述的数据。而要了解 terminal 上的颜色,首先需要了解 <a href="/misc/goto?guid=4959749971175454259" rel="nofollow,noindex"> ANSI escape code </a></p> <p>。</p> <p>颜色修饰数据对于 terminal 而言,是跟 " <strong>\n</strong> " 类似的让显示出现变化的一种转义字符。与常见的转义字符不同,修饰颜色字符(在大部分平台上)按照 <a href="/misc/goto?guid=4959749971256762774" rel="nofollow,noindex"> CSI codes </a> 的格式以 " <strong>ESC</strong> " + " <strong>[</strong> " 字符开头,形如: <strong>ESC[</strong> + <em> <u>code1;code2;...;codeN</u> </em> + <strong>m</strong> 结束(其中的 code 即修饰颜色的数据)。例如:</p> <pre> <code class="language-javascript">echo -e "\033[31;42mhello"; # 控制字符[红色文字;绿色背景结束符号hello echo -e "\033[0m"; # 重置颜色修饰 echo -e "\033[33mworld"; # 控制字符[黄色文字结束符号world echo -e "\033[0m"; # 重置颜色修饰</code></pre> <p>各位用户(win除外)可以在 terminal 上尝试一下执行效果,或者使用 Node.js (包括win)运行以下代码试试:</p> <pre> <code class="language-javascript">console.log("\033[31;42mhello"); // 控制字符[红色文字;绿色背景结束符号hello console.log("\033[0m"); // 重置颜色修饰 console.log("\033[33mworld"); // 控制字符[黄色文字结束符号world console.log("\033[0m"); // 重置颜色修饰</code></pre> <p>执行效果:</p> <p><img src="https://simg.open-open.com/show/881ac372440b3f39461854281f2be2bc.png"> 注意:ESC 转义字符在 ASCII 码中十进制是 27,八进制是 033,十六进制是 0x1B。所以在 Node.js 中除了 <strong>\033</strong> 之外还可以写成 <strong>\u001b</strong> (严格模式强制)。</p> <h2><strong>ANSI colors and styles</strong></h2> <p>ANSI 的标准中,特定的 code 表示特定的含义,对于 terminal 的颜色主要有三方面的定义。分别是样式、颜色、明亮度。</p> <p><strong>样式</strong></p> <p>常见的字体样式分别是(支持情况视 terminal 而定):</p> <p><img src="https://simg.open-open.com/show/852158f84ce79e86258015aaf98f38d6.png"></p> <p><strong>颜色 & 明亮</strong></p> <p>code 30 - 37 为字体颜色,91 - 97 为字体颜色的明亮版。40 - 47 为背景色,100 - 107 为背景色的明亮版。terminal 的默认字体色 code 是 39,默认背景色是 49。</p> <p><img src="https://simg.open-open.com/show/b6aa8341ebe37ff80c7bfd3c7d045f5f.png"> 完整的 code 信息参见 <a href="/misc/goto?guid=4959749971256762774" rel="nofollow,noindex"> CSI codes </a> 中的 SGR (Select Graphic Rendition) parameters。</p> <h2><strong>Color</strong> 模块实现</h2> <p>了解了 ANSI 编码中关于颜色部分的知识之后,在 Node.js 中实现一个颜色模块就很简单了。</p> <p>首先我们可以明确一点,跟某段输出的内容加上颜色,其实要做的事情就是将该内容使用修饰颜色的数据包起来即可。例如输出一段绿底红字,相当于输出 “绿色背景红色文字修饰数据” + “输出文字” + “重置修饰”。其效果可以简单这样写:</p> <pre> <code class="language-javascript">function getRedTextGreenBg(text) { return '\033[31;42m' + text + '\033[0m'; } console.log(getRedTextGreenBg('hello world'));</code></pre> <p>如果了解 CSI codes 的规则就会发现,对于颜色数据 <strong>ESC[</strong> + <em> <u>code1;code2;...;codeN</u> </em> + <strong>m</strong> 的写法其实和 <strong>ESC[</strong> + <em> <u>code1</u> </em> + <strong>m</strong> + <strong>ESC[</strong> + <em> <u>code2</u> </em> + <strong>m</strong> + ... + <strong>ESC[</strong> + <em> <u>codeN</u> </em> + <strong>m</strong> 的效果是一样的,目前 Node.js 中大部分 Color 模块都是按照后者的情况来实现的。</p> <p>完整一点的 styles 数据可以参考 <a href="/misc/goto?guid=4959749970921119703" rel="nofollow,noindex"> chalk </a> 的 <a href="/misc/goto?guid=4959749971366794008" rel="nofollow,noindex"> ansi-styles </a> 。那么我这边换个简单的思路模仿 chalk 的调用方式来实现一版,供各位大佬围观:</p> <pre> <code class="language-javascript">'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!'));</code></pre> <p>执行效果:</p> <p><img src="https://simg.open-open.com/show/028520289c178fd6fad94cdd5538ec75.png"></p> <p> </p> <p>来自:https://zhuanlan.zhihu.com/p/27308276</p> <p> </p>
本文由用户 想此次 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!