<commit_before>/*
* @Author: gbk <ck0123456@gmail.com>
* @Date:   2016-04-21 17:34:00
* @Last Modified by:   gbk
* @Last Modified time: 2017-05-19 13:22:05
*/

'use strict';

var mkdirp = require('mkdirp');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var Progress = require('progress');
var Balancer = require('load-balancer');
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

var util = require('./util');
var loader = require('./loader');
var pkg = require('../package.json');

// plugin defination
module.exports = {

  description: pkg.description,

  options: [
    [ '-s, --src <dir>', 'source directory, default to `src`', 'src' ],
    [ '-d, --dist <dir>', 'build directory, default to `dist`', 'dist' ],
    [ '-e  --entry <file>', 'app entry, default to `app/app.js`', 'app/app.js' ],
    [ '    --pages [pages]', 'add multi-page entries' ],
    [ '    --buildvars', 'build varibles' ],
    [ '    --vars', 'runtime varibles' ],
    [ '    --externals', 'webpack external varibles' ],
    [ '-o, --loose', 'use babel es2015 loose mode to transform codes' ],
    [ '-c, --keepconsole', 'keep `console.log`' ],
    [ '    --skipminify', 'skip minify js and css' ],
    [ '-p, --progress', 'show progress' ],
    [ '    --exportcss', 'export css files' ],
    [ '    --multiCompilers', 'generate multi-compilers' ],
    [ '    --minifyExtension <extension>', 'minify file extension' ],
    [ '    --includes', 'loader should include paths' ],
    [ '    --polyfill', 'use core-js to do polyfills' ],
    [ '    --mangle', 'mangle varibles when minify' ],
    [ '    --alias', 'path alias' ],
    [ '    --publicPath <path>', 'set publicPath in webpack'],
    [ '    --analyse [port]', 'analyse bundle size'],
  ],

  action: function(options) {

    // options
    var src = options.src;
    var dist = options.dist;
    var entry = options.entry;
    var pages = options.pages;
    var vars = options.vars || {};
    var buildvars = util.parseBuildVars(vars, options.buildvars || {});
    var externals = options.externals || {
      'react': 'window.React',
      'react-dom': 'window.ReactDOM || window.React'
    };
    var loose = options.loose;
    var keepconsole = options.keepconsole;
    var skipminify = options.skipminify;
    var showProgress = options.progress;
    var exportcss = options.exportcss !== false;
    var multiCompilers = !!options.multiCompilers;
    var minifyExtension = options.minifyExtension || '';
    var includes = options.includes;
    var polyfill = !!options.polyfill;
    var mangle = !!options.mangle;
    var alias = (function(aliasMap) {
      for (var key in aliasMap) {
        aliasMap[key] = util.cwdPath(src, aliasMap[key]);
      }
      return aliasMap;
    })(typeof options.alias === 'object' ? options.alias : {
      i18n: 'i18n'
    });
    var publicPath = options.publicPath || '/';
    var analyse = options.analyse;

    // start time stamp
    var startStamp = Date.now();

    // copy task
    mkdirp.sync(util.cwdPath(dist));
    util.copy([
      util.cwdPath(src, 'lib', '**', '*.*'),
      util.cwdPath('html', '**', '*.*')
    ], util.cwdPath(dist));

    // entries
    var entries = {
      app: util.makeEntry(src, entry)
    };
    if (pages) {
      entries = util.makePageEntries(src, entries, pages);
    }

    // resolve
    var resolveRoot = [
      util.relPath('..', 'node_modules')
    ];
    if (process.cwd() !== util.relPath('..', '..', '..')) {
      resolveRoot.push(util.relPath('..', '..'));
    }
    var resolve = {
      root: resolveRoot,
      alias: alias,
      extensions: ['', '.js', '.jsx']
    };
    var resolveLoader = {
      root: resolveRoot
    };

    // plugins
    var plugins = [
      new webpack.optimize.OccurenceOrderPlugin()
    ];
    if (exportcss) {
      plugins.push(new ExtractTextPlugin('[name].css'));
    }
    if (showProgress) {
      var bar = new Progress('webpack compile [:bar]', {
        total: 1,
        width: 20
      });
      var oldPercentage = 0;
      plugins.push(new webpack.ProgressPlugin(function handler(percentage) {
        bar.tick(percentage - oldPercentage);
        oldPercentage = percentage;
      }));
    }
    if (analyse) {
      var analysePort = parseInt(analyse);
      plugins.push(new BundleAnalyzerPlugin({
        analyzerMode: analysePort > 0 ? 'server' : 'static',
        analyzerPort: analysePort || 8888,
        reportFilename: util.cwdPath('webpack-bundle-analyzer-report.html')
      }));
    }

    // split buildvars into a table
    var keysArr = [];
    var valuesArr = [];
    for (var key in buildvars) {
      keysArr.push(key);
      if (Array.isArray(buildvars[key]) && buildvars[key].length) {
        valuesArr.push(buildvars[key]);
      } else {
        console.error(key + ' in buildvars MUST have at least one value!');
        process.exit(0);
      }
    }

    // generate all vars combination
    var combinations = [];
    if (keysArr.length) {
      var findRoute = function(combination) {
        combination = combination || [];
        var values = valuesArr[combination.length];
        if (values) {
          values.forEach(function(value) {
            findRoute(combination.concat([ value ]));
          });
        } else {
          var vars = {};
          keysArr.forEach(function(key, index) {
            vars[key] = combination[index];
          });
          combinations.push(vars);
        }
      }
      findRoute();
    }

    // minify task
    var minify = skipminify ? function() {
      util.finishLog(startStamp);
    } : function(assets) {
      new Balancer.Master().send(util.relPath('minify.js'), {
        keepconsole: keepconsole,
        minifyExtension: minifyExtension,
        mangle: mangle
      }, assets.map(function(a) {
        return util.cwdPath(dist, a.name);
      }), function() {
        util.finishLog(startStamp);
      });
    };

    // run compiler
    if (combinations.length > 1 || multiCompilers) { // multi-compilers

      var compilers = combinations.length > 1 ? combinations.map(function(vars, index) {
        return util.preProcess({
          entry: entries,
          output: {
            path: util.cwdPath(dist),
            filename: '[name]' + util.suffixByVars(vars, buildvars) + '.js',
            publicPath: publicPath
          },
          plugins: plugins.concat([
            new webpack.DefinePlugin(util.parseVars(vars))
          ]),
          resolve: resolve,
          resolveLoader: resolveLoader,
          externals: externals,
          cache: true,
          module: {
            loaders: loader(options, index === 0)
          }
        });
      }) : util.preProcess({
          entry: entries,
          output: {
            path: util.cwdPath(dist),
            filename: '[name].js',
            publicPath: publicPath
          },
          plugins: plugins,
          resolve: resolve,
          resolveLoader: resolveLoader,
          externals: externals,
          cache: true,
          module: {
            loaders: loader(options)
          }
        });

      webpack(compilers, function(err, stats) {

        // print wepack compile result
        if (err) {
          return util.buildFail(err.toString());
        }
        console.log('=============');
        var assets = [];
        stats.stats.forEach(function(stat) {
          if (stat.hasErrors()) {
            return util.buildFail(stat.toJson().errors[0].split('\n').slice(0, 2).join('\n'));
          }
          console.log(stat.toString({
            version: false,
            hash: false,
            chunks: false,
            children: false,
            colors: true
          }) + '\n=============');

          // concat assets
          Array.prototype.push.apply(assets, stat.toJson({
            hash: false,
            chunks: false,
            children: false,
            modules: false
          }).assets);
        });

        // minify task
        minify(assets);
      });

    } else { // single-compiler

      // vars defined
      if (combinations.length) {
        plugins.push(new webpack.DefinePlugin(util.parseVars(combinations[0])));
      }

      webpack(util.preProcess({
        entry: entries,
        output: {
          path: util.cwdPath(dist),
          filename: '[name].js',
          publicPath: publicPath
        },
        plugins: plugins,
        resolve: resolve,
        resolveLoader: resolveLoader,
        externals: externals,
        cache: true,
        module: {
          loaders: loader(options, true)
        }
      }), function(err, stats) {

        // print wepack compile result
        if (err) {
          return util.buildFail(err.toString());
        }
        if (stats.hasErrors()) {
          return util.buildFail(stats.toJson().errors[0].split('\n').slice(0, 2).join('\n'));
        }
        console.log('\n' + stats.toString({
          hash: false,
          chunks: false,
          children: false,
          colors: true
        }));

        // minify task
        minify(stats.toJson({
          hash: false,
          chunks: false,
          children: false,
          modules: false
        }).assets);
      });
    }

  }
};

<commit_msg>fix: style is missing in en build<commit_after>/*
* @Author: gbk <ck0123456@gmail.com>
* @Date:   2016-04-21 17:34:00
* @Last Modified by:   gbk
* @Last Modified time: 2017-05-19 13:22:05
*/

'use strict';

var mkdirp = require('mkdirp');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var Progress = require('progress');
var Balancer = require('load-balancer');
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

var util = require('./util');
var loader = require('./loader');
var pkg = require('../package.json');

// plugin defination
module.exports = {

  description: pkg.description,

  options: [
    [ '-s, --src <dir>', 'source directory, default to `src`', 'src' ],
    [ '-d, --dist <dir>', 'build directory, default to `dist`', 'dist' ],
    [ '-e  --entry <file>', 'app entry, default to `app/app.js`', 'app/app.js' ],
    [ '    --pages [pages]', 'add multi-page entries' ],
    [ '    --buildvars', 'build varibles' ],
    [ '    --vars', 'runtime varibles' ],
    [ '    --externals', 'webpack external varibles' ],
    [ '-o, --loose', 'use babel es2015 loose mode to transform codes' ],
    [ '-c, --keepconsole', 'keep `console.log`' ],
    [ '    --skipminify', 'skip minify js and css' ],
    [ '-p, --progress', 'show progress' ],
    [ '    --exportcss', 'export css files' ],
    [ '    --multiCompilers', 'generate multi-compilers' ],
    [ '    --minifyExtension <extension>', 'minify file extension' ],
    [ '    --includes', 'loader should include paths' ],
    [ '    --polyfill', 'use core-js to do polyfills' ],
    [ '    --mangle', 'mangle varibles when minify' ],
    [ '    --alias', 'path alias' ],
    [ '    --publicPath <path>', 'set publicPath in webpack'],
    [ '    --analyse [port]', 'analyse bundle size'],
  ],

  action: function(options) {

    // options
    var src = options.src;
    var dist = options.dist;
    var entry = options.entry;
    var pages = options.pages;
    var vars = options.vars || {};
    var buildvars = util.parseBuildVars(vars, options.buildvars || {});
    var externals = options.externals || {
      'react': 'window.React',
      'react-dom': 'window.ReactDOM || window.React'
    };
    var loose = options.loose;
    var keepconsole = options.keepconsole;
    var skipminify = options.skipminify;
    var showProgress = options.progress;
    var exportcss = options.exportcss !== false;
    var multiCompilers = !!options.multiCompilers;
    var minifyExtension = options.minifyExtension || '';
    var includes = options.includes;
    var polyfill = !!options.polyfill;
    var mangle = !!options.mangle;
    var alias = (function(aliasMap) {
      for (var key in aliasMap) {
        aliasMap[key] = util.cwdPath(src, aliasMap[key]);
      }
      return aliasMap;
    })(typeof options.alias === 'object' ? options.alias : {
      i18n: 'i18n'
    });
    var publicPath = options.publicPath || '/';
    var analyse = options.analyse;

    // start time stamp
    var startStamp = Date.now();

    // copy task
    mkdirp.sync(util.cwdPath(dist));
    util.copy([
      util.cwdPath(src, 'lib', '**', '*.*'),
      util.cwdPath('html', '**', '*.*')
    ], util.cwdPath(dist));

    // entries
    var entries = {
      app: util.makeEntry(src, entry)
    };
    if (pages) {
      entries = util.makePageEntries(src, entries, pages);
    }

    // resolve
    var resolveRoot = [
      util.relPath('..', 'node_modules')
    ];
    if (process.cwd() !== util.relPath('..', '..', '..')) {
      resolveRoot.push(util.relPath('..', '..'));
    }
    var resolve = {
      root: resolveRoot,
      alias: alias,
      extensions: ['', '.js', '.jsx']
    };
    var resolveLoader = {
      root: resolveRoot
    };

    // plugins
    var plugins = [
      new webpack.optimize.OccurenceOrderPlugin()
    ];
    if (exportcss) {
      plugins.push(new ExtractTextPlugin('[name].css', {
        allChunks: !pages // 如果用户以单页形式进行代码分离。需要把其他chunk的css一同抽到app.css里
      }));
    }
    if (showProgress) {
      var bar = new Progress('webpack compile [:bar]', {
        total: 1,
        width: 20
      });
      var oldPercentage = 0;
      plugins.push(new webpack.ProgressPlugin(function handler(percentage) {
        bar.tick(percentage - oldPercentage);
        oldPercentage = percentage;
      }));
    }
    if (analyse) {
      var analysePort = parseInt(analyse);
      plugins.push(new BundleAnalyzerPlugin({
        analyzerMode: analysePort > 0 ? 'server' : 'static',
        analyzerPort: analysePort || 8888,
        reportFilename: util.cwdPath('webpack-bundle-analyzer-report.html')
      }));
    }

    // split buildvars into a table
    var keysArr = [];
    var valuesArr = [];
    for (var key in buildvars) {
      keysArr.push(key);
      if (Array.isArray(buildvars[key]) && buildvars[key].length) {
        valuesArr.push(buildvars[key]);
      } else {
        console.error(key + ' in buildvars MUST have at least one value!');
        process.exit(0);
      }
    }

    // generate all vars combination
    var combinations = [];
    if (keysArr.length) {
      var findRoute = function(combination) {
        combination = combination || [];
        var values = valuesArr[combination.length];
        if (values) {
          values.forEach(function(value) {
            findRoute(combination.concat([ value ]));
          });
        } else {
          var vars = {};
          keysArr.forEach(function(key, index) {
            vars[key] = combination[index];
          });
          combinations.push(vars);
        }
      }
      findRoute();
    }

    // minify task
    var minify = skipminify ? function() {
      util.finishLog(startStamp);
    } : function(assets) {
      new Balancer.Master().send(util.relPath('minify.js'), {
        keepconsole: keepconsole,
        minifyExtension: minifyExtension,
        mangle: mangle
      }, assets.map(function(a) {
        return util.cwdPath(dist, a.name);
      }), function() {
        util.finishLog(startStamp);
      });
    };

    // run compiler
    if (combinations.length > 1 || multiCompilers) { // multi-compilers

      var compilers = combinations.length > 1 ? combinations.map(function(vars, index) {
        return util.preProcess({
          entry: entries,
          output: {
            path: util.cwdPath(dist),
            filename: '[name]' + util.suffixByVars(vars, buildvars) + '.js',
            publicPath: publicPath
          },
          plugins: plugins.concat([
            new webpack.DefinePlugin(util.parseVars(vars))
          ]),
          resolve: resolve,
          resolveLoader: resolveLoader,
          externals: externals,
          cache: true,
          module: {
            loaders: loader(options, index === 0)
          }
        });
      }) : util.preProcess({
          entry: entries,
          output: {
            path: util.cwdPath(dist),
            filename: '[name].js',
            publicPath: publicPath
          },
          plugins: plugins,
          resolve: resolve,
          resolveLoader: resolveLoader,
          externals: externals,
          cache: true,
          module: {
            loaders: loader(options)
          }
        });

      webpack(compilers, function(err, stats) {

        // print wepack compile result
        if (err) {
          return util.buildFail(err.toString());
        }
        console.log('=============');
        var assets = [];
        stats.stats.forEach(function(stat) {
          if (stat.hasErrors()) {
            return util.buildFail(stat.toJson().errors[0].split('\n').slice(0, 2).join('\n'));
          }
          console.log(stat.toString({
            version: false,
            hash: false,
            chunks: false,
            children: false,
            colors: true
          }) + '\n=============');

          // concat assets
          Array.prototype.push.apply(assets, stat.toJson({
            hash: false,
            chunks: false,
            children: false,
            modules: false
          }).assets);
        });

        // minify task
        minify(assets);
      });

    } else { // single-compiler

      // vars defined
      if (combinations.length) {
        plugins.push(new webpack.DefinePlugin(util.parseVars(combinations[0])));
      }

      webpack(util.preProcess({
        entry: entries,
        output: {
          path: util.cwdPath(dist),
          filename: '[name].js',
          publicPath: publicPath
        },
        plugins: plugins,
        resolve: resolve,
        resolveLoader: resolveLoader,
        externals: externals,
        cache: true,
        module: {
          loaders: loader(options, true)
        }
      }), function(err, stats) {

        // print wepack compile result
        if (err) {
          return util.buildFail(err.toString());
        }
        if (stats.hasErrors()) {
          return util.buildFail(stats.toJson().errors[0].split('\n').slice(0, 2).join('\n'));
        }
        console.log('\n' + stats.toString({
          hash: false,
          chunks: false,
          children: false,
          colors: true
        }));

        // minify task
        minify(stats.toJson({
          hash: false,
          chunks: false,
          children: false,
          modules: false
        }).assets);
      });
    }

  }
};

<|endoftext|>


<commit_before>import BCryptHash from './BCryptHash';

var hash = {
  bcrypt: require('./BCryptHash')
};

/**
 * Create Hash instance
 * @param {String} type Type of hash instance
 * @param {Object} [config] Additional options for hash instance
 * @returns {*}
 */
export default function (type, config) {
  if (hash[type.toLowerCase()] instanceof Function) {
    return new hash[type.toLowerCase()](config);
  } else {
    throw new Error('Unrecognized type -> ' + type);
  }
}
<commit_msg>Fix import in HashService<commit_after>import BCryptHash from './BCryptHash';

var hash = {
  bcrypt: BCryptHash
};

/**
 * Create Hash instance
 * @param {String} type Type of hash instance
 * @param {Object} [config] Additional options for hash instance
 * @returns {*}
 */
export default function (type, config) {
  if (hash[type.toLowerCase()] instanceof Function) {
    return new hash[type.toLowerCase()](config);
  } else {
    throw new Error('Unrecognized type -> ' + type);
  }
}
<|endoftext|>


<commit_before>"use strict";

class CircleSlider {
  /**
   * Creates an instance of CircleSlider inside the element with the id `targetId`
   * @param {String} targetId    The id of the element to contain the circle slider.
   * @memberof CircleSlider
   */
  constructor(targetId) {
    this.root = document.getElementById(targetId);
    this.outputAngle = 0;

    // validation
    if (!this.root) {
      console.error("CircleSlider: Didn't find any element with id " + targetId);
    }

    // create the child elements and append them
    this.hc = this._createHandleContainerElem();
    this.handle = this._createHandleElem();
    this.hc.appendChild(this.handle);
    this.root.appendChild(this.hc);

    // just to keep track of all event names
    this.events = {
      sliderMove: "sliderMove",
      sliderUp: "sliderUp"
    }

    // active is true when user is holding down handle
    this.active = false;
    // mouse events
    this._addEventListeners("mousedown", "mousemove", "mouseup");
    // touch events
    this._addEventListeners("touchstart", "touchmove", "touchend");

    // bind methods
    this._mouseMoveHandler = this._mouseMoveHandler.bind(this);
  }

  // public methods

  /**
   * Use this function to call a callback function to react to
   * synthetic events from this class.
   *
   * @param {String}    The name of the event to listen to
   * @param {Function}  The callback function for the event
   * @memberof CircleSlider
   */
  on(name, callback) {
    const eventName = this.root.id + "-" + name;
    this.root.addEventListener(eventName, callback);
  }

  /**
   * Returns the angle/value of the slider.
   *
   * @returns The current value
   * @memberof CircleSlider
   */
  getAngle() {
    return this.outputAngle;
  }

  /**
   * Manually sets the angle/value of the slider.
   *
   * @param {Number} angle  The new value for the slider
   * @memberof CircleSlider
   */
  setAngle(angle) {
    const rawAngle = 360 - angle;
    this._moveHandle(rawAngle);
  }

  // "private" methods

  _fireEvent(name, data) {
    const eventName = this.root.id + "-" + name;
    const event = new CustomEvent(eventName, { detail: data });
    this.root.dispatchEvent(event);
  }

  _addEventListeners(startEvent, moveEvent, endEvent) {
    // user presses handle
    this.handle.addEventListener(startEvent, (e) => {
      // prevent text selection
      e.preventDefault();

      if (!this.active) {
        this.active = true;

        // user moves handle
        document.addEventListener(moveEvent, this._mouseMoveHandler, false);

        // user lets go
        document.addEventListener(endEvent, () => {
          this.active = false;
          document.removeEventListener(moveEvent, this._mouseMoveHandler, false);
          this._fireEvent(this.events.sliderUp, this.outputAngle);
        })
      }
    })
  }

  _mouseMoveHandler(e) {
    e.preventDefault();
    this._moveHandle(this.getAngle(e));
  }

  _moveHandle(rawAngle) {
    this.hc.style.cssText = `transform: rotate(${rawAngle}deg);`;
    this.outputAngle = 360 - Math.round(rawAngle);
    this._fireEvent(this.events.sliderMove, this.outputAngle);
  }

  _getCenter(elem) {
    const rect = elem.getBoundingClientRect();
    return {
      x: rect.left + (rect.width / 2),
      y: rect.top + (rect.height / 2),
    };
  }

  _radToDeg(rad) {
    return rad * (180 / Math.PI);
  }

  getAngle(e) {
    const pivot = this._getCenter(this.root);
    const mouse = {
      x: e.pageX,
      y: e.pageY,
    }
    const offset = -90;
    let angle = this._radToDeg(Math.atan2(mouse.x - pivot.x, -(mouse.y - pivot.y))) + offset;
    if (angle < 0) angle += 360;
    return angle;
  }

  // Uninteresting methods

  _createHandleContainerElem() {
    let hc = document.createElement("div");
    hc.className = "cs-handle-container";
    return hc;
  }

  _createHandleElem() {
    let h = document.createElement("div");
    h.className = "cs-handle";
    return h;
  }
}<commit_msg>✅ Enable snapping handle to multiples of number<commit_after>"use strict";

class CircleSlider {
  /**
   * Creates an instance of CircleSlider inside the element with the id `targetId`
   * @param {String} targetId         The id of the element to contain the circle slider.
   * @param {Number} [snapMultiplier] Makes the handle snap to every multiple of this number.
   * @memberof CircleSlider
   */
  constructor(targetId, snapMultiplier) {
    this.root = document.getElementById(targetId);
    this.outputAngle = 0;
    this.snapMultiplier = snapMultiplier;

    // validation
    if (!this.root) {
      console.error("CircleSlider: Didn't find any element with id " + targetId);
    }

    // create the child elements and append them
    this.hc = this._createHandleContainerElem();
    this.handle = this._createHandleElem();
    this.hc.appendChild(this.handle);
    this.root.appendChild(this.hc);

    // just to keep track of all event names
    this.events = {
      sliderMove: "sliderMove",
      sliderUp: "sliderUp"
    }

    // active is true when user is holding down handle
    this.active = false;
    // mouse events
    this._addEventListeners("mousedown", "mousemove", "mouseup");
    // touch events
    this._addEventListeners("touchstart", "touchmove", "touchend");

    // bind methods
    this._mouseMoveHandler = this._mouseMoveHandler.bind(this);
  }

  // public methods

  /**
   * Use this function to call a callback function to react to
   * synthetic events from this class.
   *
   * @param {String}    The name of the event to listen to
   * @param {Function}  The callback function for the event
   * @memberof CircleSlider
   */
  on(name, callback) {
    const eventName = this.root.id + "-" + name;
    this.root.addEventListener(eventName, callback);
  }

  /**
   * Returns the angle/value of the slider.
   *
   * @returns The current value
   * @memberof CircleSlider
   */
  getAngle() {
    return this.outputAngle;
  }

  /**
   * Manually sets the angle/value of the slider.
   *
   * @param {Number} angle  The new value for the slider
   * @memberof CircleSlider
   */
  setAngle(angle) {
    const rawAngle = 360 - angle;
    this._moveHandle(rawAngle);
  }

  // "private" methods

  _fireEvent(name, data) {
    const eventName = this.root.id + "-" + name;
    const event = new CustomEvent(eventName, { detail: data });
    this.root.dispatchEvent(event);
  }

  _addEventListeners(startEvent, moveEvent, endEvent) {
    // user presses handle
    this.handle.addEventListener(startEvent, (e) => {
      // prevent text selection
      e.preventDefault();

      if (!this.active) {
        this.active = true;

        // user moves handle
        document.addEventListener(moveEvent, this._mouseMoveHandler, false);

        // user lets go
        document.addEventListener(endEvent, () => {
          this.active = false;
          document.removeEventListener(moveEvent, this._mouseMoveHandler, false);
          this._fireEvent(this.events.sliderUp, this.outputAngle);
        })
      }
    })
  }

  _mouseMoveHandler(e) {
    e.preventDefault();
    this._moveHandle(this.getAngle(e));
  }

  _moveHandle(rawAngle) {
    // snap handle to multiples of snapMultiplier
    if (this.snapMultiplier) {
      const sm = this.snapMultiplier;
      const delta = Math.abs(rawAngle - (Math.round(rawAngle / sm) * sm));
      if (delta <= 5) {
        rawAngle = Math.round(rawAngle / sm) * sm;
      }
    }

    // move the handle visually
    this.hc.style.cssText = `transform: rotate(${rawAngle}deg);`;

    // format angle that gets exposed
    let outputAngle = 360 - Math.round(rawAngle);
    if (outputAngle === 360) {
      outputAngle = 0;
    }
    this.outputAngle = outputAngle;

    this._fireEvent(this.events.sliderMove, this.outputAngle);
  }

  _getCenter(elem) {
    const rect = elem.getBoundingClientRect();
    return {
      x: rect.left + (rect.width / 2),
      y: rect.top + (rect.height / 2),
    };
  }

  _radToDeg(rad) {
    return rad * (180 / Math.PI);
  }

  getAngle(e) {
    const pivot = this._getCenter(this.root);
    const mouse = {
      x: e.pageX,
      y: e.pageY,
    }
    const offset = -90;
    let angle = this._radToDeg(Math.atan2(mouse.x - pivot.x, -(mouse.y - pivot.y))) + offset;
    if (angle < 0) angle += 360;
    return angle;
  }

  // Uninteresting methods

  _createHandleContainerElem() {
    let hc = document.createElement("div");
    hc.className = "cs-handle-container";
    return hc;
  }

  _createHandleElem() {
    let h = document.createElement("div");
    h.className = "cs-handle";
    return h;
  }
}<|endoftext|>


<commit_before>/*!
 * Search - Index
 * Copyright (C) 2011 Oliver Nightingale
 * MIT Licensed
 */

/**
 * Search.Index provides the public api for the Search library.  It also manages setting up both a wordStore
 * and a docStore to persist all the words and documents that make up this index.  An index must be initialised
 * with a name, this name is important as it will be used to create and access the Search.Stores.  If the name
 * is changed then any previously created indexes will be unavailable.
 *
 */
Search.Index = function (name) {
  this.name = name
  this.fields = {} // by default no fields will be indexed
  this.wordStore = new Search.Store (name + "-words")
  this.docStore = new Search.Store (name + "-docs")
  this.queueLength = 0
  this.adding = false

  // do this elsewhere???
  this.wordStore.init(function () { console.log('wordStore initialized') })
  this.docStore.init(function () { console.log('docStore initialized') })
}

Search.Index.prototype = {

  /**
   * ## Search.Index.prototype.addList
   * Add a list of objects to the index
   */
  addList: function (objs) {
    var self = this
    var list = objs.slice(0, objs.length)
    var deferred = new Search.Deferred ()
    var obj = list.pop()
    self.add(obj).then(function () {
      if (list.length) self.addList(list)
      list = null // reset list to prevent memory leaks?
    })
  },

  /**
   * ## Search.Index.prototype.add
   * Adds a new document to the index
   */
  add: function (obj) {
    var self = this
    var doc = new Search.Document(obj, this.fields)
    var returnDeferred = new Search.Deferred ()

    var words = doc.words()

    var findDeferred = new Search.Deferred(words.map(function (word) {
      return self.wordStore.find(word.id)
    }))

    findDeferred.then(function (existingWords) {

      existingWords.forEach(function (existingWord) {
        if (existingWord) {
          matchingWord = words.filter(function (word) {
            return word.id === existingWord.id
          })[0]

          existingWord.docs.forEach(function (doc) {
            matchingWord.docs.push(doc)
          })
        };
      })

      var saveDeferred = new Search.Deferred(words.map(function (word) {
        return self.wordStore.save(word)
      }))

      saveDeferred.then(function () {
        self.docStore.save(doc.asJSON()).then(function () {
          returnDeferred.resolve()
        })
      })
    })

    return returnDeferred
  },

  empty: function () {
    var self = this

    return new Search.Deferred ([
      self.wordStore.destroyAll(),
      self.docStore.destroyAll()
    ])
  },

  field: function (name, opts) {
    this.fields[name] = opts || {multiplier: 1}
  },

  search: function (term) {
    var self = this
    var returnDeferred = new Search.Deferred ()

    // convert the term into search words
    var words = term
      .split(' ')
      .map(function (str) {
        var word = new Search.Word(str)
        if (!word.isStopWord()) return word.toString()
      })
      .filter(function (wordString) {
        return wordString
      })

    var wordDeferred = new Search.Deferred (words.map(function (word) { return self.wordStore.find(word) }))

    wordDeferred.then(function (words) {
      if (!words[0]) {
        returnDeferred.resolve([])
      } else {
        var wordDocs = words
          .map(function (word) {
            return word.docs
          })
          .sort(function (a, b) {
            if (a.score < b.score) return 1
            if (a.score > b.score) return -1
            return 0
          })

        var docIds = Search.utils.intersect.apply(Search.utils, wordDocs.map(function (docs) {
          return docs.map(function (doc) {
            return doc.documentId
          })
        }))

        var docDeferred = new Search.Deferred (docIds.map(function (docId) { return self.docStore.find(docId) }))

        docDeferred.then(function (searchDocs) {
          returnDeferred.resolve(searchDocs.map(function (searchDoc) {
            return searchDoc.original
          }))
        })
      }
    })

    return returnDeferred

  }
}<commit_msg>fix ordering<commit_after>/*!
 * Search - Index
 * Copyright (C) 2011 Oliver Nightingale
 * MIT Licensed
 */

/**
 * Search.Index provides the public api for the Search library.  It also manages setting up both a wordStore
 * and a docStore to persist all the words and documents that make up this index.  An index must be initialised
 * with a name, this name is important as it will be used to create and access the Search.Stores.  If the name
 * is changed then any previously created indexes will be unavailable.
 *
 */
Search.Index = function (name) {
  this.name = name
  this.fields = {} // by default no fields will be indexed
  this.wordStore = new Search.Store (name + "-words")
  this.docStore = new Search.Store (name + "-docs")
  this.queueLength = 0
  this.adding = false

  // do this elsewhere???
  this.wordStore.init(function () { console.log('wordStore initialized') })
  this.docStore.init(function () { console.log('docStore initialized') })
}

Search.Index.prototype = {

  /**
   * ## Search.Index.prototype.addList
   * Add a list of objects to the index
   */
  addList: function (objs) {
    var self = this
    var list = objs.slice(0, objs.length)
    var deferred = new Search.Deferred ()
    var obj = list.pop()
    self.add(obj).then(function () {
      if (list.length) self.addList(list)
      list = null // reset list to prevent memory leaks?
    })
  },

  /**
   * ## Search.Index.prototype.add
   * Adds a new document to the index
   */
  add: function (obj) {
    var self = this
    var doc = new Search.Document(obj, this.fields)
    var returnDeferred = new Search.Deferred ()

    var words = doc.words()

    var findDeferred = new Search.Deferred(words.map(function (word) {
      return self.wordStore.find(word.id)
    }))

    findDeferred.then(function (existingWords) {

      existingWords.forEach(function (existingWord) {
        if (existingWord) {
          matchingWord = words.filter(function (word) {
            return word.id === existingWord.id
          })[0]

          existingWord.docs.forEach(function (doc) {
            matchingWord.docs.push(doc)
          })
        };
      })

      var saveDeferred = new Search.Deferred(words.map(function (word) {
        return self.wordStore.save(word)
      }))

      saveDeferred.then(function () {
        self.docStore.save(doc.asJSON()).then(function () {
          returnDeferred.resolve()
        })
      })
    })

    return returnDeferred
  },

  empty: function () {
    var self = this

    return new Search.Deferred ([
      self.wordStore.destroyAll(),
      self.docStore.destroyAll()
    ])
  },

  field: function (name, opts) {
    this.fields[name] = opts || {multiplier: 1}
  },

  search: function (term) {
    var self = this
    var returnDeferred = new Search.Deferred ()

    // convert the term into search words
    var words = term
      .split(' ')
      .map(function (str) {
        var word = new Search.Word(str)
        if (!word.isStopWord()) return word.toString()
      })
      .filter(function (wordString) {
        return wordString
      })

    var wordDeferred = new Search.Deferred (words.map(function (word) { return self.wordStore.find(word) }))

    wordDeferred.then(function (words) {
      if (!words[0]) {
        returnDeferred.resolve([])
      } else {
        var wordDocs = words
          .map(function (word) {
            return word.docs.sort(function (a, b) {
              return b.score - a.score
            })
          })

        var docIds = Search.utils.intersect.apply(Search.utils, wordDocs.map(function (docs) {
          return docs.map(function (doc) {
            return doc.documentId
          })
        }))

        var docDeferred = new Search.Deferred (docIds.map(function (docId) { return self.docStore.find(docId) }))

        docDeferred.then(function (searchDocs) {
          returnDeferred.resolve(searchDocs.map(function (searchDoc) {
            return searchDoc.original
          }))
        })
      }
    })

    return returnDeferred

  }
}<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import Immutable from 'immutable';
import Promise from 'bluebird';
import superagent from 'superagent';

import TagContainer from './TagContainer';

export default class TagInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      waiting: false,
      data: props.options
    };

    this.handleSelectItem = this.handleSelectItem.bind(this);
    this.handleDeselectItem = this.handleDeselectItem.bind(this);
    this.handleGetOptions = this.handleGetOptions.bind(this);
  }
  /**
   * Selects an item
   * pass it to parent (If any)
   *
   * @param {any} item
   * @memberof TagInput
   */
  handleSelectItem(item) {
    let { value } = this.props;

    value = value.push(item);

    // Sending the tags to parent
    this.props.onChange(value);
  }

  /**
   * Deselects an item
   * pass it to parent (If any)
   *
   * @param {any} item
   * @memberof TagInput
   */
  handleDeselectItem(item) {
    let { value } = this.props;

    const selectItemBy = item.key ? 'key' : 'id';
    const index = this.props.value.findIndex(selectedItem => item[selectItemBy] === selectedItem[selectItemBy]);

    if (index > -1) {
      value = value.splice(index, 1);
    }

    // Sending the tags to parent
    this.props.onChange(value);
  }

  fetchServer(query) {
    const { fetchUrl, httpHeaders } = this.props;

    this.setState({
      waiting: true
    });

    return new Promise((resolve, reject) => {
      let req = superagent.get(fetchUrl);
      // Setting the http headers
      Object.keys(httpHeaders).forEach((key) => {
        req.set(key, httpHeaders[key]);
      });

      req
        .accept('application/json')
        .query({ query: query })
        .end((err, res) => {
          if (err) {
            reject(err);
          }
          resolve(res.body);
        });
    });
  }

  handleGetOptions(query = '', active = false) {
    if (active || this.state.data.some(field => field.label === query)) {
      return;
    }

    this.fetchServer(query)
      .then((res) => {
        this.setState({
          data: this.props.extractor(res),
          waiting: false
        });
      });
  }

  render() {
    const {
      data,
      waiting
    } = this.state;

    return (
      <TagContainer
        {...this.props}
        options={data}
        loading={waiting}
        selection={this.props.value}
        onSelect={this.handleSelectItem}
        onDeselect={this.handleDeselectItem}
        onHandleFetch={this.handleGetOptions}
      />
    );
  }
}

// default props
TagInput.defaultProps = {
  loading:              false,
  multiple:             true,
  filterable:           true,
  darkTheme:            false,

  className:            '',
  orderOptionsBy:       'title',
  label:                'Select Tags...',
  togglePosition:       'left',
  noOptionsMessage:     '',
  toggleSwitchStyle:    'search',
  fetchUrl:             '',

  optionGroupTitles:    [],
  options:              [],

  httpHeaders:          {},
  value:                new Immutable.List(),

  onHandleFetch:        function onHandleFetch() {},
  extractor:            data => data
};

// prop types checking
TagInput.propTypes = {
  loading:            PropTypes.bool,
  multiple:           PropTypes.bool,
  filterable:         PropTypes.bool,
  darkTheme:          PropTypes.bool,

  className:          PropTypes.string,
  orderOptionsBy:     PropTypes.string,
  label:              PropTypes.string,
  togglePosition:     PropTypes.string,
  noOptionsMessage:   PropTypes.string,
  toggleSwitchStyle:  PropTypes.string,
  fetchUrl:           PropTypes.string,

  options:            PropTypes.array,
  optionGroupTitles:  PropTypes.array,

  httpHeaders:        PropTypes.object,
  value:              PropTypes.instanceOf(Immutable.List).isRequired,

  onChange:           PropTypes.func.isRequired,
  onHandleFetch:      PropTypes.func,
  extractor:          PropTypes.func
};
<commit_msg>adds shouldComponentUpdate<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import Immutable from 'immutable';
import Promise from 'bluebird';
import superagent from 'superagent';

import TagContainer from './TagContainer';

export default class TagInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      waiting: false,
      data: props.options
    };

    this.handleSelectItem = this.handleSelectItem.bind(this);
    this.handleDeselectItem = this.handleDeselectItem.bind(this);
    this.handleGetOptions = this.handleGetOptions.bind(this);
  }

  shouldComponentUpdate(nextProps) {
    const fieldsToCheck = ['value', 'loading', 'options', 'optionGroupTitles', 'filterable', 'orderOptionsBy', 'className'];

    return fieldsToCheck.some(field => nextProps[field] !== this.props[field]);
  }

  /**
   * Selects an item
   * pass it to parent (If any)
   *
   * @param {any} item
   * @memberof TagInput
   */
  handleSelectItem(item) {
    let { value } = this.props;

    value = value.push(item);

    // Sending the tags to parent
    this.props.onChange(value);
  }

  /**
   * Deselects an item
   * pass it to parent (If any)
   *
   * @param {any} item
   * @memberof TagInput
   */
  handleDeselectItem(item) {
    let { value } = this.props;

    const selectItemBy = item.key ? 'key' : 'id';
    const index = this.props.value.findIndex(selectedItem => item[selectItemBy] === selectedItem[selectItemBy]);

    if (index > -1) {
      value = value.splice(index, 1);
    }

    // Sending the tags to parent
    this.props.onChange(value);
  }

  fetchServer(query) {
    const { fetchUrl, httpHeaders } = this.props;

    this.setState({
      waiting: true
    });

    return new Promise((resolve, reject) => {
      let req = superagent.get(fetchUrl);
      // Setting the http headers
      Object.keys(httpHeaders).forEach((key) => {
        req.set(key, httpHeaders[key]);
      });

      req
        .accept('application/json')
        .query({ query: query })
        .end((err, res) => {
          if (err) {
            reject(err);
          }
          resolve(res.body);
        });
    });
  }

  handleGetOptions(query = '', active = false) {
    if (active || this.state.data.some(field => field.label === query)) {
      return;
    }

    this.fetchServer(query)
      .then((res) => {
        this.setState({
          data: this.props.extractor(res),
          waiting: false
        });
      });
  }

  render() {
    const {
      data,
      waiting
    } = this.state;

    return (
      <TagContainer
        {...this.props}
        options={data}
        loading={waiting}
        selection={this.props.value}
        onSelect={this.handleSelectItem}
        onDeselect={this.handleDeselectItem}
        onHandleFetch={this.handleGetOptions}
      />
    );
  }
}

// default props
TagInput.defaultProps = {
  loading:              false,
  multiple:             true,
  filterable:           true,
  darkTheme:            false,

  className:            '',
  orderOptionsBy:       'title',
  label:                'Select Tags...',
  togglePosition:       'left',
  noOptionsMessage:     '',
  toggleSwitchStyle:    'search',
  fetchUrl:             '',

  optionGroupTitles:    [],
  options:              [],

  httpHeaders:          {},
  value:                new Immutable.List(),

  onHandleFetch:        function onHandleFetch() {},
  extractor:            data => data
};

// prop types checking
TagInput.propTypes = {
  loading:            PropTypes.bool,
  multiple:           PropTypes.bool,
  filterable:          PropTypes.bool,
  darkTheme:          PropTypes.bool,

  className:          PropTypes.string,
  orderOptionsBy:     PropTypes.string,
  label:              PropTypes.string,
  togglePosition:     PropTypes.string,
  noOptionsMessage:   PropTypes.string,
  toggleSwitchStyle:  PropTypes.string,
  fetchUrl:           PropTypes.string,

  options:            PropTypes.array,
  optionGroupTitles:  PropTypes.array,

  httpHeaders:        PropTypes.object,
  value:              PropTypes.instanceOf(Immutable.List).isRequired,

  onChange:           PropTypes.func.isRequired,
  onHandleFetch:      PropTypes.func,
  extractor:          PropTypes.func
};
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import './index.css';
import App from './App';
import PosterPicker from './components/PosterPicker';
import NotFound from './components/NotFound';
import registerServiceWorker from './registerServiceWorker';

const Root = () => {
    return (
        <Router>
            <Switch>
                <Route exact path="/" component={PosterPicker} />
                <Route path="/card/:cardId" component={App} />
                <Route component={NotFound} />
            </Switch>
        </Router>
    )
}

ReactDOM.render(<Root />, document.getElementById('root'));
registerServiceWorker();<commit_msg>Remove router<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
<|endoftext|>


<commit_before>import assert from 'assert';

import Rx from 'rxjs/Rx';
import Discord from 'discord.js';
import Keyv from 'keyv';
import randomItem from 'random-item';

import { pokemon as pokemonModel } from './pokemon';
import { minLevenshtein } from './util';

const client = new Discord.Client();

const isLanguage = langName => entry => entry.language.name === langName;

const getNameOf = pkmn => pkmn.species.names.find(isLanguage('en')).name;

function fixPokemonName(name) {
    if( ['ho-oh', 'mr-mime'].includes(name.toLowerCase()) ) {
        return name;
    }

    return name.replace(/\-.+/g, '');
}

function quizObservable(question, correctAnswerObs, hintsObs, timeoutObs) {
    const sharedCorrectAnswerObs = correctAnswerObs.share();
    const sharedTimeoutObs = timeoutObs.share();

    const endObs = sharedCorrectAnswerObs.merge(sharedTimeoutObs).delay(10);

    return Rx.Observable.of({ type: 'question', question })
        .concat(Rx.Observable.merge(
            sharedCorrectAnswerObs.map(answer => ({ type: 'correctAnswer', answer })),
            hintsObs.map(hint => ({ type: 'hint', hint })),
            sharedTimeoutObs.map(() => ({ type: 'timeout' }))
        ))
        .takeUntil(endObs);
}

function quizPokemonObservable(cache, guessesObs) {
    return Rx.Observable.defer(() => {
        const randomPokemonObs =
            Rx.Observable.defer(() =>
                pokemonModel.getRandom(cache)
            )
            .share();

        const randomFlavorTextObs =
            randomPokemonObs
            .map(pkmn =>
                randomItem(
                    pkmn.species.flavor_text_entries.filter(isLanguage('en'))
                )
                .flavor_text
            );

        const nameObs =
            randomPokemonObs
            .map(pkmn => pkmn.name)
            .map(fixPokemonName);

        return Rx.Observable.combineLatest(
            randomPokemonObs, randomFlavorTextObs, nameObs
        )
        .mergeMap(([pkmn, flavorText, name]) => {
            const nameRegex = new RegExp(name, 'ig');

            return quizObservable(
                // question
                `**Who's that Pokémon!?** \`\`\`${flavorText.replace(nameRegex, '[REDACTED]')}\`\`\``,

                // observable of right answers
                guessesObs.filter(msg => minLevenshtein(msg.cleanContent, name) <= 2),

                // observable of hints
                Rx.Observable.empty(),

                // timeout observable
                Rx.Observable.timer(25 * 1000)
            )
            .map(ev => {
                ev.pokemon = pkmn;
                return ev;
            });
        })
        .startWith({ type: 'fetchingPokemon' });
    });
}

Promise.resolve()
.then(() => {
    assert.ok(process.env.DISCORD_TOKEN != null, 'DISCORD_TOKEN is not specified, unable to log in.');

    return client.login(process.env.DISCORD_TOKEN);
})
.then(async () => {

    if(process.env.DISCORD_CLIENT_ID != null) {
        const clientId = process.env.DISCORD_CLIENT_ID;
        const inviteUrl = `https://discordapp.com/oauth2/authorize?&client_id=${clientId}&scope=bot&permissions=0`;

        console.log(`Invite URL: ${inviteUrl}`);
    }
    else {
        console.log('*** DISCORD_CLIENT_ID not specified; no invite URL will be generated.');
        console.log('*** The bot will not respond to the `invite` either.');
    }

    const cache = new Keyv({ ttl: 6*60*60*1000 });

    const msgObs = Rx.Observable.fromEvent(client, 'message')
        .filter(msg => msg.author != client.user);

    const msgToMeObs = msgObs.filter(msg => msg.isMentioned(client.user));

    const startGameObs = msgToMeObs
        .filter(msg => /start/.test(msg.cleanContent))
        .map(msg => msg.channel);

    const endGameObs = msgToMeObs
        .filter(msg => /[end|stop]/.test(msg.cleanContent))
        .map(msg => msg.channel);

    const actions = {
        async question(channel, ev) {
            await channel.send(ev.question);
        },

        async correctAnswer(channel, ev) {
            await channel.send(`${ev.answer.author} got it right!! It was **${getNameOf(ev.pokemon)}**!!`);
        },

        async hint(channel, ev) {
            await channel.send(`Here's a hint: ${ev.hint}`);
        },

        async timeout(channel, ev) {
            await channel.send(`No one answered it right!! It was **${getNameOf(ev.pokemon)}**!`);
        },

        async fetchingPokemon(channel) {
            await channel.send(`Getting the next Pokemon...`);
        },

        async end(channel) {
            await channel.send(`That's all, folks!`);
        }
    };

    await Promise.all([
        startGameObs
        .mergeMap(channel =>
            quizPokemonObservable(cache, msgObs)
            .repeat(50)
            .takeUntil(
                endGameObs.filter(endChan => channel == endChan)
            )
            .concat(Rx.Observable.of({ type: 'end' }))
            .mergeMap(ev => actions[ev.type](channel, ev) )
        )
        .toPromise(),

        msgToMeObs
        .filter(() =>
            process.env.DISCORD_CLIENT_ID != null && process.env.DISCORD_OWNER_ID != null
        )
        .filter(msg => msg.author.id == process.env.DISCORD_OWNER_ID)
        .filter(msg => /invite/.test(msg.cleanContent))
        .mergeMap(async msg => {
            const clientId = process.env.DISCORD_CLIENT_ID;
            const inviteUrl = `https://discordapp.com/oauth2/authorize?&client_id=${clientId}&scope=bot&permissions=0`;

            await msg.author.send(`Here's an invite URL: ${inviteUrl}`);
        })
        .toPromise()
    ]);
})
.catch(e => console.error(e.stack));
<commit_msg>Make bot more error-resilient<commit_after>import assert from 'assert';

import Rx from 'rxjs/Rx';
import Discord from 'discord.js';
import Keyv from 'keyv';
import randomItem from 'random-item';

import { pokemon as pokemonModel } from './pokemon';
import { minLevenshtein } from './util';

const client = new Discord.Client();

const isLanguage = langName => entry => entry.language.name === langName;

const getNameOf = pkmn => pkmn.species.names.find(isLanguage('en')).name;

function fixPokemonName(name) {
    if( ['ho-oh', 'mr-mime'].includes(name.toLowerCase()) ) {
        return name;
    }

    return name.replace(/\-.+/g, '');
}

function quizObservable(question, correctAnswerObs, hintsObs, timeoutObs) {
    const sharedCorrectAnswerObs = correctAnswerObs.share();
    const sharedTimeoutObs = timeoutObs.share();

    const endObs = sharedCorrectAnswerObs.merge(sharedTimeoutObs).delay(10);

    return Rx.Observable.of({ type: 'question', question })
        .concat(Rx.Observable.merge(
            sharedCorrectAnswerObs.map(answer => ({ type: 'correctAnswer', answer })),
            hintsObs.map(hint => ({ type: 'hint', hint })),
            sharedTimeoutObs.map(() => ({ type: 'timeout' }))
        ))
        .takeUntil(endObs);
}

function quizPokemonObservable(cache, guessesObs) {
    return Rx.Observable.defer(() => {
        const randomPokemonObs =
            Rx.Observable.defer(() =>
                pokemonModel.getRandom(cache)
            )
            .retry(3)
            .share();

        const randomFlavorTextObs =
            randomPokemonObs
            .map(pkmn =>
                randomItem(
                    pkmn.species.flavor_text_entries.filter(isLanguage('en'))
                )
                .flavor_text
            );

        const nameObs =
            randomPokemonObs
            .map(pkmn => pkmn.name)
            .map(fixPokemonName);

        return Rx.Observable.combineLatest(
            randomPokemonObs, randomFlavorTextObs, nameObs
        )
        .mergeMap(([pkmn, flavorText, name]) => {
            const nameRegex = new RegExp(name, 'ig');

            return quizObservable(
                // question
                `**Who's that Pokémon!?** \`\`\`${flavorText.replace(nameRegex, '[REDACTED]')}\`\`\``,

                // observable of right answers
                guessesObs.filter(msg => minLevenshtein(msg.cleanContent, name) <= 2),

                // observable of hints
                Rx.Observable.empty(),

                // timeout observable
                Rx.Observable.timer(25 * 1000)
            )
            .map(ev => {
                ev.pokemon = pkmn;
                return ev;
            });
        })
        .startWith({ type: 'fetchingPokemon' });
    });
}

Promise.resolve()
.then(() => {
    assert.ok(process.env.DISCORD_TOKEN != null, 'DISCORD_TOKEN is not specified, unable to log in.');

    return client.login(process.env.DISCORD_TOKEN);
})
.then(async () => {

    if(process.env.DISCORD_CLIENT_ID != null) {
        const clientId = process.env.DISCORD_CLIENT_ID;
        const inviteUrl = `https://discordapp.com/oauth2/authorize?&client_id=${clientId}&scope=bot&permissions=0`;

        console.log(`Invite URL: ${inviteUrl}`);
    }
    else {
        console.log('*** DISCORD_CLIENT_ID not specified; no invite URL will be generated.');
        console.log('*** The bot will not respond to the `invite` either.');
    }

    const cache = new Keyv({ ttl: 6*60*60*1000 });

    const msgObs = Rx.Observable.fromEvent(client, 'message')
        .filter(msg => msg.author != client.user);

    const msgToMeObs = msgObs.filter(msg => msg.isMentioned(client.user));

    const startGameObs = msgToMeObs
        .filter(msg => /start/.test(msg.cleanContent))
        .map(msg => msg.channel);

    const endGameObs = msgToMeObs
        .filter(msg => /[end|stop]/.test(msg.cleanContent))
        .map(msg => msg.channel);

    const actions = {
        async question(channel, ev) {
            await channel.send(ev.question);
        },

        async correctAnswer(channel, ev) {
            await channel.send(`${ev.answer.author} got it right!! It was **${getNameOf(ev.pokemon)}**!!`);
        },

        async hint(channel, ev) {
            await channel.send(`Here's a hint: ${ev.hint}`);
        },

        async timeout(channel, ev) {
            await channel.send(`No one answered it right!! It was **${getNameOf(ev.pokemon)}**!`);
        },

        async fetchingPokemon(channel) {
            await channel.send(`Getting the next Pokemon...`);
        },

        async end(channel) {
            await channel.send(`That's all, folks!`);
        },

        async error(channel, ev) {
            await channel.send(`Oh my, looks like an error occured! \`${ev.error}\``);
        }
    };

    await Promise.all([
        startGameObs
        .mergeMap(channel =>
            quizPokemonObservable(cache, msgObs)
            .repeat(50)
            .takeUntil(
                endGameObs.filter(endChan => channel == endChan)
            )
            .concat(Rx.Observable.of({ type: 'end' }))
            .catch(error => Rx.Observable.of({ type: 'error', error }))
            .mergeMap(ev => actions[ev.type](channel, ev) )
        )
        .toPromise(),

        msgToMeObs
        .filter(() =>
            process.env.DISCORD_CLIENT_ID != null && process.env.DISCORD_OWNER_ID != null
        )
        .filter(msg => msg.author.id == process.env.DISCORD_OWNER_ID)
        .filter(msg => /invite/.test(msg.cleanContent))
        .mergeMap(async msg => {
            const clientId = process.env.DISCORD_CLIENT_ID;
            const inviteUrl = `https://discordapp.com/oauth2/authorize?&client_id=${clientId}&scope=bot&permissions=0`;

            await msg.author.send(`Here's an invite URL: ${inviteUrl}`);
        })
        .toPromise()
    ]);
})
.catch(e => console.error(e.stack));
<|endoftext|>


<commit_before>'use strict';
var path = require('path'),
    fs = require('fs'),
    async = require('async'),
    raml = require('raml-parser'),
    _ = require('lodash'),
    schemaMocker = require('./schema.js'),
    RequestMocker = require('./requestMocker.js');

function generate(options, callback) {
    var formats = {};
    if (options) {
        if (options.formats) {
            formats = options.formats;
        }
        if (!callback || !_.isFunction(callback)) {
            console.error('[RAML-MOCKER] You must define a callback function:\n');
            showUsage();
        }
        try {
            if (options.path) {
                generateFromPath(options.path, formats, callback);
            } else if (options.files && _.isArray(options.files)) {
                generateFromFiles(options.files, formats, callback);
            }
        } catch (exception) {
            console.error('[RAML-MOCKER] A runtime error has ocurred:\n');
            console.error(exception.stack);
            showUsage();
        }
    } else {
        console.error('[RAML-MOCKER] You must define a options object:\n');
        showUsage();
    }
}

function showUsage() {
    console.log('--------------------------------------------------------------------');
    console.log('---------------------- HOW TO USE RAML MOCKER ----------------------');
    console.log('--  var ramlMocker = require(\'raml-mocker\');                      --');
    console.log('--  var options = { path: \'test/raml\' };                          --');
    console.log('--  var callback = function (requests){ console.log(requests); }; --');
    console.log('--  ramlMocker.generate(options, callback);                       --');
    console.log('--------------------------------------------------------------------');
}

function generateFromPath(filesPath, formats, callback) {
    fs.readdir(filesPath, function (err, files) {
        if (err) {
            throw err;
        }
        var filesToGenerate = [];
        _.each(files, function (file) {
            if (file.substr(-5) === '.raml') {
                filesToGenerate.push(path.join(filesPath, file));
            }
        });
        generateFromFiles(filesToGenerate, formats, callback);
    });
}

function generateFromFiles(files, formats, callback) {
    var requestsToMock = [];
    async.each(files, function (file, cb) {
        raml.loadFile(file).then(function (data) {
            getRamlRequestsToMock(data, '/', formats, function (reqs) {
                requestsToMock = _.union(requestsToMock, reqs);
                cb();
            });
        }, function (error) {
            cb('Error parsing: ' + error);
        });
    }, function (err) {
        if (err) {
            console.log(err);
        } else {
            callback(requestsToMock);
        }
    });
}

function getRamlRequestsToMock(definition, uri, formats, callback) {
    var requestsToMock = [];
    if (definition.relativeUri) {
        var nodeURI = definition.relativeUri;
        if (definition.uriParameters) {
            _.each(definition.uriParameters, function (uriParam, name) {
                nodeURI = nodeURI.replace('{' + name + '}', ':' + name);
            });
        }
        uri = (uri + '/' + nodeURI).replace(/\/{2,}/g, '/');
    }
    var tasks = [];
    if (definition.methods) {
        tasks.push(function (cb) {
            getRamlRequestsToMockMethods(definition, uri, formats, function (reqs) {
                requestsToMock = _.union(requestsToMock, reqs);
                cb();
            });
        });
    }
    if (definition.resources) {
        tasks.push(function (cb) {
            getRamlRequestsToMockResources(definition, uri, formats, function (reqs) {
                requestsToMock = _.union(requestsToMock, reqs);
                cb();
            });
        });
    }
    async.parallel(tasks, function (err) {
        if (err) {
            console.log(err);
        }
        callback(requestsToMock);
    });
}

function getRamlRequestsToMockMethods(definition, uri, formats, callback) {
    var responsesByCode = [];
    _.each(definition.methods, function (method) {
        if (method.method && /get|post|put|delete/i.test(method.method) && method.responses) {
            var responsesMethodByCode = getResponsesByCode(method.responses);

            var methodMocker = new RequestMocker(uri, method.method);

            var currentMockDefaultCode = null;
            _.each(responsesMethodByCode, function (reqDefinition) {
                methodMocker.addResponse(reqDefinition.code, function () {
                    if (reqDefinition.schema) {
                        return schemaMocker(reqDefinition.schema, formats);
                    } else {
                        return null;
                    }
                }, function () {
                    return reqDefinition.example;
                });
                if ((!currentMockDefaultCode || currentMockDefaultCode > reqDefinition.code) && /^2\d\d$/.test(reqDefinition.code)) {
                    methodMocker.mock = methodMocker.getResponses()[reqDefinition.code];
                    methodMocker.example = methodMocker.getExamples()[reqDefinition.code];
                    currentMockDefaultCode = reqDefinition.code;
                }
            });
            if (currentMockDefaultCode) {
                methodMocker.defaultCode = currentMockDefaultCode;
            }
            responsesByCode.push(methodMocker);
        }
    });
    callback(responsesByCode);
}

function getResponsesByCode(responses) {
    var responsesByCode = [];
    _.each(responses, function (response, code) {
        var body = response.body;
        var schema = null;
        var example = null;
        if (!_.isNaN(Number(code))) {
            code = Number(code);
            if (body && response.body['application/json']) {
                body = response.body['application/json'];
                if (body.example) {
                    example = body.example;
                }
                if (body.schema) {
                    try {
                        schema = JSON.parse(body.schema);
                    } catch (exception) {
                        console.log(exception.stack);
                    }
                }
            }
            responsesByCode.push({
                code: code,
                schema: schema,
                example: example
            });
        }
    });
    return responsesByCode;
}

function getRamlRequestsToMockResources(definition, uri, formats, callback) {
    var requestsToMock = [];
    async.each(definition.resources, function (def, cb) {
        getRamlRequestsToMock(def, uri, formats, function (reqs) {
            requestsToMock = _.union(requestsToMock, reqs);
            cb(null);
        });
    }, function (err) {
        if (err) {
            console.log(err);
        }
        callback(requestsToMock);
    });
}
module.exports = {
    generate: generate
};
<commit_msg>Clarifies the code<commit_after>'use strict';
var path = require('path'),
    fs = require('fs'),
    async = require('async'),
    raml = require('raml-parser'),
    _ = require('lodash'),
    schemaMocker = require('./schema.js'),
    RequestMocker = require('./requestMocker.js');

function generate(options, callback) {
    var formats = {};
    if (options) {
        if (options.formats) {
            formats = options.formats;
        }
        if (!callback || !_.isFunction(callback)) {
            console.error('[RAML-MOCKER] You must define a callback function:\n');
            showUsage();
        }
        try {
            if (options.path) {
                generateFromPath(options.path, formats, callback);
            } else if (options.files && _.isArray(options.files)) {
                generateFromFiles(options.files, formats, callback);
            }
        } catch (exception) {
            console.error('[RAML-MOCKER] A runtime error has ocurred:\n');
            console.error(exception.stack);
            showUsage();
        }
    } else {
        console.error('[RAML-MOCKER] You must define a options object:\n');
        showUsage();
    }
}

function showUsage() {
    console.log('--------------------------------------------------------------------');
    console.log('---------------------- HOW TO USE RAML MOCKER ----------------------');
    console.log('--  var ramlMocker = require(\'raml-mocker\');                      --');
    console.log('--  var options = { path: \'test/raml\' };                          --');
    console.log('--  var callback = function (requests){ console.log(requests); }; --');
    console.log('--  ramlMocker.generate(options, callback);                       --');
    console.log('--------------------------------------------------------------------');
}

function generateFromPath(filesPath, formats, callback) {
    fs.readdir(filesPath, function (err, files) {
        if (err) {
            throw err;
        }
        var filesToGenerate = [];
        _.each(files, function (file) {
            if (file.substr(-5) === '.raml') {
                filesToGenerate.push(path.join(filesPath, file));
            }
        });
        generateFromFiles(filesToGenerate, formats, callback);
    });
}

function generateFromFiles(files, formats, callback) {
    var requestsToMock = [];
    async.each(files, function (file, cb) {
        raml.loadFile(file).then(function (data) {
            getRamlRequestsToMock(data, '/', formats, function (reqs) {
                requestsToMock = _.union(requestsToMock, reqs);
                cb();
            });
        }, function (error) {
            cb('Error parsing: ' + error);
        });
    }, function (err) {
        if (err) {
            console.log(err);
        } else {
            callback(requestsToMock);
        }
    });
}

function getRamlRequestsToMock(definition, uri, formats, callback) {
    var requestsToMock = [];
    if (definition.relativeUri) {
        var nodeURI = definition.relativeUri;
        if (definition.uriParameters) {
            _.each(definition.uriParameters, function (uriParam, name) {
                nodeURI = nodeURI.replace('{' + name + '}', ':' + name);
            });
        }
        uri = (uri + '/' + nodeURI).replace(/\/{2,}/g, '/');
    }
    var tasks = [];
    if (definition.methods) {
        tasks.push(function (cb) {
            getRamlRequestsToMockMethods(definition, uri, formats, function (reqs) {
                requestsToMock = _.union(requestsToMock, reqs);
                cb();
            });
        });
    }
    if (definition.resources) {
        tasks.push(function (cb) {
            getRamlRequestsToMockResources(definition, uri, formats, function (reqs) {
                requestsToMock = _.union(requestsToMock, reqs);
                cb();
            });
        });
    }
    async.parallel(tasks, function (err) {
        if (err) {
            console.log(err);
        }
        callback(requestsToMock);
    });
}

function getRamlRequestsToMockMethods(definition, uri, formats, callback) {
    var responsesByCode = [];
    _.each(definition.methods, function (method) {
        if (method.method && /get|post|put|delete/i.test(method.method) && method.responses) {
            var responsesMethodByCode = getResponsesByCode(method.responses);

            var methodMocker = new RequestMocker(uri, method.method);

            var currentMockDefaultCode = null;
            _.each(responsesMethodByCode, function (reqDefinition) {
                methodMocker.addResponse(reqDefinition.code, function () {
                    if (reqDefinition.schema) {
                        return schemaMocker(reqDefinition.schema, formats);
                    } else {
                        return null;
                    }
                }, function () {
                    return reqDefinition.example;
                });
                if ((!currentMockDefaultCode || currentMockDefaultCode > reqDefinition.code) && /^2\d\d$/.test(reqDefinition.code)) {
                    methodMocker.mock = methodMocker.getResponses()[reqDefinition.code];
                    methodMocker.example = methodMocker.getExamples()[reqDefinition.code];
                    currentMockDefaultCode = reqDefinition.code;
                }
            });
            if (currentMockDefaultCode) {
                methodMocker.defaultCode = currentMockDefaultCode;
            }
            responsesByCode.push(methodMocker);
        }
    });
    callback(responsesByCode);
}

function getResponsesByCode(responses) {
    var responsesByCode = [];
    _.each(responses, function (response, code) {
        var body = response.body && response.body['application/json'];
        var schema = null;
        var example = null;
        if (!_.isNaN(Number(code)) && body) {
            code = Number(code);
            example = body.example;
            try {
                schema = body.schema && JSON.parse(body.schema);
            } catch (exception) {
                console.log(exception.stack);
            }
            responsesByCode.push({
                code: code,
                schema: schema,
                example: example
            });
        }
    });
    return responsesByCode;
}

function getRamlRequestsToMockResources(definition, uri, formats, callback) {
    var requestsToMock = [];
    async.each(definition.resources, function (def, cb) {
        getRamlRequestsToMock(def, uri, formats, function (reqs) {
            requestsToMock = _.union(requestsToMock, reqs);
            cb(null);
        });
    }, function (err) {
        if (err) {
            console.log(err);
        }
        callback(requestsToMock);
    });
}
module.exports = {
    generate: generate
};
<|endoftext|>


<commit_before>import path from 'path'
import fs from 'fs'

import _ from 'lodash'

import getModuleDependencies from './lib/getModuleDependencies'
import registerConfigAsDependency from './lib/registerConfigAsDependency'
import processTailwindFeatures from './processTailwindFeatures'
import formatCSS from './lib/formatCSS'
import resolveConfig from './util/resolveConfig'
import getAllConfigs from './util/getAllConfigs'
import { supportedConfigFiles } from './constants'
import defaultConfig from '../stubs/defaultConfig.stub.js'
import log from './util/log'

function resolveConfigPath(filePath) {
  // require('tailwindcss')({ theme: ..., variants: ... })
  if (_.isObject(filePath) && !_.has(filePath, 'config') && !_.isEmpty(filePath)) {
    return undefined
  }

  // require('tailwindcss')({ config: 'custom-config.js' })
  if (_.isObject(filePath) && _.has(filePath, 'config') && _.isString(filePath.config)) {
    return path.resolve(filePath.config)
  }

  // require('tailwindcss')({ config: { theme: ..., variants: ... } })
  if (_.isObject(filePath) && _.has(filePath, 'config') && _.isObject(filePath.config)) {
    return undefined
  }

  // require('tailwindcss')('custom-config.js')
  if (_.isString(filePath)) {
    return path.resolve(filePath)
  }

  // require('tailwindcss')
  for (const configFile of supportedConfigFiles) {
    try {
      const configPath = path.resolve(configFile)
      fs.accessSync(configPath)
      return configPath
    } catch (err) {}
  }

  return undefined
}

const getConfigFunction = (config) => () => {
  if (_.isUndefined(config)) {
    return resolveConfig([...getAllConfigs(defaultConfig)])
  }

  // Skip this if Jest is running: https://github.com/facebook/jest/pull/9841#issuecomment-621417584
  if (process.env.JEST_WORKER_ID === undefined) {
    if (!_.isObject(config)) {
      getModuleDependencies(config).forEach((mdl) => {
        delete require.cache[require.resolve(mdl.file)]
      })
    }
  }

  const configObject = _.isObject(config) ? _.get(config, 'config', config) : require(config)

  return resolveConfig([...getAllConfigs(configObject)])
}

module.exports = function (config) {
  const resolvedConfigPath = resolveConfigPath(config)
  const getConfig = getConfigFunction(resolvedConfigPath || config)
  const mode = _.get(getConfig(), 'mode', 'aot')

  if (mode === 'jit') {
    log.warn([
      `You have enabled the JIT engine which is currently in preview.`,
      'Preview features are not covered by semver, may introduce breaking changes, and can change at any time.',
    ])
    return require('../jit/index.js')(config)
  }

  const plugins = []

  if (!_.isUndefined(resolvedConfigPath)) {
    plugins.push(registerConfigAsDependency(resolvedConfigPath))
  }

  return {
    postcssPlugin: 'tailwindcss',
    plugins: [...plugins, processTailwindFeatures(getConfig), formatCSS],
  }
}

module.exports.postcss = true
<commit_msg>Only warn about JIT engine once<commit_after>import path from 'path'
import fs from 'fs'

import _ from 'lodash'

import getModuleDependencies from './lib/getModuleDependencies'
import registerConfigAsDependency from './lib/registerConfigAsDependency'
import processTailwindFeatures from './processTailwindFeatures'
import formatCSS from './lib/formatCSS'
import resolveConfig from './util/resolveConfig'
import getAllConfigs from './util/getAllConfigs'
import { supportedConfigFiles } from './constants'
import defaultConfig from '../stubs/defaultConfig.stub.js'
import log from './util/log'

function resolveConfigPath(filePath) {
  // require('tailwindcss')({ theme: ..., variants: ... })
  if (_.isObject(filePath) && !_.has(filePath, 'config') && !_.isEmpty(filePath)) {
    return undefined
  }

  // require('tailwindcss')({ config: 'custom-config.js' })
  if (_.isObject(filePath) && _.has(filePath, 'config') && _.isString(filePath.config)) {
    return path.resolve(filePath.config)
  }

  // require('tailwindcss')({ config: { theme: ..., variants: ... } })
  if (_.isObject(filePath) && _.has(filePath, 'config') && _.isObject(filePath.config)) {
    return undefined
  }

  // require('tailwindcss')('custom-config.js')
  if (_.isString(filePath)) {
    return path.resolve(filePath)
  }

  // require('tailwindcss')
  for (const configFile of supportedConfigFiles) {
    try {
      const configPath = path.resolve(configFile)
      fs.accessSync(configPath)
      return configPath
    } catch (err) {}
  }

  return undefined
}

const getConfigFunction = (config) => () => {
  if (_.isUndefined(config)) {
    return resolveConfig([...getAllConfigs(defaultConfig)])
  }

  // Skip this if Jest is running: https://github.com/facebook/jest/pull/9841#issuecomment-621417584
  if (process.env.JEST_WORKER_ID === undefined) {
    if (!_.isObject(config)) {
      getModuleDependencies(config).forEach((mdl) => {
        delete require.cache[require.resolve(mdl.file)]
      })
    }
  }

  const configObject = _.isObject(config) ? _.get(config, 'config', config) : require(config)

  return resolveConfig([...getAllConfigs(configObject)])
}

let warned = false

module.exports = function (config) {
  const resolvedConfigPath = resolveConfigPath(config)
  const getConfig = getConfigFunction(resolvedConfigPath || config)
  const mode = _.get(getConfig(), 'mode', 'aot')

  if (mode === 'jit') {
    if (!warned) {
      log.warn([
        `You have enabled the JIT engine which is currently in preview.`,
        'Preview features are not covered by semver, may introduce breaking changes, and can change at any time.',
      ])
      warned = true
    }
    return require('../jit/index.js')(config)
  }

  const plugins = []

  if (!_.isUndefined(resolvedConfigPath)) {
    plugins.push(registerConfigAsDependency(resolvedConfigPath))
  }

  return {
    postcssPlugin: 'tailwindcss',
    plugins: [...plugins, processTailwindFeatures(getConfig), formatCSS],
  }
}

module.exports.postcss = true
<|endoftext|>


<commit_before>import express from 'express';
import basicAuth from 'node-basicauth';
import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
import compression from 'compression';
import babelify from 'express-babelify-middleware';
import fs from 'fs';
import morgan from 'morgan';
import { join } from 'path';
import favicon from 'serve-favicon';
import stylus from 'stylus';
import nib from 'nib';

import { isArray, isObject, isFunction, isString } from 'magic-types';
import log from 'magic-server-log';

import router from './router';
import headers from './headers';
import handle404 from './errors/handle404';
import handle500 from './errors/handle500';

// import { init as initAdmin } from 'magic-admin';
// import blog from 'magic-blog';
// import db from 'magic-db';

export const conjure =
  () =>
    express();

export const Magic = app => {
  const dir = app.get('cwd') || process.cwd();
  const css = app.get('css') || stylus;
  // const dbSettings = app.get('dbOpts') || false;
  const routes = app.get('router');
  const env = app.get('env') || 'production';
  const publicDir = app.get('publicDir') || 'public';
  const viewDir = app.get('viewDir') || 'views';
  const appDirs = app.get('dirs');
  const basicAuthConfig = app.get('basicAuth');
  const port = app.get('port') || 1337;
  const viewEngine = app.get('view engine') || 'pug';
  const babelifyFiles = app.get('babelifyFiles');
  const logLevel = app.get('logLevel') || 'combined';

  const dirs = {
    root: dir,
    public: join(dir, publicDir),
    views: join(dir, viewDir),
    ...appDirs,
  };

  const faviconPath = join(dirs.public, 'favicon.ico');

  app.set('css', css);
  app.set('dirs', dirs);

  // set req.app to use in middleware
  app.use(
    (req, res, next) => {
      req.app = app;
      next();
    });

  // set expiry headers
  app.use(headers);

  // enable http basicAuth
  if (basicAuthConfig) {
    app.use(basicAuth(basicAuthConfig));
  }

  // fs.existsSync only gets called once on first request
  if (faviconPath && !app.get('faviconChecked') && !app.get('faviconExists')) {
    app.set('faviconChecked', true);
    app.set('faviconExists', fs.existsSync(faviconPath));
  }

  if (app.get('faviconExists')) {
    app.use(favicon(faviconPath));
  }

  app.set('views', dirs.views);
  app.set('view engine', viewEngine);

  app.use(compression({ threshold: 128 }));

  const cssMiddleware =
    (str, path) =>
      css(str)
        .set('filename', path)
        .set('compress', env === 'production')
        .use(nib())
        .import('nib');

  app.use(css.middleware({
    src: dirs.public,
    maxage: '1d',
    compile: cssMiddleware,
  }));

  if (isString(babelifyFiles) || isArray(babelifyFiles)) {
    [].concat(babelifyFiles).forEach(
      f => {
        // Precompile a browserified file at a path
        const fileUrl = `/js/${f}.js`;
        const bundleUrl = `${dirs.public}/js/${f}/index.js`;

        app.use(fileUrl, babelify(bundleUrl));
      }
    );
  }

  app.use(express.static(join(__dirname, 'public'), { maxAge: '1w' }));

  app.use(express.static(dirs.public, { maxAge: '1d' }));

  // if (dbSettings && !app.get('db')) {
  //   app.use(db);
  // }

  // if (app.enabled('admin')) {
  //   app.use(initAdmin);
  // }

  /*
   TODO: reenable
   if (app.get('blogRoot')) {
   let blogRoot = app.get('blogRoot');
   if (typeof blogRoot !== 'string' && typeof blogRoot !== 'number') {
   blogRoot = 'blog';
   }
   if (blogRoot.charAt(0) !== '/') {
   blogRoot = '/' + blogRoot;
   } else {
   app.set('blogRoot', blogRoot.substr(1));
   }
   app.use(blogRoot, blog);
   }
   */

  // logging
  app.use(morgan(logLevel));

  // if host sets bodyparser to true, init it
  if (app.enabled('bodyParser')) {
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
  }

  // if host sets cookieparser to true, init it:
  if (app.enabled('cookieParser')) {
    app.use(cookieParser());
  }

  // load host specific router
  if (routes) {
    if (isArray(routes) || isObject(routes)) {
      Object.keys(routes).forEach(
        key => {
          if (isFunction(routes[key])) {
            app.use(routes[key]);
          }
        }
      );
    } else if (isFunction(routes)) {
      app.use(routes);
    }
  }

  // default router
  app.use(router);

  // we are in a 404 error
  app.use(handle404);

  // oops, worst case fallback, 500 server error.
  app.use(handle500);

  app.get('*', (req, res, next) => {
    console.log('catchall');
    res.status(200).send('yay');
  });

  app.listen(port, err => {
    if (err) {
      log.error(err);
    }

    log(`app listening to port ${port}`);
  });

  return app;
};

export default Magic;
<commit_msg>export express.Router()<commit_after>import express from 'express';
import basicAuth from 'node-basicauth';
import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
import compression from 'compression';
import babelify from 'express-babelify-middleware';
import fs from 'fs';
import morgan from 'morgan';
import { join } from 'path';
import favicon from 'serve-favicon';
import stylus from 'stylus';
import nib from 'nib';

import { isArray, isObject, isFunction, isString } from 'magic-types';
import log from 'magic-server-log';

import appRoutes from './routes';
import headers from './headers';
import handle404 from './errors/handle404';
import handle500 from './errors/handle500';

// import { init as initAdmin } from 'magic-admin';
// import blog from 'magic-blog';
// import db from 'magic-db';

export const conjure =
  () =>
    express();

export const router = express.Router();

export const Magic = app => {
  const dir = app.get('cwd') || process.cwd();
  const css = app.get('css') || stylus;
  // const dbSettings = app.get('dbOpts') || false;
  const routes = app.get('router');
  const env = app.get('env') || 'production';
  const publicDir = app.get('publicDir') || 'public';
  const viewDir = app.get('viewDir') || 'views';
  const appDirs = app.get('dirs');
  const basicAuthConfig = app.get('basicAuth');
  const port = app.get('port') || 1337;
  const viewEngine = app.get('view engine') || 'pug';
  const babelifyFiles = app.get('babelifyFiles');
  const logLevel = app.get('logLevel') || 'combined';

  const dirs = {
    root: dir,
    public: join(dir, publicDir),
    views: join(dir, viewDir),
    ...appDirs,
  };

  const faviconPath = join(dirs.public, 'favicon.ico');

  app.set('css', css);
  app.set('dirs', dirs);

  // set req.app to use in middleware
  app.use(
    (req, res, next) => {
      req.app = app;
      next();
    });

  // set expiry headers
  app.use(headers);

  // enable http basicAuth
  if (basicAuthConfig) {
    app.use(basicAuth(basicAuthConfig));
  }

  // fs.existsSync only gets called once on first request
  if (faviconPath && !app.get('faviconChecked') && !app.get('faviconExists')) {
    app.set('faviconChecked', true);
    app.set('faviconExists', fs.existsSync(faviconPath));
  }

  if (app.get('faviconExists')) {
    app.use(favicon(faviconPath));
  }

  app.set('views', dirs.views);
  app.set('view engine', viewEngine);

  app.use(compression({ threshold: 128 }));

  const cssMiddleware =
    (str, path) =>
      css(str)
        .set('filename', path)
        .set('compress', env === 'production')
        .use(nib())
        .import('nib');

  app.use(css.middleware({
    src: dirs.public,
    maxage: '1d',
    compile: cssMiddleware,
  }));

  if (isString(babelifyFiles) || isArray(babelifyFiles)) {
    [].concat(babelifyFiles).forEach(
      f => {
        // Precompile a browserified file at a path
        const fileUrl = `/js/${f}.js`;
        const bundleUrl = `${dirs.public}/js/${f}/index.js`;

        app.use(fileUrl, babelify(bundleUrl));
      }
    );
  }

  app.use(express.static(join(__dirname, 'public'), { maxAge: '1w' }));

  app.use(express.static(dirs.public, { maxAge: '1d' }));

  // if (dbSettings && !app.get('db')) {
  //   app.use(db);
  // }

  // if (app.enabled('admin')) {
  //   app.use(initAdmin);
  // }

  /*
   TODO: reenable
   if (app.get('blogRoot')) {
   let blogRoot = app.get('blogRoot');
   if (typeof blogRoot !== 'string' && typeof blogRoot !== 'number') {
   blogRoot = 'blog';
   }
   if (blogRoot.charAt(0) !== '/') {
   blogRoot = '/' + blogRoot;
   } else {
   app.set('blogRoot', blogRoot.substr(1));
   }
   app.use(blogRoot, blog);
   }
   */

  // logging
  app.use(morgan(logLevel));

  // if host sets bodyparser to true, init it
  if (app.enabled('bodyParser')) {
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
  }

  // if host sets cookieparser to true, init it:
  if (app.enabled('cookieParser')) {
    app.use(cookieParser());
  }

  // load host specific router
  if (routes) {
    if (isArray(routes) || isObject(routes)) {
      Object.keys(routes).forEach(
        key => {
          if (isFunction(routes[key])) {
            app.use(routes[key]);
          }
        }
      );
    } else if (isFunction(routes)) {
      app.use(routes);
    }
  }

  // default router
  app.use(appRoutes);

  // we are in a 404 error
  app.use(handle404);

  // oops, worst case fallback, 500 server error.
  app.use(handle500);

  app.get('*', (req, res, next) => {
    console.log('catchall');
    res.status(200).send('yay');
  });

  app.listen(port, err => {
    if (err) {
      log.error(err);
    }

    log(`app listening to port ${port}`);
  });

  return app;
};

export default Magic;
<|endoftext|>


<commit_before>/* global process */
/* eslint no-console: 0 */

'use strict'

process.env.FORCE_COLOR = true // Force colors for packages that depend on https://www.npmjs.com/package/supports-color

const path = require('path')
const sgf = require('staged-git-files')
const appRoot = require('app-root-path')
const Listr = require('listr')
const cosmiconfig = require('cosmiconfig')

const packageJson = require(appRoot.resolve('package.json')) // eslint-disable-line
const runScript = require('./runScript')
const resolvePaths = require('./resolvePaths')
const generateTasks = require('./generateTasks')

cosmiconfig(packageJson.name, {
    rc: 'lintstaged'
})
    .then((result) => {
        // result.config is the parsed configuration object
        // result.filepath is the path to the config file that was found
        const config = result.config
        const concurrent = config.concurrent || true

        // If git-root is defined -> set git root as sgf's cwd
        if ('git-root' in config) {
            sgf.cwd = path.resolve(config['git-root'])
        }

        sgf('ACM', (err, files) => {
            if (err) {
                console.error(err)
            }

            const tasks = generateTasks(config, resolvePaths(files))
                .map(task => ({
                    title: `Running tasks for ${ task.pattern }`,
                    task: () => (new Listr(runScript(task.commands, task.fileList, packageJson)))
                }))

            if (tasks.length) {
                new Listr(tasks, { concurrent }).run().catch((error) => {
                    console.error(error)
                    process.exit(1)
                })
            }
        })
    })
    .catch((parsingError) => {
        // do something constructive
        console.error(`Could not parse lint-staged config.
Make sure you have created it. See ${ packageJson.homepage }.

${ parsingError }
`)
        process.exit(1)
    })

<commit_msg>Use name from package.json<commit_after>/* global process */
/* eslint no-console: 0 */

'use strict'

process.env.FORCE_COLOR = true // Force colors for packages that depend on https://www.npmjs.com/package/supports-color

const path = require('path')
const sgf = require('staged-git-files')
const appRoot = require('app-root-path')
const Listr = require('listr')
const cosmiconfig = require('cosmiconfig')

const packageJson = require(appRoot.resolve('package.json')) // eslint-disable-line
const runScript = require('./runScript')
const resolvePaths = require('./resolvePaths')
const generateTasks = require('./generateTasks')

cosmiconfig(packageJson.name, {
    rc: 'lintstaged'
})
    .then((result) => {
        // result.config is the parsed configuration object
        // result.filepath is the path to the config file that was found
        const config = result.config
        const concurrent = config.concurrent || true

        // If git-root is defined -> set git root as sgf's cwd
        if ('git-root' in config) {
            sgf.cwd = path.resolve(config['git-root'])
        }

        sgf('ACM', (err, files) => {
            if (err) {
                console.error(err)
            }

            const tasks = generateTasks(config, resolvePaths(files))
                .map(task => ({
                    title: `Running tasks for ${ task.pattern }`,
                    task: () => (new Listr(runScript(task.commands, task.fileList, packageJson)))
                }))

            if (tasks.length) {
                new Listr(tasks, { concurrent }).run().catch((error) => {
                    console.error(error)
                    process.exit(1)
                })
            }
        })
    })
    .catch((parsingError) => {
        // do something constructive
        console.error(`Could not parse ${ packageJson.name } config.
Make sure you have created it. See ${ packageJson.homepage }.

${ parsingError }
`)
        process.exit(1)
    })

<|endoftext|>


<commit_before>export { el, h, html } from './html';
export { list, List } from './list';
export { listPool, ListPool } from './pool';
export { mount } from './mount';
export { unmount } from './unmount';
export { place, Place } from './place';
export { router, Router } from './router';
export { setAttr } from './setattr';
export { setStyle } from './setstyle';
export { setChildren } from './setchildren';
export { s, svg } from './svg';
export { text } from './text';
<commit_msg>listpool<commit_after>export { el, h, html } from './html';
export { list, List } from './list';
export { listPool, ListPool } from './listpool';
export { mount } from './mount';
export { unmount } from './unmount';
export { place, Place } from './place';
export { router, Router } from './router';
export { setAttr } from './setattr';
export { setStyle } from './setstyle';
export { setChildren } from './setchildren';
export { s, svg } from './svg';
export { text } from './text';
<|endoftext|>


<commit_before>'use strict'

const path = require('path')
const isPlainObj = require('is-plain-obj')
const pify = require('pify')
const componentsLookup = require('components-lookup')
const server = require('./server')

const js = (() => {

	const filePath = path.resolve(__dirname, './client.js')
	const babel = { babelrc: false }
	const opts = { optimize: false, babel }

	// Load and transform js for the client
	return require('rosid-handler-js')(filePath, opts)

})()

/**
 * Return the HTML of the UI that can be viewed in the browser.
 * @public
 * @param {?*} filePath - Not used by this module.
 * @param {?Object} opts - Options.
 * @returns {Promise} Returns the following properties if resolved: {String}.
 */
module.exports = function(filePath, opts = {}) {

	return Promise.resolve().then(() => {

		if (isPlainObj(opts)===false && opts!=null) {
			throw new Error(`'opts' must be an object, null or undefined`)
		}

		const resolvers = [
			{
				id: 'view',
				label: 'View',
				languages: [ 'twig' ],
				resolve: (fileName, fileExt) => [ `${ fileName }${ fileExt }` ]
			},
			{
				id: 'data',
				label: 'Data',
				languages: [ 'json', 'js' ],
				resolve: (fileName, fileExt) => [ `${ fileName }.data.json`, `${ fileName }.data.js` ]
			},
			{
				id: 'notes',
				label: 'Notes',
				languages: [ 'markdown' ],
				resolve: (fileName, fileExt) => [ `${ fileName }.md` ]
			},
			{
				id: 'config',
				label: 'Config',
				languages: [ 'json' ],
				parse: (contents) => JSON.parse(contents),
				resolve: (fileName, fileExt) => [ `${ fileName }.config.json` ]
			}
		]

		const statuses = {
			wip: {
				label: 'WIP',
				description: 'Work in progress',
				color: '#fe913d'
			},
			pending: {
				label: 'Pending',
				description: 'Ready, but waiting for finalization',
				color: '#2d90e8'
			},
			ready: {
				label: 'Ready',
				description: 'Ready to implement',
				color: '#2bc052'
			}
		}

		opts = Object.assign({
			lang: 'en',
			title: 'Rosid',
			description: 'UI to help you build and document web components.',
			pattern: '**/[^_]*.{ejs,njk}',
			src: '',
			resolvers,
			statuses
		}, opts)

	}).then(() => {

		// Get the components data
		return componentsLookup(opts.pattern, opts.resolvers, {
			cwd: opts.src
		})

	}).then((components) => {

		// Use transformed js file and pass both js and components to next promise
		return js.then((js) => ({
			js,
			components
		}))

	}).then(({ js, components }) => {

		components.forEach((component) => {

			// Add output to each components. This placeholder will be filled by the UI,
			// but must exist too show up in the inspector.
			component.data.push({
				index: component.data.length,
				id: 'output',
				label: 'Output',
				languages: [ 'html' ],
				data: null
			})

		})

		// Initial state of the site
		const initalState = {
			components,
			opts
		}

		// Render the page
		return pify(server)(initalState, js)

	}).then((str) => {

		return str

	})

}<commit_msg>Pattern is based on src<commit_after>'use strict'

const path = require('path')
const isPlainObj = require('is-plain-obj')
const pify = require('pify')
const componentsLookup = require('components-lookup')
const server = require('./server')

const js = (() => {

	const filePath = path.resolve(__dirname, './client.js')
	const babel = { babelrc: false }
	const opts = { optimize: false, babel }

	// Load and transform js for the client
	return require('rosid-handler-js')(filePath, opts)

})()

/**
 * Return the HTML of the UI that can be viewed in the browser.
 * @public
 * @param {?*} filePath - Not used by this module.
 * @param {?Object} opts - Options.
 * @returns {Promise} Returns the following properties if resolved: {String}.
 */
module.exports = function(filePath, opts = {}) {

	return Promise.resolve().then(() => {

		if (isPlainObj(opts)===false && opts!=null) {
			throw new Error(`'opts' must be an object, null or undefined`)
		}

		const resolvers = [
			{
				id: 'view',
				label: 'View',
				languages: [ 'twig' ],
				resolve: (fileName, fileExt) => [ `${ fileName }${ fileExt }` ]
			},
			{
				id: 'data',
				label: 'Data',
				languages: [ 'json', 'js' ],
				resolve: (fileName, fileExt) => [ `${ fileName }.data.json`, `${ fileName }.data.js` ]
			},
			{
				id: 'notes',
				label: 'Notes',
				languages: [ 'markdown' ],
				resolve: (fileName, fileExt) => [ `${ fileName }.md` ]
			},
			{
				id: 'config',
				label: 'Config',
				languages: [ 'json' ],
				parse: (contents) => JSON.parse(contents),
				resolve: (fileName, fileExt) => [ `${ fileName }.config.json` ]
			}
		]

		const statuses = {
			wip: {
				label: 'WIP',
				description: 'Work in progress',
				color: '#fe913d'
			},
			pending: {
				label: 'Pending',
				description: 'Ready, but waiting for finalization',
				color: '#2d90e8'
			},
			ready: {
				label: 'Ready',
				description: 'Ready to implement',
				color: '#2bc052'
			}
		}

		opts = Object.assign({
			lang: 'en',
			title: 'Rosid',
			description: 'UI to help you build and document web components.',
			src: '',
			pattern: '**/[^_]*.{ejs,njk}',
			resolvers,
			statuses
		}, opts)

	}).then(() => {

		// Get the components data
		return componentsLookup(opts.pattern, opts.resolvers, {
			cwd: opts.src
		})

	}).then((components) => {

		// Use transformed js file and pass both js and components to next promise
		return js.then((js) => ({
			js,
			components
		}))

	}).then(({ js, components }) => {

		components.forEach((component) => {

			// Add output to each components. This placeholder will be filled by the UI,
			// but must exist too show up in the inspector.
			component.data.push({
				index: component.data.length,
				id: 'output',
				label: 'Output',
				languages: [ 'html' ],
				data: null
			})

		})

		// Initial state of the site
		const initalState = {
			components,
			opts
		}

		// Render the page
		return pify(server)(initalState, js)

	}).then((str) => {

		return str

	})

}<|endoftext|>