function preferredMediaTypes(accept, provided) {
  // RFC 2616 sec 14.2: no header = */*
  var accepts = parseAccept(accept === undefined ? '*/*' : accept || '');

  if (!provided) {
    // sorted list of all types
    return accepts
      .filter(isQuality)
      .sort(compareSpecs)
      .map(getFullType);
  }

  var priorities = provided.map(function getPriority(type, index) {
    return getMediaTypePriority(type, accepts, index);
  });

  // sorted list of accepted types
  return priorities.filter(isQuality).sort(compareSpecs).map(function getType(priority) {
    return provided[priorities.indexOf(priority)];
  });
}

function
preferredMediaTypes
(
accept
,
provided
)
{
// RFC 2616 sec 14.2: no header = */*
var
accepts
=
parseAccept
(
accept
===
undefined
'*/*'
:
accept
||
''
)
;
if
(
!
provided
)
{
// sorted list of all types
return
accepts
.
filter
(
isQuality
)
.
sort
(
compareSpecs
)
.
map
(
getFullType
)
;
}
var
priorities
=
provided
.
map
(
function
getPriority
(
type
,
index
)
{
return
getMediaTypePriority
(
type
,
accepts
,
index
)
;
}
)
;
// sorted list of accepted types
return
priorities
.
filter
(
isQuality
)
.
sort
(
compareSpecs
)
.
map
(
function
getType
(
priority
)
{
return
provided
[
priorities
.
indexOf
(
priority
)
]
;
}
)
;
}

Get the preferred media types from an Accept header.
@public

Get the preferred media types from an Accept header .


function quoteCount(string) {
  var count = 0;
  var index = 0;

  while ((index = string.indexOf('"', index)) !== -1) {
    count++;
    index++;
  }

  return count;
}

function quoteCount ( string ) { var count = 0 ; var index = 0 ; while ( ( index = string . indexOf ( '"' , index ) ) !== - 1 ) { count ++ ; index ++ ; } return count ; }

Count the number of quotes in a string.
@private

Count the number of quotes in a string .


function splitKeyValuePair(str) {
  var index = str.indexOf('=');
  var key;
  var val;

  if (index === -1) {
    key = str;
  } else {
    key = str.substr(0, index);
    val = str.substr(index + 1);
  }

  return [key, val];
}

function splitKeyValuePair ( str ) { var index = str . indexOf ( '=' ) ; var key ; var val ; if ( index === - 1 ) { key = str ; } else { key = str . substr ( 0 , index ) ; val = str . substr ( index + 1 ) ; } return [ key , val ] ; }


function splitMediaTypes(accept) {
  var accepts = accept.split(',');

  for (var i = 1, j = 0; i < accepts.length; i++) {
    if (quoteCount(accepts[j]) % 2 == 0) {
      accepts[++j] = accepts[i];
    } else {
      accepts[j] += ',' + accepts[i];
    }
  }

  // trim accepts
  accepts.length = j + 1;

  return accepts;
}

function
splitMediaTypes
(
accept
)
{
var
accepts
=
accept
.
split
(
','
)
;
for
(
var
i
=
1
,
j
=
0
;
i
<
accepts
.
length
;
i
++
)
{
if
(
quoteCount
(
accepts
[
j
]
)
%
2
==
0
)
{
accepts
[
++
j
]
=
accepts
[
i
]
;
}
else
{
accepts
[
j
]
+=
','
+
accepts
[
i
]
;
}
}
// trim accepts
accepts
.
length
=
j
+
1
;
return
accepts
;
}

Split an Accept header into media types.
@private

Split an Accept header into media types .


function splitParameters(str) {
  var parameters = str.split(';');

  for (var i = 1, j = 0; i < parameters.length; i++) {
    if (quoteCount(parameters[j]) % 2 == 0) {
      parameters[++j] = parameters[i];
    } else {
      parameters[j] += ';' + parameters[i];
    }
  }

  // trim parameters
  parameters.length = j + 1;

  for (var i = 0; i < parameters.length; i++) {
    parameters[i] = parameters[i].trim();
  }

  return parameters;
}

function
splitParameters
(
str
)
{
var
parameters
=
str
.
split
(
';'
)
;
for
(
var
i
=
1
,
j
=
0
;
i
<
parameters
.
length
;
i
++
)
{
if
(
quoteCount
(
parameters
[
j
]
)
%
2
==
0
)
{
parameters
[
++
j
]
=
parameters
[
i
]
;
}
else
{
parameters
[
j
]
+=
';'
+
parameters
[
i
]
;
}
}
// trim parameters
parameters
.
length
=
j
+
1
;
for
(
var
i
=
0
;
i
<
parameters
.
length
;
i
++
)
{
parameters
[
i
]
=
parameters
[
i
]
.
trim
(
)
;
}
return
parameters
;
}


function loadWebpackConfig () {
  var webpackConfig = require('./webpack.config.js');
  webpackConfig.devtool = 'inline-source-map';
  webpackConfig.module.preLoaders = [
    {
      test: /\.jsx?$/,
      include: path.resolve('lib'),
      loader: 'isparta'
    }
  ];
  return webpackConfig;
}

function loadWebpackConfig ( ) { var webpackConfig = require ( './webpack.config.js' ) ; webpackConfig . devtool = 'inline-source-map' ; webpackConfig . module . preLoaders = [ { test : / \.jsx?$ / , include : path . resolve ( 'lib' ) , loader : 'isparta' } ] ; return webpackConfig ; }

Loads configuration while ensuring sounce-map is enabled

Loads configuration while ensuring sounce - map is enabled


function assign (obj, keyPath, value) {
  const lastKeyIndex = keyPath.length - 1

  for (let i = 0; i < lastKeyIndex; ++i) {
    const key = keyPath[i]
    if (!(key in obj)) obj[key] = {}
    obj = obj[key]
  }

  obj[keyPath[lastKeyIndex]] = value
}

function assign ( obj , keyPath , value ) { const lastKeyIndex = keyPath . length - 1 for ( let i = 0 ; i < lastKeyIndex ; ++ i ) { const key = keyPath [ i ] if ( ! ( key in obj ) ) obj [ key ] = { } obj = obj [ key ] } obj [ keyPath [ lastKeyIndex ] ] = value }

assigns values to an object, creating keys in
`keyPath` if they don't exist yet.
@param {object} obj - The object to assign values to
@param {array} keyPath - The path to assign in object [a,b] => obj.a.b
@param {any} value - The value to assign to the object

assigns values to an object creating keys in keyPath if they don t exist yet .


function getFilterString(selectedValues) {
	if (selectedValues && Object.keys(selectedValues).length) {
		return Object
			// take all selectedValues
			.entries(selectedValues)
			// filter out filter components having some value
			.filter(([, componentValues]) =>
				filterComponents.includes(componentValues.componentType)
					// in case of an array filter out empty array values as well
					&& (
						(componentValues.value && componentValues.value.length)
						// also consider range values in the shape { start, end }
						|| componentValues.value.start || componentValues.value.end
					))
			// parse each filter value
			.map(([componentId, componentValues]) => parseFilterValue(componentId, componentValues))
			// return as a string separated with comma
			.join();
	}
	return null;
}

transforms the selectedValues from store into the X-Search-Filters string for analytics

transforms the selectedValues from store into the X - Search - Filters string for analytics


function evaluatePage(page, fn) {
	var args =  Array.prototype.slice.call(arguments, 2);
	return this.ready.then(function() {
		var stack;
		page = page || this.page;
		var res = HorsemanPromise.fromCallback(function(done) {
				// Wrap fn to be able to catch exceptions and reject Promise
				stack = HorsemanPromise.reject(new Error('See next line'));
				return page.evaluate(function evaluatePage(fnstr, args) {
					try {
						var fn;
						eval('fn = ' + fnstr);

						var res = fn.apply(this, args); // Call fn with args
						return { res: res };
					} catch (err) {
						return { err: err, iserr: err instanceof Error };
					}
				}, fn.toString(), args, done);
			})
			.then(function handleErrback(args) {
				return stack.catch(function(err) {
					if (args.err) {
						if (args.iserr) {
							var stack = err.stack.split('\n').slice(1);
							// Append Node stack to Phantom stack
							args.err.stack += '\n' + stack.join('\n');
						}
						return HorsemanPromise.reject(args.err);
					}
					return args.res;
				});
			});
		stack.catch(function() {});
		return res;
	});
}

Evaluates a function on the given page.
@this Horseman
@param {Page} page
@param {function} fn
@param {...*} [arguments]

Evaluates a function on the given page .


function waitForPage(page, optsOrFn) {
	var self = this;
	var args, value, fname, timeout = self.options.timeout, fn;

	if(typeof optsOrFn === "function"){
			fn = optsOrFn;
			args = Array.prototype.slice.call(arguments);
			value = args.pop();
			fname = fn.name || '<anonymous>';
	} else if(typeof optsOrFn === "object"){
			fn = optsOrFn.fn;
			args = [page, fn].concat(optsOrFn.args || []);
			value = optsOrFn.value;
			fname = fn.name || '<anonymous>';
			if(optsOrFn.timeout){
				timeout = optsOrFn.timeout;
			}
	}

	debug.apply(debug, ['.waitFor()', fname].concat(args.slice(2)));
	return this.ready.then(function() {
		return new HorsemanPromise(function(resolve, reject) {
			var start = Date.now();
			var checkInterval = setInterval(function waitForCheck() {
				var _page = page || self.page;
				var diff = Date.now() - start;
				if (diff > timeout) {
					clearInterval(checkInterval);
					debug('.waitFor() timed out');
					if (typeof _page.onTimeout === 'function') {
						_page.onTimeout('waitFor');
					}
					reject(new TimeoutError(
							'timeout during .waitFor() after ' + diff + ' ms'));
				} else {
					return evaluatePage.apply(self, args)
						.tap(function(res) {
							debugv('.waitFor() iteration',
									fname,
									res,
									diff,
									self.id
							);
						})
						.then(function(res) {
							if (res === value) {
								debug('.waitFor() completed successfully');
								clearInterval(checkInterval);
								resolve();
							}
						})
						.catch(function(err) {
							clearInterval(checkInterval);
							reject(err);
						});
				}
			}, self.options.interval);
		});
	});
}

function
waitForPage
(
page
,
optsOrFn
)
{
var
self
=
this
;
var
args
,
value
,
fname
,
timeout
=
self
.
options
.
timeout
,
fn
;
if
(
typeof
optsOrFn
===
"function"
)
{
fn
=
optsOrFn
;
args
=
Array
.
prototype
.
slice
.
call
(
arguments
)
;
value
=
args
.
pop
(
)
;
fname
=
fn
.
name
||
'<anonymous>'
;
}
else
if
(
typeof
optsOrFn
===
"object"
)
{
fn
=
optsOrFn
.
fn
;
args
=
[
page
,
fn
]
.
concat
(
optsOrFn
.
args
||
[
]
)
;
value
=
optsOrFn
.
value
;
fname
=
fn
.
name
||
'<anonymous>'
;
if
(
optsOrFn
.
timeout
)
{
timeout
=
optsOrFn
.
timeout
;
}
}
debug
.
apply
(
debug
,
[
'.waitFor()'
,
fname
]
.
concat
(
args
.
slice
(
2
)
)
)
;
return
this
.
ready
.
then
(
function
(
)
{
return
new
HorsemanPromise
(
function
(
resolve
,
reject
)
{
var
start
=
Date
.
now
(
)
;
var
checkInterval
=
setInterval
(
function
waitForCheck
(
)
{
var
_page
=
page
||
self
.
page
;
var
diff
=
Date
.
now
(
)
start
;
if
(
diff
>
timeout
)
{
clearInterval
(
checkInterval
)
;
debug
(
'.waitFor() timed out'
)
;
if
(
typeof
_page
.
onTimeout
===
'function'
)
{
_page
.
onTimeout
(
'waitFor'
)
;
}
reject
(
new
TimeoutError
(
'timeout during .waitFor() after '
+
diff
+
' ms'
)
)
;
}
else
{
return
evaluatePage
.
apply
(
self
,
args
)
.
tap
(
function
(
res
)
{
debugv
(
'.waitFor() iteration'
,
fname
,
res
,
diff
,
self
.
id
)
;
}
)
.
then
(
function
(
res
)
{
if
(
res
===
value
)
{
debug
(
'.waitFor() completed successfully'
)
;
clearInterval
(
checkInterval
)
;
resolve
(
)
;
}
}
)
.
catch
(
function
(
err
)
{
clearInterval
(
checkInterval
)
;
reject
(
err
)
;
}
)
;
}
}
,
self
.
options
.
interval
)
;
}
)
;
}
)
;
}

Waits for a function to evaluate to a given value on the given page
@param {Page | undefined} page
@param {function | object} optsOrFn - If optsOrFn is a function, use the classic signature waitForPage(page, fn, arg1, arg2, value), If arg is an object, use waitForPage(page, options)
@param {array} optsOrFn.args - arguments of fn
@param {function} optsOrFn.fn - function to evaluate
@param {*} optsOrFn.value - expected value of function
@param {number} [optsOrFn.timeout=null] - timeout in ms
@param {...*} [arguments]
@param {*} value
@emits Horseman#TimeoutError


function Horseman(options) {
	this.ready = false;
	if (!(this instanceof Horseman)) { return new Horseman(options); }
	this.options = defaults(clone(options) || {}, DEFAULTS);

	this.id = ++instanceId;
	debug('.setup() creating phantom instance %s', this.id);

	var phantomOptions = {
		'load-images': this.options.loadImages,
		'ssl-protocol': this.options.sslProtocol
	};

	if (typeof this.options.ignoreSSLErrors !== 'undefined') {
		phantomOptions['ignore-ssl-errors'] = this.options.ignoreSSLErrors;
	}
	if (typeof this.options.webSecurity !== 'undefined') {
		phantomOptions['web-security'] = this.options.webSecurity;
	}
	if (typeof this.options.proxy !== 'undefined') {
		phantomOptions.proxy = this.options.proxy;
	}
	if (typeof this.options.proxyType !== 'undefined') {
		phantomOptions['proxy-type'] = this.options.proxyType;
	}
	if (typeof this.options.proxyAuth !== 'undefined') {
		phantomOptions['proxy-auth'] = this.options.proxyAuth;
	}
	if (typeof this.options.diskCache !== 'undefined') {
		phantomOptions['disk-cache'] = this.options.diskCache;
	}
	if (typeof this.options.diskCachePath !== 'undefined') {
		phantomOptions['disk-cache-path'] = this.options.diskCachePath;
	}
	if (typeof this.options.cookiesFile !== 'undefined') {
		phantomOptions['cookies-file'] = this.options.cookiesFile;
	}

	if (this.options.debugPort) {
		phantomOptions['remote-debugger-port'] = this.options.debugPort;
		phantomOptions['remote-debugger-autorun'] = 'no';
		if (this.options.debugAutorun !== false) {
			phantomOptions['remote-debugger-autorun'] = 'yes';
		}
	}

	Object.keys(this.options.phantomOptions || {}).forEach(function (key) {
		if (typeof phantomOptions[key] !== 'undefined') {
			debug('Horseman option ' + key + ' overridden by phantomOptions');
		}
		phantomOptions[key] = this.options.phantomOptions[key];
	}.bind(this));

	var instantiationOptions = {
		parameters: phantomOptions
	};

	if (typeof this.options.phantomPath !== 'undefined') {
		instantiationOptions['path'] = this.options.phantomPath;
	}

	// Store the url that was requested for the current url
	this.targetUrl = null;

	// Store the HTTP status code for resources requested.
	this.responses = {};

	this.tabs = [];
	this.onTabCreated = noop;
	this.onTabClosed = noop;

	this.ready = prepare(this, instantiationOptions);
}


function getColors (image, cb) {
	var data = [];

	var img = createImage(image);

	var promise = new Promise(function (resolve) {
		img.onload = function () {
			var canvas = document.createElement('canvas');
			canvas.width = img.width;
			canvas.height = img.height;
			canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);

			var ctx = canvas.getContext('2d');

			var imageData = ctx.getImageData(0, 0, img.width, 1).data;

			for (var i = 0; i < img.width; i++) {
				data.push([imageData[i*4]/255, imageData[i*4+1]/255, imageData[i*4+2]/255]);
			}

			resolve(data);
		};
	});

	return promise;
}

function getColors ( image , cb ) { var data = [ ] ; var img = createImage ( image ) ; var promise = new Promise ( function ( resolve ) { img . onload = function ( ) { var canvas = document . createElement ( 'canvas' ) ; canvas . width = img . width ; canvas . height = img . height ; canvas . getContext ( '2d' ) . drawImage ( img , 0 , 0 , img . width , img . height ) ; var ctx = canvas . getContext ( '2d' ) ; var imageData = ctx . getImageData ( 0 , 0 , img . width , 1 ) . data ; for ( var i = 0 ; i < img . width ; i ++ ) { data . push ( [ imageData [ i * 4 ] / 255 , imageData [ i * 4 + 1 ] / 255 , imageData [ i * 4 + 2 ] / 255 ] ) ; } resolve ( data ) ; } ; } ) ; return promise ; }


function createCubehelix (steps, opts) {
	var data = [];

	for (var i = 0; i < steps; i++ ){
		data.push(cubehelix.rgb(i/steps, opts).map((v) => v/255));
	}

	return data;
}

function createCubehelix ( steps , opts ) { var data = [ ] ; for ( var i = 0 ; i < steps ; i ++ ) { data . push ( cubehelix . rgb ( i / steps , opts ) . map ( ( v ) => v / 255 ) ) ; } return data ; }


function toImageData (colors) {
	return colors.map((color) => color.map((v) => v*255).concat(255))
	.reduce((prev, curr) => prev.concat(curr));
}

function toImageData ( colors ) { return colors . map ( ( color ) => color . map ( ( v ) => v * 255 ) . concat ( 255 ) ) . reduce ( ( prev , curr ) => prev . concat ( curr ) ) ; }


function compress (colors, factor) {
	var data = [];

	var len = (colors.length) / factor;
	var step = (colors.length-1) / len;

	for (var i = 0; i < colors.length; i+= step) {
		data.push(colors[i|0]);
	}

	return data;
}

function compress ( colors , factor ) { var data = [ ] ; var len = ( colors . length ) / factor ; var step = ( colors . length - 1 ) / len ; for ( var i = 0 ; i < colors . length ; i += step ) { data . push ( colors [ i | 0 ] ) ; } return data ; }

return interpolated imagedata with only each @factor pixel left


function toColormap (data) {
	var stops = [];

	for (var i = 0; i < data.length; i++) {
		stops.push({
			index: Math.round(i * 100 / (data.length - 1)) / 100,
			rgb: data[i].map((v) => Math.round(v*255))
		});
	}

	return stops;
}

function toColormap ( data ) { var stops = [ ] ; for ( var i = 0 ; i < data . length ; i ++ ) { stops . push ( { index : Math . round ( i * 100 / ( data . length - 1 ) ) / 100 , rgb : data [ i ] . map ( ( v ) => Math . round ( v * 255 ) ) } ) ; } return stops ; }


function startDownload(src, storageFile) {
    var uri = Windows.Foundation.Uri(src);
    var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
    var download = downloader.createDownload(uri, storageFile);
    return download.startAsync();
}

function startDownload ( src , storageFile ) { var uri = Windows . Foundation . Uri ( src ) ; var downloader = new Windows . Networking . BackgroundTransfer . BackgroundDownloader ( ) ; var download = downloader . createDownload ( uri , storageFile ) ; return download . startAsync ( ) ; }

this can throw exceptions, callers responsibility

this can throw exceptions callers responsibility


function(options) {
    this._handlers = {
        'progress': [],
        'cancel': [],
        'error': [],
        'complete': []
    };

    // require options parameter
    if (typeof options === 'undefined') {
        throw new Error('The options argument is required.');
    }

    // require options.src parameter
    if (typeof options.src === 'undefined' && options.type !== "local") {
        throw new Error('The options.src argument is required for merge replace types.');
    }

    // require options.id parameter
    if (typeof options.id === 'undefined') {
        throw new Error('The options.id argument is required.');
    }

    // define synchronization strategy
    //
    //     replace: This is the normal behavior. Existing content is replaced
    //              completely by the imported content, i.e. is overridden or
    //              deleted accordingly.
    //     merge:   Existing content is not modified, i.e. only new content is
    //              added and none is deleted or modified.
    //     local:   Existing content is not modified, i.e. only new content is
    //              added and none is deleted or modified.
    //
    if (typeof options.type === 'undefined') {
        options.type = 'replace';
    }

    if (typeof options.headers === 'undefined') {
        options.headers = null;
    }

    if (typeof options.copyCordovaAssets === 'undefined') {
        options.copyCordovaAssets = false;
    }

    if (typeof options.copyRootApp === 'undefined') {
        options.copyRootApp = false;
    }

    if (typeof options.timeout === 'undefined') {
        options.timeout = 15.0;
    }

    if (typeof options.trustHost === 'undefined') {
        options.trustHost = false;
    }

    if (typeof options.manifest === 'undefined') {
        options.manifest = "";
    }

    if (typeof options.validateSrc === 'undefined') {
        options.validateSrc = true;
    }

    // store the options to this object instance
    this.options = options;

    // triggered on update and completion
    var that = this;
    var success = function(result) {
        if (result && typeof result.progress !== 'undefined') {
            that.emit('progress', result);
        } else if (result && typeof result.localPath !== 'undefined') {
            that.emit('complete', result);
        }
    };

    // triggered on error
    var fail = function(msg) {
        var e = (typeof msg === 'string') ? new Error(msg) : msg;
        that.emit('error', e);
    };

    // wait at least one process tick to allow event subscriptions
    setTimeout(function() {
        exec(success, fail, 'Sync', 'sync', [options.src, options.id, options.type, options.headers, options.copyCordovaAssets, options.copyRootApp, options.timeout, options.trustHost, options.manifest, options.validateSrc]);
    }, 10);
}

ContentSync constructor.

@param {Object} options to initiate a new content synchronization.
@param {String} src is a URL to the content sync end-point.
@param {String} id is used as a unique identifier for the sync operation
@param {Object} type defines the sync strategy applied to the content.
@param {String} replace completely removes existing content then copies new content.
@param {String} merge   does not modify existing content, but adds new content.
@param {Object} headers are used to set the headers for when we send a request to the src URL
@param {Boolean} validateSrc whether to validate src url with a HEAD request before download (ios only, default true).
@return {ContentSync} instance that can be monitored and cancelled.


function createAppChannel (app, key) {
  assert(~['consumerChannel', 'publisherChannel'].indexOf(key),
    'Channel key must be "consumerChannel" or "publisherChannel"')
  assert(app.connection, 'Cannot create a channel without a connection')
  assert(!app[key], 'Channel "' + key + '" already exists')

  return co(function * () {
    const channel =
      app[key] =
        yield app.connection.createChannel()

    channel.__coworkersCloseHandler = module.exports.closeHandler.bind(null, app, key)
    channel.__coworkersErrorHandler = module.exports.errorHandler.bind(null, app, key)
    channel.once('close', channel.__coworkersCloseHandler)
    channel.once('error', channel.__coworkersErrorHandler)
    app.emit('channel:create', channel)

    // attach special event to determine if a message has been confirmed
    // this event is handled in context.js
    if (key === 'consumerChannel') {
      if (app.prefetchOpts) {
        channel.prefetch(app.prefetchOpts.count, app.prefetchOpts.global)
      }
      wrap(channel, ['ack', 'nack'], function (fn, args) {
        const message = args[0]
        assert(!message.messageAcked, 'Messages cannot be acked/nacked more than once (will close channel)')

        const ret = fn.apply(this, args)
        message.messageAcked = true
        return ret
      })
    }

    return channel
  })
}

Create consumer or publisher RabbitMQ channel
@param {String} key channel key {consumer, publisher}
@return {Promise} channel promise


function errorHandler (app, key, err) {
  // delete app key
  delete app[key]
  // log and adjust err message
  const msg = `"app.${key}" unexpectedly errored: ${err.message}`
  debug(msg, err)
  err.message = msg
  // throw the error
  throw err
}

function
errorHandler
(
app
,
key
,
err
)
{
// delete app key
delete
app
[
key
]
// log and adjust err message
const
msg
=
`
${
key
}
${
err
.
message
}
`
debug
(
msg
,
err
)
err
.
message
=
msg
// throw the error
throw
err
}


function createAppConnection (app, url, socketOptions) {
  assert(!app.connection, 'Cannot create connection if it already exists')

  return co(function * () {
    const conn =
      app.connection =
        yield amqplib.connect(url, socketOptions)

    conn.__coworkersCloseHandler = module.exports.closeHandler.bind(null, app)
    conn.__coworkersErrorHandler = module.exports.errorHandler.bind(null, app)
    conn.once('close', conn.__coworkersCloseHandler)
    conn.once('error', conn.__coworkersErrorHandler)
    app.emit('connection:create', conn)

    return conn
  })
}

Create a RabbitMQ connection
@param  {Application} app        coworkers application
@param  {String} url             connection url
@param  {Object} [socketOptions] connection socket options
@return {Promise}                connection promise


function errorHandler (app, err) {
  delete app.connection
  // log and adjust err message
  const msg = `"app.connection" unexpectedly errored: ${err.message}`
  debug(msg, err)
  err.message = msg
  // throw the error
  throw err
}

function
errorHandler
(
app
,
err
)
{
delete
app
.
connection
// log and adjust err message
const
msg
=
`
${
err
.
message
}
`
debug
(
msg
,
err
)
err
.
message
=
msg
// throw the error
throw
err
}


function Application (options) {
  if (!(this instanceof Application)) return new Application(options)
  EventEmitter.call(this)
  // options defaults
  const env = getEnv()
  const COWORKERS_CLUSTER = env.COWORKERS_CLUSTER
  const COWORKERS_QUEUE = env.COWORKERS_QUEUE
  const COWORKERS_QUEUE_WORKER_NUM = env.COWORKERS_QUEUE_WORKER_NUM || 1
  options = options || {}
  // hack: instanceof check while avoiding rabbitmq-schema dep (for now)
  if (options.constructor.name === 'Schema') {
    options = { schema: options }
  }
  defaults(options, {
    cluster: COWORKERS_CLUSTER,
    queueName: COWORKERS_QUEUE,
    queueWorkerNum: COWORKERS_QUEUE_WORKER_NUM
  })
  defaults(options, {
    cluster: true
  })
  // set options on app
  this.schema = options.schema
  this.queueName = options.queueName
  this.queueWorkerNum = options.queueWorkerNum
  // validate options
  if (options.cluster && cluster.isMaster) {
    this.clusterManager = new ClusterManager(this)
    if (exists(options.queueName)) {
      console.warn('warn: "queueName" is not required when clustering is enabled')
    }
  } else {
    assert(exists(options.queueName), '"queueName" is required for consumer processes')
  }
  // app properties
  this.context = {}
  this.middlewares = []
  this.queueMiddlewares = {
    // <queueName>: [middlewares...]
  }
  Object.defineProperty(this, 'queueNames', {
    get () {
      return Object.keys(this.queueMiddlewares)
    }
  })
  /*
  this.connection = <amqplibConnection>
  this.consumerChannel = <amqplibChannel>
  this.publisherChannel = <amqplibChannel>
  this.consumerTags = [...]
  */
}

Initialize a new `Application` inherits from EventEmitter
@constructor
@param  {Object|RabbitSchema} [options|schema] coworkers application options or rabbitmq schema
@param  {RabbitSchema} [options.schema] a RabbitMQ schema created by https://npmjs.com/rabbitmq-schema, optional
@param  {Boolean} [options.cluster] whether to use clustering or not
@param  {String} [options.queueName] queue name which this application is consuming
@api public

Initialize a new Application inherits from EventEmitter


function assertAndConsumeAppQueue (app, queueName) {
  return co(function * () {
    const queue = app.queueMiddlewares[queueName]
    const queueOpts = queue.queueOpts
    const consumeOpts = queue.consumeOpts
    const handler = app.messageHandler(queueName)

    yield app.consumerChannel.assertQueue(queueName, queueOpts)

    return yield app.consumerChannel.consume(queueName, handler, consumeOpts)
  })
}

function assertAndConsumeAppQueue ( app , queueName ) { return co ( function * ( ) { const queue = app . queueMiddlewares [ queueName ] const queueOpts = queue . queueOpts const consumeOpts = queue . consumeOpts const handler = app . messageHandler ( queueName ) yield app . consumerChannel . assertQueue ( queueName , queueOpts ) return yield app . consumerChannel . consume ( queueName , handler , consumeOpts ) } ) }

Start consuming message from app's queues
@param  {Application} app coworkers instance
@param  {String} queueName app queue's name
@return {Promise} consume promise (yields consumer tag)

Start consuming message from app s queues


function parseShardFun (str /* : string */) /* : ShardV1 */ {
  str = str.trim()

  if (str.length === 0) {
    throw new Error('empty shard string')
  }

  if (!str.startsWith(PREFIX)) {
    throw new Error(`invalid or no path prefix: ${str}`)
  }

  const parts = str.slice(PREFIX.length).split('/')
  const version = parts[0]

  if (version !== 'v1') {
    throw new Error(`expect 'v1' version, got '${version}'`)
  }

  const name = parts[1]

  if (!parts[2]) {
    throw new Error('missing param')
  }

  const param = parseInt(parts[2], 10)

  switch (name) {
    case 'prefix':
      return new Prefix(param)
    case 'suffix':
      return new Suffix(param)
    case 'next-to-last':
      return new NextToLast(param)
    default:
      throw new Error(`unkown sharding function: ${name}`)
  }
}

function
parseShardFun
(
str
/* : string */
)
/* : ShardV1 */
{
str
=
str
.
trim
(
)
if
(
str
.
length
===
0
)
{
throw
new
Error
(
'empty shard string'
)
}
if
(
!
str
.
startsWith
(
PREFIX
)
)
{
throw
new
Error
(
`
${
str
}
`
)
}
const
parts
=
str
.
slice
(
PREFIX
.
length
)
.
split
(
'/'
)
const
version
=
parts
[
0
]
if
(
version
!==
'v1'
)
{
throw
new
Error
(
`
${
version
}
`
)
}
const
name
=
parts
[
1
]
if
(
!
parts
[
2
]
)
{
throw
new
Error
(
'missing param'
)
}
const
param
=
parseInt
(
parts
[
2
]
,
10
)
switch
(
name
)
{
case
'prefix'
:
return
new
Prefix
(
param
)
case
'suffix'
:
return
new
Suffix
(
param
)
case
'next-to-last'
:
return
new
NextToLast
(
param
)
default
:
throw
new
Error
(
`
${
name
}
`
)
}
}

Convert a given string to the matching sharding function.

@param {string} str
@returns {ShardV1}

Convert a given string to the matching sharding function .


function isEqualNode (a, b) {
  return (
    // Check if both nodes are ignored.
    (isIgnored(a) && isIgnored(b)) ||
    // Check if both nodes have the same checksum.
    (getCheckSum(a) === getCheckSum(b)) ||
    // Fall back to native isEqualNode check.
    a.isEqualNode(b)
  )
}

Checks if nodes are equal using the following by checking if
they are both ignored, have the same checksum, or have the
same contents.

@param {Node} a - One of the nodes to compare.
@param {Node} b - Another node to compare.

Checks if nodes are equal using the following by checking if they are both ignored have the same checksum or have the same contents .


function dispatch (node, type) {
  // Trigger event for this element if it has a key.
  if (getKey(node)) {
    var ev = document.createEvent('Event')
    var prop = { value: node }
    ev.initEvent(type, false, false)
    Object.defineProperty(ev, 'target', prop)
    Object.defineProperty(ev, 'srcElement', prop)
    node.dispatchEvent(ev)
  }

  // Dispatch to all children.
  var child = node.firstChild
  while (child) child = dispatch(child, type).nextSibling
  return node
}

Recursively trigger an event for a node and it's children.
Only emits events for keyed nodes.

@param {Node} node - the initial node.
@return {Node}

Recursively trigger an event for a node and it s children . Only emits events for keyed nodes .


function join (socket, multiaddr, pub, cb) {
    const log = socket.log = config.log.bind(config.log, '[' + socket.id + ']')

    if (getConfig().strictMultiaddr && !util.validateMa(multiaddr)) {
      joinsTotal.inc()
      joinsFailureTotal.inc()
      return cb('Invalid multiaddr')
    }

    if (getConfig().cryptoChallenge) {
      if (!pub.length) {
        joinsTotal.inc()
        joinsFailureTotal.inc()
        return cb('Crypto Challenge required but no Id provided')
      }

      if (!nonces[socket.id]) {
        nonces[socket.id] = {}
      }

      if (nonces[socket.id][multiaddr]) {
        log('response cryptoChallenge', multiaddr)

        nonces[socket.id][multiaddr].key.verify(
          Buffer.from(nonces[socket.id][multiaddr].nonce),
          Buffer.from(pub, 'hex'),
          (err, ok) => {
            if (err || !ok) {
              joinsTotal.inc()
              joinsFailureTotal.inc()
            }
            if (err) { return cb('Crypto error') } // the errors NEED to be a string otherwise JSON.stringify() turns them into {}
            if (!ok) { return cb('Signature Invalid') }

            joinFinalize(socket, multiaddr, cb)
          })
      } else {
        joinsTotal.inc()
        const addr = multiaddr.split('ipfs/').pop()

        log('do cryptoChallenge', multiaddr, addr)

        util.getIdAndValidate(pub, addr, (err, key) => {
          if (err) { joinsFailureTotal.inc(); return cb(err) }
          const nonce = uuid() + uuid()

          socket.once('disconnect', () => {
            delete nonces[socket.id]
          })

          nonces[socket.id][multiaddr] = { nonce: nonce, key: key }
          cb(null, nonce)
        })
      }
    } else {
      joinsTotal.inc()
      joinFinalize(socket, multiaddr, cb)
    }
  }


function dataType (value) {
  if (!value) return null
  if (value['anyOf'] || value['allOf'] || value['oneOf']) {
    return ''
  }
  if (!value.type) {
    return 'object'
  }
  if (value.type === 'array') {
    return dataType(value.items || {}) + '[]'
  }
  return value.type
}

function dataType ( value ) { if ( ! value ) return null if ( value [ 'anyOf' ] || value [ 'allOf' ] || value [ 'oneOf' ] ) { return '' } if ( ! value . type ) { return 'object' } if ( value . type === 'array' ) { return dataType ( value . items || { } ) + '[]' } return value . type }

Returns a descriptive string for a datatype
@param value
@returns {String} a string like string[] or object[][]


function pd(event) {
    const retv = privateData.get(event);
    console.assert(
        retv != null,
        "'this' is expected an Event object, but got",
        event
    );
    return retv
}

Get private data.
@param {Event} event The event object to get private data.
@returns {PrivateData} The private data of the event.
@private


function defineRedirectDescriptor(key) {
    return {
        get() {
            return pd(this).event[key]
        },
        set(value) {
            pd(this).event[key] = value;
        },
        configurable: true,
        enumerable: true,
    }
}

function defineRedirectDescriptor ( key ) { return { get ( ) { return pd ( this ) . event [ key ] } , set ( value ) { pd ( this ) . event [ key ] = value ; } , configurable : true , enumerable : true , } }

Get the property descriptor to redirect a given property.
@param {string} key Property name to define property descriptor.
@returns {PropertyDescriptor} The property descriptor to redirect the property.
@private

Get the property descriptor to redirect a given property .


function defineCallDescriptor(key) {
    return {
        value() {
            const event = pd(this).event;
            return event[key].apply(event, arguments)
        },
        configurable: true,
        enumerable: true,
    }
}

function defineCallDescriptor ( key ) { return { value ( ) { const event = pd ( this ) . event ; return event [ key ] . apply ( event , arguments ) } , configurable : true , enumerable : true , } }

Get the property descriptor to call a given method property.
@param {string} key Property name to define property descriptor.
@returns {PropertyDescriptor} The property descriptor to call the method property.
@private

Get the property descriptor to call a given method property .


function defineWrapper(BaseEvent, proto) {
    const keys = Object.keys(proto);
    if (keys.length === 0) {
        return BaseEvent
    }

    /** CustomEvent */
    function CustomEvent(eventTarget, event) {
        BaseEvent.call(this, eventTarget, event);
    }

    CustomEvent.prototype = Object.create(BaseEvent.prototype, {
        constructor: { value: CustomEvent, configurable: true, writable: true },
    });

    // Define accessors.
    for (let i = 0; i < keys.length; ++i) {
        const key = keys[i];
        if (!(key in BaseEvent.prototype)) {
            const descriptor = Object.getOwnPropertyDescriptor(proto, key);
            const isFunc = typeof descriptor.value === "function";
            Object.defineProperty(
                CustomEvent.prototype,
                key,
                isFunc
                    ? defineCallDescriptor(key)
                    : defineRedirectDescriptor(key)
            );
        }
    }

    return CustomEvent
}

function
defineWrapper
(
BaseEvent
,
proto
)
{
const
keys
=
Object
.
keys
(
proto
)
;
if
(
keys
.
length
===
0
)
{
return
BaseEvent
}
/** CustomEvent */
function
CustomEvent
(
eventTarget
,
event
)
{
BaseEvent
.
call
(
this
,
eventTarget
,
event
)
;
}
CustomEvent
.
prototype
=
Object
.
create
(
BaseEvent
.
prototype
,
{
constructor
:
{
value
:
CustomEvent
,
configurable
:
true
,
writable
:
true
}
,
}
)
;
// Define accessors.
for
(
let
i
=
0
;
i
<
keys
.
length
;
++
i
)
{
const
key
=
keys
[
i
]
;
if
(
!
(
key
in
BaseEvent
.
prototype
)
)
{
const
descriptor
=
Object
.
getOwnPropertyDescriptor
(
proto
,
key
)
;
const
isFunc
=
typeof
descriptor
.
value
===
"function"
;
Object
.
defineProperty
(
CustomEvent
.
prototype
,
key
,
isFunc
defineCallDescriptor
(
key
)
:
defineRedirectDescriptor
(
key
)
)
;
}
}
return
CustomEvent
}

Define new wrapper class.
@param {Function} BaseEvent The base wrapper class.
@param {Object} proto The prototype of the original event.
@returns {Function} The defined wrapper class.
@private


function getWrapper(proto) {
    if (proto == null || proto === Object.prototype) {
        return Event
    }

    let wrapper = wrappers.get(proto);
    if (wrapper == null) {
        wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto);
        wrappers.set(proto, wrapper);
    }
    return wrapper
}

function getWrapper ( proto ) { if ( proto == null || proto === Object . prototype ) { return Event } let wrapper = wrappers . get ( proto ) ; if ( wrapper == null ) { wrapper = defineWrapper ( getWrapper ( Object . getPrototypeOf ( proto ) ) , proto ) ; wrappers . set ( proto , wrapper ) ; } return wrapper }

Get the wrapper class of a given prototype.
@param {Object} proto The prototype of the original event to get its wrapper.
@returns {Function} The wrapper class.
@private

Get the wrapper class of a given prototype .


function wrapEvent(eventTarget, event) {
    const Wrapper = getWrapper(Object.getPrototypeOf(event));
    return new Wrapper(eventTarget, event)
}

function wrapEvent ( eventTarget , event ) { const Wrapper = getWrapper ( Object . getPrototypeOf ( event ) ) ; return new Wrapper ( eventTarget , event ) }

Wrap a given event to management a dispatching.
@param {EventTarget} eventTarget The event target of this dispatching.
@param {Object} event The event to wrap.
@returns {Event} The wrapper instance.
@private

Wrap a given event to management a dispatching .


function getListeners(eventTarget) {
    const listeners = listenersMap.get(eventTarget);
    if (listeners == null) {
        throw new TypeError(
            "'this' is expected an EventTarget object, but got another value."
        )
    }
    return listeners
}

Get listeners.
@param {EventTarget} eventTarget The event target to get.
@returns {Map<string, ListenerNode>} The listeners.
@private


function defineEventAttributeDescriptor(eventName) {
    return {
        get() {
            const listeners = getListeners(this);
            let node = listeners.get(eventName);
            while (node != null) {
                if (node.listenerType === ATTRIBUTE) {
                    return node.listener
                }
                node = node.next;
            }
            return null
        },

        set(listener) {
            if (typeof listener !== "function" && !isObject(listener)) {
                listener = null; // eslint-disable-line no-param-reassign
            }
            const listeners = getListeners(this);

            // Traverse to the tail while removing old value.
            let prev = null;
            let node = listeners.get(eventName);
            while (node != null) {
                if (node.listenerType === ATTRIBUTE) {
                    // Remove old value.
                    if (prev !== null) {
                        prev.next = node.next;
                    } else if (node.next !== null) {
                        listeners.set(eventName, node.next);
                    } else {
                        listeners.delete(eventName);
                    }
                } else {
                    prev = node;
                }

                node = node.next;
            }

            // Add new value.
            if (listener !== null) {
                const newNode = {
                    listener,
                    listenerType: ATTRIBUTE,
                    passive: false,
                    once: false,
                    next: null,
                };
                if (prev === null) {
                    listeners.set(eventName, newNode);
                } else {
                    prev.next = newNode;
                }
            }
        },
        configurable: true,
        enumerable: true,
    }
}

Get the property descriptor for the event attribute of a given event.
@param {string} eventName The event name to get property descriptor.
@returns {PropertyDescriptor} The property descriptor.
@private

Get the property descriptor for the event attribute of a given event .


function defineCustomEventTarget(eventNames) {
    /** CustomEventTarget */
    function CustomEventTarget() {
        EventTarget.call(this);
    }

    CustomEventTarget.prototype = Object.create(EventTarget.prototype, {
        constructor: {
            value: CustomEventTarget,
            configurable: true,
            writable: true,
        },
    });

    for (let i = 0; i < eventNames.length; ++i) {
        defineEventAttribute(CustomEventTarget.prototype, eventNames[i]);
    }

    return CustomEventTarget
}

function
defineCustomEventTarget
(
eventNames
)
{
/** CustomEventTarget */
function
CustomEventTarget
(
)
{
EventTarget
.
call
(
this
)
;
}
CustomEventTarget
.
prototype
=
Object
.
create
(
EventTarget
.
prototype
,
{
constructor
:
{
value
:
CustomEventTarget
,
configurable
:
true
,
writable
:
true
,
}
,
}
)
;
for
(
let
i
=
0
;
i
<
eventNames
.
length
;
++
i
)
{
defineEventAttribute
(
CustomEventTarget
.
prototype
,
eventNames
[
i
]
)
;
}
return
CustomEventTarget
}

Define a custom EventTarget with event attributes.
@param {string[]} eventNames Event names for event attributes.
@returns {EventTarget} The custom EventTarget.
@private

Define a custom EventTarget with event attributes .


function(fileName, retrying) {
        let file = assets[fileName] || {};
        let key = path.posix.join(uploadPath, fileName);
        let putPolicy = new qiniu.rs.PutPolicy({ scope: bucket + ':' + key });
        let uploadToken = putPolicy.uploadToken(mac);
        let formUploader = new qiniu.form_up.FormUploader(qiniuConfig);
        let putExtra = new qiniu.form_up.PutExtra();

        return new Promise((resolve) => {
          let begin = Date.now();

          formUploader.putFile(
            uploadToken,
            key,
            file.existsAt,
            putExtra,
            function(err, body) {
              // handle upload error
              if (err) {
                // eslint-disable-next-line no-console
                console.log(`Upload file ${fileName} failed: ${err.message || err.name || err.stack}`);
                if (!~retryFiles.indexOf(fileName)) retryFiles.push(fileName);
              } else {
                uploadedFiles++;
              }

              spinner.text = tip(uploadedFiles, retryFiles.length, totalFiles, retrying);
              body.duration = Date.now() - begin;
              resolve(body);
            });
        });
      }

function
(
fileName
,
retrying
)
{
let
file
=
assets
[
fileName
]
||
{
}
;
let
key
=
path
.
posix
.
join
(
uploadPath
,
fileName
)
;
let
putPolicy
=
new
qiniu
.
rs
.
PutPolicy
(
{
scope
:
bucket
+
':'
+
key
}
)
;
let
uploadToken
=
putPolicy
.
uploadToken
(
mac
)
;
let
formUploader
=
new
qiniu
.
form_up
.
FormUploader
(
qiniuConfig
)
;
let
putExtra
=
new
qiniu
.
form_up
.
PutExtra
(
)
;
return
new
Promise
(
(
resolve
)
=>
{
let
begin
=
Date
.
now
(
)
;
formUploader
.
putFile
(
uploadToken
,
key
,
file
.
existsAt
,
putExtra
,
function
(
err
,
body
)
{
// handle upload error
if
(
err
)
{
// eslint-disable-next-line no-console
console
.
log
(
`
${
fileName
}
${
err
.
message
||
err
.
name
||
err
.
stack
}
`
)
;
if
(
!
~
retryFiles
.
indexOf
(
fileName
)
)
retryFiles
.
push
(
fileName
)
;
}
else
{
uploadedFiles
++
;
}
spinner
.
text
=
tip
(
uploadedFiles
,
retryFiles
.
length
,
totalFiles
,
retrying
)
;
body
.
duration
=
Date
.
now
(
)
begin
;
resolve
(
body
)
;
}
)
;
}
)
;
}


function(err) {
        if (err) {
          // eslint-disable-next-line no-console
          console.log('\n');
          return Promise.reject(err);
        }

        if (retryFilesCountDown < 0) retryFilesCountDown = 0;

        // Get batch files
        let _files = retryFiles.splice(
          0,
          batch <= retryFilesCountDown ? batch : retryFilesCountDown
        );
        retryFilesCountDown = retryFilesCountDown - _files.length;

        if (_files.length) {
          return Promise.all(
            _files.map(file => performUpload(file, true))
          ).then(() => retryFailedFiles(), retryFailedFiles);
        } else {
          if (retryFiles.length) {
            return Promise.reject(new Error('File uploaded failed'));
          } else {
            return Promise.resolve();
          }
        }
      }

function
(
err
)
{
if
(
err
)
{
// eslint-disable-next-line no-console
console
.
log
(
'\n'
)
;
return
Promise
.
reject
(
err
)
;
}
if
(
retryFilesCountDown
<
0
)
retryFilesCountDown
=
0
;
// Get batch files
let
_files
=
retryFiles
.
splice
(
0
,
batch
<=
retryFilesCountDown
batch
:
retryFilesCountDown
)
;
retryFilesCountDown
=
retryFilesCountDown
_files
.
length
;
if
(
_files
.
length
)
{
return
Promise
.
all
(
_files
.
map
(
file
=>
performUpload
(
file
,
true
)
)
)
.
then
(
(
)
=>
retryFailedFiles
(
)
,
retryFailedFiles
)
;
}
else
{
if
(
retryFiles
.
length
)
{
return
Promise
.
reject
(
new
Error
(
'File uploaded failed'
)
)
;
}
else
{
return
Promise
.
resolve
(
)
;
}
}
}


function (ev) {
    var nextPointers

    if (!ev.defaultPrevented) {
      if (_preventDefault) {
        ev.preventDefault()
      }

      if (!_mouseDown) {
        _mouseDown = true

        nextPointers = utils.clone(_currPointers) // See [2]
        nextPointers['mouse'] = [ev.pageX, ev.pageY]

        if (!_started) {
          _started = true
          _handlers.start(nextPointers)
        }

        _currPointers = nextPointers
      }
    }
  }

function
(
ev
)
{
var
nextPointers
if
(
!
ev
.
defaultPrevented
)
{
if
(
_preventDefault
)
{
ev
.
preventDefault
(
)
}
if
(
!
_mouseDown
)
{
_mouseDown
=
true
nextPointers
=
utils
.
clone
(
_currPointers
)
// See [2]
nextPointers
[
'mouse'
]
=
[
ev
.
pageX
,
ev
.
pageY
]
if
(
!
_started
)
{
_started
=
true
_handlers
.
start
(
nextPointers
)
}
_currPointers
=
nextPointers
}
}
}


function teamcity(runner) {
	Base.call(this, runner);
	var stats = this.stats;
	var flowId = document.title || new Date().getTime();

	runner.on('suite', function (suite) {
		if (suite.root) return;
		suite.startDate = new Date();
		log('##teamcity[testSuiteStarted name=\'' + escape(suite.title) + '\' flowId=\'' + flowId + '\']');
	});

	runner.on('test', function (test) {
		log('##teamcity[testStarted name=\'' + escape(test.title) + '\' flowId=\'' + flowId + '\'  captureStandardOutput=\'true\']');
	});

	runner.on('fail', function (test, err) {
		log('##teamcity[testFailed name=\'' + escape(test.title) + '\' flowId=\'' + flowId + '\' message=\'' + escape(err.message) + '\' captureStandardOutput=\'true\' details=\'' + escape(err.stack) + '\']');
	});

	runner.on('pending', function (test) {
		log('##teamcity[testIgnored name=\'' + escape(test.title) + '\' flowId=\'' + flowId + '\' message=\'pending\']');
	});

	runner.on('test end', function (test) {
		log('##teamcity[testFinished name=\'' + escape(test.title) + '\' flowId=\'' + flowId + '\' duration=\'' + test.duration + '\']');
	});

	runner.on('suite end', function (suite) {
		if (suite.root) return;
		log('##teamcity[testSuiteFinished name=\'' + escape(suite.title) + '\' duration=\'' + (new Date() - suite.startDate) + '\' flowId=\'' + flowId + '\']');
	});

	runner.on('end', function () {
		log('##teamcity[testSuiteFinished name=\'mocha.suite\' duration=\'' + stats.duration + '\' flowId=\'' + flowId + '\']');
	});
}

Initialize a new `Teamcity` reporter for the browser.

@param {Runner} runner
@param {options} options
@api public

Initialize a new Teamcity reporter for the browser .


function convert(integer) {
  var str = Number(integer).toString(16);
  return str.length === 1 ? '0' + str : str;
}

function convert ( integer ) { var str = Number ( integer ) . toString ( 16 ) ; return str . length === 1 ? '0' + str : str ; }


function parse(text, options) {
  options = Object.assign({}, { relaxed: true }, options);

  // relaxed implies not strict
  if (typeof options.relaxed === 'boolean') options.strict = !options.relaxed;
  if (typeof options.strict === 'boolean') options.relaxed = !options.strict;

  return JSON.parse(text, (key, value) => deserializeValue(this, key, value, options));
}

function
parse
(
text
,
options
)
{
options
=
Object
.
assign
(
{
}
,
{
relaxed
:
true
}
,
options
)
;
// relaxed implies not strict
if
(
typeof
options
.
relaxed
===
'boolean'
)
options
.
strict
=
!
options
.
relaxed
;
if
(
typeof
options
.
strict
===
'boolean'
)
options
.
relaxed
=
!
options
.
strict
;
return
JSON
.
parse
(
text
,
(
key
,
value
)
=>
deserializeValue
(
this
,
key
,
value
,
options
)
)
;
}

Parse an Extended JSON string, constructing the JavaScript value or object described by that
string.

@param {string} text
@param {object} [options] Optional settings
@param {boolean} [options.relaxed=true] Attempt to return native JS types where possible, rather than BSON types (if true)
@return {object}

@example
const EJSON = require('mongodb-extjson');
const text = '{ "int32": { "$numberInt": "10" } }';

// prints { int32: { [String: '10'] _bsontype: 'Int32', value: '10' } }
console.log(EJSON.parse(text, { relaxed: false }));

// prints { int32: 10 }
console.log(EJSON.parse(text));

Parse an Extended JSON string constructing the JavaScript value or object described by that string .


function stringify(value, replacer, space, options) {
  if (space != null && typeof space === 'object') (options = space), (space = 0);
  if (replacer != null && typeof replacer === 'object')
    (options = replacer), (replacer = null), (space = 0);
  options = Object.assign({}, { relaxed: true }, options);

  const doc = Array.isArray(value)
    ? serializeArray(value, options)
    : serializeDocument(value, options);

  return JSON.stringify(doc, replacer, space);
}

function stringify ( value , replacer , space , options ) { if ( space != null && typeof space === 'object' ) ( options = space ) , ( space = 0 ) ; if ( replacer != null && typeof replacer === 'object' ) ( options = replacer ) , ( replacer = null ) , ( space = 0 ) ; options = Object . assign ( { } , { relaxed : true } , options ) ; const doc = Array . isArray ( value ) ? serializeArray ( value , options ) : serializeDocument ( value , options ) ; return JSON . stringify ( doc , replacer , space ) ; }

Converts a BSON document to an Extended JSON string, optionally replacing values if a replacer
function is specified or optionally including only the specified properties if a replacer array
is specified.

@param {object} value The value to convert to extended JSON
@param {function|array} [replacer] A function that alters the behavior of the stringification process, or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of the value object to be included in the JSON string. If this value is null or not provided, all properties of the object are included in the resulting JSON string
@param {string|number} [space] A String or Number object that's used to insert white space into the output JSON string for readability purposes.
@param {object} [options] Optional settings
@param {boolean} [options.relaxed=true] Enabled Extended JSON's `relaxed` mode
@returns {string}

@example
const EJSON = require('mongodb-extjson');
const Int32 = require('mongodb').Int32;
const doc = { int32: new Int32(10) };

// prints '{"int32":{"$numberInt":"10"}}'
console.log(EJSON.stringify(doc, { relaxed: false }));

// prints '{"int32":10}'
console.log(EJSON.stringify(doc));

Converts a BSON document to an Extended JSON string optionally replacing values if a replacer function is specified or optionally including only the specified properties if a replacer array is specified .


function serialize(bson, options) {
  options = options || {};
  return JSON.parse(stringify(bson, options));
}

function serialize ( bson , options ) { options = options || { } ; return JSON . parse ( stringify ( bson , options ) ) ; }

Serializes an object to an Extended JSON string, and reparse it as a JavaScript object.

@param {object} bson The object to serialize
@param {object} [options] Optional settings passed to the `stringify` function
@return {object}

Serializes an object to an Extended JSON string and reparse it as a JavaScript object .


function makeDefineVirtualModule(loader, load, addDep, args){

		function namer(loadName){
			var baseName = loadName.substr(0, loadName.indexOf("!"));

			return function(part, plugin){
				return baseName + "-" + part + (plugin ? ("." + plugin) : "");
			};
		}

		function addresser(loadAddress){
			return function(part, plugin){
				var base = loadAddress + "." + part;
				return base + (plugin ? ("." + plugin) : "");
			};
		}

		var name = namer(load.name);
		var address = addresser(load.address);

		// A function for disposing of modules during live-reload
		var disposeModule = function(moduleName){
			if(loader.has(moduleName))
				loader["delete"](moduleName);
		};
		if(loader.liveReloadInstalled || loader.has("live-reload")) {
			loader.import("live-reload", { name: module.id }).then(function(reload){
				disposeModule = reload.disposeModule || disposeModule;
			});
		}

		return function(defn){
			if(defn.condition) {
				if(defn.arg) {
					// viewModel
					args.push(defn.arg);
				}

				var moduleName = typeof defn.name === "function" ?
					defn.name(name) : name(defn.name);
				var moduleAddress = typeof defn.address === "function" ?
					defn.address(address) : address(defn.address);

				// from="something.js"
				if(defn.from) {
					addDep(defn.from, false);
				}

				else if(defn.getLoad) {
					var moduleSource = defn.source();
					return defn.getLoad(moduleName).then(function(newLoad){
						moduleName = newLoad.name || moduleName;

						// For live-reload
						disposeModule(moduleName);

						loader.define(moduleName, moduleSource, {
							metadata: newLoad.metadata,
							address: moduleAddress
						});
						addDep(moduleName);
					});
				}

				else if(defn.source) {
					addDep(moduleName);

					if(loader.has(moduleName))
						loader["delete"](moduleName);

					if(typeof defn.source !== "string") {
						return Promise.resolve(defn.source)
							.then(function(source){
								loader.define(moduleName, source, {
									address: address(defn.name),
									metadata: defn.metadata
								});
							});
					}

					return loader.define(moduleName, defn.source, {
						address: address(defn.name)
					});
				}
			}
		}
	}

Make functions that will define virtual modules


function getFilename(name) {
		var hash = name.indexOf('#');
		var bang = name.indexOf('!');

		return name.slice(hash < bang ? (hash + 1) : 0, bang);
	}

function getFilename ( name ) { var hash = name . indexOf ( '#' ) ; var bang = name . indexOf ( '!' ) ; return name . slice ( hash < bang ? ( hash + 1 ) : 0 , bang ) ; }


function matchSemver (myProtocol, senderProtocol, callback) {
  const mps = myProtocol.split('/')
  const sps = senderProtocol.split('/')
  const myName = mps[1]
  const myVersion = mps[2]

  const senderName = sps[1]
  const senderVersion = sps[2]

  if (myName !== senderName) {
    return callback(null, false)
  }
  // does my protocol satisfy the sender?
  const valid = semver.satisfies(myVersion, '~' + senderVersion)

  callback(null, valid)
}

function
matchSemver
(
myProtocol
,
senderProtocol
,
callback
)
{
const
mps
=
myProtocol
.
split
(
'/'
)
const
sps
=
senderProtocol
.
split
(
'/'
)
const
myName
=
mps
[
1
]
const
myVersion
=
mps
[
2
]
const
senderName
=
sps
[
1
]
const
senderVersion
=
sps
[
2
]
if
(
myName
!==
senderName
)
{
return
callback
(
,
false
)
}
// does my protocol satisfy the sender?
const
valid
=
semver
.
satisfies
(
myVersion
,
'~'
+
senderVersion
)
callback
(
,
valid
)
}

Match protocols using semver `~` matching.

@param {string} myProtocol
@param {string} senderProtocol
@param {function(Error, boolean)} callback
@returns {undefined}
@type {matchHandler}

Match protocols using semver ~ matching .


function matchExact (myProtocol, senderProtocol, callback) {
  const result = myProtocol === senderProtocol
  callback(null, result)
}

function matchExact ( myProtocol , senderProtocol , callback ) { const result = myProtocol === senderProtocol callback ( null , result ) }

Match protocols exactly.

@param {string} myProtocol
@param {string} senderProtocol
@param {function(Error, boolean)} callback
@returns {undefined}
@type {matchHandler}


function diffArrays(arr1, arr2) {
        if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
            return true;
        }
        if (arr1.length !== arr2.length) {
            return true;
        }
        for (var i = 0, len = arr1.length; i < len; i++) {
            if (arr1[i] !== arr2[i]) {
                return true;
            }
        }
        return false;
    }

function diffArrays ( arr1 , arr2 ) { if ( ! Array . isArray ( arr1 ) || ! Array . isArray ( arr2 ) ) { return true ; } if ( arr1 . length !== arr2 . length ) { return true ; } for ( var i = 0 , len = arr1 . length ; i < len ; i ++ ) { if ( arr1 [ i ] !== arr2 [ i ] ) { return true ; } } return false ; }

Diff two arrays.
@param {Array} arr1 - The first array
@param {Array} arr2 - The second array
@return {boolean} true if the arrays are different, false otherwise


function getSourceRuleString(sourceRule) {
        function getRuleString(rule) {
            if (rule.length === 1) {
                return '"' + rule + '"';
            }
            return '("' + rule.join('" AND "') + '")';
        }

        return sourceRule.map(getRuleString).join(' OR ');
    }

function
getSourceRuleString
(
sourceRule
)
{
function
getRuleString
(
rule
)
{
if
(
rule
.
length
===
1
)
{
return
'"'
+
rule
+
'"'
;
}
return
'("'
+
rule
.
join
(
'" AND "'
)
+
'")'
;
}
return
sourceRule
.
map
(
getRuleString
)
.
join
(
' OR '
)
;
}

Turn the rules for a sourceType into a human-readable string
@param {string[][]} sourceRule - The sourceType rules
@return {string} the readable rules

Turn the rules for a sourceType into a human - readable string


function getTimelineArgs(scope) {
        var timelineArgs = {sourceType: scope.sourceType};
        // if this is a valid sourceType...
        if (rules.hasOwnProperty(scope.sourceType)) {
            var sourceRules = rules[scope.sourceType];
            var valid = false;
            // Loop over the required args for the source
            for (var i = 0, len = sourceRules.length; i < len; i++) {
                var rule = sourceRules[i];
                var params = {};
                for (var j = 0, ruleLen = rule.length; j < ruleLen; j++) {
                    if (angular.isDefined(scope[rule[j]])) { // if the rule is present, add it to the params collection
                        params[rule[j]] = scope[rule[j]];
                    }
                }
                if (Object.keys(params).length === ruleLen) {
                    angular.merge(timelineArgs, params);
                    valid = true;
                    break;
                }
            }
            if (!valid) {
                throw new TimelineArgumentException(scope.sourceType, 'args: ' + getSourceRuleString(sourceRules));
            }
        } else {
            throw new TimelineArgumentException(scope.sourceType, 'unknown type');
        }

        return timelineArgs;
    }

Get the arguments for the timeline based on parameter rules
@param {Object} scope - The directive scope
@return {Object} Key-Value arg object


function(method,klass){
    while(!!klass){
        var key = null,
            pro = klass.prototype;
        // find method in current klass
        Object.keys(pro).some(function(name){
            if (method===pro[name]){
                key = name;
                return !0;
            }
        });
        // method finded in klass
        if (key!=null){
            return {
                name:key,
                klass:klass
            };
        }
        klass = klass.supor;
    }
}

function
(
method
,
klass
)
{
while
(
!
!
klass
)
{
var
key
=
,
pro
=
klass
.
prototype
;
// find method in current klass
Object
.
keys
(
pro
)
.
some
(
function
(
name
)
{
if
(
method
===
pro
[
name
]
)
{
key
=
name
;
return
!
0
;
}
}
)
;
// method finded in klass
if
(
key
!=
)
{
return
{
name
:
key
,
klass
:
klass
}
;
}
klass
=
klass
.
supor
;
}
}


function(config){
    _logger.info('begin dump files ...');
    var map = {};
    ['fileInclude','fileExclude'].forEach(function(name){
        var value = config[name];
        if (!!value){
            if (typeof value==='string'){
                var reg = new RegExp(value,'i');
                config[name] = function(file){
                    return reg.test(file);
                };
            }else if(!!value.test){
                config[name] = function(file){
                    return value.test(file);
                }
            }
        }
        if (!_util.isFunction(config[name])){
            var flag = name!=='fileExclude';
            config[name] = function(file){
                return flag;
            };
        }
    });
    (config.resRoot||'').split(',').forEach(function(dir){
        if (!dir){
            return;
        }
        var ret = _fs.lsfile(dir,function(name,file){
            return !config.fileExclude(file)&&
                config.fileInclude(file);
        });
        ret.forEach(function(v){
            map[v] = v.replace(config.webRoot,config.temp);
        });
    });
    _logger.debug('package file map -> %j',map);
    Object.keys(map).forEach(function(src){
        var dst = map[src];
        _fs.copy(src,dst,function(a){
            _logger.info('copy file %s',a);
        });
    });
}

function
(
config
)
{
_logger
.
info
(
'begin dump files ...'
)
;
var
map
=
{
}
;
[
'fileInclude'
,
'fileExclude'
]
.
forEach
(
function
(
name
)
{
var
value
=
config
[
name
]
;
if
(
!
!
value
)
{
if
(
typeof
value
===
'string'
)
{
var
reg
=
new
RegExp
(
value
,
'i'
)
;
config
[
name
]
=
function
(
file
)
{
return
reg
.
test
(
file
)
;
}
;
}
else
if
(
!
!
value
.
test
)
{
config
[
name
]
=
function
(
file
)
{
return
value
.
test
(
file
)
;
}
}
}
if
(
!
_util
.
isFunction
(
config
[
name
]
)
)
{
var
flag
=
name
!==
'fileExclude'
;
config
[
name
]
=
function
(
file
)
{
return
flag
;
}
;
}
}
)
;
(
config
.
resRoot
||
''
)
.
split
(
','
)
.
forEach
(
function
(
dir
)
{
if
(
!
dir
)
{
return
;
}
var
ret
=
_fs
.
lsfile
(
dir
,
function
(
name
,
file
)
{
return
!
config
.
fileExclude
(
file
)
&&
config
.
fileInclude
(
file
)
;
}
)
;
ret
.
forEach
(
function
(
v
)
{
map
[
v
]
=
v
.
replace
(
config
.
webRoot
,
config
.
temp
)
;
}
)
;
}
)
;
_logger
.
debug
(
'package file map -> %j'
,
map
)
;
Object
.
keys
(
map
)
.
forEach
(
function
(
src
)
{
var
dst
=
map
[
src
]
;
_fs
.
copy
(
src
,
dst
,
function
(
a
)
{
_logger
.
info
(
'copy file %s'
,
a
)
;
}
)
;
}
)
;
}

dump files to temporary directory
@param  {Object} config - config object
@return {Void}


function(config){
    _logger.info('begin zip package ...');
    var cmd = [
        'java','-jar',
        JSON.stringify(config.zip),
        JSON.stringify(config.temp),
        JSON.stringify(config.output)
    ].join(' ');
    _logger.debug('do command: %s',cmd);
    exec(cmd,function(error,stdout,stderr){
        if (error){
            _logger.error('zip package error for reason:\n%s',error.stack);
            process.abort();
            return;
        }
        if (stdout){
            _logger.info(stdout);
        }
        if (stderr){
            _logger.error(stderr);
        }
        uploadToServer(config);
    });
}

function
(
config
)
{
_logger
.
info
(
'begin zip package ...'
)
;
var
cmd
=
[
'java'
,
'-jar'
,
JSON
.
stringify
(
config
.
zip
)
,
JSON
.
stringify
(
config
.
temp
)
,
JSON
.
stringify
(
config
.
output
)
]
.
join
(
' '
)
;
_logger
.
debug
(
'do command: %s'
,
cmd
)
;
exec
(
cmd
,
function
(
error
,
stdout
,
stderr
)
{
if
(
error
)
{
_logger
.
error
(
'zip package error for reason:\n%s'
,
error
.
stack
)
;
process
.
abort
(
)
;
return
;
}
if
(
stdout
)
{
_logger
.
info
(
stdout
)
;
}
if
(
stderr
)
{
_logger
.
error
(
stderr
)
;
}
uploadToServer
(
config
)
;
}
)
;
}

zip files package
@param  {Object} config - config object
@return {Void}


function(config){
    if (!_fs.exist(config.output)){
        return abortProcess(
            config,'no package to be uploaded'
        );
    }
    _logger.info('begin build upload form ...');
    var form = new FormData();
    var ex = _util.merge(
        {
            version: '0.1',
            platform: 'ios&android'
        },
        config.extension
    );
    // build form
    Object.keys(ex).forEach(function(name){
        form.append(name,ex[name]);
    });
    form.append('token',config.token);
    form.append('resID',config.appid);
    form.append('appID',config.nativeId);
    form.append('userData',JSON.stringify({domains:config.domains}));
    form.append('zip',fs.createReadStream(config.output));
    // submit form
    _logger.info('begin upload package to web cache server ...');
    form.submit(config.api,function(err,res){
        if (err){
            return abortProcess(
                config,'upload failed for reason:\n%s',err.stack
            );
        }
        // chunk response data
        var arr = [];
        res.on('data',function(chunk){
            arr.push(chunk);
        });
        // parse response result
        res.on('end',function(){
            var ret = null,
                txt = arr.join('');
            try{
                ret = JSON.parse(txt);
            }catch(ex){
                // result error
                return abortProcess(
                    config,'[%s] %s\n%s',
                    res.statusCode,txt,ex.stack
                );
            }
            if (!!ret&&ret.code==0){
                clearTemp(config);
                _logger.info('package upload success');
                config.ondone();
            }else{
                return abortProcess(
                    config,'package upload failed for reason: [%s] %s',
                    res.statusCode,txt
                );
            }
        });
        res.resume();
    });
}

upload package to web cache server
@param  {Object} config - config object
@return {Void}


function(config){
    _logger.info('clear temporary directory and files');
    _fs.rmdir(config.temp);
    _fs.rm(config.output);
}

function
(
config
)
{
_logger
.
info
(
'clear temporary directory and files'
)
;
_fs
.
rmdir
(
config
.
temp
)
;
_fs
.
rm
(
config
.
output
)
;
}

clear temporary infomation
@param  {Object} config - config object
@return {Void}


function(config){
    var args = [].slice.call(arguments,0);
    clearTemp(args.shift());
    _logger.error.apply(_logger,args);
    process.abort();
}

function ( config ) { var args = [ ] . slice . call ( arguments , 0 ) ; clearTemp ( args . shift ( ) ) ; _logger . error . apply ( _logger , args ) ; process . abort ( ) ; }

abort process when error
@param  {Object} config - config object
@return {Void}


function(content){
        var ret,
            handler = function(map){
                ret = map;
            },
            sandbox = {NEJ:{deps:handler, config:handler}};
        // detect dep config
        try{
            //eval(content);
            vm.createContext(sandbox);
            vm.runInContext(content,sandbox);
        }catch(ex){
            // ignore
        }
        return ret||null;
    }

function
(
content
)
{
var
ret
,
handler
=
function
(
map
)
{
ret
=
map
;
}
,
sandbox
=
{
NEJ
:
{
deps
:
handler
,
config
:
handler
}
}
;
// detect dep config
try
{
//eval(content);
vm
.
createContext
(
sandbox
)
;
vm
.
runInContext
(
content
,
sandbox
)
;
}
catch
(
ex
)
{
// ignore
}
return
ret
||
;
}


function(patform,deps,func){
        var args = exports.formatARG.apply(
            exports,arguments
        );
        if (!this.patches){
            this.patches = [];
        }
        // illegal patch
        if (!args[0]){
            return;
        }
        // cache patch config
        this.patches.push({
            expression:args[0],
            dependency:args[1],
            source:(args[2]||'').toString()
        });
    }

function
(
patform
,
deps
,
func
)
{
var
args
=
exports
.
formatARG
.
apply
(
exports
,
arguments
)
;
if
(
!
this
.
patches
)
{
this
.
patches
=
[
]
;
}
// illegal patch
if
(
!
args
[
0
]
)
{
return
;
}
// cache patch config
this
.
patches
.
push
(
{
expression
:
args
[
0
]
,
dependency
:
args
[
1
]
,
source
:
(
args
[
2
]
||
''
)
.
toString
(
)
}
)
;
}


function(content){
        // emulate NEJ patch env
        var ret = {},
            sandbox = {
                NEJ:{
                    patch:_doPatch.bind(ret)
                }
            };
        // eval content for nej patch check
        try{
            //eval(util.format('(%s)();',content));
            vm.createContext(sandbox);
            vm.runInContext(util.format('(%s)();',content),sandbox);
        }catch(ex){
            // ignore
        }
        return ret.patches;
    }

function
(
content
)
{
// emulate NEJ patch env
var
ret
=
{
}
,
sandbox
=
{
NEJ
:
{
patch
:
_doPatch
.
bind
(
ret
)
}
}
;
// eval content for nej patch check
try
{
//eval(util.format('(%s)();',content));
vm
.
createContext
(
sandbox
)
;
vm
.
runInContext
(
util
.
format
(
'(%s)();'
,
content
)
,
sandbox
)
;
}
catch
(
ex
)
{
// ignore
}
return
ret
.
patches
;
}


function(uri,deps,func){
        var args = exports.formatARG.apply(
            exports,arguments
        );
        this.isNEJ = !0;
        this.dependency = args[1];
        this.source = (args[2]||'').toString();
    }

function ( uri , deps , func ) { var args = exports . formatARG . apply ( exports , arguments ) ; this . isNEJ = ! 0 ; this . dependency = args [ 1 ] ; this . source = ( args [ 2 ] || '' ) . toString ( ) ; }


function(event){
        if (event.type=='script'){
            event.value = this._checkResInScript(
                event.file,
                event.content,
                options
            );
        }
    }

function ( event ) { if ( event . type == 'script' ) { event . value = this . _checkResInScript ( event . file , event . content , options ) ; } }


function(uri,config){
        return this._formatURI(uri,{
            fromPage:config.fromPage,
            pathRoot:config.output,
            webRoot:config.webRoot
        });
    }

function ( uri , config ) { return this . _formatURI ( uri , { fromPage : config . fromPage , pathRoot : config . output , webRoot : config . webRoot } ) ; }


function(uri,config){
        uri = uri.replace(
            config.srcRoot,
            config.outHtmlRoot
        );
        return this._formatURI(uri,{
            pathRoot:config.output,
            webRoot:config.webRoot,
            domain:config.mdlRoot
        });
    }

function ( uri , config ) { uri = uri . replace ( config . srcRoot , config . outHtmlRoot ) ; return this . _formatURI ( uri , { pathRoot : config . output , webRoot : config . webRoot , domain : config . mdlRoot } ) ; }


function(uri,config){
        return uri.replace(
            config.srcRoot,
            config.outHtmlRoot
        ).replace(
            config.webRoot,'/'
        );
    }

function ( uri , config ) { return uri . replace ( config . srcRoot , config . outHtmlRoot ) . replace ( config . webRoot , '/' ) ; }


function global(map){
    Object.keys(map).forEach(function(key){
        var file = map[key],
            arr = file.split('#'),
            mdl = require('./lib/'+arr[0]+'.js');
        // for util/logger#Logger
        if (!!arr[1]){
            // for util/logger#level,logger
            var brr = arr[1].split(',');
            if (brr.length>1){
                var ret = {};
                brr.forEach(function(name){
                    ret[name] = mdl[name];
                });
                mdl = ret;
            }else{
                mdl = mdl[brr[0]];
            }
        }
        exports[key] = mdl;
    });
}

function
global
(
map
)
{
Object
.
keys
(
map
)
.
forEach
(
function
(
key
)
{
var
file
=
map
[
key
]
,
arr
=
file
.
split
(
'#'
)
,
mdl
=
require
(
'./lib/'
+
arr
[
0
]
+
'.js'
)
;
// for util/logger#Logger
if
(
!
!
arr
[
1
]
)
{
// for util/logger#level,logger
var
brr
=
arr
[
1
]
.
split
(
','
)
;
if
(
brr
.
length
>
1
)
{
var
ret
=
{
}
;
brr
.
forEach
(
function
(
name
)
{
ret
[
name
]
=
mdl
[
name
]
;
}
)
;
mdl
=
ret
;
}
else
{
mdl
=
mdl
[
brr
[
0
]
]
;
}
}
exports
[
key
]
=
mdl
;
}
)
;
}


function fmix32 (hash) {
    hash ^= hash >>> 16
    hash = multiply(hash, 0x85ebca6b)
    hash ^= hash >>> 13
    hash = multiply(hash, 0xc2b2ae35)
    hash ^= hash >>> 16
    return hash
}

function fmix32 ( hash ) { hash ^= hash >>> 16 hash = multiply ( hash , 0x85ebca6b ) hash ^= hash >>> 13 hash = multiply ( hash , 0xc2b2ae35 ) hash ^= hash >>> 16 return hash }

We don't use `>>> 0`. We let the values negate. The only use of addition in Murmur uses the result of a multiplication, which will be converted to unsigned integer by our 16-bit at a time multiplication.

We don t use >>> 0 . We let the values negate . The only use of addition in Murmur uses the result of a multiplication which will be converted to unsigned integer by our 16 - bit at a time multiplication .


function fmix32_pure (hash) {
    hash = (hash ^ (hash >>> 16)) >>> 0
    hash = multiply(hash, 0x85ebca6b)
    hash = (hash ^ (hash >>> 13)) >>> 0
    hash = multiply(hash, 0xc2b2ae35)
    hash = (hash ^ (hash >>> 16)) >>> 0
    return hash
}

function fmix32_pure ( hash ) { hash = ( hash ^ ( hash >>> 16 ) ) >>> 0 hash = multiply ( hash , 0x85ebca6b ) hash = ( hash ^ ( hash >>> 13 ) ) >>> 0 hash = multiply ( hash , 0xc2b2ae35 ) hash = ( hash ^ ( hash >>> 16 ) ) >>> 0 return hash }

With this, unused, function we always make sure we have an unsigned integer value, but it's not absolutely necessary. We're only interested in the integer value when we perform addition or write the value to our buffer. We do not do this within Murmur's mix function. I'm leaving it in place for a benchmark where I can gauge the cost of `>>> 0`.

With this unused function we always make sure we have an unsigned integer value but it s not absolutely necessary . We re only interested in the integer value when we perform addition or write the value to our buffer . We do not do this within Murmur s mix function . I m leaving it in place for a benchmark where I can gauge the cost of >>> 0 .


function bindKeys (scope, obj, def, parentNode, path) {
  var meta, key

  if (typeof obj !== 'object' || obj === null)
    throw new TypeError(
      'Invalid type of value "' + obj + '", object expected.')

  Object.defineProperty(obj, memoizedObjectKey, {
    value: {},
    configurable: true
  })

  Object.defineProperty(obj, metaKey, {
    value: {},
    configurable: true
  })

  meta = obj[metaKey]

  for (key in def) {
    meta[key] = {
      keyPath: {
        key: key,
        root: path.root,
        target: obj
      },
      activeNodes: [],
      previousValues: [],

      // Assign the current marker relevant to this object. This is in case of
      // arrays of objects.
      currentMarker: def[key][markerKey],

      valueIsArray: null
    }

    bindKey(scope, obj, def, key, parentNode)
  }
}

Define getters & setters. This function is the internal entry point to a lot
of functionality.

@param {*} [scope]
@param {Object} obj
@param {Object} def
@param {Node} parentNode - This is not the same as
`Node.prototype.parentNode`, this is the internal parent node if the key
was bound to its parent.
@param {Array} path

Define getters & setters . This function is the internal entry point to a lot of functionality .


function parentSetter (x) {
    var previousValue = memoizedObject[key]
    var returnValue

    // Optimistically set the memoized value, so it persists even if an error
    // occurs after this point.
    memoizedObject[key] = x

    // Check for no-op.
    if (x === previousValue) return x

    // Need to qualify this check for non-empty value.
    if (definition && x !== null && x !== void 0)
      bindKeys(scope, x, definition, parentNode, keyPath)

    else if (change) {
      returnValue = change(parentNode, x,
        previousValue === void 0 ? null : previousValue, keyPath)
      if (returnValue !== void 0)
        changeValue(parentNode, returnValue, branch[replaceAttributeKey])
    }

    return x
  }

Special case for binding same node as parent.

Special case for binding same node as parent .


function replaceNode (value, previousValue, i) {
    var activeNode = activeNodes[i]
    var currentNode = node
    var returnValue

    // Cast values to null if undefined.
    if (value === void 0) value = null
    if (previousValue === void 0) previousValue = null

    // If value is null, just remove the Node.
    if (value === null) {
      removeNode(null, previousValue, i)
      return null
    }

    if (valueIsArray) keyPath.index = i
    else delete keyPath.index

    previousValues[i] = value

    if (definition) {
      if (activeNode) removeNode(value, previousValue, i)
      currentNode = processNodes(scope, node, definition)
      keyPath.target = valueIsArray ? value[i] : value
      bindKeys(scope, value, definition, currentNode, keyPath)
      if (mount) {
        keyPath.target = value
        mount(currentNode, value, null, keyPath)
      }
    }

    else {
      currentNode = activeNode || node.cloneNode(true)

      if (change) {
        returnValue = change(currentNode, value, previousValue, keyPath)
        if (returnValue !== void 0)
          changeValue(currentNode, returnValue, branch[replaceAttributeKey])
      }
      else {
        // Add default update behavior. Note that this event does not get
        // removed, since it is assumed that it will be garbage collected.
        if (previousValue === null &&
          ~updateTags.indexOf(currentNode.tagName))
          currentNode.addEventListener('input',
            updateChange(branch[replaceAttributeKey], keyPath, key))

        changeValue(currentNode, value, branch[replaceAttributeKey])
      }

      // Do not actually add an element to the DOM if it's only a change
      // between non-empty values.
      if (activeNode) return null
    }

    activeNodes[i] = currentNode

    return currentNode
  }

The return value of this function is a Node to be added, otherwise null.

The return value of this function is a Node to be added otherwise null .


function pop () {
    var i = this.length - 1
    var previousValue = previousValues[i]
    var value = Array.prototype.pop.call(this)

    removeNode(null, previousValue, i)
    previousValues.length = activeNodes.length = this.length

    return value
  }

function pop ( ) { var i = this . length - 1 var previousValue = previousValues [ i ] var value = Array . prototype . pop . call ( this ) removeNode ( null , previousValue , i ) previousValues . length = activeNodes . length = this . length return value }

Below are optimized array mutator methods. They have to exist within this closure. Note that the native implementations of these methods do not trigger setter functions on array indices.

Below are optimized array mutator methods . They have to exist within this closure . Note that the native implementations of these methods do not trigger setter functions on array indices .


function changeValue (node, value, attribute) {
  var firstChild

  switch (attribute) {
  case 'textContent':
    firstChild = node.firstChild
    if (firstChild && !firstChild.nextSibling &&
      firstChild.nodeType === TEXT_NODE)
      firstChild.textContent = value
    else node.textContent = value
    break
  case 'checked':
    node.checked = Boolean(value)
    break
  case 'value':
    // Prevent some misbehavior in certain browsers when setting a value to
    // itself, i.e. text caret not in the correct position.
    if (node.value !== value) node.value = value
    break
  default:
    break
  }
}

Default behavior when a return value is given for a change function.

Default behavior when a return value is given for a change function .


function getNextNode (index, activeNodes) {
  var i, j, nextNode

  for (i = index, j = activeNodes.length; i < j; i++)
    if (activeNodes[i]) {
      nextNode = activeNodes[i]
      break
    }

  return nextNode
}

function getNextNode ( index , activeNodes ) { var i , j , nextNode for ( i = index , j = activeNodes . length ; i < j ; i ++ ) if ( activeNodes [ i ] ) { nextNode = activeNodes [ i ] break } return nextNode }

Find next node in a potentially sparse array.

Find next node in a potentially sparse array .


function updateChange (targetKey, path, key) {
  var target = path.target
  var index = path.index
  var replaceKey = key

  if (typeof index === 'number') {
    target = target[key]
    replaceKey = index
  }

  return function handleChange (event) {
    target[replaceKey] = event.target[targetKey]
  }
}

function updateChange ( targetKey , path , key ) { var target = path . target var index = path . index var replaceKey = key if ( typeof index === 'number' ) { target = target [ key ] replaceKey = index } return function handleChange ( event ) { target [ replaceKey ] = event . target [ targetKey ] } }

Internal event listener to update data on input change.

Internal event listener to update data on input change .


function simulacra (obj, def, matchNode) {
  var document = this ? this.document : window.document
  var Node = this ? this.Node : window.Node
  var node, query

  // Before continuing, check if required features are present.
  featureCheck(this || window, features)

  if (obj === null || typeof obj !== 'object' || isArray(obj))
    throw new TypeError('First argument must be a singular object.')

  if (!isArray(def))
    throw new TypeError('Second argument must be an array.')

  if (typeof def[0] === 'string') {
    query = def[0]
    def[0] = document.querySelector(query)
    if (!def[0]) throw new Error(
      'Top-level Node "' + query + '" could not be found in the document.')
  }
  else if (!(def[0] instanceof Node)) throw new TypeError(
    'The first position of the top-level must be either a Node or a CSS ' +
    'selector string.')

  if (!def[isProcessedKey]) {
    // Auto-detect template tag.
    if ('content' in def[0]) def[0] = def[0].content

    def[0] = def[0].cloneNode(true)
    cleanNode(this, def[0])
    ensureNodes(def[0], def[1])
    setProperties(def)
  }

  node = processNodes(this, def[0], def[1])

  bindKeys(this, obj, def[1], node, { root: obj })

  if (matchNode) {
    rehydrate(this, obj, def[1], node, matchNode)
    return matchNode
  }

  return node
}

Bind an object to the DOM.

@param {Object} obj
@param {Object} def
@param {Node} [matchNode]
@return {Node}


function cleanNode (scope, node) {
  // A constant for showing text nodes.
  var showText = 0x00000004
  var document = scope ? scope.document : window.document
  var treeWalker = document.createTreeWalker(
    node, showText, processNodes.acceptNode, false)
  var textNode

  while (treeWalker.nextNode()) {
    textNode = treeWalker.currentNode
    textNode.textContent = textNode.textContent.trim()
  }

  node.normalize()
}

function
cleanNode
(
scope
,
node
)
{
// A constant for showing text nodes.
var
showText
=
0x00000004
var
document
=
scope
scope
.
document
:
window
.
document
var
treeWalker
=
document
.
createTreeWalker
(
node
,
showText
,
processNodes
.
acceptNode
,
false
)
var
textNode
while
(
treeWalker
.
nextNode
(
)
)
{
textNode
=
treeWalker
.
currentNode
textNode
.
textContent
=
textNode
.
textContent
.
trim
(
)
}
node
.
normalize
(
)
}

Internal function to strip empty text nodes.

Internal function to strip empty text nodes .


function processNodes (scope, node, def) {
  var document = scope ? scope.document : window.document
  var key, branch, result, mirrorNode, parent, marker, indices
  var i, j, treeWalker, orderedKeys

  result = def[templateKey]

  if (!result) {
    node = node.cloneNode(true)

    indices = []

    matchNodes(scope, node, def)

    orderedKeys = Object.keys(def).sort(function (a, b) {
      var nodeA = def[a][0][matchedNodeKey]
      var nodeB = def[b][0][matchedNodeKey]

      if (nodeA && nodeB)
        return nodeA.index - nodeB.index

      return 0
    })

    for (i = 0; i < orderedKeys.length; i++) {
      key = orderedKeys[i]
      branch = def[key]
      if (branch[isBoundToParentKey]) continue

      result = branch[0][matchedNodeKey]
      indices.push(result.index)
      mirrorNode = result.node
      parent = mirrorNode.parentNode

      // This value is memoized so that `appendChild` can be used instead of
      // `insertBefore`, which is a performance optimization.
      if (mirrorNode.nextElementSibling === null)
        branch[isMarkerLastKey] = true

      if (processNodes.useCommentNode) {
        marker = parent.insertBefore(
          document.createComment(' end "' + key + '" '), mirrorNode)
        parent.insertBefore(
          document.createComment(' begin "' + key + '" '), marker)
      }
      else marker = parent.insertBefore(
        document.createTextNode(''), mirrorNode)

      branch[markerKey] = marker

      parent.removeChild(mirrorNode)
    }

    Object.defineProperty(def, templateKey, {
      value: {
        node: node.cloneNode(true),
        indices: indices
      }
    })
  }
  else {
    node = result.node.cloneNode(true)
    indices = result.indices
    i = 0
    j = 0

    treeWalker = document.createTreeWalker(
      node, showAll, acceptNode, false)

    for (key in def) {
      branch = def[key]
      if (branch[isBoundToParentKey]) continue

      while (treeWalker.nextNode()) {
        if (i === indices[j]) {
          branch[markerKey] = treeWalker.currentNode
          i++
          break
        }
        i++
      }

      j++
    }
  }

  return node
}

Internal function to remove bound nodes and replace them with markers.

@param {*} [scope]
@param {Node} node
@param {Object} def
@return {Node}

Internal function to remove bound nodes and replace them with markers .


function matchNodes (scope, node, def) {
  var document = scope ? scope.document : window.document
  var treeWalker = document.createTreeWalker(
    node, showAll, acceptNode, false)
  var nodes = []
  var i, j, key, currentNode, childWalker
  var nodeIndex = 0

  // This offset is a bit tricky, it's used to determine the index of the
  // marker in the processed node, which depends on whether comment nodes
  // are used and the count of child nodes.
  var offset = processNodes.useCommentNode ? 1 : 0

  for (key in def) nodes.push(def[key][0])

  while (treeWalker.nextNode() && nodes.length) {
    for (i = 0, j = nodes.length; i < j; i++) {
      currentNode = nodes[i]
      if (treeWalker.currentNode.isEqualNode(currentNode)) {
        Object.defineProperty(currentNode, matchedNodeKey, {
          value: {
            index: nodeIndex + offset,
            node: treeWalker.currentNode
          }
        })
        if (processNodes.useCommentNode) offset++
        childWalker = document.createTreeWalker(
          currentNode, showAll, acceptNode, false)
        while (childWalker.nextNode()) offset--
        nodes.splice(i, 1)
        break
      }
    }

    nodeIndex++
  }
}

Internal function to find and set matching DOM nodes on cloned nodes.

@param {*} [scope]
@param {Node} node
@param {Object} def

Internal function to find and set matching DOM nodes on cloned nodes .


function rehydrate (scope, obj, def, node, matchNode) {
  var document = scope ? scope.document : window.document

  var key, branch, x, value, change, definition, mount, keyPath
  var meta, valueIsArray, activeNodes, index, treeWalker, currentNode

  for (key in def) {
    branch = def[key]
    meta = obj[metaKey][key]
    change = !branch[hasDefinitionKey] && branch[1]
    definition = branch[hasDefinitionKey] && branch[1]
    mount = branch[2]
    keyPath = meta.keyPath

    if (branch[isBoundToParentKey]) {
      x = obj[key]

      if (definition && x !== null && x !== void 0)
        bindKeys(scope, x, definition, matchNode, keyPath)
      else if (change)
        change(matchNode, x, null, keyPath)

      continue
    }

    activeNodes = meta.activeNodes
    if (!activeNodes.length) continue

    valueIsArray = meta.valueIsArray
    x = valueIsArray ? obj[key] : [ obj[key] ]
    index = 0
    treeWalker = document.createTreeWalker(
      matchNode, whatToShow, acceptNode, false)

    while (index < activeNodes.length && treeWalker.nextNode()) {
      currentNode = activeNodes[index]

      if (treeWalker.currentNode.isEqualNode(currentNode)) {
        activeNodes.splice(index, 1, treeWalker.currentNode)

        value = x[index]

        if (valueIsArray) keyPath.index = index
        else delete keyPath.index

        if (definition) {
          rehydrate(scope, value, definition,
            currentNode, treeWalker.currentNode)

          if (mount) {
            keyPath.target = value
            mount(treeWalker.currentNode, value, null, keyPath)
          }
        }
        else if (change)
          change(treeWalker.currentNode, value, null, keyPath)

        index++
      }
    }

    if (index !== activeNodes.length) throw new Error(
      'Matching nodes could not be found on key "' + key + '", expected ' +
      activeNodes.length + ', found ' + index + '.')

    // Rehydrate marker node.
    currentNode = treeWalker.currentNode

    // Try to re-use comment node.
    if (processNodes.useCommentNode &&
      currentNode.nextSibling !== null &&
      currentNode.nextSibling.nodeType === COMMENT_NODE)
      branch[markerKey] = currentNode.nextSibling
    else branch[markerKey] = currentNode.parentNode.insertBefore(
      document.createTextNode(''), currentNode.nextSibling)
  }
}

Rehydration of existing DOM nodes by recursively checking equality.

@param {*} scope
@param {Object} obj
@param {Object} def
@param {Node} node
@param {Node} matchNode

Rehydration of existing DOM nodes by recursively checking equality .


function render (obj, def, html) {
  var i, nodes, handler, parser, element, elementPrototype

  // If given bindings with a root node, pick only the binding keys.
  if (Array.isArray(def)) def = def[1]

  // Generating the render function is processing intensive. Skip if possible.
  if (renderFnKey in def) return def[renderFnKey](obj)

  // Callback API looks weird. This is actually synchronous, not asynchronous.
  handler = new htmlParser.DomHandler(function (error, result) {
    if (error) throw error
    nodes = result
  }, handlerOptions)

  parser = new htmlParser.Parser(handler)
  parser.write(html)
  parser.end()

  for (i = nodes.length; i--;)
    if (nodes[i].type === 'tag') {
      element = nodes[i]
      break
    }

  if (!element) throw new Error('No element found!')

  elementPrototype = Object.getPrototypeOf(element)
  Element.prototype = elementPrototype
  Object.defineProperties(elementPrototype, elementExtension)

  processDefinition(def, nodes)
  def[renderFnKey] = makeRender(def, nodes)

  return def[renderFnKey](obj)
}

Internal function for rendering strings. The benchmark to beat is plain old
string concatenation and for loops. Although this won't be faster, it should
work with more or less the same functionality as the DOM version.

Only a tiny subset of the actual DOM is implemented here, so it may not work
for all front-end functionality.

@param {Object} obj
@param {Object} def
@param {String} [html]
@return {String}

Internal function for rendering strings . The benchmark to beat is plain old string concatenation and for loops . Although this won t be faster it should work with more or less the same functionality as the DOM version .


function featureCheck (globalScope, features) {
  var i, j, k, l, feature, path

  for (i = 0, j = features.length; i < j; i++) {
    path = features[i]

    if (typeof path[0] === 'string') {
      feature = globalScope

      for (k = 0, l = path.length; k < l; k++) {
        if (!(path[k] in feature)) throw new Error('Missing ' +
          path.slice(0, k + 1).join('.') + ' feature which is required.')

        feature = feature[path[k]]
      }
    }

    else {
      feature = path[0]

      for (k = 1, l = path.length; k < l; k++) {
        if (k > 1) feature = feature[path[k]]

        if (typeof feature === 'undefined') throw new Error('Missing ' +
          path[0].name + path.slice(1, k + 1).join('.') +
          ' feature which is required.')
      }
    }
  }
}

function
featureCheck
(
globalScope
,
features
)
{
var
i
,
j
,
k
,
l
,
feature
,
path
for
(
i
=
0
,
j
=
features
.
length
;
i
<
j
;
i
++
)
{
path
=
features
[
i
]
if
(
typeof
path
[
0
]
===
'string'
)
{
feature
=
globalScope
for
(
k
=
0
,
l
=
path
.
length
;
k
<
l
;
k
++
)
{
if
(
!
(
path
[
k
]
in
feature
)
)
throw
new
Error
(
'Missing '
+
path
.
slice
(
0
,
k
+
1
)
.
join
(
'.'
)
+
' feature which is required.'
)
feature
=
feature
[
path
[
k
]
]
}
}
else
{
feature
=
path
[
0
]
for
(
k
=
1
,
l
=
path
.
length
;
k
<
l
;
k
++
)
{
if
(
k
>
1
)
feature
=
feature
[
path
[
k
]
]
if
(
typeof
feature
===
'undefined'
)
throw
new
Error
(
'Missing '
+
path
[
0
]
.
name
+
path
.
slice
(
1
,
k
+
1
)
.
join
(
'.'
)
+
' feature which is required.'
)
}
}
}
}

Check if capabilities are available, or throw an error.

@param {*} globalScope

Check if capabilities are available or throw an error .


function bemNames(entitys, delimiters) {
  var resultString = '';
  var names = entitys || { mods: {}, mixin: '' };
  var delims = _extends({
    ns: '',
    el: '__',
    mod: '--',
    modVal: '-'
  }, delimiters);
  var mixin = isString(names.mixin) ? ' ' + names.mixin : '';

  if (!names.block) return '';
  resultString = delims.ns ? delims.ns + names.block : names.block;

  if (names.el) resultString += delims.el + names.el;

  if (isPObject(names.mods)) {
    resultString += Object.keys(names.mods).reduce(function (prev, name) {
      var val = names.mods[name];
      /* eslint-disable no-param-reassign */
      if (val === true) {
        prev += ' ' + resultString + delims.mod + name;
      } else if (isString(val) || isNumber(val)) {
        prev += ' ' + resultString + delims.mod + name + delims.modVal + names.mods[name];
      }
      /* eslint-enable no-param-reassign */

      return prev;
    }, '');
  }
  return resultString + mixin;
}

function
bemNames
(
entitys
,
delimiters
)
{
var
resultString
=
''
;
var
names
=
entitys
||
{
mods
:
{
}
,
mixin
:
''
}
;
var
delims
=
_extends
(
{
ns
:
''
,
el
:
'__'
,
mod
:
'--'
,
modVal
:
'-'
}
,
delimiters
)
;
var
mixin
=
isString
(
names
.
mixin
)
' '
+
names
.
mixin
:
''
;
if
(
!
names
.
block
)
return
''
;
resultString
=
delims
.
ns
delims
.
ns
+
names
.
block
:
names
.
block
;
if
(
names
.
el
)
resultString
+=
delims
.
el
+
names
.
el
;
if
(
isPObject
(
names
.
mods
)
)
{
resultString
+=
Object
.
keys
(
names
.
mods
)
.
reduce
(
function
(
prev
,
name
)
{
var
val
=
names
.
mods
[
name
]
;
/* eslint-disable no-param-reassign */
if
(
val
===
true
)
{
prev
+=
' '
+
resultString
+
delims
.
mod
+
name
;
}
else
if
(
isString
(
val
)
||
isNumber
(
val
)
)
{
prev
+=
' '
+
resultString
+
delims
.
mod
+
name
+
delims
.
modVal
+
names
.
mods
[
name
]
;
}
/* eslint-enable no-param-reassign */
return
prev
;
}
,
''
)
;
}
return
resultString
+
mixin
;
}

Create String from BEM entitys
@param {Object} entitys BEM entitys
@param {String} entitys.block Block
@param {String} [entitys.el] Element
@param {Object<string>} [entitys.mods] Modifiers
@param {String} [entitys.mixin] Mixin
@param {Object<string>} delimiters Delimiters for BEM entitys
@returns {String}


function deepMergeConfigs(configs, options) {
  return merge.all(configs.filter(config => config), options);
}

function deepMergeConfigs ( configs , options ) { return merge . all ( configs . filter ( config => config ) , options ) ; }

Merges an array of configs

@param {array<config>} configs The configs to merge
@param {object} options https://github.com/KyleAMathews/deepmerge#options
@returns {object} The merged configuration


async function loadYaml(context, params) {
  try {
    const response = await context.github.repos.getContents(params);
    return parseConfig(response.data.content);
  } catch (e) {
    if (e.code === 404) {
      return null;
    }

    throw e;
  }
}

async function loadYaml ( context , params ) { try { const response = await context . github . repos . getContents ( params ) ; return parseConfig ( response . data . content ) ; } catch ( e ) { if ( e . code === 404 ) { return null ; } throw e ; } }

Loads a file from GitHub

@param {Context} context A Probot context
@param {object} params Params to fetch the file with
@returns {Promise<object>} The parsed YAML file
@async


function getBaseParams(params, base) {
  if (typeof base !== 'string') {
    throw new Error(`Invalid repository name in key "${BASE_KEY}"`);
  }

  const match = base.match(BASE_REGEX);
  if (match == null) {
    throw new Error(`Invalid repository name in key "${BASE_KEY}": ${base}`);
  }

  return {
    owner: match[1] || params.owner,
    repo: match[2],
    path: match[3] || params.path,
  };
}

function getBaseParams ( params , base ) { if ( typeof base !== 'string' ) { throw new Error ( ` ${ BASE_KEY } ` ) ; } const match = base . match ( BASE_REGEX ) ; if ( match == null ) { throw new Error ( ` ${ BASE_KEY } ${ base } ` ) ; } return { owner : match [ 1 ] || params . owner , repo : match [ 2 ] , path : match [ 3 ] || params . path , } ; }

Computes parameters for the repository specified in base

Base can either be the name of a repository in the same organization or
a full slug "organization/repo".

@param {object} params An object containing owner, repo and path
@param {string} base A string specifying the base repository
@returns {object} The params of the base configuration