debug.js (4394B)
1 2 /** 3 * This is the common logic for both the Node.js and web browser 4 * implementations of `debug()`. 5 * 6 * Expose `debug()` as the module. 7 */ 8 9 exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; 10 exports.coerce = coerce; 11 exports.disable = disable; 12 exports.enable = enable; 13 exports.enabled = enabled; 14 exports.humanize = require('ms'); 15 16 /** 17 * The currently active debug mode names, and names to skip. 18 */ 19 20 exports.names = []; 21 exports.skips = []; 22 23 /** 24 * Map of special "%n" handling functions, for the debug "format" argument. 25 * 26 * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". 27 */ 28 29 exports.formatters = {}; 30 31 /** 32 * Previous log timestamp. 33 */ 34 35 var prevTime; 36 37 /** 38 * Select a color. 39 * @param {String} namespace 40 * @return {Number} 41 * @api private 42 */ 43 44 function selectColor(namespace) { 45 var hash = 0, i; 46 47 for (i in namespace) { 48 hash = ((hash << 5) - hash) + namespace.charCodeAt(i); 49 hash |= 0; // Convert to 32bit integer 50 } 51 52 return exports.colors[Math.abs(hash) % exports.colors.length]; 53 } 54 55 /** 56 * Create a debugger with the given `namespace`. 57 * 58 * @param {String} namespace 59 * @return {Function} 60 * @api public 61 */ 62 63 function createDebug(namespace) { 64 65 function debug() { 66 // disabled? 67 if (!debug.enabled) return; 68 69 var self = debug; 70 71 // set `diff` timestamp 72 var curr = +new Date(); 73 var ms = curr - (prevTime || curr); 74 self.diff = ms; 75 self.prev = prevTime; 76 self.curr = curr; 77 prevTime = curr; 78 79 // turn the `arguments` into a proper Array 80 var args = new Array(arguments.length); 81 for (var i = 0; i < args.length; i++) { 82 args[i] = arguments[i]; 83 } 84 85 args[0] = exports.coerce(args[0]); 86 87 if ('string' !== typeof args[0]) { 88 // anything else let's inspect with %O 89 args.unshift('%O'); 90 } 91 92 // apply any `formatters` transformations 93 var index = 0; 94 args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { 95 // if we encounter an escaped % then don't increase the array index 96 if (match === '%%') return match; 97 index++; 98 var formatter = exports.formatters[format]; 99 if ('function' === typeof formatter) { 100 var val = args[index]; 101 match = formatter.call(self, val); 102 103 // now we need to remove `args[index]` since it's inlined in the `format` 104 args.splice(index, 1); 105 index--; 106 } 107 return match; 108 }); 109 110 // apply env-specific formatting (colors, etc.) 111 exports.formatArgs.call(self, args); 112 113 var logFn = debug.log || exports.log || console.log.bind(console); 114 logFn.apply(self, args); 115 } 116 117 debug.namespace = namespace; 118 debug.enabled = exports.enabled(namespace); 119 debug.useColors = exports.useColors(); 120 debug.color = selectColor(namespace); 121 122 // env-specific initialization logic for debug instances 123 if ('function' === typeof exports.init) { 124 exports.init(debug); 125 } 126 127 return debug; 128 } 129 130 /** 131 * Enables a debug mode by namespaces. This can include modes 132 * separated by a colon and wildcards. 133 * 134 * @param {String} namespaces 135 * @api public 136 */ 137 138 function enable(namespaces) { 139 exports.save(namespaces); 140 141 exports.names = []; 142 exports.skips = []; 143 144 var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); 145 var len = split.length; 146 147 for (var i = 0; i < len; i++) { 148 if (!split[i]) continue; // ignore empty strings 149 namespaces = split[i].replace(/\*/g, '.*?'); 150 if (namespaces[0] === '-') { 151 exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); 152 } else { 153 exports.names.push(new RegExp('^' + namespaces + '$')); 154 } 155 } 156 } 157 158 /** 159 * Disable debug output. 160 * 161 * @api public 162 */ 163 164 function disable() { 165 exports.enable(''); 166 } 167 168 /** 169 * Returns true if the given mode name is enabled, false otherwise. 170 * 171 * @param {String} name 172 * @return {Boolean} 173 * @api public 174 */ 175 176 function enabled(name) { 177 var i, len; 178 for (i = 0, len = exports.skips.length; i < len; i++) { 179 if (exports.skips[i].test(name)) { 180 return false; 181 } 182 } 183 for (i = 0, len = exports.names.length; i < len; i++) { 184 if (exports.names[i].test(name)) { 185 return true; 186 } 187 } 188 return false; 189 } 190 191 /** 192 * Coerce `val`. 193 * 194 * @param {Mixed} val 195 * @return {Mixed} 196 * @api private 197 */ 198 199 function coerce(val) { 200 if (val instanceof Error) return val.stack || val.message; 201 return val; 202 }