<commit_before>/*jslint white: true*/
/*global module */
module.exports = function (config) {
    'use strict';
    config.set({
        basePath: '../../',
        frameworks: ['jasmine', 'requirejs', 'es6-shim'],
        client: {
            jasmine: {
                failFast: false,
                DEFAULT_TIMEOUT_INTERVAL: 20000
            }
        },
        plugins: [
            'karma-jasmine',
            'karma-chrome-launcher',
            'karma-firefox-launcher',
            'karma-phantomjs-launcher',
            'karma-requirejs',
            'karma-coverage',
            'karma-mocha-reporter',
            'karma-es6-shim'
        ],
        preprocessors: {
            'kbase-extension/static/kbase/js/**/*.js': ['coverage']
        },
        files: [
            'kbase-extension/static/narrative_paths.js',
            {pattern: 'test/unit/spec/**/*.js', included: false},
            // {pattern: 'test/unit/spec/appWidgets/input/newObjectInputSpec.js', included: false},
            // {pattern: 'test/unit/spec/common/validate-Spec.js', included: false},
            {pattern: 'node_modules/string.prototype.startswith/startswith.js', included: true},
            {pattern: 'node_modules/string.prototype.endswith/endswith.js', included: true},
            {pattern: 'node_modules/jasmine-ajax/lib/mock-ajax.js', included: true},
            {pattern: 'kbase-extension/static/ext_components/kbase-ui-plugin-catalog/src/plugin/modules/data/categories.yml', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.css', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/templates/**/*.html', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/config/**/*.json', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/config/**/*.yaml', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.js', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.gif', included: false, served: true},
            {pattern: 'test/unit/testConfig.json', included: false, served: true, nocache: true},
            {pattern: 'test/*.tok', included: false, served: true, nocache: true},
            {pattern: 'test/data/**/*', included: false, served: true},
            'test/unit/testUtil.js',
            'test/unit/test-main.js'
        ],
        exclude: [
            'kbase-extension/static/buildTools/*.js',
            'kbase-extension/static/ext_components/**/test/**/*.js',
            'kbase-extension/static/kbase/js/patched-components/**/*'
        ],
        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['mocha', 'coverage'],
        coverageReporter: {
            type: 'html',
            dir: 'js-coverage/',
            reporters: [{
                type: 'html',
                subdir: 'html'
            }, {
                type: 'lcov',
                subdir: 'lcov'
            }],
            includeAllSources: true
        },
        // web server port
        port: 9876,
        // enable / disable colors in the output (reporters and logs)
        colors: true,
        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,
        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: false,
        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['ChromeHeadless'], //['PhantomJS', 'Firefox', 'ChromeHeadless'],
        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        // phantomjsLauncher: {
        //     options: {
        //         settings: {
        //             webSecurityEnabled: false
        //         }
        //     }
        // },
        browserNoActivityTimeout: 30000,
        singleRun: true,
        proxies: {
            '/narrative/static/': '/base/kbase-extension/static/',
            '/narrative/static/base': 'http://localhost:32323/narrative/static/base',
            '/narrative/static/notebook': 'http://localhost:32323/narrative/static/notebook',
            '/narrative/static/components': 'http://localhost:32323/narrative/static/components',
            '/narrative/static/services': 'http://localhost:32323/narrative/static/services',
            '/narrative/static/bidi': 'http://localhost:32323/narrative/static/bidi',
            '/static/kbase/config': '/base/kbase-extension/static/kbase/config',
            '/test/': '/base/test/'
        },
        client: {
          requireJsShowNoTimestampsError: '^(?!.*(^/narrative/static/))',
          clearContext: false
        },
        concurrency: Infinity

    });
};
<commit_msg>don't report coverage for generated api clients<commit_after>/*jslint white: true*/
/*global module */
module.exports = function (config) {
    'use strict';
    config.set({
        basePath: '../../',
        frameworks: ['jasmine', 'requirejs', 'es6-shim'],
        client: {
            jasmine: {
                failFast: false,
                DEFAULT_TIMEOUT_INTERVAL: 20000
            }
        },
        plugins: [
            'karma-jasmine',
            'karma-chrome-launcher',
            'karma-firefox-launcher',
            'karma-phantomjs-launcher',
            'karma-requirejs',
            'karma-coverage',
            'karma-mocha-reporter',
            'karma-es6-shim'
        ],
        preprocessors: {
            'kbase-extension/static/kbase/js/*/!(api)/**/*.js': ['coverage'],
            'kbase-extension/static/kbase/js/api/!(*[Cc]*)*.js': ['coverage']
        },
        files: [
            'kbase-extension/static/narrative_paths.js',
            {pattern: 'test/unit/spec/**/*.js', included: false},
            // {pattern: 'test/unit/spec/appWidgets/input/newObjectInputSpec.js', included: false},
            // {pattern: 'test/unit/spec/common/validate-Spec.js', included: false},
            {pattern: 'node_modules/string.prototype.startswith/startswith.js', included: true},
            {pattern: 'node_modules/string.prototype.endswith/endswith.js', included: true},
            {pattern: 'node_modules/jasmine-ajax/lib/mock-ajax.js', included: true},
            {pattern: 'kbase-extension/static/ext_components/kbase-ui-plugin-catalog/src/plugin/modules/data/categories.yml', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.css', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/templates/**/*.html', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/config/**/*.json', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/config/**/*.yaml', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.js', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.gif', included: false, served: true},
            {pattern: 'test/unit/testConfig.json', included: false, served: true, nocache: true},
            {pattern: 'test/*.tok', included: false, served: true, nocache: true},
            {pattern: 'test/data/**/*', included: false, served: true},
            'test/unit/testUtil.js',
            'test/unit/test-main.js'
        ],
        exclude: [
            'kbase-extension/static/buildTools/*.js',
            'kbase-extension/static/ext_components/**/test/**/*.js',
            'kbase-extension/static/kbase/js/patched-components/**/*'
        ],
        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['mocha', 'coverage'],
        coverageReporter: {
            type: 'html',
            dir: 'js-coverage/',
            reporters: [{
                type: 'html',
                subdir: 'html'
            }, {
                type: 'lcov',
                subdir: 'lcov'
            }],
            includeAllSources: true
        },
        // web server port
        port: 9876,
        // enable / disable colors in the output (reporters and logs)
        colors: true,
        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,
        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: false,
        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['ChromeHeadless'], //['PhantomJS', 'Firefox', 'ChromeHeadless'],
        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        // phantomjsLauncher: {
        //     options: {
        //         settings: {
        //             webSecurityEnabled: false
        //         }
        //     }
        // },
        browserNoActivityTimeout: 30000,
        singleRun: true,
        proxies: {
            '/narrative/static/': '/base/kbase-extension/static/',
            '/narrative/static/base': 'http://localhost:32323/narrative/static/base',
            '/narrative/static/notebook': 'http://localhost:32323/narrative/static/notebook',
            '/narrative/static/components': 'http://localhost:32323/narrative/static/components',
            '/narrative/static/services': 'http://localhost:32323/narrative/static/services',
            '/narrative/static/bidi': 'http://localhost:32323/narrative/static/bidi',
            '/static/kbase/config': '/base/kbase-extension/static/kbase/config',
            '/test/': '/base/test/'
        },
        client: {
          requireJsShowNoTimestampsError: '^(?!.*(^/narrative/static/))',
          clearContext: false
        },
        concurrency: Infinity

    });
};
<|endoftext|>


<commit_before>/*jslint white: true*/
/*global module */
module.exports = function (config) {
    'use strict';
    config.set({
        basePath: '../../',
        frameworks: ['jasmine', 'requirejs', 'es6-shim'],
        plugins: [
            'karma-jasmine',
            'karma-chrome-launcher',
            'karma-firefox-launcher',
            'karma-phantomjs-launcher',
            'karma-requirejs',
            'karma-coverage',
            'karma-mocha-reporter',
            'karma-es6-shim'
        ],
        preprocessors: {
            'kbase-extension/static/kbase/js/**/*.js': ['coverage']
        },
        files: [
            'kbase-extension/static/narrative_paths.js',
            // {pattern: 'test/unit/spec/**/*.js', included: false},
            {pattern: 'test/unit/spec/narrative_core/staticNarrativesManager-spec.js', included: false},
            // {pattern: 'test/unit/spec/narrative_core/upload/fileUploadWidget-spec.js', included: false},
            {pattern: 'node_modules/string.prototype.startswith/startswith.js', included: true},
            {pattern: 'node_modules/string.prototype.endswith/endswith.js', included: true},
            {pattern: 'node_modules/jasmine-ajax/lib/mock-ajax.js', included: true},
            {pattern: 'kbase-extension/static/ext_components/kbase-ui-plugin-catalog/src/plugin/modules/data/categories.yml', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.css', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/templates/**/*.html', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/config/**/*.json', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/config/**/*.yaml', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.js', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.gif', included: false, served: true},
            {pattern: 'test/unit/testConfig.json', included: false, served: true, nocache: true},
            {pattern: 'test/*.tok', included: false, served: true, nocache: true},
            {pattern: 'test/data/**/*', included: false, served: true},
            'test/unit/testUtil.js',
            'test/unit/test-main.js'
        ],
        exclude: [
            'kbase-extension/static/buildTools/*.js',
            'kbase-extension/static/ext_components/**/test/**/*.js',
            'kbase-extension/static/kbase/js/patched-components/**/*'
        ],
        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['mocha', 'coverage'],
        coverageReporter: {
            type: 'html',
            dir: 'js-coverage/',
            reporters: [{
                type: 'html',
                subdir: 'html'
            }, {
                type: 'lcov',
                subdir: 'lcov'
            }],
            includeAllSources: true
        },
        // web server port
        port: 9876,
        // enable / disable colors in the output (reporters and logs)
        colors: true,
        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,
        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: false,
        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['ChromeHeadless'], //['PhantomJS', 'Firefox', 'ChromeHeadless'],
        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        // phantomjsLauncher: {
        //     options: {
        //         settings: {
        //             webSecurityEnabled: false
        //         }
        //     }
        // },
        browserNoActivityTimeout: 30000,
        singleRun: true,
        proxies: {
            '/narrative/static/': '/base/kbase-extension/static/',
            '/narrative/static/base': 'http://localhost:32323/narrative/static/base',
            '/narrative/static/notebook': 'http://localhost:32323/narrative/static/notebook',
            '/narrative/static/components': 'http://localhost:32323/narrative/static/components',
            '/narrative/static/services': 'http://localhost:32323/narrative/static/services',
            '/narrative/static/bidi': 'http://localhost:32323/narrative/static/bidi',
            '/static/kbase/config': '/base/kbase-extension/static/kbase/config',
            '/test/': '/base/test/'
        },
        client: {
            requireJsShowNoTimestampsError: '^(?!.*(^/narrative/static/))'
        },
        concurrency: Infinity

    });
};
<commit_msg>restore disabled front end tests<commit_after>/*jslint white: true*/
/*global module */
module.exports = function (config) {
    'use strict';
    config.set({
        basePath: '../../',
        frameworks: ['jasmine', 'requirejs', 'es6-shim'],
        plugins: [
            'karma-jasmine',
            'karma-chrome-launcher',
            'karma-firefox-launcher',
            'karma-phantomjs-launcher',
            'karma-requirejs',
            'karma-coverage',
            'karma-mocha-reporter',
            'karma-es6-shim'
        ],
        preprocessors: {
            'kbase-extension/static/kbase/js/**/*.js': ['coverage']
        },
        files: [
            'kbase-extension/static/narrative_paths.js',
            {pattern: 'test/unit/spec/**/*.js', included: false},
            // {pattern: 'test/unit/spec/narrative_core/staticNarrativesManager-spec.js', included: false},
            // {pattern: 'test/unit/spec/narrative_core/upload/fileUploadWidget-spec.js', included: false},
            {pattern: 'node_modules/string.prototype.startswith/startswith.js', included: true},
            {pattern: 'node_modules/string.prototype.endswith/endswith.js', included: true},
            {pattern: 'node_modules/jasmine-ajax/lib/mock-ajax.js', included: true},
            {pattern: 'kbase-extension/static/ext_components/kbase-ui-plugin-catalog/src/plugin/modules/data/categories.yml', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.css', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/templates/**/*.html', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/config/**/*.json', included: false, served: true},
            {pattern: 'kbase-extension/static/kbase/config/**/*.yaml', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.js', included: false, served: true},
            {pattern: 'kbase-extension/static/**/*.gif', included: false, served: true},
            {pattern: 'test/unit/testConfig.json', included: false, served: true, nocache: true},
            {pattern: 'test/*.tok', included: false, served: true, nocache: true},
            {pattern: 'test/data/**/*', included: false, served: true},
            'test/unit/testUtil.js',
            'test/unit/test-main.js'
        ],
        exclude: [
            'kbase-extension/static/buildTools/*.js',
            'kbase-extension/static/ext_components/**/test/**/*.js',
            'kbase-extension/static/kbase/js/patched-components/**/*'
        ],
        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['mocha', 'coverage'],
        coverageReporter: {
            type: 'html',
            dir: 'js-coverage/',
            reporters: [{
                type: 'html',
                subdir: 'html'
            }, {
                type: 'lcov',
                subdir: 'lcov'
            }],
            includeAllSources: true
        },
        // web server port
        port: 9876,
        // enable / disable colors in the output (reporters and logs)
        colors: true,
        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,
        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: false,
        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['ChromeHeadless'], //['PhantomJS', 'Firefox', 'ChromeHeadless'],
        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        // phantomjsLauncher: {
        //     options: {
        //         settings: {
        //             webSecurityEnabled: false
        //         }
        //     }
        // },
        browserNoActivityTimeout: 30000,
        singleRun: true,
        proxies: {
            '/narrative/static/': '/base/kbase-extension/static/',
            '/narrative/static/base': 'http://localhost:32323/narrative/static/base',
            '/narrative/static/notebook': 'http://localhost:32323/narrative/static/notebook',
            '/narrative/static/components': 'http://localhost:32323/narrative/static/components',
            '/narrative/static/services': 'http://localhost:32323/narrative/static/services',
            '/narrative/static/bidi': 'http://localhost:32323/narrative/static/bidi',
            '/static/kbase/config': '/base/kbase-extension/static/kbase/config',
            '/test/': '/base/test/'
        },
        client: {
            requireJsShowNoTimestampsError: '^(?!.*(^/narrative/static/))'
        },
        concurrency: Infinity

    });
};
<|endoftext|>


<commit_before>var _moduleFor = require('./internal/_moduleFor');
var _curryN = require('./internal/_curryN');
var _curry = require('./internal/_curry');
var _isFunction = require('./internal/_isFunction');
var _slice = require('./internal/_slice');
var _equal = require('./internal/_equal');

var Semigroup = require('./Semigroup');

var Monoid = module.exports;

/**
 * Returns the empty value for the type of value.
 *
 * A monoid should obey the law for all values a: _.concat(_.empty(a), a) is equal to _.concat(a, _.empty(a)) is equal to a
 *
 * @sig Monoid m => m -> m
 * @since 0.4.0
 * @param {Monoid} value
 * @returns {Monoid} the empty value for the type
 * @example
 *
 *      _.empty([1,2,3]); // []
 */
Monoid.empty = _curry(function(value) {
    var M = _moduleFor(value);
    return M.empty();
});

/**
 * Returns true if the value is equal to the empty value for the type
 *
 * @sig Monoid m => m -> Boolean
 * @since 0.4.0
 * @param {Monoid} value the monoid being checked
 * @returns {Boolean}
 * @example
 *
 *      _.empty([]);      // true
 *      _.empty([1,2,3]); // false
 *      _.empty('');      // true
 *      _.empty('abc');   // false
 */
Monoid.isEmpty = _curry(function(value) {
    return _equal(value, Monoid.empty(value));
});

Monoid.concat = Semigroup.concat;
Monoid.concatAll = Semigroup.concatAll;

Monoid.member = function(value) {
    return Semigroup.member(value) && _isFunction(_moduleFor(value).empty);
};
<commit_msg>Added cycleN to monoid<commit_after>var _moduleFor = require('./internal/_moduleFor');
var _curryN = require('./internal/_curryN');
var _curry = require('./internal/_curry');
var _isFunction = require('./internal/_isFunction');
var _slice = require('./internal/_slice');
var _equal = require('./internal/_equal');

var Semigroup = require('./Semigroup');

var Monoid = module.exports;

/**
 * Returns the empty value for the type of value.
 *
 * A monoid should obey the law for all values a: _.concat(_.empty(a), a) is equal to _.concat(a, _.empty(a)) is equal to a
 *
 * @sig Monoid m => m -> m
 * @since 0.4.0
 * @param {Monoid} value
 * @returns {Monoid} the empty value for the type
 * @example
 *
 *      _.empty([1,2,3]); // []
 */
Monoid.empty = _curry(function(value) {
    var M = _moduleFor(value);
    return M.empty();
});

/**
 * Returns true if the value is equal to the empty value for the type
 *
 * @sig Monoid m => m -> Boolean
 * @since 0.4.0
 * @param {Monoid} value the monoid being checked
 * @returns {Boolean}
 * @example
 *
 *      _.empty([]);      // true
 *      _.empty([1,2,3]); // false
 *      _.empty('');      // true
 *      _.empty('abc');   // false
 */
Monoid.isEmpty = _curry(function(value) {
    return _equal(value, Monoid.empty(value));
});

/**
 * Concats a monoid to itself a specified number of times
 *
 * @sig Monoid m => Number -> m -> m
 * @since 0.5.0
 * @param {Number} n the number of times to repeat the monoid
 * @param {Monoid} monoid the monoid being repeatedly concatenated
 * @returns {Monoid} monoid repeated n number of times
 * @example
 *
 *      _.cycleN(4, [1,2]);    // [1,2,1,2,1,2,1,2]
 *      _.cycleN(3, 'ABC');    // 'ABCABCABC'
 */
Monoid.cycleN = _curry(function(n, monoid) {
    var res = Monoid.empty(monoid);
    while (n > 0) {
        res = Monoid.concat(res, monoid);
        n -= 1;
    }
    return res;
});

Monoid.concat = Semigroup.concat;
Monoid.concatAll = Semigroup.concatAll;

Monoid.member = function(value) {
    return Semigroup.member(value) && _isFunction(_moduleFor(value).empty);
};
<|endoftext|>


<commit_before>'use strict';

var Vorpal = require('./../../lib/vorpal');
var vorpal = new Vorpal();
var less = require('vorpal-less');
var repl = require('vorpal-repl');
vorpal.use(less).use(repl);

vorpal.command('add [numbers...]', 'Adds numbers together')
  .alias('addition')
  .alias('plus')
  .action(function (args, cb) {
    var numbers = args.numbers;
    var sum = 0;
    for (var i = 0; i < numbers.length; ++i) {
      sum += parseFloat(numbers[i]);
    }
    this.log(sum);
    cb(undefined, sum);
  });

vorpal.command('double [values...]', 'Doubles a value on each tab press')
  .autocompletion(function (text, iteration, cb) {
    if (iteration > 1000000) {
      cb(undefined, ['cows', 'hogs', 'horses']);
    } else {
      var number = String(text).trim();
      if (!isNaN(number)) {
        number = (number < 1) ? 1 : number;
        cb(undefined, 'double ' + number * 2);
      } else {
        cb(undefined, 'double 2');
      }
    }
  })
  .action(function (args, cb) {
    cb();
  });

vorpal.command('fdsdf <word>')
  .option('-m, --more')
  .action(function (args, cb) {
    this.log('BAMSHLACK');
    cb();
  });

vorpal.command('foo <word>')
  .option('-m, --more')
  .autocompletion(function (text, iter, cb) {
    cb(undefined, 'foo ' + text + '1');
  })
  .action(function (args, cb) {
    vorpal.activeCommand.log('aaaaaaaaaaaa');
    this.log(args);
    cb();
  });

vorpal.command('bar <word>')
  .action(function (args, cb) {
    this.log(args);
    cb();
  });

vorpal.command('reverse')
  .option('-c, --cow')
  .action(function (args, cb) {
    this.log(String(args.stdin || '').split('').reverse().join(''));
    cb();
  });

vorpal.command('promptme')
  .action(function (args, cb) {
    this.prompt({
      type: 'list',
      name: 'data',
      choices: ['a', 'c', 'd'],
      message: 'test'
    }, function (result) {
      console.log(result);
      cb();
    });
  });

vorpal.command('cancelme')
  .action(function (args, cb) {
    setTimeout(function () {
      cb();
    }, 10000)
  })
  .cancel(function (a, b) {
    console.log('cancelled!', a, b);
  });

vorpal.command('inputme')
  .action(function (args, cb) {
    this.prompt({
      type: 'input',
      name: 'data',
      message: 'say something im giving up on you: '
    }, function (result) {
      console.log(result);
      cb();
    });
  });

vorpal
  .delimiter('calc:')
  .show()
  .parse(process.argv);

// vorpal.exec('foo "bar and" -m "so and so"');

/*
vorpal.catch('[commands...]')
  .option('-d, --dog')
  .parse(function (str) {
    return str + ' | reverse -c';
  })
  .action(function (args, cb) {
    if (args.commands) {
      console.log(args);
      this.log(args.commands.join(' '));
    }
    cb();
  });
*/
<commit_msg>fixed #42 - mid-command inquirer prompt breaks on control + c<commit_after>'use strict';

var Vorpal = require('./../../lib/vorpal');
var vorpal = new Vorpal();
var less = require('vorpal-less');
var repl = require('vorpal-repl');
vorpal.use(less).use(repl);

vorpal.command('add [numbers...]', 'Adds numbers together')
  .alias('addition')
  .alias('plus')
  .action(function (args, cb) {
    var numbers = args.numbers;
    var sum = 0;
    for (var i = 0; i < numbers.length; ++i) {
      sum += parseFloat(numbers[i]);
    }
    this.log(sum);
    cb(undefined, sum);
  });

vorpal.command('double [values...]', 'Doubles a value on each tab press')
  .autocompletion(function (text, iteration, cb) {
    if (iteration > 1000000) {
      cb(undefined, ['cows', 'hogs', 'horses']);
    } else {
      var number = String(text).trim();
      if (!isNaN(number)) {
        number = (number < 1) ? 1 : number;
        cb(undefined, 'double ' + number * 2);
      } else {
        cb(undefined, 'double 2');
      }
    }
  })
  .action(function (args, cb) {
    cb();
  });

vorpal.command('fdsdf <word>')
  .option('-m, --more')
  .action(function (args, cb) {
    this.log('BAMSHLACK');
    cb();
  });

vorpal.command('foo <word>')
  .option('-m, --more')
  .autocompletion(function (text, iter, cb) {
    cb(undefined, 'foo ' + text + '1');
  })
  .action(function (args, cb) {
    vorpal.activeCommand.log('aaaaaaaaaaaa');
    this.log(args);
    cb();
  });

vorpal.command('bar <word>')
  .action(function (args, cb) {
    this.log(args);
    cb();
  });

vorpal.command('reverse')
  .option('-c, --cow')
  .action(function (args, cb) {
    this.log(String(args.stdin || '').split('').reverse().join(''));
    cb();
  });

vorpal.command('promptme')
  .action(function (args, cb) {
    this.prompt({
      type: 'list',
      name: 'data',
      choices: ['a', 'c', 'd'],
      message: 'test'
    }, function (result) {
      console.log(result);
      cb();
    });
  });

vorpal.command('cancelme')
  .action(function (args, cb) {
    setTimeout(function () {
      cb();
    }, 10000)
  })
  .cancel(function (a, b) {
    console.log('cancelled!', a, b);
  });

vorpal.command('inputme')
  .action(function (args, cb) {
    this.prompt({
      type: 'input',
      name: 'data',
      message: 'say something im giving up on you: '
    }, function (result) {
      console.log(result);
      cb();
    });
  });

vorpal
  .delimiter('calc:')
  .show()
  .parse(process.argv);
<|endoftext|>


<commit_before>import React from 'react';
import {
  Platform,
  I18nManager,
  Image,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import Actions from './navigationStore';
import _backButtonImage from '../images/back_chevron.png';

const hitSlop = { top: 15, bottom: 15, left: 15, right: 15 };
export function BackButton(state) {
  const textButtonStyle = [
    styles.barBackButtonText,
    state.backButtonTextStyle,
  ];
  const style = [
    styles.backButton,
    state.leftButtonStyle,
  ];
  const buttonImage = state.backButtonImage || _backButtonImage;
  const tintColor = getValue(state.backButtonTintColor, state) || state.tintColor || state.navBarButtonColor || state.headerTintColor;
  let onPress = state.onBack;
  if (onPress) {
    onPress = onPress.bind(null, state);
  } else {
    onPress = Actions.pop;
  }

  const text = state.backTitle ?
    (<Text style={textButtonStyle}>
      {state.backTitle}
    </Text>)
    : null;

  return (
    <TouchableOpacity
      testID="backNavButton"
      style={styles.backButtonContainer}
      onPress={onPress}
      hitSlop={state.hitSlop || hitSlop}
    >
      <View style={style}>
      {buttonImage && !state.hideBackImage && <Image
        source={buttonImage}
        style={[
          styles.backButtonImage,
          state.barButtonIconStyle,
          state.leftButtonIconStyle,
          { tintColor },
        ]}
      />
      }
      {text}
      </View>
    </TouchableOpacity>
  );
}

export function LeftButton(state) {
  let onPress = state.onLeft;
  let buttonImage = getValue(state.leftButtonImage, state);
  let menuIcon = state.drawerIcon;
  const style = [styles.leftButton, state.leftButtonStyle];
  const leftButtonTextStyle = getValue(state.leftButtonTextStyle, state);
  const leftButtonIconStyle = getValue(state.leftButtonIconStyle, state);
  const leftButtonStyle = [styles.defaultImageStyle, leftButtonIconStyle];
  const leftTitle = state.getLeftTitle ? state.getLeftTitle(state) : getValue(state.leftTitle, state);
  const textColor = getValue(state.leftButtonTintColor, state);
  const tintColor = textColor || state.tintColor || state.navBarButtonColor || state.headerTintColor;
  const textStyle = [styles.barLeftButtonText, tintColor && { color: tintColor }, leftButtonTextStyle, textColor && { color: textColor }];

  if (state.leftButton) {
    const Button = state.leftButton || state.left;
    return (
      <Button
        {...state}
        key={'leftNavBarBtn'}
        testID="leftNavButton"
        style={[...style, ...leftButtonStyle]}
        textStyle={textStyle}
      />
    );
  }

  if (!onPress && state.drawerImage && state.drawerPosition !== 'right') {
    buttonImage = state.drawerImage;
    if (buttonImage || menuIcon) {
      onPress = Actions.drawerOpen;
    }
    if (!menuIcon) {
      menuIcon = (
        <Image
          source={buttonImage}
          style={[state.leftButtonIconStyle || styles.defaultImageStyle, { tintColor }]}
        />
      );
    }
  }

  if (onPress && (leftTitle || buttonImage)) {
    onPress = onPress.bind(null, state);
    return (
      <TouchableOpacity
        key={'leftNavBarBtn'}
        testID="leftNavButton"
        style={style}
        onPress={onPress}
        hitSlop={state.hitSlop || hitSlop}
      >
        {leftTitle && <Text style={textStyle}>
          {leftTitle}
        </Text>
        }
        {!leftTitle && buttonImage && <View style={{ flex: 1, justifyContent: 'center', alignItems: 'flex-start' }}>
          {menuIcon || <Image
            source={buttonImage}
            style={[state.leftButtonIconStyle || styles.defaultImageStyle, { tintColor }]}
          />
          }
        </View>
        }
      </TouchableOpacity>
    );
  }
  if ((!!state.onLeft ^ !!(leftTitle || buttonImage))) {
    console.warn(
      `Both onLeft and leftTitle/leftButtonImage
            must be specified for the scene: ${state.name}`,
    );
  }
  return null;
}

function getValue(value, params) {
  return value instanceof Function ? value(params) : value;
}

export function RightButton(state) {
  if (!state) {
    return null;
  }

  let onPress = state.onRight;
  let buttonImage = getValue(state.rightButtonImage, state);
  let menuIcon = state.drawerIcon;
  const style = [styles.rightButton, state.rightButtonStyle];
  const rightButtonTextStyle = getValue(state.rightButtonTextStyle, state);
  const rightButtonIconStyle = getValue(state.rightButtonIconStyle, state);
  const rightButtonStyle = [styles.defaultImageStyle, rightButtonIconStyle];
  const rightTitle = state.getRightTitle ? state.getRightTitle(state) : getValue(state.rightTitle, state);
  const textColor = getValue(state.rightButtonTintColor, state);
  const tintColor = textColor || state.tintColor || state.navBarButtonColor || state.headerTintColor;
  const textStyle = [styles.barRightButtonText, tintColor && { color: tintColor }, rightButtonTextStyle, textColor && { color: textColor }];

  if (state.rightButton || state.right) {
    const Button = state.rightButton || state.right;
    return (
      <Button
        {...state}
        key={'rightNavBarBtn'}
        testID="rightNavButton"
        style={style}
        textButtonStyle={textStyle}
      />
    );
  }

  if (!onPress && state.drawerImage && state.drawerPosition === 'right') {
    buttonImage = state.drawerImage;
    if (buttonImage || menuIcon) {
      onPress = Actions.drawerOpen;
    }
    if (!menuIcon) {
      menuIcon = (
        <Image
          source={buttonImage}
          style={[rightButtonStyle, { tintColor }]}
        />
      );
    }
  }

  if (onPress && (rightTitle || buttonImage)) {
    onPress = onPress.bind(null, state);
    return (
      <TouchableOpacity
        key={'rightNavBarBtn'}
        testID="rightNavButton"
        style={style}
        onPress={onPress}
        hitSlop={state.hitSlop || hitSlop}
      >
        {rightTitle && <Text style={textStyle}>
          {rightTitle}
        </Text>
        }
        {!rightTitle && buttonImage && <View style={{ flex: 1, justifyContent: 'center', alignItems: 'flex-end' }}>
          {menuIcon || <Image
            source={buttonImage}
            style={[state.rightButtonIconStyle || styles.defaultImageStyle, { tintColor }]}
          />
          }
        </View>
        }
      </TouchableOpacity>
    );
  }
  if ((!!state.onRight ^ !!(typeof (rightTitle) !== 'undefined'
    || typeof (buttonImage) !== 'undefined'))) {
    console.warn(
      `Both onRight and rightTitle/rightButtonImage
            must be specified for the scene: ${state.routeName}`,
    );
  }
  return null;
}
const styles = StyleSheet.create({
  title: {
    textAlign: 'center',
    color: '#0A0A0A',
    fontSize: 18,
    width: 180,
    alignSelf: 'center',
  },
  titleImage: {
    width: 180,
    alignSelf: 'center',
  },
  titleWrapper: {
    marginTop: 10,
    position: 'absolute',
    ...Platform.select({
      ios: {
        top: 20,
      },
      android: {
        top: 5,
      },
      windows: {
        top: 5,
      },
    }),
    left: 0,
    right: 0,
  },
  header: {
    backgroundColor: '#EFEFF2',
    paddingTop: 0,
    top: 0,
    ...Platform.select({
      ios: {
        height: 64,
      },
      android: {
        height: 54,
      },
      windows: {
        height: 54,
      },
    }),
    right: 0,
    left: 0,
    borderBottomWidth: 0.5,
    borderBottomColor: '#828287',
    position: 'absolute',
  },
  backButton: {
    position: 'absolute',
    ...Platform.select({
      ios: {
        top: 12,
      },
      android: {
        top: 10,
      },
      windows: {
        top: 8,
      },
    }),
    left: 2,
    paddingLeft: 8,
    flexDirection: 'row',
    transform: [{ scaleX: I18nManager.isRTL ? -1 : 1 }],
  },
  rightButton: {
    ...Platform.select({
      ios: {
        position: 'absolute',
        top: 12,
      },
      android: {
        top: 0,
      },
      windows: {
        top: 8,
      },
    }),
    right: 2,
    paddingRight: 8,
  },
  leftButton: {
    ...Platform.select({
      ios: {
        position: 'absolute',
        top: 12,
      },
      android: {
        top: 0,
      },
      windows: {
        top: 8,
      },
    }),
    left: 2,
    paddingLeft: 8,
  },
  barRightButtonText: {
    color: 'rgb(0, 122, 255)',
    textAlign: 'right',
    fontSize: 17,
  },
  barBackButtonText: {
    color: 'rgb(0, 122, 255)',
    textAlign: 'left',
    fontSize: 17,
    paddingLeft: 6,
  },
  barLeftButtonText: {
    color: 'rgb(0, 122, 255)',
    textAlign: 'left',
    fontSize: 17,
  },
  backButtonContainer: {
    ...Platform.select({
      ios: {
        position: 'absolute',
        top: 0,
        left: 0,
      },
    }),
    height: 50,
    width: 70,
  },
  backButtonImage: {
    ...Platform.select({
      android: {
        marginTop: 5,
      },
    }),
    width: 13,
    height: 21,
  },
  defaultImageStyle: {
    height: 24,
    resizeMode: 'contain',
  },
});
<commit_msg>remove hitSlop from back button (because it is already there)<commit_after>import React from 'react';
import {
  Platform,
  I18nManager,
  Image,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import Actions from './navigationStore';
import _backButtonImage from '../images/back_chevron.png';

const hitSlop = { top: 15, bottom: 15, left: 15, right: 15 };
export function BackButton(state) {
  const textButtonStyle = [
    styles.barBackButtonText,
    state.backButtonTextStyle,
  ];
  const style = [
    styles.backButton,
    state.leftButtonStyle,
  ];
  const buttonImage = state.backButtonImage || _backButtonImage;
  const tintColor = getValue(state.backButtonTintColor, state) || state.tintColor || state.navBarButtonColor || state.headerTintColor;
  let onPress = state.onBack;
  if (onPress) {
    onPress = onPress.bind(null, state);
  } else {
    onPress = Actions.pop;
  }

  const text = state.backTitle ?
    (<Text style={textButtonStyle}>
      {state.backTitle}
    </Text>)
    : null;

  return (
    <TouchableOpacity
      testID="backNavButton"
      style={styles.backButtonContainer}
      onPress={onPress}
    >
      <View style={style}>
      {buttonImage && !state.hideBackImage && <Image
        source={buttonImage}
        style={[
          styles.backButtonImage,
          state.barButtonIconStyle,
          state.leftButtonIconStyle,
          { tintColor },
        ]}
      />
      }
      {text}
      </View>
    </TouchableOpacity>
  );
}

export function LeftButton(state) {
  let onPress = state.onLeft;
  let buttonImage = getValue(state.leftButtonImage, state);
  let menuIcon = state.drawerIcon;
  const style = [styles.leftButton, state.leftButtonStyle];
  const leftButtonTextStyle = getValue(state.leftButtonTextStyle, state);
  const leftButtonIconStyle = getValue(state.leftButtonIconStyle, state);
  const leftButtonStyle = [styles.defaultImageStyle, leftButtonIconStyle];
  const leftTitle = state.getLeftTitle ? state.getLeftTitle(state) : getValue(state.leftTitle, state);
  const textColor = getValue(state.leftButtonTintColor, state);
  const tintColor = textColor || state.tintColor || state.navBarButtonColor || state.headerTintColor;
  const textStyle = [styles.barLeftButtonText, tintColor && { color: tintColor }, leftButtonTextStyle, textColor && { color: textColor }];

  if (state.leftButton) {
    const Button = state.leftButton || state.left;
    return (
      <Button
        {...state}
        key={'leftNavBarBtn'}
        testID="leftNavButton"
        style={[...style, ...leftButtonStyle]}
        textStyle={textStyle}
      />
    );
  }

  if (!onPress && state.drawerImage && state.drawerPosition !== 'right') {
    buttonImage = state.drawerImage;
    if (buttonImage || menuIcon) {
      onPress = Actions.drawerOpen;
    }
    if (!menuIcon) {
      menuIcon = (
        <Image
          source={buttonImage}
          style={[state.leftButtonIconStyle || styles.defaultImageStyle, { tintColor }]}
        />
      );
    }
  }

  if (onPress && (leftTitle || buttonImage)) {
    onPress = onPress.bind(null, state);
    return (
      <TouchableOpacity
        key={'leftNavBarBtn'}
        testID="leftNavButton"
        style={style}
        onPress={onPress}
        hitSlop={state.hitSlop || hitSlop}
      >
        {leftTitle && <Text style={textStyle}>
          {leftTitle}
        </Text>
        }
        {!leftTitle && buttonImage && <View style={{ flex: 1, justifyContent: 'center', alignItems: 'flex-start' }}>
          {menuIcon || <Image
            source={buttonImage}
            style={[state.leftButtonIconStyle || styles.defaultImageStyle, { tintColor }]}
          />
          }
        </View>
        }
      </TouchableOpacity>
    );
  }
  if ((!!state.onLeft ^ !!(leftTitle || buttonImage))) {
    console.warn(
      `Both onLeft and leftTitle/leftButtonImage
            must be specified for the scene: ${state.name}`,
    );
  }
  return null;
}

function getValue(value, params) {
  return value instanceof Function ? value(params) : value;
}

export function RightButton(state) {
  if (!state) {
    return null;
  }

  let onPress = state.onRight;
  let buttonImage = getValue(state.rightButtonImage, state);
  let menuIcon = state.drawerIcon;
  const style = [styles.rightButton, state.rightButtonStyle];
  const rightButtonTextStyle = getValue(state.rightButtonTextStyle, state);
  const rightButtonIconStyle = getValue(state.rightButtonIconStyle, state);
  const rightButtonStyle = [styles.defaultImageStyle, rightButtonIconStyle];
  const rightTitle = state.getRightTitle ? state.getRightTitle(state) : getValue(state.rightTitle, state);
  const textColor = getValue(state.rightButtonTintColor, state);
  const tintColor = textColor || state.tintColor || state.navBarButtonColor || state.headerTintColor;
  const textStyle = [styles.barRightButtonText, tintColor && { color: tintColor }, rightButtonTextStyle, textColor && { color: textColor }];

  if (state.rightButton || state.right) {
    const Button = state.rightButton || state.right;
    return (
      <Button
        {...state}
        key={'rightNavBarBtn'}
        testID="rightNavButton"
        style={style}
        textButtonStyle={textStyle}
      />
    );
  }

  if (!onPress && state.drawerImage && state.drawerPosition === 'right') {
    buttonImage = state.drawerImage;
    if (buttonImage || menuIcon) {
      onPress = Actions.drawerOpen;
    }
    if (!menuIcon) {
      menuIcon = (
        <Image
          source={buttonImage}
          style={[rightButtonStyle, { tintColor }]}
        />
      );
    }
  }

  if (onPress && (rightTitle || buttonImage)) {
    onPress = onPress.bind(null, state);
    return (
      <TouchableOpacity
        key={'rightNavBarBtn'}
        testID="rightNavButton"
        style={style}
        onPress={onPress}
        hitSlop={state.hitSlop || hitSlop}
      >
        {rightTitle && <Text style={textStyle}>
          {rightTitle}
        </Text>
        }
        {!rightTitle && buttonImage && <View style={{ flex: 1, justifyContent: 'center', alignItems: 'flex-end' }}>
          {menuIcon || <Image
            source={buttonImage}
            style={[state.rightButtonIconStyle || styles.defaultImageStyle, { tintColor }]}
          />
          }
        </View>
        }
      </TouchableOpacity>
    );
  }
  if ((!!state.onRight ^ !!(typeof (rightTitle) !== 'undefined'
    || typeof (buttonImage) !== 'undefined'))) {
    console.warn(
      `Both onRight and rightTitle/rightButtonImage
            must be specified for the scene: ${state.routeName}`,
    );
  }
  return null;
}
const styles = StyleSheet.create({
  title: {
    textAlign: 'center',
    color: '#0A0A0A',
    fontSize: 18,
    width: 180,
    alignSelf: 'center',
  },
  titleImage: {
    width: 180,
    alignSelf: 'center',
  },
  titleWrapper: {
    marginTop: 10,
    position: 'absolute',
    ...Platform.select({
      ios: {
        top: 20,
      },
      android: {
        top: 5,
      },
      windows: {
        top: 5,
      },
    }),
    left: 0,
    right: 0,
  },
  header: {
    backgroundColor: '#EFEFF2',
    paddingTop: 0,
    top: 0,
    ...Platform.select({
      ios: {
        height: 64,
      },
      android: {
        height: 54,
      },
      windows: {
        height: 54,
      },
    }),
    right: 0,
    left: 0,
    borderBottomWidth: 0.5,
    borderBottomColor: '#828287',
    position: 'absolute',
  },
  backButton: {
    position: 'absolute',
    ...Platform.select({
      ios: {
        top: 12,
      },
      android: {
        top: 10,
      },
      windows: {
        top: 8,
      },
    }),
    left: 2,
    paddingLeft: 8,
    flexDirection: 'row',
    transform: [{ scaleX: I18nManager.isRTL ? -1 : 1 }],
  },
  rightButton: {
    ...Platform.select({
      ios: {
        position: 'absolute',
        top: 12,
      },
      android: {
        top: 0,
      },
      windows: {
        top: 8,
      },
    }),
    right: 2,
    paddingRight: 8,
  },
  leftButton: {
    ...Platform.select({
      ios: {
        position: 'absolute',
        top: 12,
      },
      android: {
        top: 0,
      },
      windows: {
        top: 8,
      },
    }),
    left: 2,
    paddingLeft: 8,
  },
  barRightButtonText: {
    color: 'rgb(0, 122, 255)',
    textAlign: 'right',
    fontSize: 17,
  },
  barBackButtonText: {
    color: 'rgb(0, 122, 255)',
    textAlign: 'left',
    fontSize: 17,
    paddingLeft: 6,
  },
  barLeftButtonText: {
    color: 'rgb(0, 122, 255)',
    textAlign: 'left',
    fontSize: 17,
  },
  backButtonContainer: {
    ...Platform.select({
      ios: {
        position: 'absolute',
        top: 0,
        left: 0,
      },
    }),
    height: 50,
    width: 70,
  },
  backButtonImage: {
    ...Platform.select({
      android: {
        marginTop: 5,
      },
    }),
    width: 13,
    height: 21,
  },
  defaultImageStyle: {
    height: 24,
    resizeMode: 'contain',
  },
});
<|endoftext|>


<commit_before>const events = require('events')
const util = require('util')

class Messenger extends events.EventEmitter {
    constructor () {
        super()
        this.parent = new events.EventEmitter
        this.connected = true
    }

    send (...vargs) {
        this.parent.emit.apply(this.parent, [ 'message' ].concat(vargs.slice(0, 2)))
    }
}

module.exports = Messenger
<commit_msg>Remove unused `require`.<commit_after>const events = require('events')

class Messenger extends events.EventEmitter {
    constructor () {
        super()
        this.parent = new events.EventEmitter
        this.connected = true
    }

    send (...vargs) {
        this.parent.emit.apply(this.parent, [ 'message' ].concat(vargs.slice(0, 2)))
    }
}

module.exports = Messenger
<|endoftext|>


<commit_before>/* Copyright © 2009 Adam Harvey
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/**
 * Creates a new Player object.
 *
 * @class Represents a chain of elements that result in a video being played.
 * @param {object} options Options to be set within the player.
 */
cinejs.Player = function (options) {
	// Initialise the filter chain.
	this.filters = [];

	// Set default options.
	this.options = {
		frameDelay: 25
	};

	// Copy in our provided options.
	for (var option in options) {
		if (options.hasOwnProperty(option)) {
			this.options[option] = options[option];
		}
	}
};

/**
 * Pre-flight check for the player to make sure that all required options are
 * set correctly.
 *
 * @throws {string} A string describing the problem found.
 */
cinejs.Player.prototype.check = function () {
	// Check for a valid source.
	if (typeof this.options.source === "undefined") {
		throw "A source element or URI must be provided";
	}
	else if (typeof this.options.source === "object") {
		if (!(this.options.source instanceof String || this.options.source instanceof HTMLVideoElement)) {
			throw "The source option must be a string or video element";
		}
	}
	else if (typeof this.options.source !== "string") {
		throw "The source option must be a string or video element";
	}

	// Check for a valid destination element.
	if (!this.options.destination instanceof HTMLCanvasElement) {
		throw "The destination option must be a canvas element";
	}

	// Simpler checks for other options.
	if (typeof this.options.frameDelay !== "number" || this.options.frameDelay < 0) {
		throw "The frame delay must be a non-negative number";
	}

	// Check any and all defined filters.
	for (var i in this.filters) {
		if (this.filters.hasOwnProperty(i)) {
			var filter = this.filters[i];

			if (typeof filter.processFrame !== "function") {
				var name = "unknown";

				if (filter.name) {
					name = filter.name;
				}

				throw "Filter " + name + " does not have a processFrame method";
			}
		}
	}
};

/**
 * Creates a hidden canvas for our intermediate video processing. While there's
 * no technical reason we can't just work off the destination canvas, this is
 * likely to result in unsightly video artifacts as processing occurs. This may
 * be overridden should the defaults not suffice (for example, if you want to
 * write a demonstration page that shows the intermediate canvas).
 *
 * @return {HTMLCanvasElement}
 */
cinejs.Player.prototype.createIntermediateCanvas = function () {
	var canvas = document.createElement("canvas");

	canvas.style.display = "none";

	// Grab the destination size as our intermediate size.
	canvas.width = this.destination.width;
	canvas.height = this.destination.height;

	document.body.appendChild(canvas);

	return canvas;
};

/**
 * Creates a hidden video element for use while playing. This may be overridden
 * should the defaults (append to the end of the document; set the style to
 * display: none) not be acceptable.
 *
 * @param {string} uri The URI to set the element source to.
 * @return {HTMLVideoElement}
 */
cinejs.Player.prototype.createVideoElement = function (uri) {
	var video = document.createElement("video");

	/* There's no need to autoplay, since we're going to start playback in
	 * play() anyway. */
	video.autoplay = false;

	video.autobuffer = true;
	video.src = uri;
	video.style.display = "none";

	/* Theoretically, we could set the width and height of the video
	 * element here. According to the HTML5 draft spec, though,
	 * canvas.drawImage() should ignore those regardless, so we'll leave it
	 * be for now -- the default should be the native size of the video,
	 * which will get rid of any unnecessary scaling overhead. */

	document.body.appendChild(video);

	return video;
};

/**
 * Starts playback of the processed video.
 *
 * @throws {string} Throws anything check() can throw.
 */
cinejs.Player.prototype.play = function () {
	this.check();

	// Create a video element, should we need one.
	var video;
	if (typeof this.options.source === "object" && this.options.source instanceof HTMLVideoElement) {
		video = this.options.source;
	}
	else {
		video = this.createVideoElement(this.options.source);
	}

	// We also need an intermediate canvas to do our processing on.
	var intermediate = this.createIntermediateCanvas();
	if (!intermediate instanceof HTMLCanvasElement) {
		throw "Intermediate canvas is not a canvas";
	}

	var self = this;
	video.addEventListener("play", function () {
		self.renderFrame(video, intermediate, self.options.destination);
	}, false);

	video.play();
};

/**
 * Actually renders a frame of the video by rendering it and calling any
 * filters required.
 *
 * @param {HTMLVideoElement} video The source video element.
 * @param {HTMLCanvasElement} intermediate An intermediate canvas to be used
 *                                         for filtering and processing.
 * @param {HTMLCanvasElement} destination The destination canvas.
 */
cinejs.Player.prototype.renderFrame = function (video, intermediate, destination) {
	if (this.filters.length === 0) {
		/* Shortcut if we have no filters defined: just splat the data
		 * straight to the destination. */
		var context = destination.getContext("2d");
		context.drawImage(video, 0, 0, destination.width, destination.height);
	}
	else {
		var intermediateContext = intermediate.getContext("2d");
		var destinationContext = destination.getContext("2d");

		/* Put the current video frame onto the intermediate canvas so
		 * we can get its raw image data. */
		intermediateContext.drawImage(video, 0, 0, intermediate.width, intermediate.height);
		var imageData = intermediateContext.getImageData(0, 0, intermediate.width, intermediate.height);

		// Now apply each filter in turn.
		for (var filter in this.filters) {
			if (this.filters.hasOwnProperty(filter)) {
				this.filters[filter].processFrame(imageData);
			}
		}

		// Finally, put the munged frame to the destination canvas.
		destinationContext.putImageData(imageData, 0, 0);

		imageData = null;
	}

	/* Make sure we're called again after the right delay, unless the video
	 * has already been stopped. */
	if (!(video.paused || video.ended)) {
		var self = this;
		window.setTimeout(function () {
			self.renderFrame(video, intermediate, destination);
		}, this.options.frameDelay);
	}
};

// vim: set cin noet ts=8 sw=8:
<commit_msg>Bug fix within cinejs.Player: destination is an option, not a direct property.<commit_after>/* Copyright © 2009 Adam Harvey
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/**
 * Creates a new Player object.
 *
 * @class Represents a chain of elements that result in a video being played.
 * @param {object} options Options to be set within the player.
 */
cinejs.Player = function (options) {
	// Initialise the filter chain.
	this.filters = [];

	// Set default options.
	this.options = {
		frameDelay: 25
	};

	// Copy in our provided options.
	for (var option in options) {
		if (options.hasOwnProperty(option)) {
			this.options[option] = options[option];
		}
	}
};

/**
 * Pre-flight check for the player to make sure that all required options are
 * set correctly.
 *
 * @throws {string} A string describing the problem found.
 */
cinejs.Player.prototype.check = function () {
	// Check for a valid source.
	if (typeof this.options.source === "undefined") {
		throw "A source element or URI must be provided";
	}
	else if (typeof this.options.source === "object") {
		if (!(this.options.source instanceof String || this.options.source instanceof HTMLVideoElement)) {
			throw "The source option must be a string or video element";
		}
	}
	else if (typeof this.options.source !== "string") {
		throw "The source option must be a string or video element";
	}

	// Check for a valid destination element.
	if (!this.options.destination instanceof HTMLCanvasElement) {
		throw "The destination option must be a canvas element";
	}

	// Simpler checks for other options.
	if (typeof this.options.frameDelay !== "number" || this.options.frameDelay < 0) {
		throw "The frame delay must be a non-negative number";
	}

	// Check any and all defined filters.
	for (var i in this.filters) {
		if (this.filters.hasOwnProperty(i)) {
			var filter = this.filters[i];

			if (typeof filter.processFrame !== "function") {
				var name = "unknown";

				if (filter.name) {
					name = filter.name;
				}

				throw "Filter " + name + " does not have a processFrame method";
			}
		}
	}
};

/**
 * Creates a hidden canvas for our intermediate video processing. While there's
 * no technical reason we can't just work off the destination canvas, this is
 * likely to result in unsightly video artifacts as processing occurs. This may
 * be overridden should the defaults not suffice (for example, if you want to
 * write a demonstration page that shows the intermediate canvas).
 *
 * @return {HTMLCanvasElement}
 */
cinejs.Player.prototype.createIntermediateCanvas = function () {
	var canvas = document.createElement("canvas");

	canvas.style.display = "none";

	// Grab the destination size as our intermediate size.
	canvas.width = this.options.destination.width;
	canvas.height = this.options.destination.height;

	document.body.appendChild(canvas);

	return canvas;
};

/**
 * Creates a hidden video element for use while playing. This may be overridden
 * should the defaults (append to the end of the document; set the style to
 * display: none) not be acceptable.
 *
 * @param {string} uri The URI to set the element source to.
 * @return {HTMLVideoElement}
 */
cinejs.Player.prototype.createVideoElement = function (uri) {
	var video = document.createElement("video");

	/* There's no need to autoplay, since we're going to start playback in
	 * play() anyway. */
	video.autoplay = false;

	video.autobuffer = true;
	video.src = uri;
	video.style.display = "none";

	/* Theoretically, we could set the width and height of the video
	 * element here. According to the HTML5 draft spec, though,
	 * canvas.drawImage() should ignore those regardless, so we'll leave it
	 * be for now -- the default should be the native size of the video,
	 * which will get rid of any unnecessary scaling overhead. */

	document.body.appendChild(video);

	return video;
};

/**
 * Starts playback of the processed video.
 *
 * @throws {string} Throws anything check() can throw.
 */
cinejs.Player.prototype.play = function () {
	this.check();

	// Create a video element, should we need one.
	var video;
	if (typeof this.options.source === "object" && this.options.source instanceof HTMLVideoElement) {
		video = this.options.source;
	}
	else {
		video = this.createVideoElement(this.options.source);
	}

	// We also need an intermediate canvas to do our processing on.
	var intermediate = this.createIntermediateCanvas();
	if (!intermediate instanceof HTMLCanvasElement) {
		throw "Intermediate canvas is not a canvas";
	}

	var self = this;
	video.addEventListener("play", function () {
		self.renderFrame(video, intermediate, self.options.destination);
	}, false);

	video.play();
};

/**
 * Actually renders a frame of the video by rendering it and calling any
 * filters required.
 *
 * @param {HTMLVideoElement} video The source video element.
 * @param {HTMLCanvasElement} intermediate An intermediate canvas to be used
 *                                         for filtering and processing.
 * @param {HTMLCanvasElement} destination The destination canvas.
 */
cinejs.Player.prototype.renderFrame = function (video, intermediate, destination) {
	if (this.filters.length === 0) {
		/* Shortcut if we have no filters defined: just splat the data
		 * straight to the destination. */
		var context = destination.getContext("2d");
		context.drawImage(video, 0, 0, destination.width, destination.height);
	}
	else {
		var intermediateContext = intermediate.getContext("2d");
		var destinationContext = destination.getContext("2d");

		/* Put the current video frame onto the intermediate canvas so
		 * we can get its raw image data. */
		intermediateContext.drawImage(video, 0, 0, intermediate.width, intermediate.height);
		var imageData = intermediateContext.getImageData(0, 0, intermediate.width, intermediate.height);

		// Now apply each filter in turn.
		for (var filter in this.filters) {
			if (this.filters.hasOwnProperty(filter)) {
				this.filters[filter].processFrame(imageData);
			}
		}

		// Finally, put the munged frame to the destination canvas.
		destinationContext.putImageData(imageData, 0, 0);

		imageData = null;
	}

	/* Make sure we're called again after the right delay, unless the video
	 * has already been stopped. */
	if (!(video.paused || video.ended)) {
		var self = this;
		window.setTimeout(function () {
			self.renderFrame(video, intermediate, destination);
		}, this.options.frameDelay);
	}
};

// vim: set cin noet ts=8 sw=8:
<|endoftext|>


<commit_before>// import merge from 'lodash/merge';
import get from 'lodash/get';
import fs from 'fs';
import mkdirp from 'mkdirp';
import { each } from 'async';
import keymirror from 'keymirror';

export const Format = keymirror({
  JS: null,
  JSON: null,
});

const Extension = {
  [Format.JS]: '.js',
  [Format.JSON]: '.json',
};

const DEFAULT_OPTIONS = {
  format: Format.JSON,
  encoding: 'utf-8',
};

export default class ExportLocales {
  constructor(options = {}) {
    this._options = {
      ...DEFAULT_OPTIONS,
      ...options,
    };
    this._locales = {};

    this.apply = this.apply.bind(this);
    this.addExtractedLocale = this.addExtractedLocale.bind(this);
  }

  getOptions() {
    return this._options;
  }

  addExtractedLocale(extractedLocales, propertyName, callback) {
    const locales = this._locales;

    extractedLocales.forEach((locale) => {
      if (!locales[locale.id]) {
        locales[locale.id] = {};
      }

      const currentLocale = locales[locale.id];
      currentLocale[propertyName] = locale.data;
    });

    this.save(callback);
  }

  save(callback) {
    const options = this._options;
    const compiler = this._compiler;
    const locales = this._locales;
    const mainDir = options.path || get(compiler, 'options.output.path') || '.';

    const { format, encoding } = options;
    const ext = Extension[format];

    mkdirp(mainDir, (err) => {
      if (err) {
        callback(err);
      }

      each(Object.keys(locales), (locale, cb) => {
        const filePath = mainDir + '/' + locale + ext;
        const jsonContent = JSON.stringify(locales[locale], void 0, 2);
        const result = format === Format.JS
          ? `module.exports = ${jsonContent};`
          : jsonContent;

        fs.readFile(filePath, encoding, (err2, currentContent) => {
          if (!err2 && currentContent === result) {
            return cb();
          }

          fs.writeFile(filePath, result, {
            flag: 'w+',
            encoding,
          }, cb);
        });
      }, callback);
    });
  }

  apply(compiler) {
    this._compiler = compiler;

    compiler.plugin('this-compilation', (compilation) => {
      compilation.plugin('normal-module-loader', (loaderContext) => {
        loaderContext.addExtractedLocale = this.addExtractedLocale;
      });

      compilation.plugin('additional-assets', (callback) => {
        // this.save(callback);
        callback();
      });
    });
  }
}
<commit_msg>added option for save immadiately<commit_after>// import merge from 'lodash/merge';
import get from 'lodash/get';
import fs from 'fs';
import mkdirp from 'mkdirp';
import { each } from 'async';
import keymirror from 'keymirror';

export const Format = keymirror({
  JS: null,
  JSON: null,
});

const Extension = {
  [Format.JS]: '.js',
  [Format.JSON]: '.json',
};

const DEFAULT_OPTIONS = {
  format: Format.JSON,
  encoding: 'utf-8',
  saveImmediately: true,
};

export default class ExportLocales {
  constructor(options = {}) {
    this._options = {
      ...DEFAULT_OPTIONS,
      ...options,
    };
    this._locales = {};

    this.apply = this.apply.bind(this);
    this.addExtractedLocale = this.addExtractedLocale.bind(this);
  }

  getOptions() {
    return this._options;
  }

  addExtractedLocale(extractedLocales, propertyName, callback) {
    const locales = this._locales;

    extractedLocales.forEach((locale) => {
      if (!locales[locale.id]) {
        locales[locale.id] = {};
      }

      const currentLocale = locales[locale.id];
      currentLocale[propertyName] = locale.data;
    });

    const options = this.getOptions();
    if (!options.saveImmediately) {
      return callback();
    }

    this.save(callback);
  }

  save(callback) {
    const options = this._options;
    const compiler = this._compiler;
    const locales = this._locales;
    const mainDir = options.path || get(compiler, 'options.output.path') || '.';

    const { format, encoding } = options;
    const ext = Extension[format];

    mkdirp(mainDir, (err) => {
      if (err) {
        callback(err);
      }

      const localeKeys = Object.keys(locales);
      localeKeys.sort(); // always same result

      each(Object.keys(localeKeys), (locale, cb) => {
        const filePath = mainDir + '/' + locale + ext;
        const jsonContent = JSON.stringify(locales[locale], void 0, 2);
        const result = format === Format.JS
          ? `module.exports = ${jsonContent};`
          : jsonContent;

        fs.readFile(filePath, encoding, (err2, currentContent) => {
          if (!err2 && currentContent === result) {
            return cb();
          }

          fs.writeFile(filePath, result, {
            flag: 'w+',
            encoding,
          }, cb);
        });
      }, callback);
    });
  }

  apply(compiler) {
    const options = this.getOptions();
    this._compiler = compiler;

    compiler.plugin('this-compilation', (compilation) => {
      compilation.plugin('normal-module-loader', (loaderContext) => {
        loaderContext.addExtractedLocale = this.addExtractedLocale;
      });

      compilation.plugin('additional-assets', (callback) => {
        if (options.saveImmediately) {
          return callback();
        }

        return this.save(callback);
      });
    });
  }
}
<|endoftext|>


<commit_before>var Keys = require('./Keys');
var parseTree = require('./parse-tree');
var matcher = require('./operations/matcher');
var getProcessor = require('./operations/getProcessor');
var Rx = require('rx');
var Observable = Rx.Observable;
var falcor = require('falcor');
var normalizePathSets = require('./operations/ranges/normalizePathSets');
var isJSONG = require('./support/isJSONG');

var Router = function(routes) {
    this._routes = routes;
    this._rst = parseTree(routes);
    this._matcher = matcher(this._rst);
};

Router.prototype = {
    get: function(paths) {
        normalizePathSets(paths);
        return accumulateValues(getProcessor(this._matcher(paths, 'get')), paths);
    }
};

function accumulateValues(matchedResults, requestedPaths) {
    var model = new falcor.Model();
    return Observable.
        from(matchedResults).
        flatMap(function(obs) {
            return obs.
                materialize().
                filter(function(x) {
                    return x.kind !== 'C';
                });
        }).
        reduce(function(seed, value) {
            if (value.kind === 'N') {
                if (isJSONG(value.value)) {
                    out = model._setJSONGsAsJSONG(model, [value.value], seed);
                } else {
                    out = model._setPathSetsAsJSONG(model, [].concat(value.value), seed);
                }
            } else if (value.kind === 'E') {
                if (value.value && isJSONG(value.value)) {
                    out = model._setJSONGsAsJSONG(model, [value.value], seed);
                } else {
                    out = model._setPathSetsAsJSONG(model, [{
                        path: value.path,
                        value: {
                            $type: 'error',
                            message: value.exception.message
                        }
                    }], seed);
                }
            }
            return seed;
        }, [{}]).
        map(function(out) {
            return {jsong: out[0].jsong};
        });
}

Router.ranges = Keys.ranges;
Router.integers = Keys.integers;
Router.keys = Keys.keys;
module.exports = Router;

<commit_msg>Ensure route functions are bound to router instance<commit_after>var Keys = require('./Keys');
var parseTree = require('./parse-tree');
var matcher = require('./operations/matcher');
var getProcessor = require('./operations/getProcessor');
var Rx = require('rx');
var Observable = Rx.Observable;
var falcor = require('falcor');
var normalizePathSets = require('./operations/ranges/normalizePathSets');
var isJSONG = require('./support/isJSONG');

var Router = function(routes) {
    this._routes = routes;
    this._rst = parseTree(routes);
    this._matcher = matcher(this._rst);
};

Router.prototype = {
    get: function(paths) {
        normalizePathSets(paths);
        return accumulateValues(getProcessor.bind(this)(this._matcher(paths, 'get')), paths);
    }
};

function accumulateValues(matchedResults, requestedPaths) {
    var model = new falcor.Model();
    return Observable.
        from(matchedResults).
        flatMap(function(obs) {
            return obs.
                materialize().
                filter(function(x) {
                    return x.kind !== 'C';
                });
        }).
        reduce(function(seed, value) {
            if (value.kind === 'N') {
                if (isJSONG(value.value)) {
                    out = model._setJSONGsAsJSONG(model, [value.value], seed);
                } else {
                    out = model._setPathSetsAsJSONG(model, [].concat(value.value), seed);
                }
            } else if (value.kind === 'E') {
                if (value.value && isJSONG(value.value)) {
                    out = model._setJSONGsAsJSONG(model, [value.value], seed);
                } else {
                    out = model._setPathSetsAsJSONG(model, [{
                        path: value.path,
                        value: {
                            $type: 'error',
                            message: value.exception.message
                        }
                    }], seed);
                }
            }
            return seed;
        }, [{}]).
        map(function(out) {
            return {jsong: out[0].jsong};
        });
}

Router.ranges = Keys.ranges;
Router.integers = Keys.integers;
Router.keys = Keys.keys;
module.exports = Router;

<|endoftext|>


<commit_before>import bodyParser from 'body-parser'
import path from 'path'

export class Router {
	app = null
	bindings = { }
	patterns = { }
	namedRoutes = { }
	bodyParserMiddleware = [ ]

	_scopedActionStack = [ { } ]
	_scopedPrefixStack = [ '/' ]

	get _scopedAction() {
		return this._scopedActionStack[this._scopedActionStack.length - 1]
	}

	get _scopedPrefix() {
		return this._scopedPrefixStack[this._scopedPrefixStack.length - 1]
	}

	constructor(app) {
		this.app = app

		let parsers = app.config.get('app.body_parsers', [ 'json', 'form' ])

		if(!Array.isArray(parsers)) {
			parsers = parsers.isNil ? [ ] : [ parsers ]
		}

		parsers = parsers.map(name => name.toString().trim().toLowerCase())

		for(const name of new Set(parsers)) {
			switch(name) {
				case 'json':
					this.bodyParserMiddleware.push(bodyParser.json())
					break
				case 'form':
					this.bodyParserMiddleware.push(bodyParser.urlencoded({ extended: true }))
					break
				default:
					Log.comment('Unsupported body parsers', name)
			}
		}
	}

	group(action, callback) {
		if(!action.controller.isNil && typeof action.controller === 'function') {
			action.controller = new action.controller(this.app)
		}

		const parentAction = this._scopedAction
		const parentPrefix = this._scopedPrefix

		const scopedAction = Object.assign({ }, parentAction, action)
		let scopedPrefix = scopedAction.prefix
		delete scopedAction.prefix
		this._scopedActionStack.push(scopedAction)

		if(!scopedPrefix.isNil && scopedPrefix.length > 0) {
			if(!parentPrefix.isNil && parentPrefix.length > 0) {
				scopedPrefix = path.join(parentPrefix, scopedPrefix)
			}

			this._scopedPrefixStack.push(this._normalizePathComponent(scopedPrefix))
		} else {
			this._scopedPrefixStack.push(parentPrefix)
		}

		callback(this, action.controller)

		this._scopedActionStack.pop()
		this._scopedPrefixStack.pop()
	}

	all(pathname, action) {
		console.log('Don’t use `all` routes. Offender: %s', pathname)
		return this.app.express.all(this._scopedPrefix + pathname, this._makeAction(action))
	}

	get(pathname, action, context) {
		return this._add('get', pathname, action, context)
	}

	post(pathname, action, context) {
		return this._add('post', pathname, action, context)
	}

	put(pathname, action, context) {
		return this._add('put', pathname, action, context)
	}

	patch(pathname, action, context) {
		return this._add('patch', pathname, action, context)
	}

	delete(pathname, action, context) {
		return this._add('delete', pathname, action, context)
	}

	_add(method, pathname, action, context) {
		const handler = this._makeAction(action)

		// WARNING: Prone to failure if ExpressJS changes this logic
		this.app.express.lazyrouter()

		const handlers = [ handler ]
		this.addMiddleware(handlers, this._scopedAction.use)

		if(typeof action === 'object') {
			this.addMiddleware(handlers, action.use)
		}

		pathname = this._normalizePathComponent(pathname)
		const compiledPath = path.join('/', this._scopedPrefix, pathname).replace(/:([a-z0-0_\-\.]+)/g, (param, name) => {
			const pattern = this.patterns[name]

			if(pattern.isNil) {
				return param
			} else {
				return `${param}(${pattern})`
			}
		})

		if(method.toLowerCase() !== 'get' && this.bodyParserMiddleware.length > 0) {
			handlers.unshift(...this.bodyParserMiddleware)
		}

		let route = this.app.express._router.route(compiledPath)
		route = route[method](...handlers)
		route.context = context || {}
		route.grindRouter = this

		return route
	}

	_makeAction(action) {
		if(typeof action === 'function') {
			return action
		}

		if(typeof action === 'string') {
			action = { method: action }
		}

		action = Object.assign({ }, this._scopedAction, action)
		const method = action.controller[action.method]
		const controller = action.controller

		return (...args) => {
			const result = method.apply(controller, args)

			if(typeof result === 'object' && typeof result.catch === 'function') {
				return result.catch(args[2])
			} else {
				return result
			}
		}
	}

	_normalizePathComponent(component) {
		return path.normalize(component.trim()).replace(/^\//, '')
	}

	bind(name, resolver, context) {
		this.bindings[name] = { resolver }

		if(!context.isNil) {
			this.bindings[name].context = context
		}

		this.app.express.param(name, (req, res, next, value) => {
			resolver(value, newValue => {
				req.params[name] = newValue
				next()
			}, err => {
				next(err)
			}, req, res)
		})
	}

	pattern(name, pattern) {
		this.patterns[name] = pattern
	}

	nameRoute(name, route) {
		route.routeName = name
		this.namedRoutes[name] = route
	}

	addMiddleware(handlers, middleware) {
		if(middleware.isNil) {
			return
		}

		if(typeof middleware === 'string') {
			middleware = { before: [ middleware ] }
		}

		if(Array.isArray(middleware)) {
			middleware = { before: middleware }
		}

		if(Array.isArray(middleware.before)) {
			handlers.unshift(...middleware.before)
		} else if(Array.isArray(middleware.before)) {
			handlers.push(...middleware.after)
		}
	}

}
<commit_msg>Added support for named middleware<commit_after>import bodyParser from 'body-parser'
import path from 'path'

export class Router {
	app = null
	bindings = { }
	patterns = { }
	namedRoutes = { }
	middleware = { }
	bodyParserMiddleware = [ ]

	_scopedActionStack = [ { } ]
	_scopedPrefixStack = [ '/' ]

	get _scopedAction() {
		return this._scopedActionStack[this._scopedActionStack.length - 1]
	}

	get _scopedPrefix() {
		return this._scopedPrefixStack[this._scopedPrefixStack.length - 1]
	}

	constructor(app) {
		this.app = app

		const parsers = app.config.get('app.body_parsers', [ 'json', 'form' ])

		if(!Array.isArray(parsers)) {
			this.bodyParserMiddleware = parsers.isNil ? [ ] : [ parsers ]
		} else {
			this.bodyParserMiddleware = parsers
		}

		this.middleware.json = bodyParser.json()
		this.middleware.form = bodyParser.urlencoded({ extended: true })
	}

	group(action, callback) {
		if(!action.controller.isNil && typeof action.controller === 'function') {
			action.controller = new action.controller(this.app)
		}

		const parentAction = this._scopedAction
		const parentPrefix = this._scopedPrefix

		const scopedAction = Object.assign({ }, parentAction, action)
		let scopedPrefix = scopedAction.prefix
		delete scopedAction.prefix
		this._scopedActionStack.push(scopedAction)

		if(!scopedPrefix.isNil && scopedPrefix.length > 0) {
			if(!parentPrefix.isNil && parentPrefix.length > 0) {
				scopedPrefix = path.join(parentPrefix, scopedPrefix)
			}

			this._scopedPrefixStack.push(this._normalizePathComponent(scopedPrefix))
		} else {
			this._scopedPrefixStack.push(parentPrefix)
		}

		callback(this, action.controller)

		this._scopedActionStack.pop()
		this._scopedPrefixStack.pop()
	}

	all(pathname, action) {
		console.log('Don’t use `all` routes. Offender: %s', pathname)
		return this.app.express.all(this._scopedPrefix + pathname, this._makeAction(action))
	}

	use(...middlewares) {
		for(const middleware of middlewares) {
			this.app.express.use(this.resolveMiddleware(middleware))
		}
	}

	get(pathname, action, context) {
		return this._add('get', pathname, action, context)
	}

	post(pathname, action, context) {
		return this._add('post', pathname, action, context)
	}

	put(pathname, action, context) {
		return this._add('put', pathname, action, context)
	}

	patch(pathname, action, context) {
		return this._add('patch', pathname, action, context)
	}

	delete(pathname, action, context) {
		return this._add('delete', pathname, action, context)
	}

	_add(method, pathname, action, context) {
		const handler = this._makeAction(action)

		// WARNING: Prone to failure if ExpressJS changes this logic
		this.app.express.lazyrouter()

		const handlers = [ handler ]
		this.addMiddleware(handlers, this._scopedAction.use)

		if(typeof action === 'object') {
			this.addMiddleware(handlers, action.use)
		}

		pathname = this._normalizePathComponent(pathname)
		const compiledPath = path.join('/', this._scopedPrefix, pathname).replace(/:([a-z0-0_\-\.]+)/g, (param, name) => {
			const pattern = this.patterns[name]

			if(pattern.isNil) {
				return param
			} else {
				return `${param}(${pattern})`
			}
		})

		if(method.toLowerCase() !== 'get' && this.bodyParserMiddleware.length > 0) {
			handlers.unshift(...this.bodyParserMiddleware)
		}

		for(const i in handlers) {
			handlers[i] = this.resolveMiddleware(handlers[i])
		}

		let route = this.app.express._router.route(compiledPath)
		route = route[method](...handlers)
		route.context = context || {}
		route.grindRouter = this

		return route
	}

	_makeAction(action) {
		if(typeof action === 'function') {
			return action
		}

		if(typeof action === 'string') {
			action = { method: action }
		}

		action = Object.assign({ }, this._scopedAction, action)
		const method = action.controller[action.method]
		const controller = action.controller

		return (...args) => {
			const result = method.apply(controller, args)

			if(typeof result === 'object' && typeof result.catch === 'function') {
				return result.catch(args[2])
			} else {
				return result
			}
		}
	}

	_normalizePathComponent(component) {
		return path.normalize(component.trim()).replace(/^\//, '')
	}

	bind(name, resolver, context) {
		this.bindings[name] = { resolver }

		if(!context.isNil) {
			this.bindings[name].context = context
		}

		this.app.express.param(name, (req, res, next, value) => {
			resolver(value, newValue => {
				req.params[name] = newValue
				next()
			}, err => {
				next(err)
			}, req, res)
		})
	}

	pattern(name, pattern) {
		this.patterns[name] = pattern
	}

	nameRoute(name, route) {
		route.routeName = name
		this.namedRoutes[name] = route
	}

	registerMiddleware(name, middleware) {
		this.middleware[name] = middleware
	}

	resolveMiddleware(middleware) {
		if(typeof middleware === 'function') {
			return middleware
		}

		if(this.middleware[middleware].isNil) {
			throw new Error(`Unknown middleware alias: ${middleware}`)
		}

		return this.middleware[middleware]
	}

	addMiddleware(handlers, middleware) {
		if(middleware.isNil) {
			return
		}

		if(typeof middleware === 'string') {
			middleware = { before: [ middleware ] }
		}

		if(Array.isArray(middleware)) {
			middleware = { before: middleware }
		}

		if(Array.isArray(middleware.before)) {
			handlers.unshift(...middleware.before)
		} else if(Array.isArray(middleware.before)) {
			handlers.push(...middleware.after)
		}
	}

}
<|endoftext|>


<commit_before>const net = require('net')
const to = require('to2')
const find = require('array-find')
const each = require('each-async')
const Map = require('es6-map')
const User = require('./User')
const Channel = require('./Channel')
const Message = require('./Message')
const defaultCommands = require('./defaultCommands')
const isValidChannelName = require('./util/isValidChannelName')

const debug = require('debug')('ircs:Server')

/**
 * Represents a single IRC server.
 */
module.exports = class Server extends net.Server {
  /**
   * Creates a server instance.
   *
   * @see Server
   * @return {Server}
   */
  static createServer (options, connectionListener) {
    return new Server(options, connectionListener)
  }

  static defaultOptions () {
    return {
      useDefaultCommands: true
    }
  }

  /**
   * Create an IRC server.
   *
   * @param {Object} options `net.Server` options.
   * @param {function()} connectionListener `net.Server` connection listener.
   */
  constructor (options, connectionListener) {
    options = Object.assign(Server.defaultOptions(), options)

    super(options, connectionListener)

    this.created = new Date()
    this._middleware = []
    this.users = []
    this.channels = new Map()
    this.hostname = options.hostname || 'localhost'

    this.on('connection', sock => {
      debug('incoming connection', sock.remoteAddress)
      const user = new User(sock)
      this.users.push(user)
      user.pipe(to.obj((message, enc, cb) => {
        debug('message', message + '')
        this.execute(message)
        cb()
      }))
    })

    if (options.useDefaultCommands) {
      defaultCommands(this)
    }

    debug('server started')
  }

  /**
   * Finds a user by their nickname.
   *
   * @param {string} nickname Nickname to look for.
   *
   * @return {User|undefined} Relevant User object if found, `undefined` if not found.
   */
  findUser (nickname) {
    nickname = normalize(nickname)
    return find(this.users, user => normalize(user.nickname) === nickname)
  }

  /**
   * Finds a channel on the server.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel|undefined} Relevant Channel object if found, `undefined` if not found.
   */
  findChannel (channelName) {
    return this.channels.get(normalize(channelName))
  }

  /**
   * Creates a new channel with the given name.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel} The new Channel.
   */
  createChannel (channelName) {
    channelName = normalize(channelName)
    if (!isValidChannelName(channelName)) {
      throw new Error('Invalid channel name')
    }

    if (!this.channels.has(channelName)) {
      this.channels.set(channelName, new Channel(channelName))
    }

    return this.channels.get(channelName)
  }

  /**
   * Gets a channel by name, creating a new one if it does not yet exist.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel} The Channel.
   */
  getChannel (channelName) {
    if (!isValidChannelName(channelName)) {
      return
    }
    return this.findChannel(channelName) || this.createChannel(channelName)
  }

  /**
   * Checks if there is a channel of a given name.
   *
   * @param {string} channelName Channel name.
   *
   * @return {boolean} True if the channel exists, false if not.
   */
  hasChannel (channelName) {
    return this.channels.has(normalize(channelName))
  }

  use (command, fn) {
    if (!fn) {
      [ command, fn ] = [ '', command ]
    }
    debug('register middleware', command)
    this._middleware.push({ command, fn })
  }

  execute (message, cb) {
    debug('exec', message + '')
    message.server = this
    each(this._middleware, (mw, idx, next) => {
      if (mw.command === '' || mw.command === message.command) {
        debug('executing', mw.command, message.parameters)
        if (mw.fn.length < 2) {
          mw.fn(message)
          next(null)
        } else {
          mw.fn(message, next)
        }
      }
    }, cb)
  }

  /**
   * Send a message to every user on the server, including the sender.
   *
   * That sounds dangerous.
   *
   * @param {Message} message Message to send.
   */
  send (message) {
    if (!(message instanceof Message)) {
      message = new Message(...arguments)
    }
    this.users.forEach(u => { u.send(message) })
  }

  /**
   * Gives the server mask.
   *
   * @return {string} Mask.
   */
  mask () {
    return this.hostname
  }
}

function normalize (str) {
  return str.toLowerCase().trim()
    // {, } and | are uppercase variants of [, ] and \ respectively
    .replace(/{/g, '[')
    .replace(/}/g, ']')
    .replace(/\|/g, '\\')
}
<commit_msg>Remove obsolete `es6-map` require<commit_after>const net = require('net')
const to = require('to2')
const find = require('array-find')
const each = require('each-async')
const User = require('./User')
const Channel = require('./Channel')
const Message = require('./Message')
const defaultCommands = require('./defaultCommands')
const isValidChannelName = require('./util/isValidChannelName')

const debug = require('debug')('ircs:Server')

/**
 * Represents a single IRC server.
 */
module.exports = class Server extends net.Server {
  /**
   * Creates a server instance.
   *
   * @see Server
   * @return {Server}
   */
  static createServer (options, connectionListener) {
    return new Server(options, connectionListener)
  }

  static defaultOptions () {
    return {
      useDefaultCommands: true
    }
  }

  /**
   * Create an IRC server.
   *
   * @param {Object} options `net.Server` options.
   * @param {function()} connectionListener `net.Server` connection listener.
   */
  constructor (options, connectionListener) {
    options = Object.assign(Server.defaultOptions(), options)

    super(options, connectionListener)

    this.created = new Date()
    this._middleware = []
    this.users = []
    this.channels = new Map()
    this.hostname = options.hostname || 'localhost'

    this.on('connection', sock => {
      debug('incoming connection', sock.remoteAddress)
      const user = new User(sock)
      this.users.push(user)
      user.pipe(to.obj((message, enc, cb) => {
        debug('message', message + '')
        this.execute(message)
        cb()
      }))
    })

    if (options.useDefaultCommands) {
      defaultCommands(this)
    }

    debug('server started')
  }

  /**
   * Finds a user by their nickname.
   *
   * @param {string} nickname Nickname to look for.
   *
   * @return {User|undefined} Relevant User object if found, `undefined` if not found.
   */
  findUser (nickname) {
    nickname = normalize(nickname)
    return find(this.users, user => normalize(user.nickname) === nickname)
  }

  /**
   * Finds a channel on the server.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel|undefined} Relevant Channel object if found, `undefined` if not found.
   */
  findChannel (channelName) {
    return this.channels.get(normalize(channelName))
  }

  /**
   * Creates a new channel with the given name.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel} The new Channel.
   */
  createChannel (channelName) {
    channelName = normalize(channelName)
    if (!isValidChannelName(channelName)) {
      throw new Error('Invalid channel name')
    }

    if (!this.channels.has(channelName)) {
      this.channels.set(channelName, new Channel(channelName))
    }

    return this.channels.get(channelName)
  }

  /**
   * Gets a channel by name, creating a new one if it does not yet exist.
   *
   * @param {string} channelName Channel name.
   *
   * @return {Channel} The Channel.
   */
  getChannel (channelName) {
    if (!isValidChannelName(channelName)) {
      return
    }
    return this.findChannel(channelName) || this.createChannel(channelName)
  }

  /**
   * Checks if there is a channel of a given name.
   *
   * @param {string} channelName Channel name.
   *
   * @return {boolean} True if the channel exists, false if not.
   */
  hasChannel (channelName) {
    return this.channels.has(normalize(channelName))
  }

  use (command, fn) {
    if (!fn) {
      [ command, fn ] = [ '', command ]
    }
    debug('register middleware', command)
    this._middleware.push({ command, fn })
  }

  execute (message, cb) {
    debug('exec', message + '')
    message.server = this
    each(this._middleware, (mw, idx, next) => {
      if (mw.command === '' || mw.command === message.command) {
        debug('executing', mw.command, message.parameters)
        if (mw.fn.length < 2) {
          mw.fn(message)
          next(null)
        } else {
          mw.fn(message, next)
        }
      }
    }, cb)
  }

  /**
   * Send a message to every user on the server, including the sender.
   *
   * That sounds dangerous.
   *
   * @param {Message} message Message to send.
   */
  send (message) {
    if (!(message instanceof Message)) {
      message = new Message(...arguments)
    }
    this.users.forEach(u => { u.send(message) })
  }

  /**
   * Gives the server mask.
   *
   * @return {string} Mask.
   */
  mask () {
    return this.hostname
  }
}

function normalize (str) {
  return str.toLowerCase().trim()
    // {, } and | are uppercase variants of [, ] and \ respectively
    .replace(/{/g, '[')
    .replace(/}/g, ']')
    .replace(/\|/g, '\\')
}
<|endoftext|>