<commit_before>import JSONStream from 'JSONStream';
import { pipe, through, concat } from 'mississippi';
import styles from 'style-stream';
import next from 'next-stream';
import doiuse from 'doiuse/stream';
import prune from './prune';
import unique from './unique';
import limitstream from './limit';
import {agents} from './user-agents';
import { map, flatten, findKey, forEach, find, values, uniq } from 'lodash';
import getCss from 'get-css';
import fromString from 'from2-string';

/*
* options must have `url`.
*/
module.exports = function evaluate(args) {

	return new Promise((resolve, reject) => {

		var options = {
			timeout: 5000
		};

		const url = args.url || '';
		let browsers = args.browsers || '';

		getCss(args.url, options)
			.then(function(response) {

				let streams = [fromString(response.css)];
				let errorsAndWarnings = [];
				let uniqe = unique();
				let limit = limitstream(1e6);
				let features = prune();

				browsers = browsers.map((obj) => obj.version ? (obj.name + ' ' + obj.version) : obj.name);

				streams = streams.concat([
					limit,
					doiuse({ browsers: browsers, skipErrors: true }, url.trim().length ? url : 'pasted content')
					.on('warning', function (warn) {
						errorsAndWarnings.push(warn)
					}),
					uniqe.features,
					features
				]);
				let stringify = features.pipe(JSONStream.stringify());
				let error = through();

				pipe(streams,
					function (err) {
						if (err) {
							console.error('Error processing CSS', err);
							console.trace();
							if (!limit.ended) {
								limit.end()
							}
							if (!uniqe.ended) {
								uniqe.features.end()
							}
							stringify.end();
							if (JSON.stringify(err) === '{}') {
								err = err.toString()
							}
							errorsAndWarnings.push(err)
						}
						error.end(', "errors":' + JSON.stringify(errorsAndWarnings));
					}
				)

				let usageData;
				const concatStream = next([
					'{ "args":', JSON.stringify(args), ',',
					'"features": ', stringify.pipe(through()), ',',
					'"counts": ', uniqe.counts, ',',
					'"size": ', limit.size,
					error,
					'}'
					], { open: false }
				);
				const finalStream = JSONStream.parse();
				concatStream.pipe(finalStream);

				finalStream.on('data', (data) => {
					usageData = data;
				});
				finalStream.on('error', (err) => {
					reject(err);
				});
				finalStream.on('end', (err) => {

					const getMissingBrowserVersions = (features) => {
			            let browsers = [];

			            for (var i = 0; i < features.length; i++) {
			                browsers.push.apply(browsers, flatten(features[i].missing));
			            }
			            return sumBrowserVersions(browsers);
			        }

			        const sumBrowserVersions = (browsers) => {

			        	return values(browsers.reduce((prev, current, index, array) => {
			                if(!(current.alias in prev.result)) {
			                    prev.result[current.alias] = current;
			                }
			               else if(prev.result[current.alias]) {
		                        prev.result[current.alias].versions = uniq(prev.result[current.alias].versions.concat(current.versions));
		                    }
			               return prev;
			            },{result: {}}).result);
			        }

				    const getPercentage = (browserset, browsersWithPercentages) => {
				        let sum = 0;
				        forEach(browserset, function(browser, key) {
				            forEach(browser.versions, function(value, key) {
				                let obje = find(browsersWithPercentages, function(o) {
				                    return (o.name === browser.alias + ' ' + value) || (o.name === browser.alias);
				                });
				                if(obje) sum += parseFloat(obje.share);
				            })
				        })

				        return sum;
				    }

				    const transformBrowserVersion = (features) => {

			            for (var i = 0; i < features.length; i++) {
				            features[i].missing = flatten(features[i].missing).reduce((prev, current, index, array) => {
				                let nextVersions = typeof current.versions === 'string' ? current.versions.replace(/[()]/g, '').replace(/,\s*$/, "").split(',') : current.versions;
				                if(!(current.browser in prev.keys)) {
				                    prev.keys[current.browser] = index;
				                    prev.result.push({
				                        browser: current.browser.trim(),
				                        versions: nextVersions,
				                        alias: findKey(agents, (o) => { return o.browser === current.browser.trim(); })
				                    });
				                }
				               else {
				                    if(prev.result[prev.keys[current.browser]]) {
				                        prev.result[prev.keys[current.browser]].versions.concat(nextVersions);
				                    }
				               }

				               return prev;
				            },{result: [], keys: {}}).result;
			            }
			            return features;
				    }

				    let data = {};
				    const features = transformBrowserVersion(usageData.features);

			        data.pageSupport = 100 - getPercentage(getMissingBrowserVersions(features), args.browsers);
			        data.elementCollection = map(features, (value, prop) => {
			            let feature = value;
			            feature.count = usageData.counts[feature.feature];
			            feature.name = feature.feature;
			            feature.impact = getPercentage(getMissingBrowserVersions([feature]), args.browsers);
			            feature.message = feature.message;
			            return feature;
			        });

					resolve(data);
				});

			})
		  	.catch(function(error) {
		    	console.error(error);
		    	reject(error);
		    });

	});
}
<commit_msg>added user-agent specific checks<commit_after>import JSONStream from 'JSONStream';
import { pipe, through, concat } from 'mississippi';
import styles from 'style-stream';
import next from 'next-stream';
import doiuse from 'doiuse/stream';
import prune from './prune';
import unique from './unique';
import limitstream from './limit';
import {agents} from './user-agents';
import { map, flatten, findKey, forEach, find, values, uniq } from 'lodash';
import getCss from 'get-css';
import fromString from 'from2-string';

/*
* options must have `url`.
*/
module.exports = function evaluate(args) {

	return new Promise((resolve, reject) => {

		var options = {
			timeout: 5000
		};

		const url = args.url || '';
		let browsers = args.browsers || '';

let doit = (item, index) => {
	//console.log(item.name+index);
	return new Promise((resolve, reject) => {
		resolve('hihihihi' + item);
	});
}

		var items = ['and_chr 50'/*,'android 4.4','chrome 50','ios_saf 9.3'*/];
		var features = [];

		let fn = (browser) => { // sample async action
			getCss(args.url, options)
				.then(function(response) {

					let streams = [fromString(response.css)];
					let errorsAndWarnings = [];
					let uniqe = unique();
					let limit = limitstream(1e6);
					let features = prune();

					//browsers = browsers.map((obj) => obj.version ? (obj.name + ' ' + obj.version) : obj.name);

					streams = streams.concat([
						limit,
						doiuse({ browsers: browser, skipErrors: true }, url.trim().length ? url : 'pasted content')
						.on('warning', function (warn) {
							errorsAndWarnings.push(warn)
						}),
						uniqe.features,
						features
					]);
					let stringify = features.pipe(JSONStream.stringify());
					let error = through();

					pipe(streams,
						function (err) {
							if (err) {
								console.error('Error processing CSS', err);
								console.trace();
								if (!limit.ended) {
									limit.end()
								}
								if (!uniqe.ended) {
									uniqe.features.end()
								}
								stringify.end();
								if (JSON.stringify(err) === '{}') {
									err = err.toString()
								}
								errorsAndWarnings.push(err)
							}
							error.end(', "errors":' + JSON.stringify(errorsAndWarnings));
						}
					)

					let usageData;
					const concatStream = next([
						'{ "args":', JSON.stringify(args), ',',
						'"features": ', stringify.pipe(through()), ',',
						'"counts": ', uniqe.counts, ',',
						'"size": ', limit.size,
						error,
						'}'
						], { open: false }
					);
					const finalStream = JSONStream.parse();
					concatStream.pipe(finalStream);

					finalStream.on('data', (data) => {
						console.log('Data: ', data);
						usageData = data;
					});
					finalStream.on('error', (err) => {
						reject(err);
					});
					finalStream.on('end', (err) => {

						const getMissingBrowserVersions = (features) => {
				            let browsers = [];

				            for (var i = 0; i < features.length; i++) {
				                browsers.push.apply(browsers, flatten(features[i].missing));
				            }
				            return sumBrowserVersions(browsers);
				        }

				        const sumBrowserVersions = (browsers) => {

				        	return values(browsers.reduce((prev, current, index, array) => {
				                if(!(current.alias in prev.result)) {
				                    prev.result[current.alias] = current;
				                }
				               else if(prev.result[current.alias]) {
			                        prev.result[current.alias].versions = uniq(prev.result[current.alias].versions.concat(current.versions));
			                    }
				               return prev;
				            },{result: {}}).result);
				        }

					    const getPercentage = (browserset, browsersWithPercentages) => {
					        let sum = 0;
					        forEach(browserset, function(browser, key) {
					            forEach(browser.versions, function(value, key) {
					                let obje = find(browsersWithPercentages, function(o) {
					                    return (o.name === browser.alias + ' ' + value) || (o.name === browser.alias);
					                });
					                if(obje) sum += parseFloat(obje.share);
					            })
					        })

					        return sum;
					    }

					    const transformBrowserVersion = (features) => {

				            for (var i = 0; i < features.length; i++) {
					            features[i].missing = flatten(features[i].missing).reduce((prev, current, index, array) => {
					                let nextVersions = typeof current.versions === 'string' ? current.versions.replace(/[()]/g, '').replace(/,\s*$/, "").split(',') : current.versions;
					                if(!(current.browser in prev.keys)) {
					                    prev.keys[current.browser] = index;
					                    prev.result.push({
					                        browser: current.browser.trim(),
					                        versions: nextVersions,
					                        alias: findKey(agents, (o) => { return o.browser === current.browser.trim(); })
					                    });
					                }
					               else {
					                    if(prev.result[prev.keys[current.browser]]) {
					                        prev.result[prev.keys[current.browser]].versions.concat(nextVersions);
					                    }
					               }

					               return prev;
					            },{result: [], keys: {}}).result;
				            }
				            return features;
					    }

					    let data = {};
					    const features = transformBrowserVersion(usageData.features);

				        //data.pageSupport = 100 - getPercentage(getMissingBrowserVersions(features), args.browsers);
				        data.elementCollection = map(features, (value, prop) => {
				            let feature = value;
				            feature.count = usageData.counts[feature.feature];
				            feature.name = feature.feature;
				            feature.impact = getPercentage(getMissingBrowserVersions([feature]), args.browsers);
				            feature.message = feature.message;
				            return feature;
				        });

						resolve(data);
					});

				})
			  	.catch(function(error) {
			    	console.error(error);
			    	reject(error);
			    });
		};
		// map over forEach since it returns

		var actions = items.map(fn); // run the function over all items.

		// we now have a promises array and we want to wait for it

		var results = Promise.all(actions); // pass array of promises

		results.then(data => {// or just .then(console.log)
			console.log('Result: ', data); // [2, 4, 6, 8, 10]
			//console.log(features);

			//resolve(data);
		});

	});
}
<|endoftext|>


<commit_before>var QUnit = require('qunitjs'),
    path = require('path'),
    _ = require('underscore'),
    trace = require('tracejs').trace,
    coverage = require('./coverage'),
    generators = require('./generators'),
    co = require('co');

// cycle.js: This file contains two functions, JSON.decycle and JSON.retrocycle,
// which make it possible to encode cyclical structures and dags in JSON, and to
// then recover them. JSONPath is used to represent the links.
// http://GOESSNER.net/articles/JsonPath/
require('../support/json/cycle');

var options = JSON.parse(process.argv[2]), currentModule, currentTest;

function getModuleName(module) {
  if (typeof module == 'undefined') {
    return;
  }
  if (typeof module == 'string') {
    return path.basename(module, '.js');
  } else {
    return path.basename(module.path, '.js');
  }
}

if (!!options.code) {
    currentModule = getModuleName(options.code.path);
} else {
    // Script-based tests could contain code and test. In that case
    // code can be not set, and the module name can be taken from the test name itself.
	currentModule = '<none>';
}

process.on('uncaughtException', function (err) {
	console.log('Exception: ' + err.message);
	console.log('Stack: ' + err.stack);
    if (QUnit.config.current) {
        QUnit.ok(false, 'Test threw unexpected exception: ' + err.message);
        QUnit.start();
    }
    process.send({
        event: 'uncaughtException',
        data: {
            message: err.message,
            stack: err.stack
        }
    });
});

QUnit.init();
QUnit.config.autostart = false;
QUnit.config.pageLoaded = true;

// make qunit api global, like it is in the browser
_.extend(global, QUnit);

// as well as the QUnit variable itself
global.QUnit = QUnit;

/**
 * Require a resource.
 * @param {Object} res
 */
function _require(res, addToGlobal) {
	var exports;
	if (typeof res === 'string') {
    	exports = require(res);
	}
	else {
    	exports = require(res.path.replace(/\.js$/, ''));
	}

    if (addToGlobal) {
        // resource can define 'namespace' to expose its exports as a named object
        if (res.namespace) {
            global[res.namespace] = exports;
        } else {
            _.extend(global, exports);
        }
    }
}

/**
 * Callback for each started test.
 * @param {Object} test
 */
QUnit.testStart(function(test) {
    // currentTest is undefined while first test is not done yet
    currentTest = test.name;

    // use last module name if no module name defined
    currentModule = getModuleName(test.module) || currentModule;
});

/**
 * Callback for each assertion.
 * @param {Object} data
 */
QUnit.log(function(data) {
    data.test = QUnit.config.current.testName;
    data.module = currentModule;
    process.send({
        event: 'assertionDone',
        data: JSON.decycle(data)
    });
});

/**
 * Callback for one done test.
 * @param {Object} test
 */
QUnit.testDone(function(data) {
    // use last module name if no module name defined
    data.module = getModuleName(data.module) || currentModule;
    process.send({
        event: 'testDone',
        data: data
    });
});

/**
 * Callback for all done tests in the file.
 * @param {Object} res
 */
QUnit.done(_.debounce(function(data) {
    data.coverage = global.__coverage__;

    process.send({
        event: 'done',
        data: data
    });
}, 1000));

if (generators.support) {
    var test = QUnit.test;

    /**
     * Support generators.
     */
    global.test = QUnit.test = function(testName, expected, callback, async) {
        var fn;

        if (arguments.length === 2) {
            callback = expected;
            expected = null;
        }

        if (generators.isGeneratorFn(callback)) {
            fn = function(assert) {
                stop();
                co(callback).call(this, assert, function(err) {
                    if (err) return console.log(err.stack)
                    start();
                });
            };
        } else {
            fn = callback;
        }

        return test.call(this, testName, expected, fn, async);
    };
}

/**
 * Provide better stack traces
 */
var error = console.error;
console.error = function(obj) {
    // log full stacktrace
    if (obj && obj.stack) {
        obj = trace(obj);
    }

    return error.apply(this, arguments);
};

if (options.coverage) {
    coverage.instrument(options);
}

// require deps
options.deps.forEach(function(dep) {
    _require(dep, true);
});

// require code, if one
if (!!options.code) {
	_require(options.code, true);
}

// require tests
options.tests.forEach(function(test) {
    QUnit.module(test);
    _require(test, true);
});

QUnit.start();
<commit_msg>Added support for dependency aliases<commit_after>var QUnit = require('qunitjs'),
    path = require('path'),
    _ = require('underscore'),
    trace = require('tracejs').trace,
    coverage = require('./coverage'),
    generators = require('./generators'),
    co = require('co');

// cycle.js: This file contains two functions, JSON.decycle and JSON.retrocycle,
// which make it possible to encode cyclical structures and dags in JSON, and to
// then recover them. JSONPath is used to represent the links.
// http://GOESSNER.net/articles/JsonPath/
require('../support/json/cycle');

var options = JSON.parse(process.argv[2]), currentModule, currentTest;

function getModuleName(module) {
  if (typeof module == 'undefined') {
    return;
  }
  if (typeof module == 'string') {
    return path.basename(module, '.js');
  } else {
    return path.basename(module.path, '.js');
  }
}

if (!!options.code) {
    currentModule = getModuleName(options.code.path);
} else {
    // Script-based tests could contain code and test. In that case
    // code can be not set, and the module name can be taken from the test name itself.
	currentModule = '<none>';
}

process.on('uncaughtException', function (err) {
	console.log('Exception: ' + err.message);
	console.log('Stack: ' + err.stack);
    if (QUnit.config.current) {
        QUnit.ok(false, 'Test threw unexpected exception: ' + err.message);
        QUnit.start();
    }
    process.send({
        event: 'uncaughtException',
        data: {
            message: err.message,
            stack: err.stack
        }
    });
});

QUnit.init();
QUnit.config.autostart = false;
QUnit.config.pageLoaded = true;

// make qunit api global, like it is in the browser
_.extend(global, QUnit);

// as well as the QUnit variable itself
global.QUnit = QUnit;

// Caches between require aliases and real module instance
var aliasCache = {};

/**
 * Require a resource.
 * @param {Object} res
 */
function _require(res, addToGlobal) {
	var exports;
	if (typeof res === 'string') {
    	exports = require(res);
	}
	else {
        exports = require(res.path.replace(/\.js$/, ''));
        // Store the alias
        if (res.alias) {
            aliasCache[res.alias] = exports;
        }
	}

    if (addToGlobal) {
        // resource can define 'namespace' to expose its exports as a named object
        if (res.namespace) {
            global[res.namespace] = exports;
        } else {
            _.extend(global, exports);
        }
    }
}

/**
 * Callback for each started test.
 * @param {Object} test
 */
QUnit.testStart(function(test) {
    // currentTest is undefined while first test is not done yet
    currentTest = test.name;

    // use last module name if no module name defined
    currentModule = getModuleName(test.module) || currentModule;
});

/**
 * Callback for each assertion.
 * @param {Object} data
 */
QUnit.log(function(data) {
    data.test = QUnit.config.current.testName;
    data.module = currentModule;
    process.send({
        event: 'assertionDone',
        data: JSON.decycle(data)
    });
});

/**
 * Callback for one done test.
 * @param {Object} test
 */
QUnit.testDone(function(data) {
    // use last module name if no module name defined
    data.module = getModuleName(data.module) || currentModule;
    process.send({
        event: 'testDone',
        data: data
    });
});

/**
 * Callback for all done tests in the file.
 * @param {Object} res
 */
QUnit.done(_.debounce(function(data) {
    data.coverage = global.__coverage__;

    process.send({
        event: 'done',
        data: data
    });
}, 1000));

if (generators.support) {
    var test = QUnit.test;

    /**
     * Support generators.
     */
    global.test = QUnit.test = function(testName, expected, callback, async) {
        var fn;

        if (arguments.length === 2) {
            callback = expected;
            expected = null;
        }

        if (generators.isGeneratorFn(callback)) {
            fn = function(assert) {
                stop();
                co(callback).call(this, assert, function(err) {
                    if (err) return console.log(err.stack)
                    start();
                });
            };
        } else {
            fn = callback;
        }

        return test.call(this, testName, expected, fn, async);
    };
}

/**
 * Provide better stack traces
 */
var error = console.error;
console.error = function(obj) {
    // log full stacktrace
    if (obj && obj.stack) {
        obj = trace(obj);
    }

    return error.apply(this, arguments);
};

if (options.coverage) {
    coverage.instrument(options);
}

// require deps
options.deps.forEach(function(dep) {
    _require(dep, true);
});

// Before requiring the code, store require aliases
function installRequireHooks() {
    // require.extensions seems to expose access to the wanted require function
    // Solution currently used by proxyquire: https://github.com/thlorenz/proxyquire
    // WARNING: node declare this as deprecated!

  Object.keys(require.extensions).forEach(function(extension) {
    var originalExtension = require.extensions[extension];

    // Override the default handler for the requested file extension
    require.extensions[extension] = function(module, filename) {
      // Override the require method for this module
      module.require = function(path) {
        // Check for an alias to exists

        if (aliasCache[path]) {
          return aliasCache[path];
        } else {
          // Old call
          return require.apply(this, arguments);
        }
      };

      return originalExtension(module, filename);
    };
  });
}

installRequireHooks();

// require code, if one
if (!!options.code) {
	_require(options.code, true);
}

// require tests
options.tests.forEach(function(test) {
    QUnit.module(test);
    _require(test, true);
});

QUnit.start();
<|endoftext|>


<commit_before>
var API = Shopify.API = function ShopifyAPI(options) {
    check(options, Object);
    check(options.shop, String);

    // Until authenticated, or while waiting for the API rate limit to cool
    // down, requests are enqueued.
    //
    // [{ method, uri, [data], callback }, ...]
    this._requestQueue = [];

    this.config = {
        shop: options.shop,
        backoff: 35
    };

    // Any additional headers here will be sent with each call to Shopify.
    this.additionalHeaders = { };

    // If user has an `access_token` or `password`, an authenticator can be
    // created.  Otherwise the user must later provide an authenticator with
    // API.addAuthenticator.
    this._authenticator = null;
    if (options.password) {
        if (!options.api_key) {
            throw new Error("api_key is required for Private Apps (assuming Private App because you provided a password");
        }

        var authenticator = new Shopify.PrivateAppAuthenticator(options);
        this.addAuthenticator(authenticator);
    } else if (options.access_token) {
        var authenticator = new Shopify.PublicAppAuthenticator(options);
        this.addAuthenticator(authenticator);
    }

    // From X-Shopify-Shop-Api-Call-Limit, like 32 in "32/40".
    this._lastCallLimit = 0;

    // Number of requests currently waiting.  If at backoff, then will
    // incremenet queue, wait a half second for each item in the queue, then
    // decrement the queue and make the API call.
    this._queueLength = 0;
};

// Add an authenticator.
API.prototype.addAuthenticator = function(authenticator) {
    this._authenticator = authenticator;
};

Object.defineProperty(API.prototype, "authenticated", {
    get: function() {
        return !!this._authenticator;
    }
});

// Wait (if necessary) for rate limiting purposes, then call callback.
API.prototype._waitAsync = function(callback) {
    var self = this;

    // If not yet at backoff, then no wait is necessary.
    if (this._lastCallLimit < this.config.backoff) {
        Meteor.setTimeout(callback, 0);
        return;
    }

    this._queueLength++;
    Meteor.setTimeout(function() {
        self._queueLength--;
        callback();
    }, 500*this._queueLength);
};

// Methods.

// Define an API method.
//
// @param info {Object} Endpoint info
// @param info.name {String}
// @param info.method {String} HTTP method of API endpoint, like "GET"
// @param info.path {String} Path of API endpoint, like "/admin/orders.json"
// @param [info.description] {String}
API.define = function(info) {
    check(info.name, Shopify._IsNonEmptyString);
    check(info.method, Shopify._IsNonEmptyString);
    check(info.path, Shopify._IsNonEmptyString);

    var description = info.method + " \"" + info.path + "\"";
    if (info.description) {
        description += ": " + info.description;
    }

    var paramFinder = /#{(.+?)}/g;
    var params = [];

    var m;
    while ((m = paramFinder.exec(info.path))) {
        params.push(m[1]);
    }

    // If params are given (e.g. `id` in GET /admin/orders/:id.json), then we
    // have to substitute `options[param]` into `path` for each param.
    var paramCode;
    if (params.length > 0) {
        var lines = [];
        params.forEach(function(param) {
            lines.push("");
            lines.push("    if (!options['" + param + "']) {");
            lines.push("        throw new Error('Missing option " + param + "');");
            lines.push("    }");
            lines.push("");
            lines.push("    path = path.replace('#{" + param + "}', options['" + param + "']);");
        });

        // Make helpers for
        lines.push("var paramCount = " + params.length + ";");
        lines.push("var isParam = { '" + params.join("': true, '") + "': true };");

        paramCode = lines.join("\n");
    } else {
        paramCode = "var paramCount = 0, isParam = { };";
    }

    var returnCode;
    if (info.returns) {
        returnCode = "            callback(null, res.data." + info.returns + ");\n";
    } else {
        returnCode = "            callback(null, res.data);\n";
    }

    API.prototype["_" + info.name] = new Function([
        // Name the function
        "return function ",
        info.name,
        // Takes options and callback.
        "(options, callback) {\n",
        // Add the description in a comment for toString
        "    /* " + description + " */\n",
        "    var self = this;\n",

        "\n",
        "    if (typeof options === 'function') {\n",
        "        callback = options;\n",
        "        options = { };\n",
        "    }\n",
        "\n",

        "    this._waitAsync(function() { // for rate limiting\n",

        "    var method = '" + info.method + "';\n",
        "    var path = '" + info.path + "';\n",

        "\n",
        paramCode,
        "\n",

        // Using paramCode helpers from above, generate a query string from all
        // the other options.
        "    var queryParams = [];\n",
        "    for (var option in options) {\n",
        "        if (isParam[option]) {\n",
        "            continue;\n",
        "        }\n",
        "\n",
        "        var optionVal = options[option];\n",
        "        if (optionVal instanceof Date) {\n",
        "            optionVal = optionVal.toISOString().slice(0, 16).replace('T', ' ');\n",
        "        }\n",
        "\n",
        "        queryParams.push(option + '=' + optionVal);\n",
        "    }\n",
        "\n",
        "    var search = queryParams.length === 0 ? '' : '?' + queryParams.join('&');\n",
        "\n",

        "    var url = 'https://' + self.config.shop + '.myshopify.com' + path + search;\n",
        "    var req = { };\n",
        "    self._authenticator.authenticate(req);\n",
        "    var res = self._httpCall(method, url, req, function(err, res) {\n",
        "        if (err) { return callback(err); }\n",
        "\n",
        "        // Try again if hit rate limit\n",
        "        if (res.statusCode === 429) { return " + info.name + "(options, callback); }\n",
        "\n",
        "        // Set call limit\n",
        "        var callLimit = res.headers['x-shopify-shop-api-call-limit'];\n",
        "        if (callLimit) {\n",
        "            var callLimitParts = callLimit.split('/');\n",
        "            var bucket = parseInt(callLimitParts[0], 10);\n",
        "            if (isNaN(bucket)) {\n",
        "                console.warn('Invalid call limit %s', callLimit);\n",
        "            } else {\n",
        "                self._lastCallLimit = parseInt(bucket);\n",
        "            }\n",
        "        }\n",
        "\n",
        "        // 2XX codes indicate success\n",
        "        if (200 <= res.statusCode && res.statusCode <= 299) {\n",
        returnCode,
        "            return;\n",
        "        }\n",
        "\n",
        "        // It failed\n",
        "        callback(res.statusCode);\n",
        "    });\n",

        "    }); // waitAsync\n",
        "}"
    ].join(""))();

    if (Meteor.isServer) {
        API.prototype[info.name] = Meteor.wrapAsync(API.prototype["_" + info.name]);
    } else {
        API.prototype[info.name] = API.prototype["_" + info.name];
    }
};

Shopify._APIMethods.forEach(function(apiMethod) {
    API.define(apiMethod);
});

API.defineConcat = function(info) {
    check(info.name, Shopify._IsNonEmptyString);
    check(info.count, Shopify._IsNonEmptyString);
    check(info.fetch, Shopify._IsNonEmptyString);

    // Orders need options.status set to "open" if getAllOrders.
    var addStatusCode;
    if (info.name === "getAllOrders") {
        addStatusCode = [
            "",
            "    // By default, getOrders only returns open orders.  So",
            "    // getAllOrders should do the same.  If not explicitly provided",
            "    // then getOrders and countOrders will behave differently.",
            "    if (!options.status) {",
            "        options.status = 'open';",
            "    }",
            ""
        ].join("\n");
    } else {
        addStatusCode = "\n";
    }

    API.prototype["_" + info.name] = new Function([
        "return function " + info.name + "(options, callback) {",
        "    var self = this;",
        "    if (typeof options === 'function') {",
        "        callback = options;",
        "        options = { };",
        "    } else {",
        "        options = _.clone(options);",
        "    }",
        addStatusCode,

        "    // Check how many items to fetch total",
        "    this._" + info.count + "(options, function(err, count) {",

        "        // Check for count fail",
        "        if (err) {",
        "            callback('count failed: ' + err);",
        "            return;",
        "        }",
        "",
        "        // Request 250 at a time starting at page 1",
        "        options.limit = 250;",
        "        options.page = 1;",
        "",
        "        // Append results here",
        "        var results = new Array(count);",

        "        // Request a page each time caller is called",
        "        (function caller(n) {",

        "            // Return if done",
        "            if (n >= count) {",
        "                callback(null, results);",
        "                return;",
        "            }",
        "",

        "            // Fetch a page",
        "            self._" + info.fetch + "(options, function(err, list) {",

        "                // Check for fetch fail",
        "                if (err) {",
        "                    callback('fetch (page ' + options.page + ') failed: ' + err);",
        "                    return;",
        "                }",
        "",
        "                // Add to results",
        "                for (var i = 0, len = list.length; i < len; i++) {",
        "                    results[n + i] = list[i];",
        "                }",
        "",
        "                // Recurse",
        "                options.page++;",
        "                caller(n + options.limit);",

        "            });", // fetch

        "        })(0);", // caller
        "",

        "    });", // count

        "};" // new Function
    ].join("\n"))();

    if (Meteor.isServer) {
        API.prototype[info.name] = Meteor.wrapAsync(API.prototype["_" + info.name]);
    } else {
        API.prototype[info.name] = API.prototype["_" + info.name];
    }
};

Shopify._APIConcatMethods.forEach(function(apiMethod) {
    API.defineConcat(apiMethod);
});

API.prototype._httpCall = function(method, uri, req, callback) {
    if (this._HOST_OVERRIDE) {
        var path;
        if (Meteor.isServer) {
            var url = Npm.require("url");
            var parsedUri = url.parse(uri);
            path = parsedUri.path;
        } else {
            var link = document.createElement("a");
            link.href = uri;
            path = link.pathname + link.search;
        }

        uri = this._HOST_OVERRIDE + path;
    }

    if (!req.headers) {
        req.headers = { };
    }

    for (var key in this.additionalHeaders) {
        var val = this.additionalHeaders[key];
        if (!req.headers[key]) {
            req.headers[key] = val;
        }
    }

    HTTP.call(method, uri, req, callback);
};

<commit_msg>Document and consolidate API.config.<commit_after>
var API = Shopify.API = function ShopifyAPI(options) {
    check(options, Object);
    check(options.shop, String);

    // Until authenticated, or while waiting for the API rate limit to cool
    // down, requests are enqueued.
    //
    // [{ method, uri, [data], callback }, ...]
    this._requestQueue = [];

    this.config = {
        // Like "my-store" in "my-store.my-shopify.com"
        shop: options.shop,

        // On hitting backoff, requests are queued
        backoff: options.backoff || 35,

        // If true, then various security assertions and warnings will be ignored
        insecure: options.insecure || false,

        // Any additional headers here will be sent with each call to Shopify.
        additionalHeaders: options.additionalHeaders || { }
    };

    // If user has an `access_token` or `password`, an authenticator can be
    // created.  Otherwise the user must later provide an authenticator with
    // API.addAuthenticator.
    this._authenticator = null;
    if (options.password) {
        if (!options.api_key) {
            throw new Error("api_key is required for Private Apps (assuming Private App because you provided a password");
        }

        var authenticator = new Shopify.PrivateAppAuthenticator(options);
        this.addAuthenticator(authenticator);
    } else if (options.access_token) {
        var authenticator = new Shopify.PublicAppAuthenticator(options);
        this.addAuthenticator(authenticator);
    }

    // From X-Shopify-Shop-Api-Call-Limit, like 32 in "32/40".
    this._lastCallLimit = 0;

    // Number of requests currently waiting.  If at backoff, then will
    // incremenet queue, wait a half second for each item in the queue, then
    // decrement the queue and make the API call.
    this._queueLength = 0;
};

// Add an authenticator.
API.prototype.addAuthenticator = function(authenticator) {
    this._authenticator = authenticator;
};

Object.defineProperty(API.prototype, "authenticated", {
    get: function() {
        return !!this._authenticator;
    }
});

// Wait (if necessary) for rate limiting purposes, then call callback.
API.prototype._waitAsync = function(callback) {
    var self = this;

    // If not yet at backoff, then no wait is necessary.
    if (this._lastCallLimit < this.config.backoff) {
        Meteor.setTimeout(callback, 0);
        return;
    }

    this._queueLength++;
    Meteor.setTimeout(function() {
        self._queueLength--;
        callback();
    }, 500*this._queueLength);
};

// Methods.

// Define an API method.
//
// @param info {Object} Endpoint info
// @param info.name {String}
// @param info.method {String} HTTP method of API endpoint, like "GET"
// @param info.path {String} Path of API endpoint, like "/admin/orders.json"
// @param [info.description] {String}
API.define = function(info) {
    check(info.name, Shopify._IsNonEmptyString);
    check(info.method, Shopify._IsNonEmptyString);
    check(info.path, Shopify._IsNonEmptyString);

    var description = info.method + " \"" + info.path + "\"";
    if (info.description) {
        description += ": " + info.description;
    }

    var paramFinder = /#{(.+?)}/g;
    var params = [];

    var m;
    while ((m = paramFinder.exec(info.path))) {
        params.push(m[1]);
    }

    // If params are given (e.g. `id` in GET /admin/orders/:id.json), then we
    // have to substitute `options[param]` into `path` for each param.
    var paramCode;
    if (params.length > 0) {
        var lines = [];
        params.forEach(function(param) {
            lines.push("");
            lines.push("    if (!options['" + param + "']) {");
            lines.push("        throw new Error('Missing option " + param + "');");
            lines.push("    }");
            lines.push("");
            lines.push("    path = path.replace('#{" + param + "}', options['" + param + "']);");
        });

        // Make helpers for
        lines.push("var paramCount = " + params.length + ";");
        lines.push("var isParam = { '" + params.join("': true, '") + "': true };");

        paramCode = lines.join("\n");
    } else {
        paramCode = "var paramCount = 0, isParam = { };";
    }

    var returnCode;
    if (info.returns) {
        returnCode = "            callback(null, res.data." + info.returns + ");\n";
    } else {
        returnCode = "            callback(null, res.data);\n";
    }

    API.prototype["_" + info.name] = new Function([
        // Name the function
        "return function ",
        info.name,
        // Takes options and callback.
        "(options, callback) {\n",
        // Add the description in a comment for toString
        "    /* " + description + " */\n",
        "    var self = this;\n",

        "\n",
        "    if (typeof options === 'function') {\n",
        "        callback = options;\n",
        "        options = { };\n",
        "    }\n",
        "\n",

        "    this._waitAsync(function() { // for rate limiting\n",

        "    var method = '" + info.method + "';\n",
        "    var path = '" + info.path + "';\n",

        "\n",
        paramCode,
        "\n",

        // Using paramCode helpers from above, generate a query string from all
        // the other options.
        "    var queryParams = [];\n",
        "    for (var option in options) {\n",
        "        if (isParam[option]) {\n",
        "            continue;\n",
        "        }\n",
        "\n",
        "        var optionVal = options[option];\n",
        "        if (optionVal instanceof Date) {\n",
        "            optionVal = optionVal.toISOString().slice(0, 16).replace('T', ' ');\n",
        "        }\n",
        "\n",
        "        queryParams.push(option + '=' + optionVal);\n",
        "    }\n",
        "\n",
        "    var search = queryParams.length === 0 ? '' : '?' + queryParams.join('&');\n",
        "\n",

        "    var url = 'https://' + self.config.shop + '.myshopify.com' + path + search;\n",
        "    var req = { };\n",
        "    self._authenticator.authenticate(req);\n",
        "    var res = self._httpCall(method, url, req, function(err, res) {\n",
        "        if (err) { return callback(err); }\n",
        "\n",
        "        // Try again if hit rate limit\n",
        "        if (res.statusCode === 429) { return " + info.name + "(options, callback); }\n",
        "\n",
        "        // Set call limit\n",
        "        var callLimit = res.headers['x-shopify-shop-api-call-limit'];\n",
        "        if (callLimit) {\n",
        "            var callLimitParts = callLimit.split('/');\n",
        "            var bucket = parseInt(callLimitParts[0], 10);\n",
        "            if (isNaN(bucket)) {\n",
        "                console.warn('Invalid call limit %s', callLimit);\n",
        "            } else {\n",
        "                self._lastCallLimit = parseInt(bucket);\n",
        "            }\n",
        "        }\n",
        "\n",
        "        // 2XX codes indicate success\n",
        "        if (200 <= res.statusCode && res.statusCode <= 299) {\n",
        returnCode,
        "            return;\n",
        "        }\n",
        "\n",
        "        // It failed\n",
        "        callback(res.statusCode);\n",
        "    });\n",

        "    }); // waitAsync\n",
        "}"
    ].join(""))();

    if (Meteor.isServer) {
        API.prototype[info.name] = Meteor.wrapAsync(API.prototype["_" + info.name]);
    } else {
        API.prototype[info.name] = API.prototype["_" + info.name];
    }
};

Shopify._APIMethods.forEach(function(apiMethod) {
    API.define(apiMethod);
});

API.defineConcat = function(info) {
    check(info.name, Shopify._IsNonEmptyString);
    check(info.count, Shopify._IsNonEmptyString);
    check(info.fetch, Shopify._IsNonEmptyString);

    // Orders need options.status set to "open" if getAllOrders.
    var addStatusCode;
    if (info.name === "getAllOrders") {
        addStatusCode = [
            "",
            "    // By default, getOrders only returns open orders.  So",
            "    // getAllOrders should do the same.  If not explicitly provided",
            "    // then getOrders and countOrders will behave differently.",
            "    if (!options.status) {",
            "        options.status = 'open';",
            "    }",
            ""
        ].join("\n");
    } else {
        addStatusCode = "\n";
    }

    API.prototype["_" + info.name] = new Function([
        "return function " + info.name + "(options, callback) {",
        "    var self = this;",
        "    if (typeof options === 'function') {",
        "        callback = options;",
        "        options = { };",
        "    } else {",
        "        options = _.clone(options);",
        "    }",
        addStatusCode,

        "    // Check how many items to fetch total",
        "    this._" + info.count + "(options, function(err, count) {",

        "        // Check for count fail",
        "        if (err) {",
        "            callback('count failed: ' + err);",
        "            return;",
        "        }",
        "",
        "        // Request 250 at a time starting at page 1",
        "        options.limit = 250;",
        "        options.page = 1;",
        "",
        "        // Append results here",
        "        var results = new Array(count);",

        "        // Request a page each time caller is called",
        "        (function caller(n) {",

        "            // Return if done",
        "            if (n >= count) {",
        "                callback(null, results);",
        "                return;",
        "            }",
        "",

        "            // Fetch a page",
        "            self._" + info.fetch + "(options, function(err, list) {",

        "                // Check for fetch fail",
        "                if (err) {",
        "                    callback('fetch (page ' + options.page + ') failed: ' + err);",
        "                    return;",
        "                }",
        "",
        "                // Add to results",
        "                for (var i = 0, len = list.length; i < len; i++) {",
        "                    results[n + i] = list[i];",
        "                }",
        "",
        "                // Recurse",
        "                options.page++;",
        "                caller(n + options.limit);",

        "            });", // fetch

        "        })(0);", // caller
        "",

        "    });", // count

        "};" // new Function
    ].join("\n"))();

    if (Meteor.isServer) {
        API.prototype[info.name] = Meteor.wrapAsync(API.prototype["_" + info.name]);
    } else {
        API.prototype[info.name] = API.prototype["_" + info.name];
    }
};

Shopify._APIConcatMethods.forEach(function(apiMethod) {
    API.defineConcat(apiMethod);
});

API.prototype._httpCall = function(method, uri, req, callback) {
    if (this._HOST_OVERRIDE) {
        var path;
        if (Meteor.isServer) {
            var url = Npm.require("url");
            var parsedUri = url.parse(uri);
            path = parsedUri.path;
        } else {
            var link = document.createElement("a");
            link.href = uri;
            path = link.pathname + link.search;
        }

        uri = this._HOST_OVERRIDE + path;
    }

    if (!req.headers) {
        req.headers = { };
    }

    for (var key in this.config.additionalHeaders) {
        var val = this.config.additionalHeaders[key];
        if (!req.headers[key]) {
            req.headers[key] = val;
        }
    }

    HTTP.call(method, uri, req, callback);
};

<|endoftext|>


<commit_before>var exampleRoutes = require('./example-route-data')
var expressApp = require('./express-application/app')
var pathfinder = require('../')
var assert = require('chai').assert
var expect = require('chai').expect

describe("Test Routes - SIMULATED ROUTES", function() {
  it("Should get all routes from the list", function() {
    var routes = pathfinder(exampleRoutes);
    assert.equal(routes.length, 6)
  })

  it("should get all GET routes", function() {
    var routes = pathfinder(exampleRoutes, "POST")

    assert.equal(routes.length, 2)
  })

  it("should include the mount path at the start of the url", function() {
    var routes = pathfinder(exampleRoutes, "DELETE") // Delete is only used in a "mounted route"
    var regex = /^\/admin\/[a-zA-Z0-9]*/

    var test = regex.test(routes[0].path)

    assert.isTrue(test)
  })

  it("should throw an Error as supplied HTTP method is not supported", function() {
    expect(() => {
      pathfinder(exampleRoutes, "FOOBAR")
    }).to.throw(Error)
  })

  it("should throw an TypeError as supplied method parameter is not of the correct type", function() {
    expect(() => {
      pathfinder(exampleRoutes, 123456)
    }).to.throw(TypeError)
  })
})

describe("Test Routes - EXPRESS APPLICATION", function() {
  it("Should get all routes from the list", function() {
    var routes = pathfinder(expressApp._router.stack)
    assert.equal(routes.length, 6)
  })

  it("should get all GET routes", function() {
    var routes = pathfinder(expressApp._router.stack, "POST")

    assert.equal(routes.length, 2)
  })

  it("should include the mount path at the start of the url", function() {
    var routes = pathfinder(expressApp._router.stack, "DELETE") // Delete is only used in a "mounted route"
    var regex = /^\/admin\/[a-zA-Z0-9]*/

    var test = regex.test(routes[0].path)

    assert.isTrue(test)
  })

  it("should throw an Error as supplied HTTP method is not supported", function() {
    expect(() => {
      pathfinder(expressApp._router.stack, "FOOBAR")
    }).to.throw(Error)
  })

  it("should throw a TypeError as supplied method parameter is not of the correct type", function() {
    expect(() => {
      pathfinder(expressApp._router.stack, 123456)
    }).to.throw(TypeError)
  })
})
<commit_msg>removed some ; for consistent style<commit_after>var exampleRoutes = require('./example-route-data')
var expressApp = require('./express-application/app')
var pathfinder = require('../')
var assert = require('chai').assert
var expect = require('chai').expect

describe("Test Routes - SIMULATED ROUTES", function() {
  it("Should get all routes from the list", function() {
    var routes = pathfinder(exampleRoutes)
    assert.equal(routes.length, 6)
  })

  it("should get all GET routes", function() {
    var routes = pathfinder(exampleRoutes, "POST")

    assert.equal(routes.length, 2)
  })

  it("should include the mount path at the start of the url", function() {
    var routes = pathfinder(exampleRoutes, "DELETE") // Delete is only used in a "mounted route"
    var regex = /^\/admin\/[a-zA-Z0-9]*/

    var test = regex.test(routes[0].path)

    assert.isTrue(test)
  })

  it("should throw an Error as supplied HTTP method is not supported", function() {
    expect(() => {
      pathfinder(exampleRoutes, "FOOBAR")
    }).to.throw(Error)
  })

  it("should throw an TypeError as supplied method parameter is not of the correct type", function() {
    expect(() => {
      pathfinder(exampleRoutes, 123456)
    }).to.throw(TypeError)
  })
})

describe("Test Routes - EXPRESS APPLICATION", function() {
  it("Should get all routes from the list", function() {
    var routes = pathfinder(expressApp._router.stack)
    assert.equal(routes.length, 6)
  })

  it("should get all GET routes", function() {
    var routes = pathfinder(expressApp._router.stack, "POST")

    assert.equal(routes.length, 2)
  })

  it("should include the mount path at the start of the url", function() {
    var routes = pathfinder(expressApp._router.stack, "DELETE") // Delete is only used in a "mounted route"
    var regex = /^\/admin\/[a-zA-Z0-9]*/

    var test = regex.test(routes[0].path)

    assert.isTrue(test)
  })

  it("should throw an Error as supplied HTTP method is not supported", function() {
    expect(() => {
      pathfinder(expressApp._router.stack, "FOOBAR")
    }).to.throw(Error)
  })

  it("should throw a TypeError as supplied method parameter is not of the correct type", function() {
    expect(() => {
      pathfinder(expressApp._router.stack, 123456)
    }).to.throw(TypeError)
  })
})
<|endoftext|>


<commit_before>const Resolutions = {
    '1080': {
        width: 1920,
        height: 1080,
        order: 7
    },
    'fullhd': {
        width: 1920,
        height: 1080,
        order: 7
    },
    '720': {
        width: 1280,
        height: 720,
        order: 6
    },
    'hd': {
        width: 1280,
        height: 720,
        order: 6
    },
    '960': {
        width: 960,
        height: 720,
        order: 5
    },

    // 16:9 resolution first.
    '360': {
        width: 640,
        height: 360,
        order: 4
    },
    '640': {
        width: 640,
        height: 480,
        order: 3
    },
    'vga': {
        width: 640,
        height: 480,
        order: 3
    },

    // 16:9 resolution first.
    '180': {
        width: 320,
        height: 180,
        order: 2
    },
    '320': {
        width: 320,
        height: 240,
        order: 1
    }
};

module.exports = Resolutions;
<commit_msg>resolutions: add 540p aka qHD<commit_after>const Resolutions = {
    '1080': {
        width: 1920,
        height: 1080,
        order: 8
    },
    'fullhd': {
        width: 1920,
        height: 1080,
        order: 8
    },
    '720': {
        width: 1280,
        height: 720,
        order: 7
    },
    'hd': {
        width: 1280,
        height: 720,
        order: 7
    },
    '960': {
        width: 960,
        height: 720,
        order: 6
    },
    '540': {
        width: 960,
        height: 540,
        order: 5
    },
    'qhd': {
        width: 960,
        height: 540,
        order: 5
    },

    // 16:9 resolution first.
    '360': {
        width: 640,
        height: 360,
        order: 4
    },
    '640': {
        width: 640,
        height: 480,
        order: 3
    },
    'vga': {
        width: 640,
        height: 480,
        order: 3
    },

    // 16:9 resolution first.
    '180': {
        width: 320,
        height: 180,
        order: 2
    },
    '320': {
        width: 320,
        height: 240,
        order: 1
    }
};

module.exports = Resolutions;
<|endoftext|>


<commit_before>import React from 'react';
import Row from './Row';
import format from 'date-fns/format';
import isEmpty from 'lodash/isEmpty';
import {newline} from '../../helpers';

import SimpleAccordion  from '../SimpleAccordion';
import Alert            from '../Alert';
import Icon             from '../Icon';

import './SellerProfile.css';

const Body = (props) => {
    const {
        assessed = [],
        unassessed = [],
        case_studies = {},
        representative,
        email,
        phone,
        number_of_employees,
        abn,
        addresses,
        documents = {},
        documentsUrl,
        tools,
        methodologies,
        technologies,
        awards = [],
        certifications = [],
        boards = [],
        public_profile,
        prices = [],
        products = {},
        CaseStudyLink = () => null,
    } = props;

    const documentTitle = {
        financial: 'Financial Statement',
        liability: 'Public Liability Insurance',
        workers: 'Workers Compensation Insurance'
    };

    return (

            <Row title="Areas of expertise" show={!isEmpty(assessed) || !isEmpty(unassessed)}>

                {!isEmpty(assessed) && (

Approved

                        {assessed.map((service, i) => (
                            {service} <Icon value="assessed-tick-nostroke" size={14}/>
                        ))}

                )}

                {!isEmpty(unassessed) && (

Also offers

                        {unassessed.map((service, i) => (
                            {service}
                        ))}

                )}

                <SimpleAccordion title="Learn about assessments">

                    These areas of expertise have not yet been formally assessed by the DTA.  They will be assessed once the seller expresses interest in a matching opportunity.

                </SimpleAccordion>

            </Row>

            <Row title="Case studies" marginBot="true" show={!isEmpty(case_studies)}>

                    {Object.keys(case_studies).map((study, i) => {
                        const {title, service, client} = case_studies[study];
                        const isEvaluated = assessed.includes(service);
                        const badgeStyleName = isEvaluated ? 'evaluated-badges' : 'provides-badges';
                        return (

                                    {/*
                                     CaseStudyLink is a configurable prop.
                                     Since it will point to different areas in different flows.
                                     */}

<CaseStudyLink id={study}>{title}</CaseStudyLink>

{client}

                                    <div styleName={`badges ${badgeStyleName}`}>
                                        {isEvaluated ? (
                                            {service} <Icon value="assessed-tick-nostroke" size={14}/>
                                        ) : (
                                            {service}
                                        )}

                        )
                    })}

            </Row>

            <Row title="Digital products" show={!isEmpty(products)}>

            <SimpleAccordion title="Learn more" show={isEmpty(public_profile) || public_profile !== false}>

                The products below are not assessed or endorsed by the Digital Marketplace.

            </SimpleAccordion>

                {Object.keys(products).map((key, i) => {
                    const product = products[key];
                    return (
                        <div key={`product.${i}`}>

                                    {product.name}

                                    {newline(product.summary)}

                                    Product pricing

                                    Product support

                            {i < Object.keys(products).length-1 && (
)}

                    )
                })}
            </Row>

            <Row title="How we work" show={tools || methodologies || technologies}>
                {methodologies && (

Methodology

{newline(methodologies)}

                )}

                {tools && (

Tools

{newline(tools)}

                )}

                {technologies && (

Technologies

{newline(technologies)}

                )}
            </Row>

            <Row title="Company Details" show={true}>

Authorised representative

                    {representative}

                    { phone && {phone}
}
                    { email && <a href={`mailto:${email}`}>{email}
}

                {number_of_employees && (

Number of employees

{number_of_employees}

                )}

                {abn && (

ABN

                            <a href={`https://abr.business.gov.au/SearchByAbn.aspx?SearchText=${abn}`} rel="external"
                               target="_blank">{abn}

                )}

                {!isEmpty(certifications) && (

Accreditions

                        {certifications.map((certification, i) => (

{certification}

                        ))}

                )}

                {!isEmpty(boards) && (

Industry engagement

                        {boards.map((board, i) => (

{board}

                        ))}

                )}
            </Row>

            <Row title="Location" show={!isEmpty(addresses)}>

                {!isEmpty(addresses) && (

Main Address

                        {Object.keys(addresses)
                            .map((key, i) => {
                            if (!isEmpty(addresses[key])) {
                                return (

                                        {addresses[key].address_line}

                                        {addresses[key].suburb}

                                        {addresses[key].state} {addresses[key].postal_code}

                                )
                            }
                            })}

                )}

            </Row>

            <Row title="Recognition" show={!isEmpty(awards)}>

Awards

                {awards.map((award, i) => (

{award}

                ))}

            </Row>

            <Row title="Documents" show={!isEmpty(documents)}>

                        Document type
                        Expiry

                    {Object.keys(documents).map((key, val) => {
                        const {filename, expiry} = documents[key];
                        if (public_profile === false || key != 'financial') {
                            return (

                                        <a href={`${documentsUrl}${filename}`} rel="external" target="_blank">
                                            {documentTitle[key]}

                                        {expiry && format(new Date(expiry), 'DD/MM/YYYY')}

                            )
                        }
                    })}

  This seller's financial statement has been provided to the DTA. It's available on request from the seller.

            </Row>

    )
};

Body.propTypes = {
    evaluated: React.PropTypes.object,
    provides: React.PropTypes.object,
    documents: React.PropTypes.object,
    documentsUrl: React.PropTypes.string,
    case_studies: React.PropTypes.object,
    representative: React.PropTypes.string,
    email: React.PropTypes.string,
    phone: React.PropTypes.string,
    website: React.PropTypes.string,
    linkedin: React.PropTypes.string,
    abn: React.PropTypes.string,
    addresses: React.PropTypes.array,
    CaseStudyLink: React.PropTypes.func,
    contact_email: React.PropTypes.string,
    contact_phone: React.PropTypes.string,
    contact_name: React.PropTypes.string,
};

export default Body;
<commit_msg>Ignore null product in profile (#314)<commit_after>import React from 'react';
import Row from './Row';
import format from 'date-fns/format';
import isEmpty from 'lodash/isEmpty';
import {newline} from '../../helpers';

import SimpleAccordion  from '../SimpleAccordion';
import Alert            from '../Alert';
import Icon             from '../Icon';

import './SellerProfile.css';

const Body = (props) => {
    const {
        assessed = [],
        unassessed = [],
        case_studies = {},
        representative,
        email,
        phone,
        number_of_employees,
        abn,
        addresses,
        documents = {},
        documentsUrl,
        tools,
        methodologies,
        technologies,
        awards = [],
        certifications = [],
        boards = [],
        public_profile,
        prices = [],
        products = {},
        CaseStudyLink = () => null,
    } = props;

    const documentTitle = {
        financial: 'Financial Statement',
        liability: 'Public Liability Insurance',
        workers: 'Workers Compensation Insurance'
    };

    return (

            <Row title="Areas of expertise" show={!isEmpty(assessed) || !isEmpty(unassessed)}>

                {!isEmpty(assessed) && (

Approved

                        {assessed.map((service, i) => (
                            {service} <Icon value="assessed-tick-nostroke" size={14}/>
                        ))}

                )}

                {!isEmpty(unassessed) && (

Also offers

                        {unassessed.map((service, i) => (
                            {service}
                        ))}

                )}

                <SimpleAccordion title="Learn about assessments">

                    These areas of expertise have not yet been formally assessed by the DTA.  They will be assessed once the seller expresses interest in a matching opportunity.

                </SimpleAccordion>

            </Row>

            <Row title="Case studies" marginBot="true" show={!isEmpty(case_studies)}>

                    {Object.keys(case_studies).map((study, i) => {
                        const {title, service, client} = case_studies[study];
                        const isEvaluated = assessed.includes(service);
                        const badgeStyleName = isEvaluated ? 'evaluated-badges' : 'provides-badges';
                        return (

                                    {/*
                                     CaseStudyLink is a configurable prop.
                                     Since it will point to different areas in different flows.
                                     */}

<CaseStudyLink id={study}>{title}</CaseStudyLink>

{client}

                                    <div styleName={`badges ${badgeStyleName}`}>
                                        {isEvaluated ? (
                                            {service} <Icon value="assessed-tick-nostroke" size={14}/>
                                        ) : (
                                            {service}
                                        )}

                        )
                    })}

            </Row>

            <Row title="Digital products" show={!isEmpty(products)}>

            <SimpleAccordion title="Learn more" show={isEmpty(public_profile) || public_profile !== false}>

                The products below are not assessed or endorsed by the Digital Marketplace.

            </SimpleAccordion>

                {Object.keys(products).map((key, i) => {
                    const product = products[key];
                    if (!isEmpty(product)) {
                        return (
                            <div key={`product.${i}`}>

                                        {product.name}

                                        {newline(product.summary)}

                                        Product pricing

                                        Product support

                                {i < Object.keys(products).length - 1 && (
)}

                        )
                    }
                })}
            </Row>

            <Row title="How we work" show={tools || methodologies || technologies}>
                {methodologies && (

Methodology

{newline(methodologies)}

                )}

                {tools && (

Tools

{newline(tools)}

                )}

                {technologies && (

Technologies

{newline(technologies)}

                )}
            </Row>

            <Row title="Company Details" show={true}>

Authorised representative

                    {representative}

                    { phone && {phone}
}
                    { email && <a href={`mailto:${email}`}>{email}
}

                {number_of_employees && (

Number of employees

{number_of_employees}

                )}

                {abn && (

ABN

                            <a href={`https://abr.business.gov.au/SearchByAbn.aspx?SearchText=${abn}`} rel="external"
                               target="_blank">{abn}

                )}

                {!isEmpty(certifications) && (

Accreditions

                        {certifications.map((certification, i) => (

{certification}

                        ))}

                )}

                {!isEmpty(boards) && (

Industry engagement

                        {boards.map((board, i) => (

{board}

                        ))}

                )}
            </Row>

            <Row title="Location" show={!isEmpty(addresses)}>

                {!isEmpty(addresses) && (

Main Address

                        {Object.keys(addresses)
                            .map((key, i) => {
                            if (!isEmpty(addresses[key])) {
                                return (

                                        {addresses[key].address_line}

                                        {addresses[key].suburb}

                                        {addresses[key].state} {addresses[key].postal_code}

                                )
                            }
                            })}

                )}

            </Row>

            <Row title="Recognition" show={!isEmpty(awards)}>

Awards

                {awards.map((award, i) => (

{award}

                ))}

            </Row>

            <Row title="Documents" show={!isEmpty(documents)}>

                        Document type
                        Expiry

                    {Object.keys(documents).map((key, val) => {
                        const {filename, expiry} = documents[key];
                        if (public_profile === false || key != 'financial') {
                            return (

                                        <a href={`${documentsUrl}${filename}`} rel="external" target="_blank">
                                            {documentTitle[key]}

                                        {expiry && format(new Date(expiry), 'DD/MM/YYYY')}

                            )
                        }
                    })}

  This seller's financial statement has been provided to the DTA. It's available on request from the seller.

            </Row>

    )
};

Body.propTypes = {
    evaluated: React.PropTypes.object,
    provides: React.PropTypes.object,
    documents: React.PropTypes.object,
    documentsUrl: React.PropTypes.string,
    case_studies: React.PropTypes.object,
    representative: React.PropTypes.string,
    email: React.PropTypes.string,
    phone: React.PropTypes.string,
    website: React.PropTypes.string,
    linkedin: React.PropTypes.string,
    abn: React.PropTypes.string,
    addresses: React.PropTypes.array,
    CaseStudyLink: React.PropTypes.func,
    contact_email: React.PropTypes.string,
    contact_phone: React.PropTypes.string,
    contact_name: React.PropTypes.string,
};

export default Body;
<|endoftext|>


<commit_before>'use strict';

var <%= safeSlugname %> = require('../lib/<%= slugname %>.js');

/*
  ======== A Handy Little Nodeunit Reference ========
  https://github.com/caolan/nodeunit

  Test methods:
    test.expect(numAssertions)
    test.done()
  Test assertions:
    test.ok(value, [message])
    test.equal(actual, expected, [message])
    test.notEqual(actual, expected, [message])
    test.deepEqual(actual, expected, [message])
    test.notDeepEqual(actual, expected, [message])
    test.strictEqual(actual, expected, [message])
    test.notStrictEqual(actual, expected, [message])
    test.throws(block, [error], [message])
    test.doesNotThrow(block, [error], [message])
    test.ifError(value)
*/

exports.<%= safeSlugname %> = {
  setUp: function(done) {
    // setup here
    done();
  },
  'no args': function(test) {
    test.expect(1);
    // tests here
    test.equal(<%= safeSlugname %>.awesome(), 'awesome', 'should be awesome.');
    test.done();
  }
};
<commit_msg>Change location of test file<commit_after>'use strict';

var <%= safeSlugname %> = require('../index.js');

/*
  ======== A Handy Little Nodeunit Reference ========
  https://github.com/caolan/nodeunit

  Test methods:
    test.expect(numAssertions)
    test.done()
  Test assertions:
    test.ok(value, [message])
    test.equal(actual, expected, [message])
    test.notEqual(actual, expected, [message])
    test.deepEqual(actual, expected, [message])
    test.notDeepEqual(actual, expected, [message])
    test.strictEqual(actual, expected, [message])
    test.notStrictEqual(actual, expected, [message])
    test.throws(block, [error], [message])
    test.doesNotThrow(block, [error], [message])
    test.ifError(value)
*/

exports.<%= safeSlugname %> = {
  setUp: function(done) {
    // setup here
    done();
  },
  'no args': function(test) {
    test.expect(1);
    // tests here
    test.equal(<%= safeSlugname %>.awesome(), 'awesome', 'should be awesome.');
    test.done();
  }
};
<|endoftext|>


<commit_before>var z = {
    win: $(window),
    body: $(document.body),
    page: $('#container'),
    context: $('#page').data('context'),
    prefix: (function() {
        try {
            var s = window.getComputedStyle(document.body, '');
            return (Array.prototype.slice.call(s).join('').match(/moz|webkit|ms|khtml/)||(s.OLink===''&&['o']))[0];
        } catch (e) {
            return 'moz';
        }
    })(),
    prefixed: function(property) {
        if (!z.prefix) return property;
        return '-' + z.prefix + '-' + property;
    },
    canInstallApps: true,
    allowAnonInstalls: !!$('body').data('allow-anon-installs'),
    enableSearchSuggestions: !!$('body').data('enable-search-suggestions'),
    // if ($('#myDialog li').length > z.confirmBreakNum) add class 'two-col'.
    confirmBreakNum: 6
};

z.prefixUpper = z.prefix[0].toUpperCase() + z.prefix.substr(1);

// Initialize webtrends tracking.
z.page.on('fragmentloaded', webtrendsAsyncInit);

(function() {
    _.extend(z, {
        nav: BrowserUtils(),
        canInstallApps: z.body.data('allow-installs')
    });

    function trigger() {
        $(window).trigger('saferesize');
    }
    window.addEventListener('resize', _.debounce(trigger, 200), false);
})();

$(document).ready(function() {
    // Initialize email links.
    z.page.on('fragmentloaded', function() {
        $('span.emaillink').each(function() {
            var $this = $(this);
            $this.find('.i').remove();
            var em = $this.text().split('').reverse().join('');
            $this.prev('a').attr('href', 'mailto:' + em);
        });
    });
    if (z.readonly) {
        $('form[method=post]')
            .before(gettext('This feature is temporarily disabled while we ' +
                            'perform website maintenance. Please check back ' +
                            'a little later.'))
            .find('button, input, select, textarea').attr('disabled', true)
            .addClass('disabled');
    }
    var data_user = $('body').data('user');
    _.extend(z, {
        anonymous: data_user.anonymous,
        pre_auth: data_user.pre_auth
    });

    // Set cookie if user is on B2G.
    // TODO: remove this once we allow purchases on desktop/android.
    if (document.cookie && z.capabilities.gaia) {
        document.cookie = 'gaia=true;path=/';
    }
    // Sets a tablet cookie.
    if (document.cookie && z.capabilities.tablet) {
        document.cookie = 'tablet=true;path=/';
    }

    stick.basic();
});

// If we're inside the Marketplace app, open external links in the Browser.
z.page.on('click', 'a.external, a[rel=external]', function() {
    if (z.capabilities.chromeless) {
        $(this).attr('target', '_blank');
    }
});

if (!localStorage.seen_aurora_pitch) {
    $('.incompatible-browser').addClass('active');
}

// Clicking cancel should dismiss notification boxes.
z.page.on('click', '.notification-box .close', function() {
    if (z.capabilities.localStorage) {
        localStorage.seen_aurora_pitch = '1';
    }
    $(this).closest('.notification-box').removeClass('active');
}).on('click', '.incompatible.button', _pd(function(e) {
    if (z.capabilities.localStorage) {
        delete localStorage.seen_aurora_pitch;
    }
    $('.incompatible-browser').addClass('active');
}));

z.page.on('fragmentloaded', function() {
    z.apps = {};
    if (z.capabilities.webApps) {
        // Get list of installed apps and mark as such.
        r = window.navigator.mozApps.getInstalled();
        r.onsuccess = function() {
            _.each(r.result, function(val) {
                z.apps[val.manifestURL] = val;
                $(window).trigger('app_install_success',
                                  [val, {'manifest_url': val.manifestURL}, false]);
            });
        };
    }

    if (!z.canInstallApps) {
        $(window).trigger('app_install_disabled');
    }

    // Navigation toggle.
    var $header = $('#site-header'),
        $nav = $header.find('nav ul'),
        $outer = $('html, body');
    $header.on('click', '.menu-button', _pd(function() {
        $nav.addClass('active');
        $('.nav-overlay').addClass('show');
    })).on('click', '.region', _pd(function() {
        $outer.animate({scrollTop: $outer.height()}, 1000);
    }));

    $(window).bind('overlay_dismissed', function() {
       $nav.removeClass('active');
    });

    // Hijack external links if we're on mobile.
    if (z.capabilities.touch) {
        $('a[rel=external]').attr('target', '_blank');
    }

    // Header controls.
    $('header').on('click', '.header-button', function(e) {
        var $this = $(this),
            $btns = $('.header-button');

        if ($this.hasClass('dismiss')) {
            // Dismiss looks like back but actually just dismisses an overlay.
            $('#filters').removeClass('show');
        } else if ($this.hasClass('filter')) {
            // `getVars()` defaults to use location.search.
            var sortoption = z.getVars();

            $('#filter-sort li a').removeClass('sel');
            switch(sortoption.sort) {
                case 'None':
                    $('#filter-sort li.relevancy a').addClass('sel');
                    break;
                case 'popularity':
                    $('#filter-sort li.popularity a').addClass('sel');
                    break;
                case 'rating':
                    $('#filter-sort li.rating a').addClass('sel');
                    break;
                case '':
                case undefined:
                    // If there's nothing selected, the first one is always the
                    // default.
                    $('#filter-sort li:first-child a').addClass('sel');
            }
            $('#filters').addClass('show');
        } else if ($this.hasClass('search')) {
            z.body.addClass('show-search');
            $btns.blur();
            $('#search-q').focus();
        } else if ($this.hasClass('cancel')) {
            z.body.removeClass('show-search');
            $('#search-q').blur();
            $btns.blur();
        }

        z.page.on('fragmentloaded', function() {
            z.body.removeClass('show-search');
            $('#search-q').blur();
        });
        e.preventDefault();
    });

});
<commit_msg>use z.body<commit_after>var z = {
    win: $(window),
    body: $(document.body),
    page: $('#container'),
    context: $('#page').data('context'),
    prefix: (function() {
        try {
            var s = window.getComputedStyle(document.body, '');
            return (Array.prototype.slice.call(s).join('').match(/moz|webkit|ms|khtml/)||(s.OLink===''&&['o']))[0];
        } catch (e) {
            return 'moz';
        }
    })(),
    prefixed: function(property) {
        if (!z.prefix) return property;
        return '-' + z.prefix + '-' + property;
    },
    canInstallApps: true,
    allowAnonInstalls: !!$('body').data('allow-anon-installs'),
    enableSearchSuggestions: !!$('body').data('enable-search-suggestions'),
    // if ($('#myDialog li').length > z.confirmBreakNum) add class 'two-col'.
    confirmBreakNum: 6
};

z.prefixUpper = z.prefix[0].toUpperCase() + z.prefix.substr(1);

// Initialize webtrends tracking.
z.page.on('fragmentloaded', webtrendsAsyncInit);

(function() {
    _.extend(z, {
        nav: BrowserUtils(),
        canInstallApps: z.body.data('allow-installs')
    });

    function trigger() {
        $(window).trigger('saferesize');
    }
    window.addEventListener('resize', _.debounce(trigger, 200), false);
})();

$(document).ready(function() {
    // Initialize email links.
    z.page.on('fragmentloaded', function() {
        $('span.emaillink').each(function() {
            var $this = $(this);
            $this.find('.i').remove();
            var em = $this.text().split('').reverse().join('');
            $this.prev('a').attr('href', 'mailto:' + em);
        });
    });
    if (z.readonly) {
        $('form[method=post]')
            .before(gettext('This feature is temporarily disabled while we ' +
                            'perform website maintenance. Please check back ' +
                            'a little later.'))
            .find('button, input, select, textarea').attr('disabled', true)
            .addClass('disabled');
    }
    var data_user = $('body').data('user');
    _.extend(z, {
        anonymous: data_user.anonymous,
        pre_auth: data_user.pre_auth
    });

    // Set cookie if user is on B2G.
    // TODO: remove this once we allow purchases on desktop/android.
    if (document.cookie && z.capabilities.gaia) {
        document.cookie = 'gaia=true;path=/';
    }
    // Sets a tablet cookie.
    if (document.cookie && z.capabilities.tablet) {
        document.cookie = 'tablet=true;path=/';
    }

    stick.basic();
});

// If we're inside the Marketplace app, open external links in the Browser.
z.page.on('click', 'a.external, a[rel=external]', function() {
    if (z.capabilities.chromeless) {
        $(this).attr('target', '_blank');
    }
});

if (!localStorage.seen_aurora_pitch) {
    $('.incompatible-browser').addClass('active');
}

// Clicking cancel should dismiss notification boxes.
z.body.on('click', '.notification-box .close', function() {
    if (z.capabilities.localStorage) {
        localStorage.seen_aurora_pitch = '1';
    }
    $(this).closest('.notification-box').removeClass('active');
}).on('click', '.incompatible.button', _pd(function(e) {
    if (z.capabilities.localStorage) {
        delete localStorage.seen_aurora_pitch;
    }
    $('.incompatible-browser').addClass('active');
}));

z.page.on('fragmentloaded', function() {
    z.apps = {};
    if (z.capabilities.webApps) {
        // Get list of installed apps and mark as such.
        r = window.navigator.mozApps.getInstalled();
        r.onsuccess = function() {
            _.each(r.result, function(val) {
                z.apps[val.manifestURL] = val;
                $(window).trigger('app_install_success',
                                  [val, {'manifest_url': val.manifestURL}, false]);
            });
        };
    }

    if (!z.canInstallApps) {
        $(window).trigger('app_install_disabled');
    }

    // Navigation toggle.
    var $header = $('#site-header'),
        $nav = $header.find('nav ul'),
        $outer = $('html, body');
    $header.on('click', '.menu-button', _pd(function() {
        $nav.addClass('active');
        $('.nav-overlay').addClass('show');
    })).on('click', '.region', _pd(function() {
        $outer.animate({scrollTop: $outer.height()}, 1000);
    }));

    $(window).bind('overlay_dismissed', function() {
       $nav.removeClass('active');
    });

    // Hijack external links if we're on mobile.
    if (z.capabilities.touch) {
        $('a[rel=external]').attr('target', '_blank');
    }

    // Header controls.
    $('header').on('click', '.header-button', function(e) {
        var $this = $(this),
            $btns = $('.header-button');

        if ($this.hasClass('dismiss')) {
            // Dismiss looks like back but actually just dismisses an overlay.
            $('#filters').removeClass('show');
        } else if ($this.hasClass('filter')) {
            // `getVars()` defaults to use location.search.
            var sortoption = z.getVars();

            $('#filter-sort li a').removeClass('sel');
            switch(sortoption.sort) {
                case 'None':
                    $('#filter-sort li.relevancy a').addClass('sel');
                    break;
                case 'popularity':
                    $('#filter-sort li.popularity a').addClass('sel');
                    break;
                case 'rating':
                    $('#filter-sort li.rating a').addClass('sel');
                    break;
                case '':
                case undefined:
                    // If there's nothing selected, the first one is always the
                    // default.
                    $('#filter-sort li:first-child a').addClass('sel');
            }
            $('#filters').addClass('show');
        } else if ($this.hasClass('search')) {
            z.body.addClass('show-search');
            $btns.blur();
            $('#search-q').focus();
        } else if ($this.hasClass('cancel')) {
            z.body.removeClass('show-search');
            $('#search-q').blur();
            $btns.blur();
        }

        z.page.on('fragmentloaded', function() {
            z.body.removeClass('show-search');
            $('#search-q').blur();
        });
        e.preventDefault();
    });

});
<|endoftext|>


<commit_before>(function () {
  'use strict';

  var pathRule = /^\/([0-9a-z]+)(\/|$)/;

  function helper (id, next) {
    var i = $.$('img.pic');
    if (i) {
      $.openImage(i.src);
      return;
    }
    // first stage
    $.openLinkByPost('', {
      op: 'view',
      id: id,
      pre: 1,
      next: next,
    });
  }

  $.register({
    rule: {
      host: [
        /^((img(paying|mega))|imzdrop)\.com$/,
        /^(www\.)?imgsee\.me$/,
        /^imgclick\.net$/,
        /^(uploadrr|imageeer)\.com$/,
      ],
      path: pathRule,
    },
    ready: function (m) {
      var f = $.$('form > input[name="next"]');
      helper(m.path[1], f && f.value);
    },
  });

  $.register({
    rule: {
      host: /^imgrock\.net$/,
      path: pathRule,
    },
    ready: function (m) {
      helper(m.path[1], 'Continue to Image...');
    },
  });

})();
// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>imgsee.me<commit_after>(function () {
  'use strict';

  var pathRule = /^\/([0-9a-z]+)(\.|\/|$)/;

  function helper (id, next) {
    var i = $.$('img.pic');
    if (i) {
      $.openImage(i.src);
      return;
    }
    // first stage
    $.openLinkByPost('', {
      op: 'view',
      id: id,
      pre: 1,
      next: next,
    });
  }

  $.register({
    rule: {
      host: [
        /^((img(paying|mega))|imzdrop)\.com$/,
        /^(www\.)?imgsee\.me$/,
        /^imgclick\.net$/,
        /^(uploadrr|imageeer)\.com$/,
      ],
      path: pathRule,
    },
    ready: function (m) {
      var f = $.$('form > input[name="next"]');
      helper(m.path[1], f && f.value);
    },
  });

  $.register({
    rule: {
      host: /^imgrock\.net$/,
      path: pathRule,
    },
    ready: function (m) {
      helper(m.path[1], 'Continue to Image...');
    },
  });

})();
// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>/* Copyright (c) 2012-2013 LevelUP contributors
 * See list at <https://github.com/rvagg/node-levelup#contributing>
 * MIT +no-false-attribs License
 * <https://github.com/rvagg/node-levelup/blob/master/LICENSE>
 */

var encodings = require('./encodings')

function getKeyEncoder (options, op) {
  var type = ((op && op.keyEncoding) || options.keyEncoding) || 'utf8'
  return encodings[type] || type
}

function getValueEncoder (options, op) {
  var type = (((op && (op.valueEncoding || op.encoding))
      || options.valueEncoding || options.encoding)) || 'utf8'
  return encodings[type] || type
}

function encodeKey (key, options, op) {
  return getKeyEncoder(options, op).encode(key)
}

function encodeValue (value, options, op) {
  return getValueEncoder(options, op).encode(value)
}

function decodeKey (key, options) {
  return getKeyEncoder(options).decode(key)
}

function decodeValue (value, options) {
  return getValueEncoder(options).decode(value)
}

function isValueAsBuffer (options, op) {
  return getValueEncoder(options, op).buffer
}

function isKeyAsBuffer (options, op) {
  return getKeyEncoder(options, op).buffer
}

module.exports = {
    encodeKey       : encodeKey
  , encodeValue     : encodeValue
  , isValueAsBuffer : isValueAsBuffer
  , isKeyAsBuffer   : isKeyAsBuffer
  , decodeValue     : decodeValue
  , decodeKey       : decodeKey
}
<commit_msg>document with comments<commit_after>/* Copyright (c) 2012-2013 LevelUP contributors
 * See list at <https://github.com/rvagg/node-levelup#contributing>
 * MIT +no-false-attribs License
 * <https://github.com/rvagg/node-levelup/blob/master/LICENSE>
 */

var encodings = require('./encodings')

function getKeyEncoder (options, op) {
  var type = ((op && op.keyEncoding) || options.keyEncoding) || 'utf8'
  return encodings[type] || type
}

function getValueEncoder (options, op) {
  var type = (((op && (op.valueEncoding || op.encoding))
      || options.valueEncoding || options.encoding)) || 'utf8'
  return encodings[type] || type
}

/*
  Encode a key.
  This method takes two options, because the leveldb instance
  has options, and this operation (a put, del, or batch)
  also has options that may override the leveldb's options.
*/

function encodeKey (key, options, op) {
  return getKeyEncoder(options, op).encode(key)
}

/*
  Encode a value.
  Takes 2 options, for the same reason as encodeKey
*/

function encodeValue (value, options, op) {
  return getValueEncoder(options, op).encode(value)
}

/*
  Decode an encoded key
*/

function decodeKey (key, options) {
  return getKeyEncoder(options).decode(key)
}

/*
  Decode an encoded value
*/

function decodeValue (value, options) {
  return getValueEncoder(options).decode(value)
}

/*
  check whether this value should be requested as a buffer
  (if false, then it will be a string)
  this allows an optimization in leveldown where leveldown
  retrives a string directly, and thus avoids a memory copy.
*/

function isValueAsBuffer (options, op) {
  return getValueEncoder(options, op).buffer
}

/*
  check whether a given key should be requested as a buffer.
*/

function isKeyAsBuffer (options, op) {
  return getKeyEncoder(options, op).buffer
}

module.exports = {
    encodeKey       : encodeKey
  , encodeValue     : encodeValue
  , isValueAsBuffer : isValueAsBuffer
  , isKeyAsBuffer   : isKeyAsBuffer
  , decodeValue     : decodeValue
  , decodeKey       : decodeKey
}
<|endoftext|>


<commit_before>$.register({
  rule: {
    host: /^imglocker\.com$/,
    path: /^(\/\w+)\/([^.]+\.\w+)$/,
  },
  start: function (m) {
    'use strict';
    var url = _.T('//img.imglocker.com{0}_{1}');
    $.openImage(url(m.path[1], m.path[2]));
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>imglocker.com<commit_after>$.register({
  rule: {
    host: /^imglocker\.com$/,
    path: /^(\/\w+)\/([^.]+\.\w+)(\.html)?$/,
  },
  start: function (m) {
    'use strict';
    var url = _.T('//img.imglocker.com{0}_{1}');
    $.openImage(url(m.path[1], m.path[2]));
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>const SekshiModule = require('../Module')
const command = require('../command')
const debug = require('debug')('sekshi:song-ban')
const moment = require('moment')
const mongoose = require('mongoose')

const BannedMedia = mongoose.modelNames().indexOf('BannedMedia') === -1
  ? mongoose.model('BannedMedia', {
      format: Number,
      cid: String,
      reason: String,
      time: { type: Date, default: Date.now },
      moderator: { type: Number, ref: 'User' }
    })
  : mongoose.model('BannedMedia')

export default class SongBan extends SekshiModule {
  constructor(sekshi, options) {
    super(sekshi, options)

    this.author = 'ReAnna'
    this.description = 'Bans songs from being played ever again.'

    this.BannedMedia = BannedMedia

    this.onAdvance = this.onAdvance.bind(this)
  }

  init() {
    this.sekshi.on(this.sekshi.ADVANCE, this.onAdvance)
  }
  destroy() {
    this.sekshi.removeListener(this.sekshi.ADVANCE, this.onAdvance)
  }

  onAdvance(booth, { media }) {
    BannedMedia.findOne({ cid: media.cid, format: media.format }).exec()
      .then(banned => {
        const modSkip = this.sekshi.getModule('modskip')
        if (banned && modSkip) {
          modSkip.skip(this.sekshi.getSelf(), banned.reason || 'This song was blacklisted.')
        }
      })
  }

  @command('songban', 'bansong', { role: command.ROLE.BOUNCER })
  songban(user, ...reason) {
    reason = reason.join(' ')
    const media = this.sekshi.getCurrentMedia()
    BannedMedia.create({
      format: media.format,
      cid: media.cid,
      reason: reason,
      moderator: user.id
    })
      .then(banned => {
        this.sekshi.sendChat(`@${user.username} This song has now been blacklisted.`)
      })
  }

  @command('songunban', 'unbansong', { role: command.ROLE.BOUNCER })
  songunban(user, cid) {
    BannedMedia.findOne({ cid: cid }).exec()
      .then(banned => {
        if (banned) BannedMedia.remove({ _id: banned._id })
      })
  }

  @command('banskip', 'bs', { role: command.ROLE.BOUNCER })
  banskip(user, ...reason) {
    const modSkip = this.sekshi.getModule('modskip')
    if (modSkip) modSkip.skip(user, ...reason)
    setTimeout(() => { this.songban(user, ...reason) }, 300)
  }
}
<commit_msg>songban: lockskip blacklisted songs<commit_after>const SekshiModule = require('../Module')
const command = require('../command')
const debug = require('debug')('sekshi:song-ban')
const moment = require('moment')
const mongoose = require('mongoose')

const BannedMedia = mongoose.modelNames().indexOf('BannedMedia') === -1
  ? mongoose.model('BannedMedia', {
      format: Number,
      cid: String,
      reason: String,
      time: { type: Date, default: Date.now },
      moderator: { type: Number, ref: 'User' }
    })
  : mongoose.model('BannedMedia')

export default class SongBan extends SekshiModule {
  constructor(sekshi, options) {
    super(sekshi, options)

    this.author = 'ReAnna'
    this.description = 'Bans songs from being played ever again.'

    this.BannedMedia = BannedMedia

    this.onAdvance = this.onAdvance.bind(this)
  }

  init() {
    this.sekshi.on(this.sekshi.ADVANCE, this.onAdvance)
  }
  destroy() {
    this.sekshi.removeListener(this.sekshi.ADVANCE, this.onAdvance)
  }

  onAdvance(booth, { media }) {
    BannedMedia.findOne({ cid: media.cid, format: media.format }).exec()
      .then(banned => {
        const modSkip = this.sekshi.getModule('modskip')
        if (banned && modSkip) {
          modSkip.lockskip(this.sekshi.getSelf(),
                           banned.reason || 'This song was blacklisted.')
        }
      })
  }

  @command('songban', 'bansong', { role: command.ROLE.BOUNCER })
  songban(user, ...reason) {
    reason = reason.join(' ')
    const media = this.sekshi.getCurrentMedia()
    BannedMedia.create({
      format: media.format,
      cid: media.cid,
      reason: reason,
      moderator: user.id
    })
      .then(banned => {
        this.sekshi.sendChat(`@${user.username} This song has now been blacklisted.`)
      })
  }

  @command('songunban', 'unbansong', { role: command.ROLE.BOUNCER })
  songunban(user, cid) {
    BannedMedia.findOne({ cid: cid }).exec()
      .then(banned => {
        if (banned) BannedMedia.remove({ _id: banned._id })
      })
  }

  @command('banskip', 'bs', { role: command.ROLE.BOUNCER })
  banskip(user, ...reason) {
    const modSkip = this.sekshi.getModule('modskip')
    if (modSkip) modSkip.skip(user, ...reason)
    setTimeout(() => { this.songban(user, ...reason) }, 300)
  }
}
<|endoftext|>