[Pkg-javascript-commits] [node-tap] 15/19: Bundle modules from tapjs as patches

Jérémy Lal kapouer at moszumanska.debian.org
Sat Nov 12 01:03:57 UTC 2016


This is an automated email from the git hooks/post-receive script.

kapouer pushed a commit to branch master
in repository node-tap.

commit d8526e291e61297843d6d5f017c6fb6fba9c44b7
Author: Jérémy Lal <kapouer at melix.org>
Date:   Sat Nov 12 01:36:41 2016 +0100

    Bundle modules from tapjs as patches
---
 debian/control                                 |   17 +-
 debian/copyright                               |   59 +-
 debian/install                                 |    3 +-
 debian/links                                   |    3 +-
 debian/nodemodules/foreground-child.js         |   80 -
 debian/patches/module-buffer-to-string.patch   |   21 +
 debian/patches/module-clean-yaml-object.patch  |   93 +
 debian/patches/module-foreground-child.patch   |   88 +
 debian/patches/module-stack-utils.patch        |  287 ++
 debian/patches/module-tap-mocha-reporter.patch | 3598 ++++++++++++++++++++++++
 debian/patches/sbuild_disable_tests.patch      |   12 +-
 debian/patches/series                          |    7 +-
 debian/patches/use_available_modules.patch     |  173 +-
 debian/rules                                   |   15 +-
 14 files changed, 4306 insertions(+), 150 deletions(-)

diff --git a/debian/control b/debian/control
index c35eac3..99be413 100644
--- a/debian/control
+++ b/debian/control
@@ -9,11 +9,13 @@ Build-Depends:
  , help2man
  , node-glob
  , node-nopt
- , node-yamlish
+ , node-js-yaml
  , node-mkdirp
  , node-slide
  , node-inherits
  , node-diff
+ , node-signal-exit
+ , node-deep-equal
  , nodejs
 Standards-Version: 3.9.8
 Homepage: https://github.com/isaacs/node-tap
@@ -26,14 +28,23 @@ Depends:
  ${misc:Depends}
  , nodejs
  , node-glob
+ , node-escape-string-regexp
+ , node-debug
  , node-nopt
- , node-yamlish
+ , node-js-yaml
  , node-mkdirp
  , node-slide
  , node-inherits
+ , node-signal-exit
+ , node-supports-color
+ , node-strip-ansi
+ , node-deep-equal
  , node-diff
+ , node-tmatch
+ , node-tap-parser
 Suggests:
- node-runforcover
+ node-coveralls
+ , node-nyc
 Description: Test-Anything-Protocol module for Node.js
  Utilities for writing test harnesses complying with TAP output format.
  .
diff --git a/debian/copyright b/debian/copyright
index ea0e25b..fd26939 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -7,11 +7,45 @@ Files: *
 Copyright: 2014 Isaac Z. Schlueter and Contributors
 License: ISC
 
-Files: debian/node_modules/foreground-child.js
+Files: node_modules/module-foreground-child.js
 Copyright: 2015 Isaac Z. Schlueter and Contributors
 License: ISC
 Source: https://github.com/tapjs/foreground-child/releases/tag/v1.5.3
-Comment: Bundled because too related to node-tap
+Comment: Bundled because tied to this package, limited interest outside of it
+
+Files: node_modules/tap-mocha-reporter/*
+Copyright: 2014 Isaac Z. Schlueter and Contributors
+License: ISC
+Source: https://github.com/tapjs/tap-mocha-reporter/releases/tag/v3.0.0
+Comment: Bundled because tied to this package, limited interest outside of it
+
+Files: node_modules/mocha-tap-reporter/reporters/*
+Copyright: 2011-2015 TJ Holowaychuk <tj at vision-media.ca>
+License: Expat
+
+Files: node_modules/stack-utils.js
+Copyright: Isaac Z. Schlueter <i at izs.me>
+ James Talmage <james at talmage.io> (github.com/jamestalmage)
+ and Contributors
+License: Expat
+Source: https://github.com/tapjs/stack-utils/releases/tag/v0.4.0
+Comment: Bundled because tied to this package, limited interest outside of it
+
+Files: node_modules/clean-yaml-object.js
+Copyright: Isaac Z. Schlueter <i at izs.me>
+ James Talmage <james at talmage.io> (github.com/jamestalmage)
+ and Contributors
+License: Expat
+Source: https://github.com/tapjs/clean-yaml-object/releases/tag/v0.1.0
+Comment: Bundled because tied to this package, limited interest outside of it
+
+Files: node_modules/buffer-to-string.js
+Copyright: Isaac Z. Schlueter <i at izs.me>
+ James Talmage <james at talmage.io> (github.com/jamestalmage)
+ and Contributors
+License: Expat
+Source: https://github.com/tapjs/buffer-to-string/releases/tag/v0.1.0
+Comment: Bundled because tied to this package, limited interest outside of it
 
 Files: debian/*
 Copyright: 2014 Jérémy Lal <kapouer at melix.org>
@@ -30,3 +64,24 @@ License: ISC
  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+License: Expat
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+ .
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
diff --git a/debian/install b/debian/install
index 7763890..ae3303b 100644
--- a/debian/install
+++ b/debian/install
@@ -1,3 +1,4 @@
 package.json usr/lib/nodejs/tap/
-bin usr/lib/nodejs/tap/
+bin/run.js usr/lib/nodejs/tap/bin/run.js
 lib usr/lib/nodejs/tap/
+node_modules usr/lib/nodejs/tap/
diff --git a/debian/links b/debian/links
index ea0f573..dc74c82 100644
--- a/debian/links
+++ b/debian/links
@@ -1,2 +1 @@
-usr/lib/nodejs/tap/bin/tap.js usr/bin/tap
-debian/nodemodules usr/lib/nodejs/tap/node_modules
+usr/lib/nodejs/tap/bin/run.js usr/bin/tap
diff --git a/debian/nodemodules/foreground-child.js b/debian/nodemodules/foreground-child.js
deleted file mode 100644
index aa48c6f..0000000
--- a/debian/nodemodules/foreground-child.js
+++ /dev/null
@@ -1,80 +0,0 @@
-var signalExit = require('signal-exit')
-var spawn = require('child_process').spawn
-if (process.platform === 'win32') {
-  spawn = require('cross-spawn')
-}
-
-module.exports = function (program, args, cb) {
-  var arrayIndex = arguments.length
-
-  if (typeof args === 'function') {
-    cb = args
-    args = undefined
-  } else {
-    cb = Array.prototype.slice.call(arguments).filter(function (arg, i) {
-      if (typeof arg === 'function') {
-        arrayIndex = i
-        return true
-      }
-    })[0]
-  }
-
-  cb = cb || function (done) {
-    return done()
-  }
-
-  if (Array.isArray(program)) {
-    args = program.slice(1)
-    program = program[0]
-  } else if (!Array.isArray(args)) {
-    args = [].slice.call(arguments, 1, arrayIndex)
-  }
-
-  var spawnOpts = { stdio: [0, 1, 2] }
-
-  if (process.send) {
-    spawnOpts.stdio.push('ipc')
-  }
-
-  var child = spawn(program, args, spawnOpts)
-
-  var childExited = false
-  signalExit(function (code, signal) {
-    child.kill(signal || 'SIGHUP')
-  })
-
-  child.on('close', function (code, signal) {
-    // Allow the callback to inspect the child’s exit code and/or modify it.
-    process.exitCode = signal ? 128 + signal : code
-
-    cb(function () {
-      childExited = true
-      if (signal) {
-        // If there is nothing else keeping the event loop alive,
-        // then there's a race between a graceful exit and getting
-        // the signal to this process.  Put this timeout here to
-        // make sure we're still alive to get the signal, and thus
-        // exit with the intended signal code.
-        setTimeout(function () {}, 200)
-        process.kill(process.pid, signal)
-      } else {
-        // Equivalent to process.exit() on Node.js >= 0.11.8
-        process.exit(process.exitCode)
-      }
-    })
-  })
-
-  if (process.send) {
-    process.removeAllListeners('message')
-
-    child.on('message', function (message, sendHandle) {
-      process.send(message, sendHandle)
-    })
-
-    process.on('message', function (message, sendHandle) {
-      child.send(message, sendHandle)
-    })
-  }
-
-  return child
-}
diff --git a/debian/patches/module-buffer-to-string.patch b/debian/patches/module-buffer-to-string.patch
new file mode 100644
index 0000000..a101c1e
--- /dev/null
+++ b/debian/patches/module-buffer-to-string.patch
@@ -0,0 +1,21 @@
+--- /dev/null
++++ b/node_modules/buffer-to-string.js
+@@ -0,0 +1,18 @@
++'use strict';
++module.exports = function (buffer, limit) {
++	limit = limit || 20;
++	return buffer.toString('hex').split('')
++		.reduce(function (arr, char) {
++			if (arr.length && arr[arr.length - 1].length === 1) {
++				arr[arr.length - 1] += char;
++				if (arr.length && arr.length % limit === 0) {
++					arr[arr.length - 1] += '\n';
++				} else {
++					arr[arr.length - 1] += ' ';
++				}
++			} else {
++				arr.push(char);
++			}
++			return arr;
++		}, []).join('').trim();
++};
diff --git a/debian/patches/module-clean-yaml-object.patch b/debian/patches/module-clean-yaml-object.patch
new file mode 100644
index 0000000..20b54f9
--- /dev/null
+++ b/debian/patches/module-clean-yaml-object.patch
@@ -0,0 +1,93 @@
+--- /dev/null
++++ b/node_modules/clean-yaml-object.js
+@@ -0,0 +1,90 @@
++'use strict';
++var bufferToString = require('buffer-to-string');
++
++module.exports = function (object, filterFn) {
++	return cleanYamlObj(object, filterFn || defaultFilter, true, []);
++};
++
++function cleanYamlObj(object, filter, isRoot, seen) {
++	if (object === undefined) {
++		return null;
++	}
++
++	if (typeof object === 'function') {
++		return object.toString();
++	}
++
++	if (Buffer.isBuffer(object)) {
++		return 'Buffer\n' + bufferToString(object);
++	}
++
++	if (object && typeof object === 'object') {
++		if (object instanceof RegExp) {
++			return object.toString();
++		}
++
++		seen = seen.concat([object]);
++
++		var isArray = Array.isArray(object);
++
++		// Fill in any holes.  This means we lose expandos,
++		// but we were gonna lose those anyway.
++		if (isArray) {
++			object = fillHoles(object);
++		}
++
++		var isError = object && typeof object === 'object' && object instanceof Error;
++
++		var set = isArray ? [] : {};
++
++		// name is typically not an ownProperty on an Error
++		if (isError && object.name && !{}.hasOwnProperty.call(object, 'name') && filter('name', isRoot, object, set)) {
++			setProp('name', object, set, seen, filter);
++		}
++
++		var keys = Object.getOwnPropertyNames(object);
++		return keys.reduce(function (set, k) {
++			// magic property!
++			if (isArray && k === 'length') {
++				return set;
++			}
++
++			// Don't dump massive EventEmitter and Domain
++			// objects onto the output, that's never friendly.
++			if (isError && /^domain/.test(k)) {
++				return set;
++			}
++
++			if (!filter(k, isRoot, object, set)) {
++				return set;
++			}
++
++			setProp(k, object, set, seen, filter);
++
++			return set;
++		}, set);
++	}
++
++	return object;
++}
++
++function setProp(propName, source, target, seen, filter) {
++	if (seen.indexOf(source[propName]) === -1) {
++		target[propName] = cleanYamlObj(source[propName], filter, false, seen);
++	} else {
++		target[propName] = '[Circular]';
++	}
++}
++
++function defaultFilter() {
++	return true;
++}
++
++function fillHoles(arr) {
++	var result = [];
++	for (var i = 0; i < arr.length; i++) {
++		result[i] = arr[i];
++	}
++	return result;
++}
++
diff --git a/debian/patches/module-foreground-child.patch b/debian/patches/module-foreground-child.patch
new file mode 100644
index 0000000..63ec5bd
--- /dev/null
+++ b/debian/patches/module-foreground-child.patch
@@ -0,0 +1,88 @@
+Description: module foreground-child
+ see copyright for more information
+Last-Update: 2016-11-11
+Forwarded: not-needed
+Author: Jérémy Lal <kapouer at melix.org>
+--- /dev/null
++++ b/node_modules/foreground-child.js
+@@ -0,0 +1,80 @@
++var signalExit = require('signal-exit')
++var spawn = require('child_process').spawn
++if (process.platform === 'win32') {
++  spawn = require('cross-spawn')
++}
++
++module.exports = function (program, args, cb) {
++  var arrayIndex = arguments.length
++
++  if (typeof args === 'function') {
++    cb = args
++    args = undefined
++  } else {
++    cb = Array.prototype.slice.call(arguments).filter(function (arg, i) {
++      if (typeof arg === 'function') {
++        arrayIndex = i
++        return true
++      }
++    })[0]
++  }
++
++  cb = cb || function (done) {
++    return done()
++  }
++
++  if (Array.isArray(program)) {
++    args = program.slice(1)
++    program = program[0]
++  } else if (!Array.isArray(args)) {
++    args = [].slice.call(arguments, 1, arrayIndex)
++  }
++
++  var spawnOpts = { stdio: [0, 1, 2] }
++
++  if (process.send) {
++    spawnOpts.stdio.push('ipc')
++  }
++
++  var child = spawn(program, args, spawnOpts)
++
++  var childExited = false
++  signalExit(function (code, signal) {
++    child.kill(signal || 'SIGHUP')
++  })
++
++  child.on('close', function (code, signal) {
++    // Allow the callback to inspect the child’s exit code and/or modify it.
++    process.exitCode = signal ? 128 + signal : code
++
++    cb(function () {
++      childExited = true
++      if (signal) {
++        // If there is nothing else keeping the event loop alive,
++        // then there's a race between a graceful exit and getting
++        // the signal to this process.  Put this timeout here to
++        // make sure we're still alive to get the signal, and thus
++        // exit with the intended signal code.
++        setTimeout(function () {}, 200)
++        process.kill(process.pid, signal)
++      } else {
++        // Equivalent to process.exit() on Node.js >= 0.11.8
++        process.exit(process.exitCode)
++      }
++    })
++  })
++
++  if (process.send) {
++    process.removeAllListeners('message')
++
++    child.on('message', function (message, sendHandle) {
++      process.send(message, sendHandle)
++    })
++
++    process.on('message', function (message, sendHandle) {
++      child.send(message, sendHandle)
++    })
++  }
++
++  return child
++}
diff --git a/debian/patches/module-stack-utils.patch b/debian/patches/module-stack-utils.patch
new file mode 100644
index 0000000..87d1c89
--- /dev/null
+++ b/debian/patches/module-stack-utils.patch
@@ -0,0 +1,287 @@
+--- /dev/null
++++ b/node_modules/stack-utils.js
+@@ -0,0 +1,284 @@
++module.exports = StackUtils;
++
++function StackUtils(opts) {
++	if (!(this instanceof StackUtils)) {
++		throw new Error('StackUtils constructor must be called with new');
++	}
++	opts = opts || {};
++	this._cwd = (opts.cwd || process.cwd()).replace(/\\/g, '/');
++	this._internals = opts.internals || [];
++}
++
++module.exports.nodeInternals = nodeInternals;
++
++function nodeInternals() {
++	return [
++		/\(native\)$/,
++		/\(domain.js:\d+:\d+\)$/,
++		/\(events.js:\d+:\d+\)$/,
++		/\(node.js:\d+:\d+\)$/,
++		/\(timers.js:\d+:\d+\)$/,
++		/\(module.js:\d+:\d+\)$/,
++		/\(internal\/[\w_-]+\.js:\d+:\d+\)$/,
++		/\s*at node\.js:\d+:\d+?$/,
++		/\/\.node-spawn-wrap-\w+-\w+\/node:\d+:\d+\)?$/
++	];
++}
++
++StackUtils.prototype.clean = function (stack) {
++	if (!Array.isArray(stack)) {
++		stack = stack.split('\n');
++	}
++
++	if (!(/^\s*at /.test(stack[0])) &&
++		(/^\s*at /.test(stack[1]))) {
++		stack = stack.slice(1);
++	}
++
++	var outdent = false;
++	var lastNonAtLine = null;
++	var result = [];
++
++	stack.forEach(function (st) {
++		st = st.replace(/\\/g, '/');
++		var isInternal = this._internals.some(function (internal) {
++			return internal.test(st);
++		});
++
++		if (isInternal) {
++			return null;
++		}
++
++		var isAtLine = /^\s*at /.test(st);
++
++		if (outdent) {
++			st = st.replace(/\s+$/, '').replace(/^(\s+)at /, '$1');
++		} else {
++			st = st.trim();
++			if (isAtLine) {
++				st = st.substring(3);
++			}
++		}
++
++		st = st.replace(this._cwd + '/', '');
++
++		if (st) {
++			if (isAtLine) {
++				if (lastNonAtLine) {
++					result.push(lastNonAtLine);
++					lastNonAtLine = null;
++				}
++				result.push(st);
++			} else {
++				outdent = true;
++				lastNonAtLine = st;
++			}
++		}
++	}, this);
++
++	stack = result.join('\n').trim();
++
++	if (stack) {
++		return stack + '\n';
++	}
++	return '';
++};
++
++StackUtils.prototype.captureString = function (limit, fn) {
++	if (typeof limit === 'function') {
++		fn = limit;
++		limit = Infinity;
++	}
++	if (!fn) {
++		fn = this.captureString;
++	}
++
++	var limitBefore = Error.stackTraceLimit;
++	if (limit) {
++		Error.stackTraceLimit = limit;
++	}
++
++	var obj = {};
++
++	Error.captureStackTrace(obj, fn);
++	var stack = obj.stack;
++	Error.stackTraceLimit = limitBefore;
++
++	return this.clean(stack);
++};
++
++StackUtils.prototype.capture = function (limit, fn) {
++	if (typeof limit === 'function') {
++		fn = limit;
++		limit = Infinity;
++	}
++	if (!fn) {
++		fn = this.capture;
++	}
++	var prepBefore = Error.prepareStackTrace;
++	var limitBefore = Error.stackTraceLimit;
++
++	Error.prepareStackTrace = function (obj, site) {
++		return site;
++	};
++
++	if (limit) {
++		Error.stackTraceLimit = limit;
++	}
++
++	var obj = {};
++	Error.captureStackTrace(obj, fn);
++	var stack = obj.stack;
++	Error.prepareStackTrace = prepBefore;
++	Error.stackTraceLimit = limitBefore;
++
++	return stack;
++};
++
++StackUtils.prototype.at = function at(fn) {
++	if (!fn) {
++		fn = at;
++	}
++
++	var site = this.capture(1, fn)[0];
++
++	if (!site) {
++		return {};
++	}
++
++	var res = {
++		line: site.getLineNumber(),
++		column: site.getColumnNumber()
++	};
++
++	this._setFile(res, site.getFileName());
++
++	if (site.isConstructor()) {
++		res.constructor = true;
++	}
++
++	if (site.isEval()) {
++		res.evalOrigin = site.getEvalOrigin();
++	}
++
++	if (site.isNative()) {
++		res.native = true;
++	}
++
++	var typename = null;
++	try {
++		typename = site.getTypeName();
++	} catch (er) {}
++
++	if (typename &&
++		typename !== 'Object' &&
++		typename !== '[object Object]') {
++		res.type = typename;
++	}
++
++	var fname = site.getFunctionName();
++	if (fname) {
++		res.function = fname;
++	}
++
++	var meth = site.getMethodName();
++	if (meth && fname !== meth) {
++		res.method = meth;
++	}
++
++	return res;
++};
++
++StackUtils.prototype._setFile = function (result, filename) {
++	if (filename) {
++		filename = filename.replace(/\\/g, '/');
++		if ((filename.indexOf(this._cwd + '/') === 0)) {
++			filename = filename.substr(this._cwd.length + 1);
++		}
++		result.file = filename;
++	}
++};
++
++var re = new RegExp(
++	'^' +
++		// Sometimes we strip out the '    at' because it's noisy
++	'(?:\\s*at )?' +
++		// $1 = ctor if 'new'
++	'(?:(new) )?' +
++		// Object.method [as foo] (, maybe
++		// $2 = function name
++		// $3 = method name
++	'(?:([^\\(\\[]*)(?: \\[as ([^\\]]+)\\])? \\()?' +
++		// (eval at <anonymous> (file.js:1:1),
++		// $4 = eval origin
++		// $5:$6:$7 are eval file/line/col, but not normally reported
++	'(?:eval at ([^ ]+) \\(([^\\)]+):(\\d+):(\\d+)\\), )?' +
++		// file:line:col
++		// $8:$9:$10
++		// $11 = 'native' if native
++	'(?:([^\\)]+):(\\d+):(\\d+)|(native))' +
++		// maybe close the paren, then end
++	'\\)?$'
++);
++
++StackUtils.prototype.parseLine = function parseLine(line) {
++	var match = line && line.match(re);
++	if (!match) {
++		return null;
++	}
++
++	var ctor = match[1] === 'new';
++	var fname = match[2];
++	var meth = match[3];
++	var evalOrigin = match[4];
++	var evalFile = match[5];
++	var evalLine = Number(match[6]);
++	var evalCol = Number(match[7]);
++	var file = match[8];
++	var lnum = match[9];
++	var col = match[10];
++	var native = match[11] === 'native';
++
++	var res = {};
++
++	if (lnum) {
++		res.line = Number(lnum);
++	}
++
++	if (col) {
++		res.column = Number(col);
++	}
++
++	this._setFile(res, file);
++
++	if (ctor) {
++		res.constructor = true;
++	}
++
++	if (evalOrigin) {
++		res.evalOrigin = evalOrigin;
++		res.evalLine = evalLine;
++		res.evalColumn = evalCol;
++		res.evalFile = evalFile && evalFile.replace(/\\/g, '/');
++	}
++
++	if (native) {
++		res.native = true;
++	}
++
++	if (fname) {
++		res.function = fname;
++	}
++
++	if (meth && fname !== meth) {
++		res.method = meth;
++	}
++
++	return res;
++};
++
++var bound = new StackUtils();
++
++Object.keys(StackUtils.prototype).forEach(function (key) {
++	StackUtils[key] = bound[key].bind(bound);
++});
diff --git a/debian/patches/module-tap-mocha-reporter.patch b/debian/patches/module-tap-mocha-reporter.patch
new file mode 100644
index 0000000..38206fe
--- /dev/null
+++ b/debian/patches/module-tap-mocha-reporter.patch
@@ -0,0 +1,3598 @@
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/formatter.js
+@@ -0,0 +1,87 @@
++// A formatter is a Duplex stream that TAP data is written into,
++// and then something else (presumably not-TAP) is read from.
++//
++// See tap-classic.js for an example of a formatter in use.
++
++var Duplex = require('stream').Duplex
++if (!Duplex) {
++  try {
++    Duplex = require('readable-stream').Duplex
++  } catch (er) {
++    throw new Error('Please install "readable-stream" to use this module ' +
++                    'with Node.js v0.8 and before')
++  }
++}
++
++var util = require('util')
++var Parser = require('tap-parser')
++util.inherits(Formatter, Duplex)
++module.exports = Formatter
++
++function Formatter(options, parser, parent) {
++  if (!(this instanceof Formatter))
++    return new Formatter(options, parser, parent)
++
++  if (!parser)
++    parser = new Parser()
++
++  Duplex.call(this, options)
++  this.child = null
++  this.parent = parent || null
++  this.level = parser.level
++  this.parser = parser
++
++  attachEvents(this, parser, options)
++
++  if (options.init)
++    options.init.call(this)
++}
++
++function attachEvents (self, parser, options) {
++  var events = [
++    'version', 'plan', 'assert', 'comment',
++    'complete', 'extra', 'bailout'
++  ]
++
++  parser.on('child', function (childparser) {
++    self.child = new Formatter(options, childparser, self)
++    if (options.child)
++      options.child.call(self, self.child)
++  })
++
++  events.forEach(function (ev) {
++    if (typeof options[ev] === 'function')
++      parser.on(ev, options[ev].bind(self))
++  })
++
++  // proxy all stream events directly
++  var streamEvents = [
++    'pipe', 'prefinish', 'finish', 'unpipe', 'close'
++  ]
++
++  streamEvents.forEach(function (ev) {
++    parser.on(ev, function () {
++      var args = [ev]
++      args.push.apply(args, arguments)
++      self.emit.apply(self, args)
++    })
++  })
++}
++
++Formatter.prototype.write = function (c, e, cb) {
++  return this.parser.write(c, e, cb)
++}
++
++Formatter.prototype.end = function (c, e, cb) {
++  return this.parser.end(c, e, cb)
++}
++
++Formatter.prototype._read = function () {}
++
++// child formatters always push data to the root obj
++Formatter.prototype.push = function (c) {
++  if (this.parent)
++    return this.parent.push(c)
++
++  Duplex.prototype.push.call(this, c)
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/ms.js
+@@ -0,0 +1,109 @@
++/**
++ * Helpers.
++ */
++
++var s = 1000;
++var m = s * 60;
++var h = m * 60;
++var d = h * 24;
++var y = d * 365.25;
++
++/**
++ * Parse or format the given `val`.
++ *
++ * Options:
++ *
++ *  - `long` verbose formatting [false]
++ *
++ * @param {String|Number} val
++ * @param {Object} options
++ * @return {String|Number}
++ * @api public
++ */
++
++module.exports = function(val, options){
++  options = options || {};
++  if ('string' == typeof val) return parse(val);
++  return options['long'] ? longFormat(val) : shortFormat(val);
++};
++
++/**
++ * Parse the given `str` and return milliseconds.
++ *
++ * @param {String} str
++ * @return {Number}
++ * @api private
++ */
++
++function parse(str) {
++  var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
++  if (!match) return;
++  var n = parseFloat(match[1]);
++  var type = (match[2] || 'ms').toLowerCase();
++  switch (type) {
++    case 'years':
++    case 'year':
++    case 'y':
++      return n * y;
++    case 'days':
++    case 'day':
++    case 'd':
++      return n * d;
++    case 'hours':
++    case 'hour':
++    case 'h':
++      return n * h;
++    case 'minutes':
++    case 'minute':
++    case 'm':
++      return n * m;
++    case 'seconds':
++    case 'second':
++    case 's':
++      return n * s;
++    case 'ms':
++      return n;
++  }
++}
++
++/**
++ * Short format for `ms`.
++ *
++ * @param {Number} ms
++ * @return {String}
++ * @api private
++ */
++
++function shortFormat(ms) {
++  if (ms >= d) return Math.round(ms / d) + 'd';
++  if (ms >= h) return Math.round(ms / h) + 'h';
++  if (ms >= m) return Math.round(ms / m) + 'm';
++  if (ms >= s) return Math.round(ms / s) + 's';
++  return ms + 'ms';
++}
++
++/**
++ * Long format for `ms`.
++ *
++ * @param {Number} ms
++ * @return {String}
++ * @api private
++ */
++
++function longFormat(ms) {
++  return plural(ms, d, 'day')
++    || plural(ms, h, 'hour')
++    || plural(ms, m, 'minute')
++    || plural(ms, s, 'second')
++    || ms + ' ms';
++}
++
++/**
++ * Pluralization helper.
++ */
++
++function plural(ms, n, name) {
++  if (ms < n) return;
++  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
++  return Math.ceil(ms / n) + ' ' + name + 's';
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/base.js
+@@ -0,0 +1,463 @@
++/**
++ * Module dependencies.
++ */
++
++var tty = require('tty')
++  , diff = require('diff')
++  , ms = require('../ms')
++  , utils = require('../utils')
++  , supportsColor = require('color-support')()
++
++/**
++ * Save timer references to avoid Sinon interfering (see GH-237).
++ */
++
++var Date = global.Date
++  , setTimeout = global.setTimeout
++  , setInterval = global.setInterval
++  , clearTimeout = global.clearTimeout
++  , clearInterval = global.clearInterval;
++
++/**
++ * Check if both stdio streams are associated with a tty.
++ */
++
++var isatty = tty.isatty(1);
++
++/**
++ * Expose `Base`.
++ */
++
++exports = module.exports = Base;
++
++/**
++ * Enable coloring by default, except in the browser interface.
++ */
++
++exports.useColors = process.env
++  ? (supportsColor || (process.env.TAP_COLORS !== undefined))
++  : false;
++
++if (exports.useColors && +process.env.TAP_COLORS === 0)
++  exports.useColors = false
++
++/**
++ * Inline diffs instead of +/-
++ */
++
++exports.inlineDiffs = false;
++
++/**
++ * Default color map.
++ */
++
++exports.colors = {
++    'pass': 90
++  , 'fail': 31
++  , 'bright pass': 92
++  , 'bright fail': 91
++  , 'bright yellow': 93
++  , 'pending': 35
++  , 'skip': 36
++  , 'suite': 0
++  , 'error title': 0
++  , 'error message': 31
++  , 'error stack': 90
++  , 'checkmark': 32
++  , 'fast': 90
++  , 'medium': 33
++  , 'slow': 31
++  , 'green': 32
++  , 'light': 90
++  , 'diff gutter': 90
++  , 'diff added': 42
++  , 'diff removed': 41
++};
++
++/**
++ * Default symbol map.
++ */
++
++exports.symbols = {
++  ok: '✓',
++  err: '✖',
++  dot: '․'
++};
++
++// With node.js on Windows: use symbols available in terminal default fonts
++if ('win32' == process.platform) {
++  exports.symbols.ok = '\u221A';
++  exports.symbols.err = '\u00D7';
++  exports.symbols.dot = '.';
++}
++
++/**
++ * Color `str` with the given `type`,
++ * allowing colors to be disabled,
++ * as well as user-defined color
++ * schemes.
++ *
++ * @param {String} type
++ * @param {String} str
++ * @return {String}
++ * @api private
++ */
++
++var color = exports.color = function(type, str) {
++  if (!exports.useColors) return String(str);
++  return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
++};
++
++/**
++ * Expose term window size, with some
++ * defaults for when stderr is not a tty.
++ */
++
++exports.window = {
++  width: isatty
++    ? process.stdout.getWindowSize
++      ? process.stdout.getWindowSize(1)[0]
++      : tty.getWindowSize()[1]
++    : 75
++};
++
++/**
++ * Expose some basic cursor interactions
++ * that are common among reporters.
++ */
++
++exports.cursor = {
++  hide: function(){
++    isatty && process.stdout.write('\u001b[?25l');
++  },
++
++  show: function(){
++    isatty && process.stdout.write('\u001b[?25h');
++  },
++
++  deleteLine: function(){
++    isatty && process.stdout.write('\u001b[2K');
++  },
++
++  beginningOfLine: function(){
++    isatty && process.stdout.write('\u001b[0G');
++  },
++
++  CR: function(){
++    if (isatty) {
++      exports.cursor.deleteLine();
++      exports.cursor.beginningOfLine();
++    } else {
++      process.stdout.write('\r');
++    }
++  }
++};
++
++/**
++ * Outut the given `failures` as a list.
++ *
++ * @param {Array} failures
++ * @api public
++ */
++
++exports.list = function(failures){
++  console.log();
++  failures.forEach(function(test, i){
++    // format
++    var fmt = color('error title', '  %s) %s:\n')
++      + color('error message', '     %s')
++      + color('error stack', '\n%s\n');
++
++    // msg
++    var err = test.err
++      , message = err.message || ''
++      , stack = err.stack || message
++
++    var index = stack.indexOf(message) + message.length
++      , msg = stack.slice(0, index)
++      , actual = err.actual
++      , expected = err.expected
++      , escape = true;
++
++
++    // uncaught
++    if (err.uncaught) {
++      msg = 'Uncaught ' + msg;
++    }
++    // explicitly show diff
++    if (err.showDiff && sameType(actual, expected)) {
++
++      if ('string' !== typeof actual) {
++        escape = false;
++        err.actual = actual = utils.stringify(actual);
++        err.expected = expected = utils.stringify(expected);
++      }
++
++      fmt = color('error title', '  %s) %s:\n%s') + color('error stack', '\n%s\n');
++      var match = message.match(/^([^:]+): expected/);
++      msg = '\n      ' + color('error message', match ? match[1] : msg);
++
++      if (exports.inlineDiffs) {
++        msg += inlineDiff(err, escape);
++      } else {
++        msg += unifiedDiff(err, escape);
++      }
++    }
++
++    // indent stack trace without msg
++    stack = utils.stackTraceFilter()(stack.slice(index ? index + 1 : index)
++      .replace(/^/gm, '  '));
++
++    console.log(fmt, (i + 1), test.fullTitle(), msg, stack);
++  });
++};
++
++/**
++ * Initialize a new `Base` reporter.
++ *
++ * All other reporters generally
++ * inherit from this reporter, providing
++ * stats such as test duration, number
++ * of tests passed / failed etc.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function Base(runner) {
++  var self = this
++    , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }
++    , failures = this.failures = [];
++
++  if (!runner) return;
++  this.runner = runner;
++
++  runner.stats = stats;
++
++  runner.on('start', function(){
++    stats.start = new Date;
++  });
++
++  runner.on('suite', function(suite){
++    stats.suites = stats.suites || 0;
++    suite.root || stats.suites++;
++  });
++
++  runner.on('test end', function(test){
++    stats.tests = stats.tests || 0;
++    stats.tests++;
++  });
++
++  runner.on('pass', function(test){
++    stats.passes = stats.passes || 0;
++
++    var medium = test.slow() / 2;
++    test.speed = test.duration > test.slow()
++      ? 'slow'
++      : test.duration > medium
++        ? 'medium'
++        : 'fast';
++
++    stats.passes++;
++  });
++
++  runner.on('fail', function(test, err){
++    stats.failures = stats.failures || 0;
++    stats.failures++;
++    test.err = err;
++    failures.push(test);
++  });
++
++  runner.on('end', function(){
++    stats.end = new Date;
++    if (!stats.duration)
++      stats.duration = stats.end - stats.start;
++  });
++
++  runner.on('pending', function(){
++    stats.pending++;
++  });
++}
++
++/**
++ * Output common epilogue used by many of
++ * the bundled reporters.
++ *
++ * @api public
++ */
++
++Base.prototype.epilogue = function(){
++  var stats = this.stats;
++  var tests;
++  var fmt;
++
++  console.log();
++
++  // passes
++  fmt = color('bright pass', ' ')
++    + color('green', ' %d passing')
++    + color('light', ' (%s)');
++
++  console.log(fmt,
++    stats.passes || 0,
++    ms(stats.duration));
++
++  // pending
++  if (stats.pending) {
++    fmt = color('pending', ' ')
++      + color('pending', ' %d pending');
++
++    console.log(fmt, stats.pending);
++  }
++
++  // failures
++  if (stats.failures) {
++    fmt = color('fail', '  %d failing');
++
++    console.log(fmt, stats.failures);
++
++    Base.list(this.failures);
++  }
++};
++
++/**
++ * Pad the given `str` to `len`.
++ *
++ * @param {String} str
++ * @param {String} len
++ * @return {String}
++ * @api private
++ */
++
++function pad(str, len) {
++  str = String(str);
++  return Array(len - str.length + 1).join(' ') + str;
++}
++
++
++/**
++ * Returns an inline diff between 2 strings with coloured ANSI output
++ *
++ * @param {Error} Error with actual/expected
++ * @return {String} Diff
++ * @api private
++ */
++
++function inlineDiff(err, escape) {
++  var msg = errorDiff(err, 'WordsWithSpace', escape);
++
++  // linenos
++  var lines = msg.split('\n');
++  if (lines.length > 4) {
++    var width = String(lines.length).length;
++    msg = lines.map(function(str, i){
++      return pad(++i, width) + ' |' + ' ' + str;
++    }).join('\n');
++  }
++
++  // legend
++  msg = '\n'
++    + color('diff removed', 'actual')
++    + ' '
++    + color('diff added', 'expected')
++    + '\n\n'
++    + msg
++    + '\n';
++
++  // indent
++  msg = msg.replace(/^/gm, '      ');
++  return msg;
++}
++
++/**
++ * Returns a unified diff between 2 strings
++ *
++ * @param {Error} Error with actual/expected
++ * @return {String} Diff
++ * @api private
++ */
++
++function unifiedDiff(err, escape) {
++  var indent = '      ';
++  function cleanUp(line) {
++    if (escape) {
++      line = escapeInvisibles(line);
++    }
++    if (line[0] === '+') return indent + colorLines('diff added', line);
++    if (line[0] === '-') return indent + colorLines('diff removed', line);
++    if (line.match(/\@\@/)) return null;
++    if (line.match(/\\ No newline/)) return null;
++    else return indent + line;
++  }
++  function notBlank(line) {
++    return line != null;
++  }
++  var msg = diff.createPatch('string', err.actual, err.expected);
++  var lines = msg.split('\n').splice(4);
++  return '\n      '
++         + colorLines('diff added',   '+ expected') + ' '
++         + colorLines('diff removed', '- actual')
++         + '\n\n'
++         + lines.map(cleanUp).filter(notBlank).join('\n');
++}
++
++/**
++ * Return a character diff for `err`.
++ *
++ * @param {Error} err
++ * @return {String}
++ * @api private
++ */
++
++function errorDiff(err, type, escape) {
++  var actual   = escape ? escapeInvisibles(err.actual)   : err.actual;
++  var expected = escape ? escapeInvisibles(err.expected) : err.expected;
++  return diff['diff' + type](actual, expected).map(function(str){
++    if (str.added) return colorLines('diff added', str.value);
++    if (str.removed) return colorLines('diff removed', str.value);
++    return str.value;
++  }).join('');
++}
++
++/**
++ * Returns a string with all invisible characters in plain text
++ *
++ * @param {String} line
++ * @return {String}
++ * @api private
++ */
++function escapeInvisibles(line) {
++    return line.replace(/\t/g, '<tab>')
++               .replace(/\r/g, '<CR>')
++               .replace(/\n/g, '<LF>\n');
++}
++
++/**
++ * Color lines for `str`, using the color `name`.
++ *
++ * @param {String} name
++ * @param {String} str
++ * @return {String}
++ * @api private
++ */
++
++function colorLines(name, str) {
++  return str.split('\n').map(function(str){
++    return color(name, str);
++  }).join('\n');
++}
++
++/**
++ * Check that a / b have the same type.
++ *
++ * @param {Object} a
++ * @param {Object} b
++ * @return {Boolean}
++ * @api private
++ */
++
++function sameType(a, b) {
++  a = Object.prototype.toString.call(a);
++  b = Object.prototype.toString.call(b);
++  return a == b;
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/classic.js
+@@ -0,0 +1,402 @@
++exports = module.exports = Classic
++
++var Base = require('./base')
++  , cursor = Base.cursor
++  , color = Base.color
++  , yaml = require('js-yaml')
++  , util = require('util')
++  , fancy = Base.useColors && !process.env.TRAVIS
++  , ms = require('../ms.js')
++  , diff = require('diff')
++  , utils = require('../utils.js')
++  , uclen = require('unicode-length').get
++  , colorSupport = require('color-support')()
++
++function hasOwnProperty (obj, key) {
++  return Object.prototype.hasOwnProperty.call(obj, key)
++}
++
++function doDiff (found, wanted, palette) {
++  // TODO: Make this a configurable thing or something?
++  //
++  // Choosing a palette for diffs in a test-runner context
++  // is really tricky.  The temptation is to make it look
++  // exactly like `git diff`, but the default red and green
++  // are very confusing with the colors used to indicate
++  // pass/fail.
++  //
++  // So, I decided to experiment with setting a background to
++  // distinguish the diff section from the rest of the test
++  // output.  The obvious choice, then, was to mimick GitHub's
++  // diff styling.
++  //
++  // The problem there is that, while those of us with an
++  // abundance of cones tend to find that palette most pleasing,
++  // it's virtually impossible for people with various sorts of
++  // red/green colorblindness to distinguish those colors.
++  //
++  // The resulting option, with a somewhat pink-ish red and a
++  // somewhat yellow-ish green, seems to be a pretty good
++  // compromise between esthetics and accessibility.  In a poll
++  // on twitter, it was the only one that no color-sighted people
++  // strongly objected to, and no color-blind people had
++  // significant trouble interpreting.  The twitter poll agrees
++  // with the results of Sim Daltonism, which showed that this
++  // palette was easily distinguishable across all forms of color
++  // deficiency.
++
++  // TODO: add a TrueColor one that looks nicer
++  palette = colorSupport.has256 ? 6 : 1
++
++  var plain = ''
++  var reset = '\u001b[m'
++
++  switch (palette) {
++    case 1:
++      // most git-like.  r/g, no background, no bold
++      var bg = ''
++      var removed = '\u001b[31m'
++      var added = '\u001b[32m'
++      break
++
++    case 2:
++      // dark option, maybe confusing with pass/fail colors?
++      var bg = '\u001b[48;5;234m'
++      var removed = '\u001b[31;1m'
++      var added = '\u001b[32;1m'
++      break
++
++    case 3:
++      // pastel option, most githubby
++      var removed = '\u001b[48;5;224m\u001b[38;5;52m'
++      var added = '\u001b[48;5;194m\u001b[38;5;22m'
++      var plain = '\u001b[38;5;233m'
++      var bg = '\u001b[48;5;255m'
++      break
++
++    case 4:
++      // orange/cyan pastel option, most r/g-colorblind friendly
++      var removed = '\u001b[48;5;223m\u001b[38;5;52m'
++      var added = '\u001b[48;5;158m\u001b[38;5;22m'
++      var plain = '\u001b[38;5;233m'
++      var bg = '\u001b[48;5;255m'
++      break
++
++    case 5:
++      // pastel option, green is bluish, red is just red
++      var removed = '\u001b[48;5;224m\u001b[38;5;52m'
++      var added = '\u001b[48;5;158m\u001b[38;5;22m'
++      var plain = '\u001b[38;5;233m'
++      var bg = '\u001b[48;5;255m'
++      break
++
++    case 6:
++      // pastel option, red is purplish, green is yellowish
++      var removed = '\u001b[48;5;218m\u001b[38;5;52m'
++      var added = '\u001b[48;5;193m\u001b[38;5;22m'
++      var plain = '\u001b[38;5;233m'
++      var bg = '\u001b[48;5;255m'
++      break
++
++    case 7:
++      // pastel option, red is purplish, green is just green
++      var removed = '\u001b[48;5;218m\u001b[38;5;52m'
++      var added = '\u001b[48;5;194m\u001b[38;5;22m'
++      var plain = '\u001b[38;5;233m'
++      var bg = '\u001b[48;5;255m'
++      break
++
++    case 8:
++      // pastel, red and blue
++      var removed = '\u001b[48;5;224m\u001b[38;5;52m'
++      var added = '\u001b[48;5;189m\u001b[38;5;17m'
++      var plain = '\u001b[38;5;233m'
++      var bg = '\u001b[48;5;255m'
++      break
++
++    case 9:
++      // pastel option, red is purplish, green is yellowish
++      var removed = '\u001b[48;5;224m\u001b[38;5;52m'
++      var added = '\u001b[48;5;193m\u001b[38;5;22m'
++      var plain = '\u001b[38;5;233m'
++      var bg = '\u001b[48;5;255m'
++      break
++
++  }
++
++
++  var maxLen = process.stdout.columns || 0
++  if (maxLen >= 5)
++    maxLen -= 5
++
++  if (!Base.useColors) {
++    bg = removed = added = reset = plain = ''
++    maxLen = 0
++  }
++
++  // If they are not strings, or only differ in trailing whitespace,
++  // then stringify them so that we can see the difference.
++  if (typeof found !== 'string' ||
++      typeof wanted !== 'string' ||
++      found.trim() === wanted.trim()) {
++    found = utils.stringify(found)
++    wanted = utils.stringify(wanted)
++  }
++
++  var patch = diff.createPatch('', wanted, found)
++  //console.error(patch)
++  var width = 0
++  patch = patch.split('\n').map(function (line, index) {
++    if (uclen(line) > width)
++      width = Math.min(maxLen, uclen(line))
++    if (line.match(/^\=+$/) ||
++        line === '\\ No newline at end of file')
++      return null
++    else
++      return line
++  }).filter(function (line, i) {
++    return line && i > 4
++  }).map(function (line) {
++    if (uclen(line) < width)
++      line += new Array(width - uclen(line) + 1).join(' ')
++    return line
++  }).map(function (line) {
++    if (line.charAt(0) === '+')
++      return bg + added + line + reset
++    else if (line.charAt(0) === '-')
++      return bg + removed + line + reset
++    else
++      return bg + plain + line + reset
++  }).join('\n')
++
++  var pref =
++    bg + added + '+++ found' +
++      (Base.useColors
++        ? new Array(width - '+++ found'.length + 1).join(' ')
++        : '') +
++      reset + '\n' +
++    bg + removed + '--- wanted' +
++      (Base.useColors
++        ? new Array(width - '--- wanted'.length + 1).join(' ')
++        : '') +
++      reset + '\n'
++
++  return pref + patch
++}
++
++util.inherits(Classic, Base)
++
++function Classic (runner) {
++  Base.call(this, runner);
++
++  var self = this
++
++  var grandTotal = 0
++  var grandPass = 0
++
++  var bailed = false
++  var hadFails = false
++  var currentSuite = null
++  var tests = []
++  var skipped = 0
++  var skipMsg = []
++  var todo = []
++  var fails = []
++  var total = 0
++  var pass = 0
++  var tickDots = 0
++  var tickColor = 'checkmark'
++
++  runner.on('bailout', function (bailout, suite) {
++    if (currentSuite)
++      runner.emit('suite end', currentSuite)
++    if (bailed)
++      return
++    bailed = true
++    console.log(Base.color('fail', 'Bail out! ' + bailout))
++  })
++
++  runner.on('suite', function (suite) {
++    if (!suite.root)
++      return
++
++    if (fancy) {
++      process.stdout.write(suite.title + ' ')
++      tickDots = 0
++      tickColor = 'checkmark'
++    }
++
++    currentSuite = suite
++    tests = []
++    todo = []
++    fails = []
++    skipMsg = []
++    skipped = 0
++    pass = 0
++    total = 0
++  })
++
++  runner.on('suite end', function (suite) {
++    if (!suite.root)
++      return
++
++    if (fancy)
++      Base.cursor.beginningOfLine()
++
++    currentSuite = null
++    var len = 60
++    var title = suite.title || '(unnamed)'
++    var num = pass + '/' + total
++    var dots = len - uclen(title) - uclen(num) - 2
++    if (dots < 3)
++      dots = 3
++    dots = ' ' + new Array(dots).join('.') + ' '
++    if (fails.length)
++      num = Base.color('fail', num)
++    else if (pass === total)
++      num = Base.color('checkmark', num)
++    else
++      num = Base.color('pending', num)
++
++    var fmt = title + dots + num
++    if (suite.duration / total > 250)
++      fmt += Base.color('slow', ' ' + ms(Math.round(suite.duration)))
++
++    console.log(fmt)
++
++    if (fails.length) {
++      var failMsg = ''
++      fails.forEach(function (t) {
++        if (t.parent)
++          failMsg += t.parent + '\n'
++        failMsg += Base.color('fail', 'not ok ' + t.name) + '\n'
++        if (t.diag) {
++          var printDiff = false
++          if (hasOwnProperty(t.diag, 'found') &&
++              hasOwnProperty(t.diag, 'wanted')) {
++            printDiff = true
++            var found = t.diag.found
++            var wanted = t.diag.wanted
++            failMsg += indent(doDiff(found, wanted), 2) + '\n'
++          }
++
++          var o = {}
++          var print = false
++          for (var i in t.diag) {
++            // Don't re-print what we already showed in the diff
++            if (printDiff && ( i === 'found' || i === 'wanted'))
++              continue
++            o[i] = t.diag[i]
++            print = true
++          }
++          if (print)
++            failMsg += indent(yaml.safeDump(o), 2) + '\n'
++        }
++      })
++      console.log(indent(failMsg, 2))
++    }
++
++    if (todo.length) {
++      var todoMsg = ''
++      var bullet = Base.color('pending', '~ ')
++      todo.forEach(function (t) {
++        if (t.todo !== true)
++          t.name += ' - ' + Base.color('pending', t.todo)
++        todoMsg += bullet + t.name + '\n'
++        if (t.diag)
++          todoMsg += indent(yaml.safeDump(t.diag), 4) + '\n'
++      })
++      console.log(indent(todoMsg, 2))
++    }
++
++    if (skipped) {
++      var fmt = Base.color('skip', indent('Skipped: %d', 2))
++      console.log(fmt, skipped)
++      if (skipMsg.length)
++        console.log(indent(skipMsg.join('\n'), 4))
++      console.log('')
++    }
++  })
++
++  runner.on('test', function (test) {
++    total ++
++    grandTotal ++
++    var t = test.result
++    if (fancy && currentSuite) {
++      var max = 57 - uclen(currentSuite.title)
++      if (max < 3)
++        max = 3
++
++      if (tickDots > max) {
++        tickDots = 0
++        Base.cursor.deleteLine()
++        Base.cursor.beginningOfLine();
++        process.stdout.write(currentSuite.title + ' ')
++      }
++      tickDots ++
++
++      if (t.todo &&
++          (tickColor === 'checkmark' || tickColor === 'skip'))
++        tickColor = 'pending'
++      else if (t.skip && tickColor === 'checkmark')
++        tickColor = 'skip'
++      else if (!t.ok)
++        tickColor = 'fail'
++
++      process.stdout.write(Base.color(tickColor, '.'))
++    }
++
++    if (t.skip) {
++      skipped += 1
++      if (t.skip !== true)
++        skipMsg.push(t.name + ' ' + Base.color('skip', t.skip))
++      else
++        skipMsg.push(t.name)
++    }
++    else if (t.todo)
++      todo.push(t)
++    else if (!t.ok) {
++      t.parent = []
++      var p = test.parent
++      while (p && p !== currentSuite) {
++        var n  = p.title || p.name || p.fullTitle()
++        if (n)
++          t.parent.unshift(n)
++        p = p.parent
++      }
++      t.parent.shift()
++      t.parent = t.parent.join(' > ')
++      fails.push(t)
++      hadFails = true
++    }
++    else {
++      pass ++
++      grandPass ++
++    }
++  })
++
++  runner.on('end', function () {
++    total = grandTotal
++    pass = grandPass
++    tests = []
++    todo = []
++    fails = []
++    skipMsg = []
++    skipped = 0
++    if (hadFails)
++      fails = [,,,]
++    runner.emit('suite end', { title: 'total', root: true })
++    self.failures = []
++    self.epilogue();
++
++    if (grandTotal === grandPass) {
++      console.log(Base.color('checkmark', '\n  ok'))
++    }
++  })
++}
++
++function indent (str, n) {
++  var ind = new Array(n + 1).join(' ')
++  str = ind + str.split('\n').join('\n' + ind)
++  return str.replace(/(\n\s*)+$/, '\n')
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/dot.js
+@@ -0,0 +1,62 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base')
++  , color = Base.color;
++
++/**
++ * Expose `Dot`.
++ */
++
++exports = module.exports = Dot;
++
++/**
++ * Initialize a new `Dot` matrix test reporter.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function Dot(runner) {
++  Base.call(this, runner);
++
++  var self = this
++    , stats = this.stats
++    , width = Base.window.width * .75 | 0
++    , n = -1;
++
++  runner.on('start', function(){
++    process.stdout.write('\n');
++  });
++
++  runner.on('pending', function(test){
++    if (++n % width == 0) process.stdout.write('\n  ');
++    process.stdout.write(color('pending', Base.symbols.dot));
++  });
++
++  runner.on('pass', function(test){
++    if (++n % width == 0) process.stdout.write('\n  ');
++    if ('slow' == test.speed) {
++      process.stdout.write(color('bright yellow', Base.symbols.dot));
++    } else {
++      process.stdout.write(color(test.speed, Base.symbols.dot));
++    }
++  });
++
++  runner.on('fail', function(test, err){
++    if (++n % width == 0) process.stdout.write('\n  ');
++    process.stdout.write(color('fail', Base.symbols.dot));
++  });
++
++  runner.on('end', function(){
++    console.log();
++    self.epilogue();
++  });
++}
++
++/**
++ * Inherit from `Base.prototype`.
++ */
++
++Dot.prototype.__proto__ = Base.prototype;
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/min.js
+@@ -0,0 +1,37 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base');
++
++/**
++ * Expose `Min`.
++ */
++
++exports = module.exports = Min;
++
++/**
++ * Initialize a new `Min` minimal test reporter (best used with --watch).
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function Min(runner) {
++  Base.call(this, runner);
++
++  runner.on('start', function(){
++    // clear screen
++    process.stdout.write('\u001b[2J');
++    // set cursor position
++    process.stdout.write('\u001b[1;3H');
++  });
++
++  runner.on('end', this.epilogue.bind(this));
++}
++
++/**
++ * Inherit from `Base.prototype`.
++ */
++
++Min.prototype.__proto__ = Base.prototype;
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/progress.js
+@@ -0,0 +1,92 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base')
++  , cursor = Base.cursor
++  , color = Base.color;
++
++/**
++ * Expose `Progress`.
++ */
++
++exports = module.exports = Progress;
++
++/**
++ * General progress bar color.
++ */
++
++Base.colors.progress = 90;
++
++/**
++ * Initialize a new `Progress` bar test reporter.
++ *
++ * @param {Runner} runner
++ * @param {Object} options
++ * @api public
++ */
++
++function Progress(runner, options) {
++  Base.call(this, runner);
++
++  var self = this
++    , options = options || {}
++    , stats = this.stats
++    , width = Base.window.width * .50 | 0
++    , total = runner.total
++    , complete = 0
++    , max = Math.max
++    , lastN = -1;
++
++  // default chars
++  options.open = options.open || '[';
++  options.complete = options.complete || '▬';
++  options.incomplete = options.incomplete || Base.symbols.dot;
++  options.close = options.close || ']';
++  options.verbose = false;
++
++  // tests started
++  runner.on('start', function(){
++    console.log();
++    cursor.hide();
++  });
++
++  // tests complete
++  runner.on('test end', function(){
++    complete++;
++    var incomplete = total - complete
++      , percent = complete / total
++      , n = width * percent | 0
++      , i = width - n;
++
++    if (lastN === n && !options.verbose) {
++      // Don't re-render the line if it hasn't changed
++      return;
++    }
++    lastN = n;
++
++    cursor.CR();
++    process.stdout.write('\u001b[J');
++    process.stdout.write(color('progress', '  ' + options.open));
++    process.stdout.write(Array(n).join(options.complete));
++    process.stdout.write(Array(i).join(options.incomplete));
++    process.stdout.write(color('progress', options.close));
++    if (options.verbose) {
++      process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
++    }
++  });
++
++  // tests are complete, output some stats
++  // and the failures if any
++  runner.on('end', function(){
++    cursor.show();
++    console.log();
++    self.epilogue();
++  });
++}
++
++/**
++ * Inherit from `Base.prototype`.
++ */
++
++Progress.prototype.__proto__ = Base.prototype;
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/silent.js
+@@ -0,0 +1 @@
++exports = module.exports = function () {}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/spec.js
+@@ -0,0 +1,82 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base')
++  , cursor = Base.cursor
++  , color = Base.color;
++
++/**
++ * Expose `Spec`.
++ */
++
++exports = module.exports = Spec;
++
++/**
++ * Initialize a new `Spec` test reporter.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function Spec(runner) {
++  Base.call(this, runner);
++
++  var self = this
++    , stats = this.stats
++    , indents = 0
++    , n = 0;
++
++  function indent() {
++    return Array(indents).join('  ')
++  }
++
++  runner.on('start', function(){
++    console.log();
++  });
++
++  runner.on('suite', function(suite){
++    ++indents;
++    console.log(color('suite', '%s%s'), indent(), suite.title);
++  });
++
++  runner.on('suite end', function(suite){
++    --indents;
++    if (1 == indents) console.log();
++  });
++
++  runner.on('pending', function(test){
++    var fmt = indent() + color('pending', '  - %s');
++    console.log(fmt, test.title);
++  });
++
++  runner.on('pass', function(test){
++    if ('fast' == test.speed) {
++      var fmt = indent()
++        + color('checkmark', '  ' + Base.symbols.ok)
++        + color('pass', ' %s');
++      cursor.CR();
++      console.log(fmt, test.title);
++    } else {
++      var fmt = indent()
++        + color('checkmark', '  ' + Base.symbols.ok)
++        + color('pass', ' %s')
++        + color(test.speed, ' (%dms)');
++      cursor.CR();
++      console.log(fmt, test.title, test.duration);
++    }
++  });
++
++  runner.on('fail', function(test, err){
++    cursor.CR();
++    console.log(indent() + color('fail', '  %d) %s'), ++n, test.title);
++  });
++
++  runner.on('end', self.epilogue.bind(self));
++}
++
++/**
++ * Inherit from `Base.prototype`.
++ */
++
++Spec.prototype.__proto__ = Base.prototype;
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/runner.js
+@@ -0,0 +1,347 @@
++// A facade from the tap-parser to the Mocha "Runner" object.
++// Note that pass/fail/suite events need to also mock the "Runnable"
++// objects (either "Suite" or "Test") since these have functions
++// which are called by the formatters.
++
++module.exports = Runner
++
++// relevant events:
++//
++// start()
++//   Start of the top-level test set
++//
++// end()
++//   End of the top-level test set.
++//
++// fail(test, err)
++//   any "not ok" test that is not the trailing test for a suite
++//   of >0 test points.
++//
++// pass(test)
++//   any "ok" test point that is not the trailing test for a suite
++//   of >0 tests
++//
++// pending(test)
++//   Any "todo" test
++//
++// suite(suite)
++//   A suite is a child test with >0 test points.  This is a little bit
++//   tricky, because TAP will provide a "child" event before we know
++//   that it's a "suite".  We see the "# Subtest: name" comment as the
++//   first thing in the subtest.  Then, when we get our first test point,
++//   we know that it's a suite, and can emit the event with the mock suite.
++//
++// suite end(suite)
++//   Emitted when we end the subtest
++//
++// test(test)
++//   Any test point which is not the trailing test for a suite.
++//
++// test end(test)
++//   Emitted immediately after the "test" event because test points are
++//   not async in TAP.
++
++var util = require('util')
++var Test = require('./test.js')
++var Suite = require('./suite.js')
++var Writable = require('stream').Writable
++if (!Writable) {
++  try {
++    Writable = require('readable-stream').Writable
++  } catch (er) {
++    throw new Error('Please install "readable-stream" to use this module ' +
++                    'with Node.js v0.8 and before')
++  }
++}
++
++var Parser = require('tap-parser')
++
++// $1 = number, $2 = units
++var timere = /^#\s*time=((?:0|[1-9][0-9]*?)(?:\.[0-9]+)?)(ms|s)?$/
++
++util.inherits(Runner, Writable)
++
++function Runner (options) {
++  if (!(this instanceof Runner))
++    return new Runner(options)
++
++  var parser = this.parser = new Parser(options)
++  this.startTime = new Date()
++
++  attachEvents(this, parser, 0)
++  Writable.call(this, options)
++}
++
++Runner.prototype.write = function () {
++  if (!this.emittedStart) {
++    this.emittedStart = true
++    this.emit('start')
++  }
++
++  return this.parser.write.apply(this.parser, arguments)
++}
++
++Runner.prototype.end = function () {
++  return this.parser.end.apply(this.parser, arguments)
++}
++
++Parser.prototype.fullTitle = function () {
++  if (!this.parent)
++    return this.name || ''
++  else
++    return (this.parent.fullTitle() + ' ' + (this.name || '')).trim()
++}
++
++function attachEvents (runner, parser, level) {
++  parser.runner = runner
++
++  if (level === 0) {
++    parser.on('line', function (c) {
++      runner.emit('line', c)
++    })
++    parser.on('version', function (v) {
++      runner.emit('version', v)
++    })
++    parser.on('complete', function (res) {
++      runner.emit('end')
++    })
++    parser.on('comment', function (c) {
++      var tmatch = c.trim().match(timere)
++      if (tmatch) {
++        var t = +tmatch[1]
++        if (tmatch[2] === 's')
++          t *= 1000
++        parser.time = t
++        if (runner.stats)
++          runner.stats.duration = t
++      }
++    })
++  }
++
++  parser.emittedSuite = false
++  parser.didAssert = false
++  parser.name = parser.name || ''
++  parser.doingChild = null
++
++  parser.on('complete', function (res) {
++    if (!res.ok) {
++      var fail = { ok: false, diag: {} }
++      var count = res.count
++      if (res.plan) {
++        var plan = res.plan.end - res.plan.start + 1
++        if (count !== plan) {
++          fail.name = 'test count !== plan'
++          fail.diag = {
++            found: count,
++            wanted: plan
++          }
++        } else {
++          // probably handled on child parser
++          return
++        }
++      } else {
++        fail.name = 'missing plan'
++      }
++      fail.diag.results = res
++      emitTest(parser, fail)
++    }
++  })
++
++  parser.on('child', function (child) {
++    child.parent = parser
++    attachEvents(runner, child, level + 1)
++
++    // if we're in a suite, but we haven't emitted it yet, then we
++    // know that an assert will follow this child, even if there are
++    // no others. That means that we will definitely have a 'suite'
++    // event to emit.
++    emitSuite(this)
++
++    this.didAssert = true
++    this.doingChild = child
++  })
++
++  if (!parser.name) {
++    parser.on('comment', function (c) {
++      if (!this.name && c.match(/^# Subtest: /)) {
++        c = c.trim().replace(/^# Subtest: /, '')
++        this.name = c
++      }
++    })
++  }
++
++  // Just dump all non-parsing stuff to stderr
++  parser.on('extra', function (c) {
++    process.stderr.write(c)
++  })
++
++  parser.on('assert', function (result) {
++    emitSuite(this)
++
++    // no need to print the trailing assert for subtests
++    // we've already emitted a 'suite end' event for this.
++    // UNLESS, there were no other asserts, AND it's root level
++    if (this.doingChild) {
++      var suite = this.doingChild.suite
++      if (this.doingChild.name === result.name) {
++        if (suite) {
++          if (result.time)
++            suite.duration = result.time
++
++          // If it's ok so far, but the ending result is not-ok, then
++          // that means that it exited non-zero.  Emit the test so
++          // that we can print it as a failure.
++          if (suite.ok && !result.ok)
++            emitTest(this, result)
++        }
++      }
++
++      var emitOn = this
++      var dc = this.doingChild
++      this.doingChild = null
++
++      if (!dc.didAssert && dc.level === 1) {
++        emitOn = dc
++      } else if (dc.didAssert) {
++        if (dc.suite)
++          runner.emit('suite end', dc.suite)
++        return
++      } else {
++        emitOn = this
++      }
++
++      emitSuite(emitOn)
++      emitTest(emitOn, result)
++      if (emitOn !== this && emitOn.suite) {
++        runner.emit('suite end', emitOn.suite)
++        delete emitOn.suite
++      }
++      if (dc.suite) {
++        runner.emit('suite end', dc.suite)
++      }
++      return
++    }
++
++    this.didAssert = true
++    this.doingChild = null
++
++    emitTest(this, result)
++  })
++
++  parser.on('complete', function (results) {
++    this.results = results
++  })
++
++  parser.on('bailout', function (reason) {
++    var suite = this.suite
++    runner.emit('bailout', reason, suite)
++    if (suite)
++      this.suite = suite.parent
++  })
++
++  // proxy all stream events directly
++  var streamEvents = [
++    'pipe', 'prefinish', 'finish', 'unpipe', 'close'
++  ]
++
++  streamEvents.forEach(function (ev) {
++    parser.on(ev, function () {
++      var args = [ev]
++      args.push.apply(args, arguments)
++      runner.emit.apply(runner, args)
++    })
++  })
++}
++
++function emitSuite (parser) {
++  if (!parser.emittedSuite && parser.name) {
++    parser.emittedSuite = true
++    var suite = parser.suite = new Suite(parser)
++    if (parser.parent && parser.parent.suite)
++      parser.parent.suite.suites.push(suite)
++    if (parser.runner.stats)
++      parser.runner.stats.suites ++
++
++    parser.runner.emit('suite', suite)
++  }
++}
++
++function emitTest (parser, result) {
++  var runner = parser.runner
++  var test = new Test(result, parser)
++
++  if (parser.suite) {
++    parser.suite.tests.push(test)
++    if (!result.ok) {
++      for (var p = parser; p && p.suite; p = p.parent) {
++        p.suite.ok = false
++      }
++    }
++    parser.suite.ok = parser.suite.ok && result.ok
++  }
++
++  runner.emit('test', test)
++  if (result.skip || result.todo) {
++    runner.emit('pending', test)
++  } else if (result.ok) {
++    runner.emit('pass', test)
++  } else {
++    var error = getError(result)
++    runner.emit('fail', test, error)
++  }
++  runner.emit('test end', test)
++}
++
++function getError (result) {
++  var err
++
++  function reviveStack (stack) {
++    if (!stack)
++      return null
++
++    return stack.trim().split('\n').map(function (line) {
++      return '    at ' + line
++    }).join('\n')
++  }
++
++  if (result.diag && result.diag.error) {
++    err = {
++      name: result.diag.error.name || 'Error',
++      message: result.diag.error.message,
++      toString: function () {
++        return this.name + ': ' + this.message
++      },
++      stack: result.diag.error.stack
++    }
++  } else {
++    err = {
++      message: (result.name || '(unnamed error)').replace(/^Error: /, ''),
++      toString: function () {
++        return 'Error: ' + this.message
++      },
++      stack: result.diag && result.diag.stack
++    }
++  }
++
++  var diag = result.diag
++
++  if (err.stack)
++    err.stack = err.toString() + '\n' + reviveStack(err.stack)
++
++  if (diag) {
++    var hasFound = diag.hasOwnProperty('found')
++    var hasWanted = diag.hasOwnProperty('wanted')
++
++    if (hasFound)
++      err.actual = diag.found
++
++    if (hasWanted)
++      err.expected = diag.wanted
++
++    if (hasFound && hasWanted)
++      err.showDiff = true
++  }
++
++  return err
++}
++
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/suite.js
+@@ -0,0 +1,22 @@
++// minimal mock of mocha's Suite class for formatters
++
++module.exports = Suite
++
++function Suite (parent) {
++  if (!parent.parent || !parent.parent.emittedSuite)
++    this.root = true
++  else
++    this.root = false
++
++  this.title = parent.name || ''
++  this.suites = []
++  this.tests = []
++  this.ok = true
++}
++
++Suite.prototype.fullTitle = function () {
++  if (!this.parent)
++    return (this.title || '').trim()
++  else
++    return (this.parent.fullTitle() + ' ' + (this.title || '')).trim()
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/test.js
+@@ -0,0 +1,41 @@
++// minimal mock of the mocha Test class for formatters
++
++module.exports = Test
++
++function Test (result, parent) {
++  this.result = result
++  this._slow = 75
++  this.duration = result.time
++  this.title = result.name
++  this.state = result.ok ? 'pass' : 'failed'
++  this.pending = result.todo || result.skip || false
++  if (result.diag && result.diag.source) {
++    var source = result.diag.source
++    this.fn = {
++      toString: function () {
++        return 'function(){' + source + '\n}'
++      }
++    }
++  }
++
++  Object.defineProperty(this, 'parent', {
++    value: parent,
++    writable: true,
++    configurable: true,
++    enumerable: false
++  })
++}
++
++Test.prototype.fullTitle = function () {
++  return (this.parent.fullTitle() + ' ' + (this.title || '')).trim()
++}
++
++Test.prototype.slow = function (ms){
++  return 75
++}
++
++Test.prototype.fn = {
++  toString: function () {
++    return 'function () {\n}'
++  }
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/utils.js
+@@ -0,0 +1,699 @@
++/**
++ * Module dependencies.
++ */
++
++var fs = require('fs')
++  , path = require('path')
++  , basename = path.basename
++  , exists = fs.existsSync || path.existsSync
++  , glob = require('glob')
++  , join = path.join
++  , debug = require('debug')('mocha:watch');
++
++/**
++ * Ignored directories.
++ */
++
++var ignore = ['node_modules', '.git'];
++
++/**
++ * Escape special characters in the given string of html.
++ *
++ * @param  {String} html
++ * @return {String}
++ * @api private
++ */
++
++exports.escape = function(html){
++  return String(html)
++    .replace('&', '&')
++    .replace('"', '"')
++    .replace('<', '<')
++    .replace('>', '>');
++};
++
++/**
++ * Array#forEach (<=IE8)
++ *
++ * @param {Array} array
++ * @param {Function} fn
++ * @param {Object} scope
++ * @api private
++ */
++
++exports.forEach = function(arr, fn, scope){
++  for (var i = 0, l = arr.length; i < l; i++)
++    fn.call(scope, arr[i], i);
++};
++
++/**
++ * Array#map (<=IE8)
++ *
++ * @param {Array} array
++ * @param {Function} fn
++ * @param {Object} scope
++ * @api private
++ */
++
++exports.map = function(arr, fn, scope){
++  var result = [];
++  for (var i = 0, l = arr.length; i < l; i++)
++    result.push(fn.call(scope, arr[i], i, arr));
++  return result;
++};
++
++/**
++ * Array#indexOf (<=IE8)
++ *
++ * @parma {Array} arr
++ * @param {Object} obj to find index of
++ * @param {Number} start
++ * @api private
++ */
++
++exports.indexOf = function(arr, obj, start){
++  for (var i = start || 0, l = arr.length; i < l; i++) {
++    if (arr[i] === obj)
++      return i;
++  }
++  return -1;
++};
++
++/**
++ * Array#reduce (<=IE8)
++ *
++ * @param {Array} array
++ * @param {Function} fn
++ * @param {Object} initial value
++ * @api private
++ */
++
++exports.reduce = function(arr, fn, val){
++  var rval = val;
++
++  for (var i = 0, l = arr.length; i < l; i++) {
++    rval = fn(rval, arr[i], i, arr);
++  }
++
++  return rval;
++};
++
++/**
++ * Array#filter (<=IE8)
++ *
++ * @param {Array} array
++ * @param {Function} fn
++ * @api private
++ */
++
++exports.filter = function(arr, fn){
++  var ret = [];
++
++  for (var i = 0, l = arr.length; i < l; i++) {
++    var val = arr[i];
++    if (fn(val, i, arr)) ret.push(val);
++  }
++
++  return ret;
++};
++
++/**
++ * Object.keys (<=IE8)
++ *
++ * @param {Object} obj
++ * @return {Array} keys
++ * @api private
++ */
++
++exports.keys = Object.keys || function(obj) {
++  var keys = []
++    , has = Object.prototype.hasOwnProperty; // for `window` on <=IE8
++
++  for (var key in obj) {
++    if (has.call(obj, key)) {
++      keys.push(key);
++    }
++  }
++
++  return keys;
++};
++
++/**
++ * Watch the given `files` for changes
++ * and invoke `fn(file)` on modification.
++ *
++ * @param {Array} files
++ * @param {Function} fn
++ * @api private
++ */
++
++exports.watch = function(files, fn){
++  var options = { interval: 100 };
++  files.forEach(function(file){
++    debug('file %s', file);
++    fs.watchFile(file, options, function(curr, prev){
++      if (prev.mtime < curr.mtime) fn(file);
++    });
++  });
++};
++
++/**
++ * Array.isArray (<=IE8)
++ *
++ * @param {Object} obj
++ * @return {Boolean}
++ * @api private
++ */
++var isArray = Array.isArray || function (obj) {
++  return '[object Array]' == {}.toString.call(obj);
++};
++
++/**
++ * @description
++ * Buffer.prototype.toJSON polyfill
++ * @type {Function}
++ */
++if(typeof Buffer !== 'undefined' && Buffer.prototype) {
++  Buffer.prototype.toJSON = Buffer.prototype.toJSON || function () {
++    return Array.prototype.slice.call(this, 0);
++  };
++}
++
++/**
++ * Ignored files.
++ */
++
++function ignored(path){
++  return !~ignore.indexOf(path);
++}
++
++/**
++ * Lookup files in the given `dir`.
++ *
++ * @return {Array}
++ * @api private
++ */
++
++exports.files = function(dir, ext, ret){
++  ret = ret || [];
++  ext = ext || ['js'];
++
++  var re = new RegExp('\\.(' + ext.join('|') + ')$');
++
++  fs.readdirSync(dir)
++    .filter(ignored)
++    .forEach(function(path){
++      path = join(dir, path);
++      if (fs.statSync(path).isDirectory()) {
++        exports.files(path, ext, ret);
++      } else if (path.match(re)) {
++        ret.push(path);
++      }
++    });
++
++  return ret;
++};
++
++/**
++ * Compute a slug from the given `str`.
++ *
++ * @param {String} str
++ * @return {String}
++ * @api private
++ */
++
++exports.slug = function(str){
++  return str
++    .toLowerCase()
++    .replace(/ +/g, '-')
++    .replace(/[^-\w]/g, '');
++};
++
++/**
++ * Strip the function definition from `str`,
++ * and re-indent for pre whitespace.
++ */
++
++exports.clean = function(str) {
++  str = str
++    .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '')
++    .replace(/^function *\(.*\) *{|\(.*\) *=> *{?/, '')
++    .replace(/\s+\}$/, '');
++
++  var spaces = str.match(/^\n?( *)/)[1].length
++    , tabs = str.match(/^\n?(\t*)/)[1].length
++    , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm');
++
++  str = str.replace(re, '');
++
++  return exports.trim(str);
++};
++
++/**
++ * Trim the given `str`.
++ *
++ * @param {String} str
++ * @return {String}
++ * @api private
++ */
++
++exports.trim = function(str){
++  return str.replace(/^\s+|\s+$/g, '');
++};
++
++/**
++ * Parse the given `qs`.
++ *
++ * @param {String} qs
++ * @return {Object}
++ * @api private
++ */
++
++exports.parseQuery = function(qs){
++  return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){
++    var i = pair.indexOf('=')
++      , key = pair.slice(0, i)
++      , val = pair.slice(++i);
++
++    obj[key] = decodeURIComponent(val);
++    return obj;
++  }, {});
++};
++
++/**
++ * Highlight the given string of `js`.
++ *
++ * @param {String} js
++ * @return {String}
++ * @api private
++ */
++
++function highlight(js) {
++  return js
++    .replace(/</g, '<')
++    .replace(/>/g, '>')
++    .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
++    .replace(/('.*?')/gm, '<span class="string">$1</span>')
++    .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
++    .replace(/(\d+)/gm, '<span class="number">$1</span>')
++    .replace(/\bnew[ \t]+(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
++    .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
++}
++
++/**
++ * Highlight the contents of tag `name`.
++ *
++ * @param {String} name
++ * @api private
++ */
++
++exports.highlightTags = function(name) {
++  var code = document.getElementById('mocha').getElementsByTagName(name);
++  for (var i = 0, len = code.length; i < len; ++i) {
++    code[i].innerHTML = highlight(code[i].innerHTML);
++  }
++};
++
++/**
++ * If a value could have properties, and has none, this function is called, which returns
++ * a string representation of the empty value.
++ *
++ * Functions w/ no properties return `'[Function]'`
++ * Arrays w/ length === 0 return `'[]'`
++ * Objects w/ no properties return `'{}'`
++ * All else: return result of `value.toString()`
++ *
++ * @param {*} value Value to inspect
++ * @param {string} [type] The type of the value, if known.
++ * @returns {string}
++ */
++var emptyRepresentation = function emptyRepresentation(value, type) {
++  type = type || exports.type(value);
++
++  switch(type) {
++    case 'function':
++      return '[Function]';
++    case 'object':
++      return '{}';
++    case 'array':
++      return '[]';
++    default:
++      return value.toString();
++  }
++};
++
++/**
++ * Takes some variable and asks `{}.toString()` what it thinks it is.
++ * @param {*} value Anything
++ * @example
++ * type({}) // 'object'
++ * type([]) // 'array'
++ * type(1) // 'number'
++ * type(false) // 'boolean'
++ * type(Infinity) // 'number'
++ * type(null) // 'null'
++ * type(new Date()) // 'date'
++ * type(/foo/) // 'regexp'
++ * type('type') // 'string'
++ * type(global) // 'global'
++ * @api private
++ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
++ * @returns {string}
++ */
++exports.type = function type(value) {
++  if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
++    return 'buffer';
++  }
++  return Object.prototype.toString.call(value)
++    .replace(/^\[.+\s(.+?)\]$/, '$1')
++    .toLowerCase();
++};
++
++/**
++ * @summary Stringify `value`.
++ * @description Different behavior depending on type of value.
++ * - If `value` is undefined or null, return `'[undefined]'` or `'[null]'`, respectively.
++ * - If `value` is not an object, function or array, return result of `value.toString()` wrapped in double-quotes.
++ * - If `value` is an *empty* object, function, or array, return result of function
++ *   {@link emptyRepresentation}.
++ * - If `value` has properties, call {@link exports.canonicalize} on it, then return result of
++ *   JSON.stringify().
++ *
++ * @see exports.type
++ * @param {*} value
++ * @return {string}
++ * @api private
++ */
++
++exports.stringify = function(value) {
++  var type = exports.type(value);
++
++  if (!~exports.indexOf(['object', 'array', 'function'], type)) {
++    if(type != 'buffer') {
++      return jsonStringify(value);
++    }
++    var json = value.toJSON();
++    // Based on the toJSON result
++    return jsonStringify(json.data && json.type ? json.data : json, 2)
++      .replace(/,(\n|$)/g, '$1');
++  }
++
++  for (var prop in value) {
++    if (Object.prototype.hasOwnProperty.call(value, prop)) {
++      return jsonStringify(exports.canonicalize(value), 2)
++        .replace(/,(\n|$)/g, '$1');
++    }
++  }
++
++  return emptyRepresentation(value, type);
++};
++
++/**
++ * @description
++ * like JSON.stringify but more sense.
++ * @param {Object}  object
++ * @param {Number=} spaces
++ * @param {number=} depth
++ * @returns {*}
++ * @private
++ */
++function jsonStringify(object, spaces, depth) {
++  if(typeof spaces == 'undefined') return _stringify(object);  // primitive types
++
++  depth = depth || 1;
++  var space = spaces * depth
++    , str = isArray(object) ? '[' : '{'
++    , end = isArray(object) ? ']' : '}'
++    , length = object.length || exports.keys(object).length
++    , repeat = function(s, n) { return new Array(n).join(s); }; // `.repeat()` polyfill
++
++  function _stringify(val) {
++    switch (exports.type(val)) {
++      case 'null':
++      case 'undefined':
++        val = '[' + val + ']';
++        break;
++      case 'array':
++      case 'object':
++        val = jsonStringify(val, spaces, depth + 1);
++        break;
++      case 'boolean':
++      case 'regexp':
++      case 'number':
++        val = val === 0 && (1/val) === -Infinity // `-0`
++          ? '-0'
++          : val.toString();
++        break;
++      case 'date':
++        val = '[Date: ' + val.toISOString() + ']';
++        break;
++      case 'buffer':
++        var json = val.toJSON();
++        // Based on the toJSON result
++        json = json.data && json.type ? json.data : json;
++        val = '[Buffer: ' + jsonStringify(json, 2, depth + 1) + ']';
++        break;
++      default:
++        val = (val == '[Function]' || val == '[Circular]')
++          ? val
++          : '"' + val + '"'; //string
++    }
++    return val;
++  }
++
++  for(var i in object) {
++    if(!Object.prototype.hasOwnProperty.call(object, i)) continue;        // not my business
++    --length;
++    str += '\n ' + repeat(' ', space)
++      + (isArray(object) ? '' : '"' + i + '": ') // key
++      +  _stringify(object[i])                   // value
++      + (length ? ',' : '');                     // comma
++  }
++
++  return str + (str.length != 1                    // [], {}
++    ? '\n' + repeat(' ', --space) + end
++    : end);
++}
++
++/**
++ * Return if obj is a Buffer
++ * @param {Object} arg
++ * @return {Boolean}
++ * @api private
++ */
++exports.isBuffer = function (arg) {
++  return typeof Buffer !== 'undefined' && Buffer.isBuffer(arg);
++};
++
++/**
++ * @summary Return a new Thing that has the keys in sorted order.  Recursive.
++ * @description If the Thing...
++ * - has already been seen, return string `'[Circular]'`
++ * - is `undefined`, return string `'[undefined]'`
++ * - is `null`, return value `null`
++ * - is some other primitive, return the value
++ * - is not a primitive or an `Array`, `Object`, or `Function`, return the value of the Thing's `toString()` method
++ * - is a non-empty `Array`, `Object`, or `Function`, return the result of calling this function again.
++ * - is an empty `Array`, `Object`, or `Function`, return the result of calling `emptyRepresentation()`
++ *
++ * @param {*} value Thing to inspect.  May or may not have properties.
++ * @param {Array} [stack=[]] Stack of seen values
++ * @return {(Object|Array|Function|string|undefined)}
++ * @see {@link exports.stringify}
++ * @api private
++ */
++
++exports.canonicalize = function(value, stack) {
++  var canonicalizedObj,
++    type = exports.type(value),
++    prop,
++    withStack = function withStack(value, fn) {
++      stack.push(value);
++      fn();
++      stack.pop();
++    };
++
++  stack = stack || [];
++
++  if (exports.indexOf(stack, value) !== -1) {
++    return '[Circular]';
++  }
++
++  switch(type) {
++    case 'undefined':
++    case 'buffer':
++    case 'null':
++      canonicalizedObj = value;
++      break;
++    case 'array':
++      withStack(value, function () {
++        canonicalizedObj = exports.map(value, function (item) {
++          return exports.canonicalize(item, stack);
++        });
++      });
++      break;
++    case 'function':
++      for (prop in value) {
++        canonicalizedObj = {};
++        break;
++      }
++      if (!canonicalizedObj) {
++        canonicalizedObj = emptyRepresentation(value, type);
++        break;
++      }
++    /* falls through */
++    case 'object':
++      canonicalizedObj = canonicalizedObj || {};
++      withStack(value, function () {
++        exports.forEach(exports.keys(value).sort(), function (key) {
++          canonicalizedObj[key] = exports.canonicalize(value[key], stack);
++        });
++      });
++      break;
++    case 'date':
++    case 'number':
++    case 'regexp':
++    case 'boolean':
++      canonicalizedObj = value;
++      break;
++    default:
++      canonicalizedObj = value.toString();
++  }
++
++  return canonicalizedObj;
++};
++
++/**
++ * Lookup file names at the given `path`.
++ */
++exports.lookupFiles = function lookupFiles(path, extensions, recursive) {
++  var files = [];
++  var re = new RegExp('\\.(' + extensions.join('|') + ')$');
++
++  if (!exists(path)) {
++    if (exists(path + '.js')) {
++      path += '.js';
++    } else {
++      files = glob.sync(path);
++      if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'");
++      return files;
++    }
++  }
++
++  try {
++    var stat = fs.statSync(path);
++    if (stat.isFile()) return path;
++  }
++  catch (ignored) {
++    return;
++  }
++
++  fs.readdirSync(path).forEach(function(file) {
++    file = join(path, file);
++    try {
++      var stat = fs.statSync(file);
++      if (stat.isDirectory()) {
++        if (recursive) {
++          files = files.concat(lookupFiles(file, extensions, recursive));
++        }
++        return;
++      }
++    }
++    catch (ignored) {
++      return;
++    }
++    if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') return;
++    files.push(file);
++  });
++
++  return files;
++};
++
++/**
++ * Generate an undefined error with a message warning the user.
++ *
++ * @return {Error}
++ */
++
++exports.undefinedError = function() {
++  return new Error('Caught undefined error, did you throw without specifying what?');
++};
++
++/**
++ * Generate an undefined error if `err` is not defined.
++ *
++ * @param {Error} err
++ * @return {Error}
++ */
++
++exports.getError = function(err) {
++  return err || exports.undefinedError();
++};
++
++
++/**
++ * @summary
++ * This Filter based on `mocha-clean` module.(see: `github.com/rstacruz/mocha-clean`)
++ * @description
++ * When invoking this function you get a filter function that get the Error.stack as an input,
++ * and return a prettify output.
++ * (i.e: strip Mocha, node_modules, bower and componentJS from stack trace).
++ * @returns {Function}
++ */
++
++exports.stackTraceFilter = function() {
++  var slash = '/'
++    , is = typeof document === 'undefined'
++      ? { node: true }
++      : { browser: true }
++    , cwd = is.node
++      ? process.cwd() + slash
++      : location.href.replace(/\/[^\/]*$/, '/');
++
++  function isNodeModule (line) {
++    return (~line.indexOf('node_modules'));
++  }
++
++  function isMochaInternal (line) {
++    return (~line.indexOf('node_modules' + slash + 'tap-mocha-reporter'))  ||
++      (~line.indexOf('components' + slash + 'mochajs'))       ||
++      (~line.indexOf('components' + slash + 'mocha'));
++  }
++
++  // node_modules, bower, componentJS
++  function isBrowserModule(line) {
++    return (~line.indexOf('node_modules')) ||
++      (~line.indexOf('components'));
++  }
++
++  function isNodeInternal (line) {
++    return (~line.indexOf('(timers.js:')) ||
++      (~line.indexOf('(domain.js:'))      ||
++      (~line.indexOf('(events.js:'))      ||
++      (~line.indexOf('(node.js:'))        ||
++      (~line.indexOf('(module.js:'))      ||
++      (~line.indexOf('at node.js:'))      ||
++      (~line.indexOf('GeneratorFunctionPrototype.next (native)')) ||
++      false
++  }
++
++  return function(stack) {
++    stack = stack.split('\n');
++
++    stack = stack.reduce(function (list, line) {
++      if (is.node && (isNodeModule(line) ||
++        isMochaInternal(line) ||
++        isNodeInternal(line)))
++        return list;
++
++      if (is.browser && (isBrowserModule(line)))
++        return list;
++
++      // Clean up cwd(absolute)
++      list.push(line.replace(cwd, ''));
++      return list;
++    }, []);
++
++    return stack.join('\n');
++  }
++};
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/index.js
+@@ -0,0 +1,106 @@
++#!/usr/bin/env node
++
++module.exports = Formatter
++
++var util = require('util')
++var reporters = require('./lib/reporters/index.js')
++Formatter.types = Object.keys(reporters).sort()
++var Writable = require('stream').Writable
++if (!Writable) {
++  try {
++    Writable = require('readable-stream').Writable
++  } catch (er) {
++    throw new Error('Please install "readable-stream" to use this module ' +
++                    'with Node.js v0.8 and before')
++  }
++}
++
++var Runner = require('./lib/runner.js')
++var Parser = require('tap-parser')
++
++util.inherits(Formatter, Writable)
++
++var exitCode
++function Formatter (type, options) {
++  if (!(this instanceof Formatter)) {
++    return new Formatter(type, options)
++  }
++  if (!reporters[type]) {
++    console.error('Unknown format type: %s\n\n%s', type, avail())
++    type = 'silent'
++  }
++
++  this.writable = true
++
++  // don't actually need a reporter to report the tap we're getting
++  // just parse it so that we exit with the correct code, but otherwise
++  // dump it straight through to stdout.
++  if (type === 'tap') {
++    var p = new Parser()
++    this.write = function (chunk) {
++      process.stdout.write(chunk)
++      return p.write(chunk)
++    }
++    this.end = p.end.bind(p)
++    p.on('complete', function () {
++      if (!p.ok)
++        exitCode = 1
++    })
++    return this
++  }
++
++  var runner = this.runner = new Runner(options)
++  this.reporter = new reporters[type](this.runner, {})
++  Writable.call(this, options)
++
++  runner.on('end', function () {
++    if (!runner.parser.ok)
++      exitCode = 1
++  })
++}
++
++process.on('exit', function (code) {
++  if (!code && exitCode)
++    process.exit(exitCode)
++})
++
++Formatter.prototype.write = function () {
++  return this.runner.write.apply(this.runner, arguments)
++}
++
++Formatter.prototype.end = function () {
++  return this.runner.end.apply(this.runner, arguments)
++}
++
++function avail () {
++  var types = Formatter.types.reduce(function (str, t) {
++    var ll = str.split('\n').pop().length + t.length
++    if (ll < 40)
++      return str + ' ' + t
++    else
++      return str + '\n' + t
++  }, '').trim()
++
++  return 'Available format types:\n\n' + types
++}
++
++
++function usage (err) {
++  console[err ? 'error' : 'log'](function () {/*
++Usage:
++  tap-mocha-reporter <type>
++
++Reads TAP data on stdin, and formats to stdout using the specified
++reporter.  (Note that some reporters write to files instead of stdout.)
++
++%s
++*/}.toString().split('\n').slice(1, -1).join('\n'), avail())
++}
++
++if (require.main === module) {
++  var type = process.argv[2]
++  if (!type)
++    return usage()
++
++  process.stdin.pipe(new Formatter(type))
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/index.js
+@@ -0,0 +1,16 @@
++exports.dot = require('./dot.js')
++exports.doc = require('./doc.js')
++exports.tap = true
++exports.json = require('./json.js')
++exports.list = require('./list.js')
++exports.min = require('./min.js')
++exports.spec = require('./spec.js')
++exports.nyan = require('./nyan.js')
++exports.xunit = require('./xunit.js')
++exports.markdown = require('./markdown.js')
++exports.progress = require('./progress.js')
++exports.landing = require('./landing.js')
++exports.jsonstream = require('./json-stream.js')
++exports.dump = require('./dump.js')
++exports.classic = require('./classic.js')
++exports.silent = require('./silent.js')
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/doc.js
+@@ -0,0 +1,62 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base')
++  , utils = require('../utils');
++
++/**
++ * Expose `Doc`.
++ */
++
++exports = module.exports = Doc;
++
++/**
++ * Initialize a new `Doc` reporter.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function Doc(runner) {
++  Base.call(this, runner);
++
++  var self = this
++    , stats = this.stats
++    , total = runner.total
++    , indents = 2;
++
++  function indent() {
++    return Array(indents).join('  ');
++  }
++
++  runner.on('suite', function(suite){
++    if (suite.root) return;
++    ++indents;
++    console.log('%s<section class="suite">', indent());
++    ++indents;
++    console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title));
++    console.log('%s<dl>', indent());
++  });
++
++  runner.on('suite end', function(suite){
++    if (suite.root) return;
++    console.log('%s</dl>', indent());
++    --indents;
++    console.log('%s</section>', indent());
++    --indents;
++  });
++
++  runner.on('pass', function(test){
++    console.log('%s  <dt>%s</dt>', indent(), utils.escape(test.title));
++    var code = utils.escape(utils.clean(test.fn.toString()));
++    console.log('%s  <dd><pre><code>%s</code></pre></dd>', indent(), code);
++  });
++
++  runner.on('fail', function(test, err){
++    console.log('%s  <dt class="error">%s</dt>', indent(), utils.escape(test.title));
++    var code = utils.escape(utils.clean(test.fn.toString()));
++    console.log('%s  <dd class="error"><pre><code>%s</code></pre></dd>', indent(), code);
++    console.log('%s  <dd class="error">%s</dd>', indent(), utils.escape(err));
++  });
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/dump.js
+@@ -0,0 +1,50 @@
++exports = module.exports = Dump
++var Base = require('./base')
++  , cursor = Base.cursor
++  , color = Base.color
++  , useColors = Base.useColors
++  , util = require('util')
++
++function Dump(runner) {
++  Base.call(this, runner);
++
++  var events = [
++    'start',
++    'version',
++    'suite',
++    'suite end',
++    'test',
++    'pending',
++    'pass',
++    'fail',
++    'test end',
++  ];
++
++  var i = process.argv.indexOf('dump')
++  if (i !== -1) {
++    var args = process.argv.slice(i + 1)
++    if (args.length)
++      events = args
++  }
++
++  runner.on('line', function (c) {
++    if (c.trim())
++      process.stderr.write(Base.color('bright yellow', c))
++  })
++
++  events.forEach(function (ev) {
++    runner.on(ev, function (obj) {
++      console.log(ev)
++      if (arguments.length) {
++        console.log(util.inspect(obj, false, Infinity, useColors))
++        console.log()
++      }
++    })
++  })
++
++  runner.on('end', function () {
++    console.log('end')
++    console.log(runner.stats)
++    console.log()
++  })
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/json-stream.js
+@@ -0,0 +1,62 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base')
++  , color = Base.color;
++
++/**
++ * Expose `List`.
++ */
++
++exports = module.exports = List;
++
++/**
++ * Initialize a new `List` test reporter.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function List(runner) {
++  Base.call(this, runner);
++
++  var self = this
++    , stats = this.stats
++    , total = runner.total;
++
++  runner.on('start', function(){
++    console.log(JSON.stringify(['start', { total: total }]));
++  });
++
++  runner.on('pass', function(test){
++    console.log(JSON.stringify(['pass', clean(test)]));
++  });
++
++  runner.on('fail', function(test, err){
++    test = clean(test);
++    test.err = err.message;
++    console.log(JSON.stringify(['fail', test]));
++  });
++
++  runner.on('end', function(){
++    process.stdout.write(JSON.stringify(['end', self.stats]));
++  });
++}
++
++/**
++ * Return a plain-object representation of `test`
++ * free of cyclic properties etc.
++ *
++ * @param {Object} test
++ * @return {Object}
++ * @api private
++ */
++
++function clean(test) {
++  return {
++      title: test.title
++    , fullTitle: test.fullTitle()
++    , duration: test.duration
++  }
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/json.js
+@@ -0,0 +1,92 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base')
++  , cursor = Base.cursor
++  , color = Base.color;
++
++/**
++ * Expose `JSON`.
++ */
++
++exports = module.exports = JSONReporter;
++
++/**
++ * Initialize a new `JSON` reporter.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function JSONReporter(runner) {
++  var self = this;
++  Base.call(this, runner);
++
++  var tests = []
++    , pending = []
++    , failures = []
++    , passes = [];
++
++  runner.on('test end', function(test){
++    tests.push(test);
++  });
++
++  runner.on('pass', function(test){
++    passes.push(test);
++  });
++
++  runner.on('fail', function(test){
++    failures.push(test);
++  });
++
++  runner.on('pending', function(test){
++    pending.push(test);
++  });
++
++  runner.on('end', function(){
++    var obj = {
++      stats: self.stats,
++      tests: tests.map(clean),
++      pending: pending.map(clean),
++      failures: failures.map(clean),
++      passes: passes.map(clean)
++    };
++
++    runner.testResults = obj;
++
++    process.stdout.write(JSON.stringify(obj, null, 2));
++  });
++}
++
++/**
++ * Return a plain-object representation of `test`
++ * free of cyclic properties etc.
++ *
++ * @param {Object} test
++ * @return {Object}
++ * @api private
++ */
++
++function clean(test) {
++  return {
++    title: test.title,
++    fullTitle: test.fullTitle(),
++    duration: test.duration,
++    err: errorJSON(test.err || {})
++  }
++}
++
++/**
++ * Transform `error` into a JSON object.
++ * @param {Error} err
++ * @return {Object}
++ */
++
++function errorJSON(err) {
++  var res = {};
++  Object.getOwnPropertyNames(err).forEach(function(key) {
++    res[key] = err[key];
++  }, err);
++  return res;
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/landing.js
+@@ -0,0 +1,96 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base')
++  , cursor = Base.cursor
++  , color = Base.color;
++
++/**
++ * Expose `Landing`.
++ */
++
++exports = module.exports = Landing;
++
++/**
++ * Airplane color.
++ */
++
++Base.colors.plane = 0;
++
++/**
++ * Airplane crash color.
++ */
++
++Base.colors['plane crash'] = 31;
++
++/**
++ * Runway color.
++ */
++
++Base.colors.runway = 90;
++
++/**
++ * Initialize a new `Landing` reporter.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function Landing(runner) {
++  Base.call(this, runner);
++
++  var self = this
++    , stats = this.stats
++    , width = Base.window.width * .75 | 0
++    , total = runner.total
++    , stream = process.stdout
++    , plane = color('plane', '✈')
++    , crashed = -1
++    , n = 0;
++
++  function runway() {
++    var buf = Array(width).join('-');
++    return '  ' + color('runway', buf);
++  }
++
++  runner.on('start', function(){
++    stream.write('\n\n\n  ');
++    cursor.hide();
++  });
++
++  runner.on('test end', function(test){
++    // check if the plane crashed
++    var col = -1 == crashed
++      ? width * ++n / total | 0
++      : crashed;
++
++    // show the crash
++    if ('failed' == test.state) {
++      plane = color('plane crash', '✈');
++      crashed = col;
++    }
++
++    // render landing strip
++    stream.write('\u001b['+(width+1)+'D\u001b[2A');
++    stream.write(runway());
++    stream.write('\n  ');
++    stream.write(color('runway', Array(col).join('⋅')));
++    stream.write(plane)
++    stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
++    stream.write(runway());
++    stream.write('\u001b[0m');
++  });
++
++  runner.on('end', function(){
++    cursor.show();
++    console.log();
++    self.epilogue();
++  });
++}
++
++/**
++ * Inherit from `Base.prototype`.
++ */
++
++Landing.prototype.__proto__ = Base.prototype;
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/list.js
+@@ -0,0 +1,63 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base')
++  , cursor = Base.cursor
++  , color = Base.color;
++
++/**
++ * Expose `List`.
++ */
++
++exports = module.exports = List;
++
++/**
++ * Initialize a new `List` test reporter.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function List(runner) {
++  Base.call(this, runner);
++
++  var self = this
++    , stats = this.stats
++    , n = 0;
++
++  runner.on('start', function(){
++    console.log();
++  });
++
++  runner.on('test', function(test){
++    process.stdout.write(color('pass', '    ' + test.fullTitle() + ': '));
++  });
++
++  runner.on('pending', function(test){
++    var fmt = color('checkmark', '  -')
++      + color('pending', ' %s');
++    console.log(fmt, test.fullTitle());
++  });
++
++  runner.on('pass', function(test){
++    var fmt = color('checkmark', '  '+Base.symbols.dot)
++      + color('pass', ' %s: ')
++      + color(test.speed, '%dms');
++    cursor.CR();
++    console.log(fmt, test.fullTitle(), test.duration);
++  });
++
++  runner.on('fail', function(test, err){
++    cursor.CR();
++    console.log(color('fail', '  %d) %s'), ++n, test.fullTitle());
++  });
++
++  runner.on('end', self.epilogue.bind(self));
++}
++
++/**
++ * Inherit from `Base.prototype`.
++ */
++
++List.prototype.__proto__ = Base.prototype;
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/markdown.js
+@@ -0,0 +1,126 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base')
++  , utils = require('../utils');
++
++/**
++ * Constants
++ */
++
++var SUITE_PREFIX = '$';
++
++/**
++ * Expose `Markdown`.
++ */
++
++exports = module.exports = Markdown;
++
++/**
++ * Initialize a new `Markdown` reporter.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function Markdown(runner) {
++  Base.call(this, runner);
++
++  var self = this
++    , stats = this.stats
++    , level = 0
++    , buf = '';
++
++  function title(str) {
++    return Array(level + 1).join('#') + ' ' + str;
++  }
++
++  function indent() {
++    return Array(level).join('  ');
++  }
++
++  function mapTOC(suite, obj) {
++    var ret = obj,
++        key = SUITE_PREFIX + suite.title;
++    obj = obj[key] = obj[key] || { suite: suite };
++    suite.suites.forEach(function(suite){
++      mapTOC(suite, obj);
++    });
++    return ret;
++  }
++
++  function stringifyTOC(obj, level) {
++    ++level;
++    var buf = '';
++    var link;
++    for (var key in obj) {
++      if ('suite' == key) continue;
++      if (key !== SUITE_PREFIX) {
++        link = ' - [' + key.substring(1) + ']';
++        link += '(#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
++        buf += Array(level).join('  ') + link;
++      }
++      buf += stringifyTOC(obj[key], level);
++    }
++    return buf;
++  }
++
++  function generateTOC() {
++    return suites.map(generateTOC_).join('')
++  }
++
++  function generateTOC_(suite) {
++    var obj = mapTOC(suite, {});
++    return stringifyTOC(obj, 0);
++  }
++
++  var suites = []
++  var currentSuite = null
++  runner.on('suite', function(suite){
++    currentSuite = suite
++    if (suite.root) {
++      suites.push(suite)
++    }
++    ++level;
++    var slug = utils.slug(suite.fullTitle());
++    buf += '<a name="' + slug + '"></a>' + '\n';
++    buf += title(suite.title) + '\n';
++  });
++
++  runner.on('suite end', function(suite){
++    if (suite.ok) {
++      buf += '\nok - ' + suite.title + '\n'
++    } else {
++      buf += '\nnot ok - ' + suite.title + '\n'
++    }
++    --level;
++  });
++
++  runner.on('test', function(test){
++    if (!test.ok || test.pending) {
++      var code = utils.clean(test.fn.toString());
++      buf += test.title + '.\n';
++      if (code) {
++        buf += '\n```js\n';
++        buf += code + '\n';
++        buf += '```\n';
++      }
++      var stack = test.err && test.err.stack
++      if (!stack) {
++        stack = test.result && test.result.diag && test.result.diag.stack
++      }
++      if (stack) {
++        buf += '\n```\n' + stack + '\n```\n';
++      }
++      buf += '\n\n';
++    }
++  });
++
++  runner.on('end', function(){
++    process.stdout.write('# TOC\n');
++    process.stdout.write(generateTOC());
++    process.stdout.write('\n\n');
++    process.stdout.write(buf);
++  });
++}
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/nyan.js
+@@ -0,0 +1,260 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base');
++
++/**
++ * Expose `Dot`.
++ */
++
++exports = module.exports = NyanCat;
++
++/**
++ * Initialize a new `Dot` matrix test reporter.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function NyanCat(runner) {
++  Base.call(this, runner);
++  var self = this
++    , stats = this.stats
++    , width = Base.window.width * .75 | 0
++    , rainbowColors = this.rainbowColors = self.generateColors()
++    , colorIndex = this.colorIndex = 0
++    , numerOfLines = this.numberOfLines = 4
++    , trajectories = this.trajectories = [[], [], [], []]
++    , nyanCatWidth = this.nyanCatWidth = 11
++    , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth)
++    , scoreboardWidth = this.scoreboardWidth = 5
++    , tick = this.tick = 0
++    , n = 0;
++
++  runner.on('start', function(){
++    Base.cursor.hide();
++    self.draw();
++  });
++
++  runner.on('pending', function(test){
++    self.draw();
++  });
++
++  runner.on('pass', function(test){
++    self.draw();
++  });
++
++  runner.on('fail', function(test, err){
++    self.draw();
++  });
++
++  runner.on('end', function(){
++    Base.cursor.show();
++    for (var i = 0; i < self.numberOfLines; i++) write('\n');
++    self.epilogue();
++  });
++}
++
++/**
++ * Draw the nyan cat
++ *
++ * @api private
++ */
++
++NyanCat.prototype.draw = function(){
++  this.appendRainbow();
++  this.drawScoreboard();
++  this.drawRainbow();
++  this.drawNyanCat();
++  this.tick = !this.tick;
++};
++
++/**
++ * Draw the "scoreboard" showing the number
++ * of passes, failures and pending tests.
++ *
++ * @api private
++ */
++
++NyanCat.prototype.drawScoreboard = function(){
++  var stats = this.stats;
++
++  function draw(type, n) {
++    write(' ');
++    write(Base.color(type, n));
++    write('\n');
++  }
++
++  draw('green', stats.passes);
++  draw('fail', stats.failures);
++  draw('pending', stats.pending);
++  write('\n');
++
++  this.cursorUp(this.numberOfLines);
++};
++
++/**
++ * Append the rainbow.
++ *
++ * @api private
++ */
++
++NyanCat.prototype.appendRainbow = function(){
++  var segment = this.tick ? '_' : '-';
++  var rainbowified = this.rainbowify(segment);
++
++  for (var index = 0; index < this.numberOfLines; index++) {
++    var trajectory = this.trajectories[index];
++    if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift();
++    trajectory.push(rainbowified);
++  }
++};
++
++/**
++ * Draw the rainbow.
++ *
++ * @api private
++ */
++
++NyanCat.prototype.drawRainbow = function(){
++  var self = this;
++
++  this.trajectories.forEach(function(line, index) {
++    write('\u001b[' + self.scoreboardWidth + 'C');
++    write(line.join(''));
++    write('\n');
++  });
++
++  this.cursorUp(this.numberOfLines);
++};
++
++/**
++ * Draw the nyan cat
++ *
++ * @api private
++ */
++
++NyanCat.prototype.drawNyanCat = function() {
++  var self = this;
++  var startWidth = this.scoreboardWidth + this.trajectories[0].length;
++  var dist = '\u001b[' + startWidth + 'C';
++  var padding = '';
++
++  write(dist);
++  write('_,------,');
++  write('\n');
++
++  write(dist);
++  padding = self.tick ? '  ' : '   ';
++  write('_|' + padding + '/\\_/\\ ');
++  write('\n');
++
++  write(dist);
++  padding = self.tick ? '_' : '__';
++  var tail = self.tick ? '~' : '^';
++  var face;
++  write(tail + '|' + padding + this.face() + ' ');
++  write('\n');
++
++  write(dist);
++  padding = self.tick ? ' ' : '  ';
++  write(padding + '""  "" ');
++  write('\n');
++
++  this.cursorUp(this.numberOfLines);
++};
++
++/**
++ * Draw nyan cat face.
++ *
++ * @return {String}
++ * @api private
++ */
++
++NyanCat.prototype.face = function() {
++  var stats = this.stats;
++  if (stats.failures) {
++    return '( x .x)';
++  } else if (stats.pending) {
++    return '( o .o)';
++  } else if(stats.passes) {
++    return '( ^ .^)';
++  } else {
++    return '( - .-)';
++  }
++};
++
++/**
++ * Move cursor up `n`.
++ *
++ * @param {Number} n
++ * @api private
++ */
++
++NyanCat.prototype.cursorUp = function(n) {
++  write('\u001b[' + n + 'A');
++};
++
++/**
++ * Move cursor down `n`.
++ *
++ * @param {Number} n
++ * @api private
++ */
++
++NyanCat.prototype.cursorDown = function(n) {
++  write('\u001b[' + n + 'B');
++};
++
++/**
++ * Generate rainbow colors.
++ *
++ * @return {Array}
++ * @api private
++ */
++
++NyanCat.prototype.generateColors = function(){
++  var colors = [];
++
++  for (var i = 0; i < (6 * 7); i++) {
++    var pi3 = Math.floor(Math.PI / 3);
++    var n = (i * (1.0 / 6));
++    var r = Math.floor(3 * Math.sin(n) + 3);
++    var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);
++    var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);
++    colors.push(36 * r + 6 * g + b + 16);
++  }
++
++  return colors;
++};
++
++/**
++ * Apply rainbow to the given `str`.
++ *
++ * @param {String} str
++ * @return {String}
++ * @api private
++ */
++
++NyanCat.prototype.rainbowify = function(str){
++  if (!Base.useColors)
++    return str;
++  var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];
++  this.colorIndex += 1;
++  return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m';
++};
++
++/**
++ * Stdout helper.
++ */
++
++function write(string) {
++  process.stdout.write(string);
++}
++
++/**
++ * Inherit from `Base.prototype`.
++ */
++
++NyanCat.prototype.__proto__ = Base.prototype;
+--- /dev/null
++++ b/node_modules/tap-mocha-reporter/lib/reporters/xunit.js
+@@ -0,0 +1,149 @@
++/**
++ * Module dependencies.
++ */
++
++var Base = require('./base')
++  , utils = require('../utils')
++  , fs = require('fs')
++  , escape = utils.escape;
++
++/**
++ * Save timer references to avoid Sinon interfering (see GH-237).
++ */
++
++var Date = global.Date
++  , setTimeout = global.setTimeout
++  , setInterval = global.setInterval
++  , clearTimeout = global.clearTimeout
++  , clearInterval = global.clearInterval;
++
++/**
++ * Expose `XUnit`.
++ */
++
++exports = module.exports = XUnit;
++
++/**
++ * Initialize a new `XUnit` reporter.
++ *
++ * @param {Runner} runner
++ * @api public
++ */
++
++function XUnit(runner, options) {
++  Base.call(this, runner);
++  var stats = this.stats
++    , tests = []
++    , self = this;
++
++  if (options.reporterOptions && options.reporterOptions.output) {
++      if (! fs.createWriteStream) {
++          throw new Error('file output not supported in browser');
++      }
++      self.fileStream = fs.createWriteStream(options.reporterOptions.output);
++  }
++
++  runner.on('pending', function(test){
++    tests.push(test);
++  });
++
++  runner.on('pass', function(test){
++    tests.push(test);
++  });
++
++  runner.on('fail', function(test){
++    tests.push(test);
++  });
++
++  runner.on('end', function(){
++    self.write(tag('testsuite', {
++        name: 'TAP Tests'
++      , tests: stats.tests
++      , failures: stats.failures
++      , errors: stats.failures
++      , skipped: stats.tests - stats.failures - stats.passes
++      , timestamp: (new Date).toUTCString()
++      , time: (stats.duration / 1000) || 0
++    }, false));
++
++    tests.forEach(function(t) { self.test(t); });
++    self.write('</testsuite>');
++  });
++}
++
++/**
++ * Override done to close the stream (if it's a file).
++ */
++XUnit.prototype.done = function(failures, fn) {
++    if (this.fileStream) {
++        this.fileStream.end(function() {
++            fn(failures);
++        });
++    } else {
++        fn(failures);
++    }
++};
++
++/**
++ * Inherit from `Base.prototype`.
++ */
++
++XUnit.prototype.__proto__ = Base.prototype;
++
++/**
++ * Write out the given line
++ */
++XUnit.prototype.write = function(line) {
++    if (this.fileStream) {
++        this.fileStream.write(line + '\n');
++    } else {
++        console.log(line);
++    }
++};
++
++/**
++ * Output tag for the given `test.`
++ */
++
++XUnit.prototype.test = function(test, ostream) {
++  var attrs = {
++      classname: test.parent.fullTitle()
++    , name: test.title
++    , time: (test.duration / 1000) || 0
++  };
++
++  if ('failed' == test.state) {
++    var err = test.err;
++    this.write(tag('testcase', attrs, false, tag('failure', {}, false, cdata(escape(err.message) + "\n" + err.stack))));
++  } else if (test.pending) {
++    this.write(tag('testcase', attrs, false, tag('skipped', {}, true)));
++  } else {
++    this.write(tag('testcase', attrs, true) );
++  }
++};
++
++/**
++ * HTML tag helper.
++ */
++
++function tag(name, attrs, close, content) {
++  var end = close ? '/>' : '>'
++    , pairs = []
++    , tag;
++
++  for (var key in attrs) {
++    pairs.push(key + '="' + escape(attrs[key]) + '"');
++  }
++
++  tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
++  if (content) tag += content + '</' + name + end;
++  return tag;
++}
++
++/**
++ * Return cdata escaped CDATA `str`.
++ */
++
++function cdata(str) {
++  return '<![CDATA[' + escape(str) + ']]>';
++}
diff --git a/debian/patches/sbuild_disable_tests.patch b/debian/patches/sbuild_disable_tests.patch
index b8d581f..fd59c8f 100644
--- a/debian/patches/sbuild_disable_tests.patch
+++ b/debian/patches/sbuild_disable_tests.patch
@@ -1,15 +1,7 @@
-Description: disable tests that are okay to fail on sbuild
- one is racey, the other one requires specific output fds
-Last-Update: 2014-10-20
+Description: disable tests requiring specific setup
+Last-Update: 2016-11-11
 Author: Jérémy Lal <kapouer at melix.org>
 Forwarded: not-needed
---- a/test/output-childtest-description.js
-+++ b/test/output-childtest-description.js
-@@ -1,3 +1,4 @@
-+return;
- var tap  =  require("../")
-   , fs   =  require("fs")
-   , path =  require('path')
 --- a/test/segv.js
 +++ b/test/segv.js
 @@ -1,3 +1,4 @@
diff --git a/debian/patches/series b/debian/patches/series
index 9347409..a0134ff 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,4 +1,7 @@
+module-foreground-child.patch
+module-tap-mocha-reporter.patch
+module-stack-utils.patch
+module-clean-yaml-object.patch
+module-buffer-to-string.patch
 nodejs_rename.patch
 use_available_modules.patch
-sbuild_disable_tests.patch
-mitigate_test_segv.patch
diff --git a/debian/patches/use_available_modules.patch b/debian/patches/use_available_modules.patch
index b4c6faf..464f03f 100644
--- a/debian/patches/use_available_modules.patch
+++ b/debian/patches/use_available_modules.patch
@@ -1,56 +1,147 @@
 Description: use already packaged modules
- ... instead of adding new ones that do the same thing
+ instead of adding new ones that do the same thing
 Forwarded: not-needed, would probably get upstream angry
 Author: Jérémy Lal <kapouer at melix.org>
 Last-Update: 2014-10-20
---- a/lib/tap-assert.js
-+++ b/lib/tap-assert.js
-@@ -1,9 +1,27 @@
- // an assert module that returns tappable data for each assertion.
--var difflet = require('difflet')
--  , deepEqual = require('deep-equal')
--  , bufferEqual = require('buffer-equal')
-+var createPatch = require('diff').createPatch
-+  , assertDeepEqual = require('assert').deepEqual
-   , Buffer = require('buffer').Buffer
- 
-+function deepEqual(a, b) {
-+  try {
-+    assertDeepEqual(a, b);
-+  } catch(e) {
-+    return false;
-+  }
-+  return true;
+--- a/lib/assert.js
++++ b/lib/assert.js
+@@ -1,6 +1,9 @@
+ var synonyms = require('./synonyms.js')
+-var deeper = require('deeper') // strict
+-var shallower = require('only-shallow') // in touch with its feelings
++var deepEqual = require('deep-equal')
++var deeper = function(a, b) {
++	return deepEqual(a, b, {strict: true});
 +}
++var shallower = deepEqual;
+ var tmatch = require('tmatch') // ok with partial estimates
+ 
+ // Load Buffer the old way for browserify's sake
+--- a/bin/run.js
++++ b/bin/run.js
+@@ -3,12 +3,17 @@
+ var fs = require('fs')
+ var spawn = require('child_process').spawn
+ var fg = require('foreground-child')
+-var opener = require('opener')
+-var colorSupport = require('color-support')
+-var nycBin = require.resolve('nyc/bin/nyc.js')
++var colorSupport = require('supports-color')
++var nycBin;
++function getNycBin() {
++ if (!nycBin) {
++   nycBin = require.resolve('nyc/bin/nyc.js');
++ }
++ return nycBin;
++}
+ var glob = require('glob')
+ var isexe = require('isexe')
+-var osHomedir = require('os-homedir')
++var osHomedir = require('os').homedir
+ var yaml = require('js-yaml')
+ 
+ var coverageServiceTest = process.env.COVERAGE_SERVICE_TEST === 'true'
+@@ -32,13 +37,18 @@
+ // Currently only Coveralls is supported, but the infrastructure
+ // is left in place in case some noble soul fixes the codecov
+ // module in the future.  See https://github.com/tapjs/node-tap/issues/270
+-var coverageServices = [
+-  {
++var coverageServices = [];
 +
-+function bufferEqual(a, b) {
-+  if (!Buffer.isBuffer(a)) return false;
-+  if (!Buffer.isBuffer(b)) return false;
-+  if (a.length != b.length) return false;
-+  for (var i=0, len=a.length; i < len; i++) {
-+    if (a[i] != b[i]) return false;
-+  }
-+  return true;
++try {
++	coverageServices.push({
+     env: 'COVERALLS_REPO_TOKEN',
+     bin: require.resolve('coveralls/bin/coveralls.js'),
+     name: 'Coveralls'
+-  }
+-]
++  });
++} catch(ex) {
++	console.info("coveralls not enabled");
 +}
 +
- module.exports = assert
  
- var syns = {}
-@@ -405,6 +423,8 @@
-   }})())
+ main()
+ 
+@@ -397,7 +407,7 @@
+ function respawnWithCoverage (options) {
+   // console.error('respawn with coverage')
+   // Re-spawn with coverage
+-  var args = [nycBin].concat(
++  var args = [getNycBin()].concat(
+     '--silent',
+     options.nycArgs,
+     '--',
+@@ -479,7 +489,7 @@
+     }
+   }
+ 
+-  var args = [nycBin, 'report', '--reporter', options.coverageReport]
++  var args = [getNycBin(), 'report', '--reporter', options.coverageReport]
+   // console.error('run coverage report', args)
+ 
+   var child
+@@ -493,7 +503,7 @@
+     child = fg(node, args)
+     if (options.coverageReport === 'lcov' && options.browser) {
+       child.on('exit', function () {
+-        opener('coverage/lcov-report/index.html')
++        require('opener')('coverage/lcov-report/index.html')
+       })
+     }
+   }
+@@ -533,7 +543,7 @@
  }
  
-+
-+
- function diffString (f, w) {
-   if (w === f) return null
-   var p = 0
-@@ -416,7 +436,7 @@
+ function runCoverageCheck (options, code, signal) {
+-  var args = [nycBin, 'check-coverage'].concat(coverageCheckArgs(options))
++  var args = [getNycBin(), 'check-coverage'].concat(coverageCheckArgs(options))
+ 
+   var child = fg(node, args)
+   child.removeAllListeners('close')
+@@ -549,7 +559,7 @@
+ }
+ 
+ function nycHelp () {
+-  fg(node, [nycBin, '--help'])
++  fg(node, [getNycBin(), '--help'])
  }
  
- function diffObject (f, w) {
--  return difflet({ indent : 2, comment : true }).compare(w, f)
-+  return createPatch('', JSON.stringify(w, null, 2), JSON.stringify(f, null, 2));
+ function nycVersion () {
+--- a/node_modules/tap-mocha-reporter/lib/reporters/base.js
++++ b/node_modules/tap-mocha-reporter/lib/reporters/base.js
+@@ -6,7 +6,7 @@
+   , diff = require('diff')
+   , ms = require('../ms')
+   , utils = require('../utils')
+-  , supportsColor = require('color-support')()
++  , supportsColor = require('supports-color')
+ 
+ /**
+  * Save timer references to avoid Sinon interfering (see GH-237).
+--- a/lib/test.js
++++ b/lib/test.js
+@@ -6,8 +6,6 @@
+   Readable = require('readable-stream').Readable
  }
  
- function diff (f, w, p) {
+-var Promise = require('bluebird')
+-
+ function Deferred () {
+   this.resolve = null
+   this.reject = null
+--- a/node_modules/tap-mocha-reporter/lib/reporters/classic.js
++++ b/node_modules/tap-mocha-reporter/lib/reporters/classic.js
+@@ -9,8 +9,9 @@
+   , ms = require('../ms.js')
+   , diff = require('diff')
+   , utils = require('../utils.js')
+-  , uclen = require('unicode-length').get
+-  , colorSupport = require('color-support')()
++  , stripAnsi = require('strip-ansi')
++  , uclen = function(str) { return stripAnsi(str).length }
++  , colorSupport = require('supports-color')
+ 
+ function hasOwnProperty (obj, key) {
+   return Object.prototype.hasOwnProperty.call(obj, key)
diff --git a/debian/rules b/debian/rules
index 78efe0e..1519373 100755
--- a/debian/rules
+++ b/debian/rules
@@ -7,15 +7,12 @@
 %:
 	dh $@
 
-override_dh_install:
-	dh_install
+override_dh_fixperms:
+	dh_fixperms
 	chmod a+x debian/node-tap/usr/lib/nodejs/tap/bin/*.js
 
-override_dh_auto_test:
-	./bin/tap.js test/*.js
-
-override_dh_auto_build: debian/tap.1
-
-debian/tap.1:
-	help2man -N -n "Test-Anything-Protocol module for Node.js" bin/tap.js -o "$@"
+override_dh_auto_build:
+	help2man -N -n "Test-Anything-Protocol module for Node.js" --no-discard-stderr bin/run.js -o debian/tap.1
 
+override_dh_auto_clean:
+	rm -f debian/tap.1

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-tap.git



More information about the Pkg-javascript-commits mailing list