diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..299877f --- /dev/null +++ b/.jshintrc @@ -0,0 +1,3 @@ +{ + "laxbreak": true +} diff --git a/browser.js b/browser.js new file mode 100644 index 0000000..be1d476 --- /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 `console.log` is not a "function". + * + * @api public + */ + +function log(fmt) { + var curr = new Date(); + var ms = curr - (this.prev || curr); + this.prev = curr; + + fmt = this.namespace + + ' ' + + 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 cb76981..1631574 100644 --- a/component.json +++ b/component.json @@ -2,9 +2,12 @@ "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"], + "main": "browser.js", + "scripts": [ + "browser.js", + "debug.js" + ], "dependencies": {} } diff --git a/debug.js b/debug.js index 509dc0d..851af35 100644 --- a/debug.js +++ b/debug.js @@ -1,74 +1,77 @@ /** + * 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){} +function enable(namespaces) { + exports.save(namespaces); - var split = (name || '').split(/[\s,]+/) - , len = split.length; + 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) + '$')); - } - else { - debug.names.push(new RegExp('^' + name + '$')); + namespaces = split[i].replace('*', '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); } } -}; +} /** * Disable debug output. @@ -76,9 +79,9 @@ debug.enable = function(name) { * @api public */ -debug.disable = function(){ - debug.enable(''); -}; +function disable() { + exports.enable(''); +} /** * Humanize the given `ms`. @@ -88,16 +91,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 +110,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..3751ed6 --- /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(console, 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" } } }