一个微小的JavaScript调试工具,以Node.js核心的调试技术为模型。 适用于Node.js和Web浏览器 传送门node
src/index.jswebpack
if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
module.exports = require('./browser.js');
} else {
module.exports = require('./node.js');
}
复制代码
经过第三方库 supports-color 判断终端是否支持颜色。git
src/node.jsgithub
exports.colors = [ 6, 2, 3, 4, 5, 1 ];
try {
var supportsColor = require('supports-color');
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
exports.colors = [
20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68,
69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134,
135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 214, 215, 220, 221
];
}
} catch (err) {
// swallow - we only care if `supports-color` is available; it doesn't have to be.
}
复制代码
debug 容许用户可使用以下格式定义 options (至关于给程序传参)web
$ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
复制代码
相比于常见的给程序传参的格式 node script --xx=xx,更酷一些。数组
exports.inspectOpts = Object.keys(process.env).filter(function (key) {
return /^debug_/i.test(key);
}).reduce(function (obj, key) {
var prop = key
.substring(6)
.toLowerCase()
.replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
var val = process.env[key];
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
else if (val === 'null') val = null;
else val = Number(val);
obj[prop] = val;
return obj;
}, {});
复制代码
经过以上格式设置的参数会存在 process.env 内。process.env 为一个对象,以 DEBUG_COLORS=no 为例, DEBUG_COLORS 为 key,no 为 value。浏览器
例如:bash
DEBUG_COLORS=no DEBUG_DEPTH=10
process.env = {
DEBUG_COLORS: no,
DEBUG_DEPTH: 10
}
复制代码
经过 reduce 把数组转换为对象,技巧是 reduce 的第二个参数(可选),初始化的值。app
var list = [1,2,3,4];
var a = list.reduce((obj,num)=>{
//此时 obj 在第一次执行时就是初始化的值 {}
obj[`${num}`] = num;
return obj;
},{})
console.log(a);
//a : { '1': 1, '2': 2, '3': 3, '4': 4 }
复制代码
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
else if (val === 'null') val = null;
else val = Number(val);
复制代码
经过正则处理相同含义的字符串,比起用 === 断定优雅许多。electron
//bad
if(val === 'yes' || val === 'on' || val === 'true'){
val = true;
}
//good
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
复制代码
src/common.js 为一个公共的模块,导出值为函数 createDebug。无论是 node 仍是 浏览器 坏境最后都做为参数传入到 common 内,这样就作到了代码分离,把可重用的代码组织在一块儿。
这里的 env 为坏境对象,把 env 全部的属性挂载到 createDebug 对象。这样能够随意扩展 env 对象,最终全部方法都会赋值给导出的对象 createDebug。
src/common.js
//赋值操做 源码
Object.keys(env).forEach(function(key) {
createDebug[key] = env[key];
});
//便捷写法
let obj1 = {'name':'cxr','age':18};
let obj2 = {...obj1};
console.log(obj2);//{ name: 'cxr', age: 18 }
console.log(obj1 === obj2);//false
复制代码
利用 tty 模块(nodejs 原生模块),当 Node.js 检测到正运行在一个文本终端(TTY)时,则 process.stdin 默认会被初始化为 tty.ReadStream 实例,且 process.stdout 和 process.stderr 默认会被初始化为 tty.WriteStream 实例。经过 isTTY 来检测:若是是 tty.WriteStream 实例,则返回 true。
// writeStream.isTTY 老是返回 true
if(process.stdout.isTTY === true)
复制代码
首先要了解的是,在 Linux 下,一切皆为文件。内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也须要使用文件描述符来指定待读写的文件。 Linux 下:
这里经过 process.stderr.fd 返回一个 fd 做为参数,tty.isatty 检测若是给定的 fd 有关联 TTY,则返回 true,不然返回 false。换句话说,就是这个输出流是否是在终端里。
//用户若是不设置color选项的状况下 将检测错误流是否在终端里
function useColors() {
return 'colors' in exports.inspectOpts
? Boolean(exports.inspectOpts.colors)
: tty.isatty(process.stderr.fd);
}
复制代码
用于控制视频文本终端上的光标位置,颜色和其余选项。 某些字节序列(大多数以Esc和'['开头)嵌入到文本中,终端查找并解释为命令,而不是字符代码。实现 node 坏境下带颜色输出的核心。 wiki
node 中书写格式:
\u001b[31mHello 它将被解析为输出红色的 Hello 。
复制代码
在 node 中使用改变终端字体颜色:
//31m 为红色 32m 为绿色
console.log('\u001b[31mHello \u001b[32mWorld');
复制代码
debug 容许用户自定义格式化插件,例如:
const createDebug = require('debug')
createDebug.formatters.h = (v) => {
return v.toString('hex')
}
// …elsewhere
const debug = createDebug('foo')
debug('this is hex: %h', new Buffer('hello world'))
// foo this is hex: 68656c6c6f20776f726c6421 +0ms
复制代码
能够看到只须要在 createDebug.formatters 对象上挂载自定义的函数 h 便可。在格式化输出的时候发现是 %h 的时候将调用用户自定义函数。 源码实现:
// apply any `formatters` transformations
var index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
// if we encounter an escaped % then don't increase the array index
if (match === '%%') return match;
index++;
var formatter = createDebug.formatters[format];
if ('function' === typeof formatter) {
var val = args[index];
match = formatter.call(self, val);
// now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
// apply env-specific formatting (colors, etc.)
createDebug.formatArgs.call(self, args);
复制代码
遵循了对修改关闭,对扩展开放的原则(OCP)。
最后在总结下学习到的知识:
经过阅读优秀源码提升本身,厚积薄发。欢迎大神指正~