From 0269707d06e8f317302833300ffd8ad0c061344e Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Wed, 28 May 2014 21:40:31 -0700 Subject: [PATCH 01/11] component: fix mismatching version number The `component.json` file is at v0.8.1 currently. --- component.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component.json b/component.json index cb76981..4a93408 100644 --- a/component.json +++ b/component.json @@ -2,7 +2,7 @@ "name": "debug", "repo": "visionmedia/debug", "description": "small debugging utility", - "version": "0.7.4", + "version": "0.8.1", "keywords": ["debug", "log", "debugger"], "main": "debug.js", "scripts": ["debug.js"], From 45010b65d0dda9ec10e7ea4f26b6040ca9f69c48 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 30 May 2014 00:07:15 -0700 Subject: [PATCH 02/11] add .jshintrc file --- .jshintrc | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .jshintrc diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..299877f --- /dev/null +++ b/.jshintrc @@ -0,0 +1,3 @@ +{ + "laxbreak": true +} From 2cffe24185a9aa3a25f1ab490bfdae0509b535f2 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 30 May 2014 00:10:10 -0700 Subject: [PATCH 03/11] rewrite: abstract common logic for Node & browsers --- browser.js | 69 +++++++++++++++++++++ component.json | 7 ++- debug.js | 131 ++++++++++++++++++++-------------------- lib/debug.js | 158 ------------------------------------------------- node.js | 104 ++++++++++++++++++++++++++++++++ package.json | 12 ++-- 6 files changed, 249 insertions(+), 232 deletions(-) create mode 100644 browser.js delete mode 100644 lib/debug.js create mode 100644 node.js diff --git a/browser.js b/browser.js new file mode 100644 index 0000000..5a93453 --- /dev/null +++ b/browser.js @@ -0,0 +1,69 @@ + +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = require('./debug'); +exports.log = log; +exports.save = save; +exports.load = load; + +/** + * Invokes `console.log()` when available. + * No-op when `consoel.log` is not a "function". + * + * @api public + */ + +function log(fmt) { + var curr = new Date(); + var ms = curr - (this.prev || curr); + this.prev = curr; + + fmt = name + + ' ' + + fmt + + ' +' + exports.humanize(ms); + + // This hackery is required for IE8, + // where the `console.log` function doesn't have 'apply' + return 'object' == typeof console + && 'function' == typeof console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`, + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + localStorage.debug = namespaces; + } catch(e) {} +} + +/** + * Load `namespaces`, + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r = ''; + try { + r = localStorage.debug || ''; + } catch(e) {} + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); diff --git a/component.json b/component.json index 4a93408..1631574 100644 --- a/component.json +++ b/component.json @@ -4,7 +4,10 @@ "description": "small debugging utility", "version": "0.8.1", "keywords": ["debug", "log", "debugger"], - "main": "debug.js", - "scripts": ["debug.js"], + "main": "browser.js", + "scripts": [ + "browser.js", + "debug.js" + ], "dependencies": {} } diff --git a/debug.js b/debug.js index 509dc0d..e207f5c 100644 --- a/debug.js +++ b/debug.js @@ -1,74 +1,78 @@ /** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * * Expose `debug()` as the module. */ -module.exports = debug; +exports = module.exports = debug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = humanize; /** - * Create a debugger with the given `name`. + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Create a debugger with the given `namespace`. * - * @param {String} name - * @return {Type} + * @param {String} namespace + * @return {Function} * @api public */ -function debug(name) { - if (!debug.enabled(name)) return function(){}; +function debug(namespace) { - return function(fmt){ - fmt = coerce(fmt); - - var curr = new Date; - var ms = curr - (debug[name] || curr); - debug[name] = curr; - - fmt = name - + ' ' - + fmt - + ' +' + debug.humanize(ms); - - // This hackery is required for IE8 - // where `console.log` doesn't have 'apply' - window.console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); + // define the `disabled` version + function disabled() { } + disabled.enabled = false; + + // define the `enabled` version + function enabled(fmt) { + fmt = exports.coerce(fmt); + exports.log.apply(enabled, arguments); + } + enabled.enabled = true; + + var fn = exports.enabled(namespace) ? enabled : disabled; + + fn.namespace = namespace; + + return fn; } /** - * The currently active debug mode names. - */ - -debug.names = []; -debug.skips = []; - -/** - * Enables a debug mode by name. This can include modes + * Enables a debug mode by namespaces. This can include modes * separated by a colon and wildcards. * - * @param {String} name + * @param {String} namespaces * @api public */ -debug.enable = function(name) { - try { - localStorage.debug = name; - } catch(e){} - - var split = (name || '').split(/[\s,]+/) - , len = split.length; +function enable(namespaces) { + var split = (namespaces || '').split(/[\s,]+/); + var len = split.length; for (var i = 0; i < len; i++) { - name = split[i].replace('*', '.*?'); - if (name[0] === '-') { - debug.skips.push(new RegExp('^' + name.substr(1) + '$')); + namespaces = split[i].replace('*', '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); } else { - debug.names.push(new RegExp('^' + name + '$')); + exports.names.push(new RegExp('^' + namespaces + '$')); } } -}; + + exports.save(namespaces); +} /** * Disable debug output. @@ -76,9 +80,9 @@ debug.enable = function(name) { * @api public */ -debug.disable = function(){ - debug.enable(''); -}; +function disable() { + exports.enable(''); +} /** * Humanize the given `ms`. @@ -88,16 +92,16 @@ debug.disable = function(){ * @api private */ -debug.humanize = function(ms) { - var sec = 1000 - , min = 60 * 1000 - , hour = 60 * min; +function humanize(ms) { + var sec = 1000; + var min = 60 * 1000; + var hour = 60 * min; if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; if (ms >= min) return (ms / min).toFixed(1) + 'm'; if (ms >= sec) return (ms / sec | 0) + 's'; return ms + 'ms'; -}; +} /** * Returns true if the given mode name is enabled, false otherwise. @@ -107,31 +111,30 @@ debug.humanize = function(ms) { * @api public */ -debug.enabled = function(name) { - for (var i = 0, len = debug.skips.length; i < len; i++) { - if (debug.skips[i].test(name)) { +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { return false; } } - for (var i = 0, len = debug.names.length; i < len; i++) { - if (debug.names[i].test(name)) { + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { return true; } } return false; -}; +} /** * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private */ function coerce(val) { if (val instanceof Error) return val.stack || val.message; return val; } - -// persist - -try { - if (window.localStorage) debug.enable(localStorage.debug); -} catch(e){} diff --git a/lib/debug.js b/lib/debug.js deleted file mode 100644 index e7422e6..0000000 --- a/lib/debug.js +++ /dev/null @@ -1,158 +0,0 @@ -/** - * Module dependencies. - */ - -var tty = require('tty'); - -/** - * Expose `debug()` as the module. - */ - -module.exports = debug; - -/** - * Enabled debuggers. - */ - -var names = [] - , skips = []; - -/** - * Colors. - */ - -var colors = [6, 2, 3, 4, 5, 1]; - -/** - * Previous debug() call. - */ - -var prev = {}; - -/** - * Previously assigned color. - */ - -var prevColor = 0; - -/** - * Is stdout a TTY? Colored output is disabled when `true`. - */ - -var isatty = tty.isatty(1); - -/** - * Select a color. - * - * @return {Number} - * @api private - */ - -function color() { - return colors[prevColor++ % colors.length]; -} - -/** - * Humanize the given `ms`. - * - * @param {Number} m - * @return {String} - * @api private - */ - -function humanize(ms) { - var sec = 1000 - , min = 60 * 1000 - , hour = 60 * min; - - if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; - if (ms >= min) return (ms / min).toFixed(1) + 'm'; - if (ms >= sec) return (ms / sec | 0) + 's'; - return ms + 'ms'; -} - -/** - * Create a debugger with the given `name`. - * - * @param {String} name - * @return {Type} - * @api public - */ - -function debug(name) { - function disabled(){} - disabled.enabled = false; - - var match = skips.some(function(re){ - return re.test(name); - }); - - if (match) return disabled; - - match = names.some(function(re){ - return re.test(name); - }); - - if (!match) return disabled; - var c = color(); - - function colored(fmt) { - fmt = coerce(fmt); - - var curr = new Date; - var ms = curr - (prev[name] || curr); - prev[name] = curr; - - fmt = ' \u001b[9' + c + 'm' + name + ' ' - + '\u001b[3' + c + 'm\u001b[90m' - + fmt + '\u001b[3' + c + 'm' - + ' +' + humanize(ms) + '\u001b[0m'; - - console.log.apply(this, arguments); - } - - function plain(fmt) { - fmt = coerce(fmt); - - fmt = new Date().toUTCString() - + ' ' + name + ' ' + fmt; - console.log.apply(this, arguments); - } - - colored.enabled = plain.enabled = true; - - return isatty || process.env.DEBUG_COLORS - ? colored - : plain; -} - -/** - * Coerce `val`. - */ - -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} - -/** - * Enable specified `namespaces` for debugging. - */ - -debug.enable = function(namespaces) { - namespaces.split(/[\s,]+/) - .forEach(function(name){ - name = name.replace('*', '.*?'); - if (name[0] == '-') { - skips.push(new RegExp('^' + name.substr(1) + '$')); - } else { - names.push(new RegExp('^' + name + '$')); - } - }); -}; - -/** - * Enable namespaces listed in `process.env.DEBUG` initially. - */ - -debug.enable(process.env.DEBUG || ''); diff --git a/node.js b/node.js new file mode 100644 index 0000000..4163847 --- /dev/null +++ b/node.js @@ -0,0 +1,104 @@ + +/** + * Module dependencies. + */ + +var tty = require('tty'); + +/** + * This is the Node.js implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = require('./debug'); +exports.log = log; +exports.save = save; +exports.load = load; + +/** + * Colors. + */ + +var colors = [6, 2, 3, 4, 5, 1]; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Is stdout a TTY? Colored output is disabled when `true`. + */ + +var useColors = tty.isatty(1) || process.env.DEBUG_COLORS; + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function selectColor() { + return colors[prevColor++ % colors.length]; +} + +/** + * Invokes `console.log()` with the specified arguments, + * after adding ANSI color escape codes if enabled. + * + * @api public + */ + +function log(fmt) { + var name = this.namespace; + + if (useColors) { + if (null == this.c) this.c = selectColor(); + + var c = this.c; + var curr = new Date(); + var ms = curr - (this.prev || curr); + this.prev = curr; + + fmt = ' \u001b[9' + c + 'm' + name + ' ' + + '\u001b[3' + c + 'm\u001b[90m' + + fmt + '\u001b[3' + c + 'm' + + ' +' + exports.humanize(ms) + '\u001b[0m'; + } else { + fmt = new Date().toUTCString() + + ' ' + name + ' ' + fmt; + } + + console.log.apply(this, arguments); +} + +/** + * Save `namespaces`, + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + process.env.DEBUG = namespaces; +} + +/** + * Load `namespaces`, + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG || ''; +} + +/** + * Enable namespaces listed in `process.env.DEBUG` initially. + */ + +exports.enable(load()); diff --git a/package.json b/package.json index 7051d22..c875bd2 100644 --- a/package.json +++ b/package.json @@ -7,16 +7,12 @@ , "author": "TJ Holowaychuk " , "dependencies": {} , "devDependencies": { "mocha": "*" } - , "main": "lib/debug.js" - , "browser": "./debug.js" - , "engines": { "node": "*" } - , "files": [ - "lib/debug.js", - "debug.js" - ] + , "main": "./node.js" + , "browser": "./browser.js" , "component": { "scripts": { - "debug/index.js": "debug.js" + "debug/index.js": "browser.js" + , "debug/debug.js": "debug.js" } } } From 0c6d45229259a1b2d9f616a796fe465f6321c993 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 30 May 2014 00:15:29 -0700 Subject: [PATCH 04/11] node: apply log to `console` Not necessary, just seems more "proper" --- node.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node.js b/node.js index 4163847..df7fbff 100644 --- a/node.js +++ b/node.js @@ -72,7 +72,7 @@ function log(fmt) { + ' ' + name + ' ' + fmt; } - console.log.apply(this, arguments); + console.log.apply(console, arguments); } /** From d05b468ee2e910f010fecdccbdbdeda8bf3865d2 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 30 May 2014 00:18:08 -0700 Subject: [PATCH 05/11] browser: , -> . --- browser.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser.js b/browser.js index 5a93453..4255ccf 100644 --- a/browser.js +++ b/browser.js @@ -35,7 +35,7 @@ function log(fmt) { } /** - * Save `namespaces`, + * Save `namespaces`. * * @param {String} namespaces * @api private @@ -48,7 +48,7 @@ function save(namespaces) { } /** - * Load `namespaces`, + * Load `namespaces`. * * @return {String} returns the previously persisted debug modes * @api private From fbbf2ca88487fec11707e4a47403af7100367885 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 30 May 2014 00:18:17 -0700 Subject: [PATCH 06/11] node: , -> . --- node.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node.js b/node.js index df7fbff..4fa71a9 100644 --- a/node.js +++ b/node.js @@ -76,7 +76,7 @@ function log(fmt) { } /** - * Save `namespaces`, + * Save `namespaces * * @param {String} namespaces * @api private @@ -87,7 +87,7 @@ function save(namespaces) { } /** - * Load `namespaces`, + * Load `namespaces`. * * @return {String} returns the previously persisted debug modes * @api private From 3eebad470aafd4447cfa8afb6f37fe168d09dc86 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 30 May 2014 00:23:56 -0700 Subject: [PATCH 07/11] browser: fix comment typo --- browser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser.js b/browser.js index 4255ccf..57fd60a 100644 --- a/browser.js +++ b/browser.js @@ -12,7 +12,7 @@ exports.load = load; /** * Invokes `console.log()` when available. - * No-op when `consoel.log` is not a "function". + * No-op when `console.log` is not a "function". * * @api public */ From bea76f587b659320a181d568b9c7ad5c0a5a424c Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 30 May 2014 00:29:14 -0700 Subject: [PATCH 08/11] browser: fix undefined `name` variable --- browser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser.js b/browser.js index 57fd60a..69c0415 100644 --- a/browser.js +++ b/browser.js @@ -22,7 +22,7 @@ function log(fmt) { var ms = curr - (this.prev || curr); this.prev = curr; - fmt = name + fmt = this.namespace + ' ' + fmt + ' +' + exports.humanize(ms); From 3314c7761c304af6bfeb01e0691c44ce362c357d Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 30 May 2014 22:13:23 -0700 Subject: [PATCH 09/11] browser: don't default save() to empty string --- browser.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser.js b/browser.js index 69c0415..be1d476 100644 --- a/browser.js +++ b/browser.js @@ -55,9 +55,9 @@ function save(namespaces) { */ function load() { - var r = ''; + var r; try { - r = localStorage.debug || ''; + r = localStorage.debug; } catch(e) {} return r; } From f3eb1a539613ee46f4da562634e34aded0e419d6 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 30 May 2014 22:13:46 -0700 Subject: [PATCH 10/11] node: don't default save() to an empty string --- node.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node.js b/node.js index 4fa71a9..3751ed6 100644 --- a/node.js +++ b/node.js @@ -94,7 +94,7 @@ function save(namespaces) { */ function load() { - return process.env.DEBUG || ''; + return process.env.DEBUG; } /** From 83bae0234362b047dd8d1828da96758f5453a3d4 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 30 May 2014 22:14:10 -0700 Subject: [PATCH 11/11] debug: invoke save() at the beginning of enable() We modify the `namespaces` argument directly for some reason, which ends up saving input that ends up being invalid RegExp code upon the next `load()`+`enable()` call combo. Avoid that completely by just saving the input directly first thing. Fixes browsers since they actually use the "saved" value. --- debug.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/debug.js b/debug.js index e207f5c..851af35 100644 --- a/debug.js +++ b/debug.js @@ -58,6 +58,8 @@ function debug(namespace) { */ function enable(namespaces) { + exports.save(namespaces); + var split = (namespaces || '').split(/[\s,]+/); var len = split.length; @@ -65,13 +67,10 @@ function enable(namespaces) { namespaces = split[i].replace('*', '.*?'); if (namespaces[0] === '-') { exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } - else { + } else { exports.names.push(new RegExp('^' + namespaces + '$')); } } - - exports.save(namespaces); } /**