<commit_before>//-- Pre/Post Processing
var cfg = require('../config');

var gulp = require('gulp'),
    util = require('gulp-util');

//--
gulp.task('compile:scripts', ['lint:scripts'], function() {
  /* Refs:
      http://browserify.org/articles.html
      https://viget.com/extend/gulp-browserify-starter-faq
      https://egghead.io/lessons/nodejs-introduction-to-browserify-part-1
      https://egghead.io/lessons/javascript-gulp-and-browserify-initial-setup
      https://www.npmjs.com/package/browserify
      https://www.npmjs.com/package/coffeeify
      https://www.npmjs.com/package/vinyl-source-stream
  */
  var browserify = require('browserify'),
       coffeeify = require('coffeeify'),
          source = require('vinyl-source-stream');

  var b = browserify({
    entries: cfg.resources.main_script,
    extensions: ['.coffee'],
    debug: true,
    transform: [coffeeify]
  });

  return b.bundle()
    .on('error', function(e) {
      util.log(e);
    })
    .pipe(source('main.js'))
    .pipe(gulp.dest(cfg.paths.dest + cfg.paths.scripts));
});

//--
gulp.task('compile:styles', ['lint:styles'], function() {
  /* Refs:
      https://www.npmjs.com/package/gulp-sourcemaps
      https://www.npmjs.com/package/gulp-stylus
      https://www.npmjs.com/package/axis
      https://www.npmjs.com/package/rupture
      https://www.npmjs.com/package/typographic
      https://www.npmjs.com/package/gulp-postcss
      https://www.npmjs.com/package/rucksack-css
      https://www.npmjs.com/package/lost
      https://www.npmjs.com/package/autoprefixer
  */
  var sourcemaps = require('gulp-sourcemaps');

  var typographic = require('typographic'),
             axis = require('axis'),
          rupture = require('rupture'),
           stylus = require('gulp-stylus');

  var autoprefixer = require('autoprefixer'),
              lost = require('lost'),
          rucksack = require('rucksack-css'),
           postcss = require('gulp-postcss');

  var processors = [rucksack({fallbacks: true}), lost(), autoprefixer()],
         plugins = [rupture(), typographic()];
//         plugins = [axis(), rupture(), typographic()];

  return gulp.src(cfg.resources.main_style)
    .pipe(sourcemaps.init())
    .pipe(stylus({use: plugins}))
    .pipe(postcss(processors))
    .on('error', function(e) {
      util.log(e);
    })
    .pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: cfg.paths.src.slice(1)}))
    .pipe(gulp.dest(cfg.paths.dest + cfg.paths.styles));
});
<commit_msg>Include regular CSS on @import<commit_after>//-- Pre/Post Processing
var cfg = require('../config');

var gulp = require('gulp'),
    util = require('gulp-util');

//--
gulp.task('compile:scripts', ['lint:scripts'], function() {
  /* Refs:
      http://browserify.org/articles.html
      https://viget.com/extend/gulp-browserify-starter-faq
      https://egghead.io/lessons/nodejs-introduction-to-browserify-part-1
      https://egghead.io/lessons/javascript-gulp-and-browserify-initial-setup
      https://www.npmjs.com/package/browserify
      https://www.npmjs.com/package/coffeeify
      https://www.npmjs.com/package/vinyl-source-stream
  */
  var browserify = require('browserify'),
       coffeeify = require('coffeeify'),
          source = require('vinyl-source-stream');

  var b = browserify({
    entries: cfg.resources.main_script,
    extensions: ['.coffee'],
    debug: true,
    transform: [coffeeify]
  });

  return b.bundle()
    .on('error', function(e) {
      util.log(e);
    })
    .pipe(source('main.js'))
    .pipe(gulp.dest(cfg.paths.dest + cfg.paths.scripts));
});

//--
gulp.task('compile:styles', ['lint:styles'], function() {
  /* Refs:
      https://www.npmjs.com/package/gulp-sourcemaps
      https://www.npmjs.com/package/gulp-stylus
      https://www.npmjs.com/package/axis
      https://www.npmjs.com/package/rupture
      https://www.npmjs.com/package/typographic
      https://www.npmjs.com/package/gulp-postcss
      https://www.npmjs.com/package/rucksack-css
      https://www.npmjs.com/package/lost
      https://www.npmjs.com/package/autoprefixer
  */
  var sourcemaps = require('gulp-sourcemaps');

  var typographic = require('typographic'),
             axis = require('axis'),
          rupture = require('rupture'),
           stylus = require('gulp-stylus');

  var autoprefixer = require('autoprefixer'),
              lost = require('lost'),
          rucksack = require('rucksack-css'),
           postcss = require('gulp-postcss');

  /* See https://github.com/jenius/axis/issues/222 */
  var processors = [rucksack({fallbacks: true}), lost(), autoprefixer()],
         plugins = [axis(), rupture(), typographic()];

  return gulp.src(cfg.resources.main_style)
    .pipe(sourcemaps.init())
    .pipe(stylus({'include css': true, use: plugins}))
    .pipe(postcss(processors))
    .on('error', function(e) {
      util.log(e);
    })
    .pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: cfg.paths.src.slice(1)}))
    .pipe(gulp.dest(cfg.paths.dest + cfg.paths.styles));
});
<|endoftext|>


<commit_before>const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PurifyCSSPlugin = require('purifycss-webpack');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const GitRevisionPlugin = require('git-revision-webpack-plugin');
const BabiliPlugin = require('babili-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const cssnano = require('cssnano');
const HtmlWebpackPlugin = require('html-webpack-plugin');

exports.devServer = ({ host, port } = {}) => ({
  devServer: {
    historyApiFallback: true,
    stats: 'errors-only',
    host, // Defaults to `localhost`
    port, // Defaults to 8080
    overlay: {
      errors: true,
      warnings: true,
    },
  },
});

exports.lintJavaScript = ({ include, exclude, options }) => ({
  module: {
    rules: [
      {
        test: /\.js$/,
        include,
        exclude,
        enforce: 'pre',

        loader: 'eslint-loader',
        options,
      },
    ],
  },
});

exports.loadCSS = ({ include, exclude } = {}) => ({
  module: {
    rules: [
      {
        test: /\.css$/,
        include,
        exclude,

        use: ['style-loader', 'css-loader'],
      },
    ],
  },
});

exports.extractCSS = ({ include, exclude, use }) => {
  // Output extracted CSS to a file
  const plugin = new ExtractTextPlugin({
    filename: '[name].[contenthash:8].css',
  });

  return {
    module: {
      rules: [
        {
          test: /\.css$/,
          include,
          exclude,

          use: plugin.extract({
            use,
            fallback: 'style-loader',
          }),
        },
      ],
    },
    plugins: [ plugin ],
  };
};

exports.autoprefix = () => ({
  loader: 'postcss-loader',
  options: {
    plugins: () => ([
      require('autoprefixer'),
    ]),
  },
});

exports.purifyCSS = ({ paths }) => ({
  plugins: [
    new PurifyCSSPlugin({ paths }),
  ],
});

exports.lintCSS = ({ include, exclude }) => ({
  module: {
    rules: [
      {
        test: /\.css$/,
        include,
        exclude,
        enforce: 'pre',

        loader: 'postcss-loader',
        options: {
          plugins: () => ([
            require('stylelint')({
              // Ignore node_modules CSS
              ignoreFiles: 'node_modules/**/*.css',
            }),
          ]),
        },
      },
    ],
  },
});

exports.loadImages = ({ include, exclude, options } = {}) => ({
  module: {
    rules: [
      {
        test: /\.(png|jpg|svg)$/,
        include,
        exclude,

        use: {
          loader: 'url-loader',
          options,
        },
      },
    ],
  },
});

exports.loadFonts = ({ include, exclude, options } = {}) => ({
  module: {
    rules: [
      {
        // Capture eot, ttf, woff, and woff2
        test: /\.(eot|ttf|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        include,
        exclude,

        use: {
          loader: 'file-loader',
          options,
        },
      },
    ],
  },
});

exports.generateSourceMaps = ({ type }) => ({
  devtool: type,
});

exports.extractBundles = (bundles) => ({
  plugins: bundles.map((bundle) => (
    new webpack.optimize.CommonsChunkPlugin(bundle)
  )),
});

exports.loadJavaScript = ({ include, exclude }) => ({
  module: {
    rules: [
      {
        test: /\.js$/,
        include,
        exclude,

        loader: 'babel-loader',
        options: {
          // Enable caching for improved performance during
          // development.
          // It uses default OS directory by default. If you need
          // something more custom, pass a path to it.
          // I.e., { cacheDirectory: '<path>' }
          cacheDirectory: true,
        },
      },
    ],
  },
});

exports.clean = (path) => ({
  plugins: [
    new CleanWebpackPlugin([path]),
  ],
});

exports.attachRevision = () => ({
  plugins: [
    new webpack.BannerPlugin({
      banner: new GitRevisionPlugin().version(),
    }),
  ],
});

exports.minifyJavaScript = () => ({
  plugins: [
    new BabiliPlugin(),
  ],
});

exports.minifyCSS = ({ options }) => ({
  plugins: [
    new OptimizeCSSAssetsPlugin({
      cssProcessor: cssnano,
      cssProcessorOptions: options,
    }),
  ],
});

exports.setFreeVariable = (key, value) => {
  const env = {};
  env[key] = JSON.stringify(value);

  return {
    plugins: [
      new webpack.DefinePlugin(env),
    ],
  };
};

exports.page = ({
  path = '',
  template = require.resolve(
    'html-webpack-plugin/default_index.ejs'
  ),
  title,
  entry,
  chunks,
} = {}) => ({
  entry,
  plugins: [
    new HtmlWebpackPlugin({
      chunks,
      filename: `${path && path + '/'}index.html`,
      template,
      title,
    }),
  ],
});
<commit_msg>Mute css optimization plugin<commit_after>const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PurifyCSSPlugin = require('purifycss-webpack');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const GitRevisionPlugin = require('git-revision-webpack-plugin');
const BabiliPlugin = require('babili-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const cssnano = require('cssnano');
const HtmlWebpackPlugin = require('html-webpack-plugin');

exports.devServer = ({ host, port } = {}) => ({
  devServer: {
    historyApiFallback: true,
    stats: 'errors-only',
    host, // Defaults to `localhost`
    port, // Defaults to 8080
    overlay: {
      errors: true,
      warnings: true,
    },
  },
});

exports.lintJavaScript = ({ include, exclude, options }) => ({
  module: {
    rules: [
      {
        test: /\.js$/,
        include,
        exclude,
        enforce: 'pre',

        loader: 'eslint-loader',
        options,
      },
    ],
  },
});

exports.loadCSS = ({ include, exclude } = {}) => ({
  module: {
    rules: [
      {
        test: /\.css$/,
        include,
        exclude,

        use: ['style-loader', 'css-loader'],
      },
    ],
  },
});

exports.extractCSS = ({ include, exclude, use }) => {
  // Output extracted CSS to a file
  const plugin = new ExtractTextPlugin({
    filename: '[name].[contenthash:8].css',
  });

  return {
    module: {
      rules: [
        {
          test: /\.css$/,
          include,
          exclude,

          use: plugin.extract({
            use,
            fallback: 'style-loader',
          }),
        },
      ],
    },
    plugins: [ plugin ],
  };
};

exports.autoprefix = () => ({
  loader: 'postcss-loader',
  options: {
    plugins: () => ([
      require('autoprefixer'),
    ]),
  },
});

exports.purifyCSS = ({ paths }) => ({
  plugins: [
    new PurifyCSSPlugin({ paths }),
  ],
});

exports.lintCSS = ({ include, exclude }) => ({
  module: {
    rules: [
      {
        test: /\.css$/,
        include,
        exclude,
        enforce: 'pre',

        loader: 'postcss-loader',
        options: {
          plugins: () => ([
            require('stylelint')({
              // Ignore node_modules CSS
              ignoreFiles: 'node_modules/**/*.css',
            }),
          ]),
        },
      },
    ],
  },
});

exports.loadImages = ({ include, exclude, options } = {}) => ({
  module: {
    rules: [
      {
        test: /\.(png|jpg|svg)$/,
        include,
        exclude,

        use: {
          loader: 'url-loader',
          options,
        },
      },
    ],
  },
});

exports.loadFonts = ({ include, exclude, options } = {}) => ({
  module: {
    rules: [
      {
        // Capture eot, ttf, woff, and woff2
        test: /\.(eot|ttf|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        include,
        exclude,

        use: {
          loader: 'file-loader',
          options,
        },
      },
    ],
  },
});

exports.generateSourceMaps = ({ type }) => ({
  devtool: type,
});

exports.extractBundles = (bundles) => ({
  plugins: bundles.map((bundle) => (
    new webpack.optimize.CommonsChunkPlugin(bundle)
  )),
});

exports.loadJavaScript = ({ include, exclude }) => ({
  module: {
    rules: [
      {
        test: /\.js$/,
        include,
        exclude,

        loader: 'babel-loader',
        options: {
          // Enable caching for improved performance during
          // development.
          // It uses default OS directory by default. If you need
          // something more custom, pass a path to it.
          // I.e., { cacheDirectory: '<path>' }
          cacheDirectory: true,
        },
      },
    ],
  },
});

exports.clean = (path) => ({
  plugins: [
    new CleanWebpackPlugin([path]),
  ],
});

exports.attachRevision = () => ({
  plugins: [
    new webpack.BannerPlugin({
      banner: new GitRevisionPlugin().version(),
    }),
  ],
});

exports.minifyJavaScript = () => ({
  plugins: [
    new BabiliPlugin(),
  ],
});

exports.minifyCSS = ({ options }) => ({
  plugins: [
    new OptimizeCSSAssetsPlugin({
      cssProcessor: cssnano,
      cssProcessorOptions: options,
      canPrint: false,
    }),
  ],
});

exports.setFreeVariable = (key, value) => {
  const env = {};
  env[key] = JSON.stringify(value);

  return {
    plugins: [
      new webpack.DefinePlugin(env),
    ],
  };
};

exports.page = ({
  path = '',
  template = require.resolve(
    'html-webpack-plugin/default_index.ejs'
  ),
  title,
  entry,
  chunks,
} = {}) => ({
  entry,
  plugins: [
    new HtmlWebpackPlugin({
      chunks,
      filename: `${path && path + '/'}index.html`,
      template,
      title,
    }),
  ],
});
<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _Pagination = require('./Pagination.js');

var _Pagination2 = _interopRequireDefault(_Pagination);

var _DatatableOptions = require('./DatatableOptions.js');

var _DatatableOptions2 = _interopRequireDefault(_DatatableOptions);

var _utils = require('./utils.js');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var style = '.spicy-datatable{width:100%;overflow:scroll;padding:0;margin:0 auto;background:#fff;font-size:0.875rem;text-align:left;border-spacing:0;}.spicy-datatable > tbody > tr > td,.spicy-datatable > tfoot > tr > td,.spicy-datatable > thead > tr > th{box-sizing:border-box;height:50px;padding:0 20px;border:none;border-top:1px solid #ddd;word-break:break-all;vertical-align:middle;}.spicy-datatable > tbody > tr{transition:0.25s all;}.spicy-datatable > tbody > tr:hover{background:whitesmoke;}.spicy-datatable > thead > tr > th{border-top:0;}.spicy-datatable-counter{text-align:left;font-size:12px;padding:0 20px;}.spicy-datatable > tbody > .spicy-datatable--selected-row{background:#7a7ca0;}';

var miniCache = {};

function getSafely(tableKey) {
  if (miniCache[tableKey]) {
    return miniCache[tableKey];
  }
  return { searchQuery: '' };
}

var SpicyDatatable = function (_Component) {
  _inherits(SpicyDatatable, _Component);

  function SpicyDatatable(props) {
    _classCallCheck(this, SpicyDatatable);

    var _this = _possibleConstructorReturn(this, (SpicyDatatable.__proto__ || Object.getPrototypeOf(SpicyDatatable)).call(this, props));

    _this.state = {
      itemsPerPage: getSafely(props.tableKey).itemsPerPage || 10,
      currentPage: getSafely(props.tableKey).currentPage || 1,
      searchQuery: getSafely(props.tableKey).searchQuery || ''
    };
    return _this;
  }

  _createClass(SpicyDatatable, [{
    key: 'render',
    value: function render() {
      var _state = this.state,
          itemsPerPage = _state.itemsPerPage,
          currentPage = _state.currentPage,
          searchQuery = _state.searchQuery;
      var _props = this.props,
          columns = _props.columns,
          originalRows = _props.rows;

      var isFilterActive = searchQuery.length > 0;
      var filteredRows = isFilterActive ? (0, _utils.filterRows)(originalRows, columns, searchQuery.toLocaleLowerCase()) : originalRows;
      var maxOnPage = currentPage * itemsPerPage;
      var rows = filteredRows.slice((currentPage - 1) * itemsPerPage, maxOnPage);
      var total = isFilterActive ? filteredRows.length : originalRows.length;
      var fromEntries = (currentPage - 1) * itemsPerPage + 1;
      var toEntries = maxOnPage > total ? total : maxOnPage;

      return _react2.default.createElement(
        'div',
        null,
        _react2.default.createElement(_DatatableOptions2.default, {
          onPageSizeChange: this.handlePageSizeChange.bind(this),
          onSearch: this.handleSearchQueryChange.bind(this)
        }),
        _react2.default.createElement(
          'table',
          { className: 'spicy-datatable' },
          _react2.default.createElement(
            'thead',
            null,
            _react2.default.createElement(
              'tr',
              null,
              columns.map(function (c) {
                return _react2.default.createElement(
                  'th',
                  { key: c.key },
                  c.label
                );
              })
            )
          ),
          _react2.default.createElement(
            'tbody',
            null,
            rows.map(function (r, i) {
              return _react2.default.createElement(
                'tr',
                {
                  key: i,
                  onClick: r.onClickHandler ? r.onClickHandler : function () {
                    return undefined;
                  },
                  style: { cursor: r.onClickHandler ? 'pointer' : 'default' },
                  className: r.isActive ? 'spicy-datatable--selected-row' : ''
                },
                columns.map(function (c, i) {
                  return _react2.default.createElement(
                    'td',
                    { key: i },
                    r[c.key]
                  );
                })
              );
            })
          )
        ),
        _react2.default.createElement(
          'div',
          { className: 'spicy-datatable-counter' },
          total > 0 ? _react2.default.createElement(
            'p',
            null,
            'Showing ',
            fromEntries,
            ' to ',
            toEntries,
            ' of ',
            total,
            ' entries.'
          ) : _react2.default.createElement(
            'p',
            null,
            'No entries to show.'
          )
        ),
        _react2.default.createElement(_Pagination2.default, {
          onPage: this.handlePagination.bind(this),
          itemsPerPage: itemsPerPage,
          total: total,
          activePage: currentPage
        })
      );
    }
  }, {
    key: 'handlePagination',
    value: function handlePagination(nextPage) {
      var tableKey = this.props.tableKey;

      this.setState({
        currentPage: nextPage
      });
      miniCache[tableKey].currentPage = nextPage;
    }
  }, {
    key: 'handleSearchQueryChange',
    value: function handleSearchQueryChange(e) {
      var value = e.target.value;
      var tableKey = this.props.tableKey;

      this.setState({ searchQuery: value, currentPage: 1 });
      miniCache[tableKey].searchQuery = value;
      miniCache[tableKey].currentPage = 1;
    }
  }, {
    key: 'handlePageSizeChange',
    value: function handlePageSizeChange(e) {
      var value = e.target.value;
      var tableKey = this.props.tableKey;

      this.setState({ itemsPerPage: Number(value), currentPage: 1 });
      miniCache[tableKey].itemsPerPage = Number(value);
      miniCache[tableKey].currentPage = 1;
    }
  }]);

  return SpicyDatatable;
}(_react.Component);

SpicyDatatable.propTypes = {
  tableKey: _react.PropTypes.string.isRequired,
  columns: _react.PropTypes.arrayOf(_react.PropTypes.shape({
    key: _react.PropTypes.string,
    label: _react.PropTypes.string
  })).isRequired,
  rows: _react.PropTypes.array
};
exports.default = SpicyDatatable;<commit_msg>compile 0.1.11<commit_after>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _Pagination = require('./Pagination.js');

var _Pagination2 = _interopRequireDefault(_Pagination);

var _DatatableOptions = require('./DatatableOptions.js');

var _DatatableOptions2 = _interopRequireDefault(_DatatableOptions);

var _utils = require('./utils.js');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var style = '.spicy-datatable{width:100%;overflow:scroll;padding:0;margin:0 auto;background:#fff;font-size:0.875rem;text-align:left;border-spacing:0;}.spicy-datatable > tbody > tr > td,.spicy-datatable > tfoot > tr > td,.spicy-datatable > thead > tr > th{box-sizing:border-box;height:50px;padding:0 20px;border:none;border-top:1px solid #ddd;word-break:break-all;vertical-align:middle;}.spicy-datatable > tbody > tr{transition:0.25s all;}.spicy-datatable > tbody > tr:hover{background:whitesmoke;}.spicy-datatable > thead > tr > th{border-top:0;}.spicy-datatable-counter{text-align:left;font-size:12px;padding:0 20px;}.spicy-datatable > tbody > .spicy-datatable--selected-row{background:#7a7ca0;}';

var miniCache = {};

function getSafely(tableKey) {
  if (miniCache[tableKey]) {
    return miniCache[tableKey];
  }
  return { searchQuery: '' };
}

function setSafely(tableKey, prop, val) {
  if (miniCache[tableKey] === undefined) {
    miniCache[tableKey] = {};
  }
  miniCache[tableKey][prop] = val;
}

var SpicyDatatable = function (_Component) {
  _inherits(SpicyDatatable, _Component);

  function SpicyDatatable(props) {
    _classCallCheck(this, SpicyDatatable);

    var _this = _possibleConstructorReturn(this, (SpicyDatatable.__proto__ || Object.getPrototypeOf(SpicyDatatable)).call(this, props));

    _this.state = {
      itemsPerPage: getSafely(props.tableKey).itemsPerPage || 10,
      currentPage: getSafely(props.tableKey).currentPage || 1,
      searchQuery: getSafely(props.tableKey).searchQuery || ''
    };
    return _this;
  }

  _createClass(SpicyDatatable, [{
    key: 'render',
    value: function render() {
      var _state = this.state,
          itemsPerPage = _state.itemsPerPage,
          currentPage = _state.currentPage,
          searchQuery = _state.searchQuery;
      var _props = this.props,
          columns = _props.columns,
          originalRows = _props.rows;

      var isFilterActive = searchQuery.length > 0;
      var filteredRows = isFilterActive ? (0, _utils.filterRows)(originalRows, columns, searchQuery.toLocaleLowerCase()) : originalRows;
      var maxOnPage = currentPage * itemsPerPage;
      var rows = filteredRows.slice((currentPage - 1) * itemsPerPage, maxOnPage);
      var total = isFilterActive ? filteredRows.length : originalRows.length;
      var fromEntries = (currentPage - 1) * itemsPerPage + 1;
      var toEntries = maxOnPage > total ? total : maxOnPage;

      return _react2.default.createElement(
        'div',
        null,
        _react2.default.createElement(_DatatableOptions2.default, {
          onPageSizeChange: this.handlePageSizeChange.bind(this),
          onSearch: this.handleSearchQueryChange.bind(this)
        }),
        _react2.default.createElement(
          'table',
          { className: 'spicy-datatable' },
          _react2.default.createElement(
            'thead',
            null,
            _react2.default.createElement(
              'tr',
              null,
              columns.map(function (c) {
                return _react2.default.createElement(
                  'th',
                  { key: c.key },
                  c.label
                );
              })
            )
          ),
          _react2.default.createElement(
            'tbody',
            null,
            rows.map(function (r, i) {
              return _react2.default.createElement(
                'tr',
                {
                  key: i,
                  onClick: r.onClickHandler ? r.onClickHandler : function () {
                    return undefined;
                  },
                  style: { cursor: r.onClickHandler ? 'pointer' : 'default' },
                  className: r.isActive ? 'spicy-datatable--selected-row' : ''
                },
                columns.map(function (c, i) {
                  return _react2.default.createElement(
                    'td',
                    { key: i },
                    r[c.key]
                  );
                })
              );
            })
          )
        ),
        _react2.default.createElement(
          'div',
          { className: 'spicy-datatable-counter' },
          total > 0 ? _react2.default.createElement(
            'p',
            null,
            'Showing ',
            fromEntries,
            ' to ',
            toEntries,
            ' of ',
            total,
            ' entries.'
          ) : _react2.default.createElement(
            'p',
            null,
            'No entries to show.'
          )
        ),
        _react2.default.createElement(_Pagination2.default, {
          onPage: this.handlePagination.bind(this),
          itemsPerPage: itemsPerPage,
          total: total,
          activePage: currentPage
        })
      );
    }
  }, {
    key: 'handlePagination',
    value: function handlePagination(nextPage) {
      var tableKey = this.props.tableKey;

      this.setState({
        currentPage: nextPage
      });
      setSafely(tableKey, 'currentPage', nextPage);
    }
  }, {
    key: 'handleSearchQueryChange',
    value: function handleSearchQueryChange(e) {
      var value = e.target.value;
      var tableKey = this.props.tableKey;

      this.setState({ searchQuery: value, currentPage: 1 });
      setSafely(tableKey, 'searchQuery', value);
      setSafely(tableKey, 'currentPage', 1);
    }
  }, {
    key: 'handlePageSizeChange',
    value: function handlePageSizeChange(e) {
      var value = e.target.value;
      var tableKey = this.props.tableKey;

      this.setState({ itemsPerPage: Number(value), currentPage: 1 });
      setSafely(tableKey, 'itemsPerPage', Number(value));
      setSafely(tableKey, 'currentPage', 1);
    }
  }]);

  return SpicyDatatable;
}(_react.Component);

SpicyDatatable.propTypes = {
  tableKey: _react.PropTypes.string.isRequired,
  columns: _react.PropTypes.arrayOf(_react.PropTypes.shape({
    key: _react.PropTypes.string,
    label: _react.PropTypes.string
  })).isRequired,
  rows: _react.PropTypes.array
};
exports.default = SpicyDatatable;<|endoftext|>


<commit_before>//
// The fetcher is responsible for fetching new
// trades at the exchange. It will emit `new trades`
// events as soon as it fetches new data.
//
// How often this is depends on:
//
//  - The capability of the exchange (to provide
//  historical data).
//  - The amount of data we get per fetch.
//  - The interval at which we need new data.

var _ = require('lodash');
var moment = require('moment');
var utc = moment.utc;
var log = require('./log.js');

var util = require('./util');
var config = util.getConfig();

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

var provider = config.watch.exchange.toLowerCase();
var DataProvider = require('../exchanges/' + provider);

var Fetcher = function() {
  _.bindAll(this);

  // Create a public dataProvider object which can retrieve live
  // trade information from an exchange.

  this.watcher = new DataProvider(config.watch);
  this.lastFetch = false;

  this.exchange = exchangeChecker.settings(config.watch);

  this.pair = [
    config.watch.asset,
    config.watch.currency
  ].join('/');

  // console.log(config);
  log.info('Starting to watch the market:',
    this.exchange.name,
    this.pair
  );

  if(!this.exchange.providesHistory) {
    this.on('new trades', function(a) {
      log.debug(
        'Fetched',
        _.size(a.all),
        'new trades, from',
        a.start.format('YYYY-MM-DD HH:mm:ss UTC'),
        'to',
        a.end.format('YYYY-MM-DD HH:mm:ss UTC')
      );
    });
  }
}

var Util = require('util');
var EventEmitter = require('events').EventEmitter;
Util.inherits(Fetcher, EventEmitter);

Fetcher.prototype.start = function() {
  // if this exchange does not support historical trades
  // start fetching.
  if(!this.exchange.providesHistory)
    this.fetch(false);
  else
    console.log(
      'either start looping right away (`since`)',
      'or first determine starting point dynamically'
    );
}

// Set the first & last trade date and set the
// timespan between them.
Fetcher.prototype.setFetchMeta = function(trades) {
  this.firstTrade = _.first(trades);
  this.first = moment.unix(this.firstTrade.date).utc();
  this.lastTrade = _.last(trades);
  this.last = moment.unix(this.lastTrade.date).utc();

  this.fetchTimespan = util.calculateTimespan(this.first, this.last);
}

// *This method is only used if this exchange does not support
// historical data.*
//
// we need to keep polling exchange because we cannot
// access older data. We need to calculate how often we
// we should poll.
//
// Returns amount of ms to wait for until next fetch.
Fetcher.prototype.calculateNextFetch = function(trades) {

  // for now just refetch every minute
  return this.fetchAfter = util.minToMs(2);

  // if the timespan per fetch is fixed at this exchange,
  // just return that number.
  if(this.exchange.fetchTimespan) {
    // todo: if the interval doesn't go in
    // sync with exchange fetchTimes we
    // need to calculate overlapping times.
    //
    // eg: if we can fetch every 60 min but user
    // interval is at 80, we would also need to
    // fetch again at 80 min.
    var min = _.min([
      this.exchange.fetchTimespan,
      config.tradingAdvisor.candleSize
    ]);
    this.fetchAfter = util.minToMs(min);
    // debugging bitstamp
    this.fetchAfter = util.minToMs(1);
    return;
  }

  var minimalInterval = util.minToMs(config.tradingAdvisor.candleSize);

  // if we got the last 100 seconds of trades last
  // time make sure we fetch at least in 55 seconds
  // again.
  var safeTreshold = 0.2;
  var defaultFetchTime = util.minToMs(1);

  if(this.fetchTimespan * safeTreshold > minimalInterval)
    // If the oldest trade in a fetch call > candle size
    // we can just use candle size.
    var fetchAfter = minimalInterval;
  else if(this.fetchTimespan * safeTreshold < defaultFetchTime)
    // If the oldest trade in a fetch call < default time
    // we fetch at default time.
    var fetchAfter = defaultFetchTime;
  else
    // use a safe fetch time to determine
    var fetchAfter = this.fetchTimespan * safeTreshold;

  this.fetchAfter = fetchAfter;
}

Fetcher.prototype.scheduleNextFetch = function() {
  setTimeout(this.fetch, this.fetchAfter);
}

Fetcher.prototype.fetch = function(since) {
  log.debug('Requested', this.pair ,'trade data from', this.exchange.name, '...');
  this.watcher.getTrades(since, this.processTrades, false);
  // this.spoofTrades();
}

Fetcher.prototype.spoofTrades = function() {
  var fs = require('fs');
  trades = JSON.parse( fs.readFileSync('./test7.json', 'utf8') );
  this.processTrades(false, trades);
}

Fetcher.prototype.processTrades = function(err, trades) {
  if(err)
    throw err;

  this.setFetchMeta(trades);
  this.calculateNextFetch();

  // schedule next fetch
  if(!this.exchange.providesHistory)
    this.scheduleNextFetch();

  this.emit('new trades', {
    timespan: this.fetchTimespan,
    start: this.first,
    first: this.firstTrade,
    end: this.last,
    last: this.lastTrade,
    all: trades,
    nextIn: this.fetchAfter
  });
}

module.exports = Fetcher;<commit_msg>refetch every min..<commit_after>//
// The fetcher is responsible for fetching new
// trades at the exchange. It will emit `new trades`
// events as soon as it fetches new data.
//
// How often this is depends on:
//
//  - The capability of the exchange (to provide
//  historical data).
//  - The amount of data we get per fetch.
//  - The interval at which we need new data.

var _ = require('lodash');
var moment = require('moment');
var utc = moment.utc;
var log = require('./log.js');

var util = require('./util');
var config = util.getConfig();

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

var provider = config.watch.exchange.toLowerCase();
var DataProvider = require('../exchanges/' + provider);

var Fetcher = function() {
  _.bindAll(this);

  // Create a public dataProvider object which can retrieve live
  // trade information from an exchange.

  this.watcher = new DataProvider(config.watch);
  this.lastFetch = false;

  this.exchange = exchangeChecker.settings(config.watch);

  this.pair = [
    config.watch.asset,
    config.watch.currency
  ].join('/');

  // console.log(config);
  log.info('Starting to watch the market:',
    this.exchange.name,
    this.pair
  );

  if(!this.exchange.providesHistory) {
    this.on('new trades', function(a) {
      log.debug(
        'Fetched',
        _.size(a.all),
        'new trades, from',
        a.start.format('YYYY-MM-DD HH:mm:ss UTC'),
        'to',
        a.end.format('YYYY-MM-DD HH:mm:ss UTC')
      );
    });
  }
}

var Util = require('util');
var EventEmitter = require('events').EventEmitter;
Util.inherits(Fetcher, EventEmitter);

Fetcher.prototype.start = function() {
  // if this exchange does not support historical trades
  // start fetching.
  if(!this.exchange.providesHistory)
    this.fetch(false);
  else
    console.log(
      'either start looping right away (`since`)',
      'or first determine starting point dynamically'
    );
}

// Set the first & last trade date and set the
// timespan between them.
Fetcher.prototype.setFetchMeta = function(trades) {
  this.firstTrade = _.first(trades);
  this.first = moment.unix(this.firstTrade.date).utc();
  this.lastTrade = _.last(trades);
  this.last = moment.unix(this.lastTrade.date).utc();

  this.fetchTimespan = util.calculateTimespan(this.first, this.last);
}

// *This method is only used if this exchange does not support
// historical data.*
//
// we need to keep polling exchange because we cannot
// access older data. We need to calculate how often we
// we should poll.
//
// Returns amount of ms to wait for until next fetch.
Fetcher.prototype.calculateNextFetch = function(trades) {

  // for now just refetch every minute
  return this.fetchAfter = util.minToMs(1);

  // if the timespan per fetch is fixed at this exchange,
  // just return that number.
  if(this.exchange.fetchTimespan) {
    // todo: if the interval doesn't go in
    // sync with exchange fetchTimes we
    // need to calculate overlapping times.
    //
    // eg: if we can fetch every 60 min but user
    // interval is at 80, we would also need to
    // fetch again at 80 min.
    var min = _.min([
      this.exchange.fetchTimespan,
      config.tradingAdvisor.candleSize
    ]);
    this.fetchAfter = util.minToMs(min);
    // debugging bitstamp
    this.fetchAfter = util.minToMs(1);
    return;
  }

  var minimalInterval = util.minToMs(config.tradingAdvisor.candleSize);

  // if we got the last 100 seconds of trades last
  // time make sure we fetch at least in 55 seconds
  // again.
  var safeTreshold = 0.2;
  var defaultFetchTime = util.minToMs(1);

  if(this.fetchTimespan * safeTreshold > minimalInterval)
    // If the oldest trade in a fetch call > candle size
    // we can just use candle size.
    var fetchAfter = minimalInterval;
  else if(this.fetchTimespan * safeTreshold < defaultFetchTime)
    // If the oldest trade in a fetch call < default time
    // we fetch at default time.
    var fetchAfter = defaultFetchTime;
  else
    // use a safe fetch time to determine
    var fetchAfter = this.fetchTimespan * safeTreshold;

  this.fetchAfter = fetchAfter;
}

Fetcher.prototype.scheduleNextFetch = function() {
  setTimeout(this.fetch, this.fetchAfter);
}

Fetcher.prototype.fetch = function(since) {
  log.debug('Requested', this.pair ,'trade data from', this.exchange.name, '...');
  this.watcher.getTrades(since, this.processTrades, false);
  // this.spoofTrades();
}

Fetcher.prototype.spoofTrades = function() {
  var fs = require('fs');
  trades = JSON.parse( fs.readFileSync('./test7.json', 'utf8') );
  this.processTrades(false, trades);
}

Fetcher.prototype.processTrades = function(err, trades) {
  if(err)
    throw err;

  this.setFetchMeta(trades);
  this.calculateNextFetch();

  // schedule next fetch
  if(!this.exchange.providesHistory)
    this.scheduleNextFetch();

  this.emit('new trades', {
    timespan: this.fetchTimespan,
    start: this.first,
    first: this.firstTrade,
    end: this.last,
    last: this.lastTrade,
    all: trades,
    nextIn: this.fetchAfter
  });
}

module.exports = Fetcher;<|endoftext|>


<commit_before><commit_msg>fix: remove debug<commit_after><|endoftext|>


<commit_before><commit_msg>make log an instance<commit_after><|endoftext|>


<commit_before><commit_msg>Finish challenge 9.2<commit_after>// 9.2.2 Translate Ruby to JavaScript
// re-do of 6.2 Die Class 2, Arbitrary Symbols

// Pseudocode

/*
-Declare a new function (Die) which accepts one argument (an array)
  -Raise an error IF the argument is not an array
  -Declare sides method that returns the length of the array
  -Declare roll method
    -get a random number from 0 to the array length
    -access the input array by index of the rando number
*/

// Initial Solution

function Die(array) {
  if (!(array instanceof Array)) {
    throw new Error("That is so very not valid.");
  };
  this.sides = array.length;
  this.roll = function(){
    var index = Math.floor(Math.random()*this.sides);
    return array[index];
  }
}

// Driver code

catanDie = ['blue', 'green', 'yellow', 'doom ship', 'doom ship', 'doom ship',];

var newGame = new Die(catanDie);

console.log(newGame.sides);

for (var i=0;i<4;i++) {
  console.log(newGame.roll());
}

notaDie = 67;
newGame = new Die(notaDie);

// Refactor

// so simple, nothing to refactor!

// Reflect
/*

What concepts did you solidify in working on this challenge?

-For me, this one was all about learning the JS syntax in contast with Ruby. While this exercise was simple  algorithmically , I found the translation aspect challenging.
-In particular, I solidified my ability to create and access objects using the Constructor notation.

What was the most difficult part of this challenge?

-Learning how to redo everything in JS; particularly figuring out how to raise an Error in response to invalid input.

Did you solve the problem in a new way this time?

-Not really :)

Was your pseudocode different from the Ruby version? What was the same and what was different?

-Also, not so much different.

*/<|endoftext|>


<commit_before><commit_msg>Make following ES5 functions work with undetectable parameters/target (document.all):<commit_after><|endoftext|>


<commit_before><commit_msg>debugging<commit_after><|endoftext|>


<commit_before><commit_msg>updates content javascript to remove shortcuts if none exist<commit_after><|endoftext|>


<commit_before>"use strict"

const { NODE_ENV, ROOT, TMP, IPPAN_ALIAS, IPV4 } = process.env

const { class:klass } = require("ippankiban/lib/class")
const { basename, dirname, isAbsolute:isAbsoluePath, join:joinPath, relative:relativePath, resolve:resolvePath } = require("path")
const { type:typeOf } = require("ippankiban/lib/type")
const { nextTick } = process
const { Event } = require("ippankiban/lib/Event")
const { EventTarget } = require("ippankiban/lib/EventTarget")
const { realpath } = require("fs")
const { Serializer:{ stringify:serialize } } = require("ippankiban/lib/Serializer")

const combineLoaders = require('webpack-combine-loaders')
const webpack = require("webpack")
const BabiliPlugin = require("babili-webpack-plugin")
const JsDocPlugin = require('jsdoc-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports.WebpackBundler = klass(EventTarget, statics => {
    const bundlers = new WeakMap
    const empty = {}

    let ready = Promise.resolve()

    let ippan_alias = false
    if ( IPPAN_ALIAS )
      ready = ready.then(() => new Promise((resolve, reject) => {
          realpath(resolvePath(ROOT, "./node_modules/ippankiban"), (err, path) => {
              if ( err )
                ippan_alias = false,
                console.error(err)
              else
                ippan_alias = path

              resolve()
          })
      }))

    return {
        constructor: function(...args){
            bundlers.set(this, new Map)

            bundlers.get(this).set("ready",
                Promise.resolve(typeOf(args[0]) == "object" ? args.shift() : {})
                .then(dict => new Promise(resolve => {
                    nextTick(() => {
                      this.from = dict.from

                      this.to_js = dict.to_js
                      this.to_css = dict.to_css

                      this.debug = dict.debug
                      this.devtool = dict.devtool
                      this.jsdoc = dict.jsdoc || dict.jsDoc
                      this.minify = dict.minify

                      ;((dict.babel||empty).presets||[]).forEach(preset => {
                          if ( typeOf(preset) == "string" )
                            this.babel_presets.add(preset)
                      })
                      ;((dict.babel||empty).plugins||[]).forEach(plugin => {
                          if ( typeOf(plugin) == "string" )
                            this.babel_plugins.add(plugin)
                      })
                      ;((dict.postcss||empty).plugins||[]).forEach(plugin => {
                          if ( typeOf(plugin) == "string" )
                            this.postcss_plugins.add(plugin)
                      })

                      this.postcss_configuration = (dict.postcss||empty).configuration||{}

                      ;Object.keys(dict.substitutes||{}).forEach(key => {
                          if ( typeOf(dict.substitutes[key]) == "string" )
                            this.substitutes.set(key, dict.substitutes[key])
                      })

                      resolve()
                    })
                }))
                .catch(e => this.dispatchEvent("error", e)))
        }
      , babel_presets: { enumerable: true,
            get: function(){
                if ( !bundlers.get(this).has("babel_presets") )
                  bundlers.get(this).set("babel_presets", new Set)

                return bundlers.get(this).get("babel_presets")
            }
        }
      , babel_plugins: { enumerable: true,
            get: function(){
                if ( !bundlers.get(this).has("babel_plugins") )
                  bundlers.get(this).set("babel_plugins", new Set)

                return bundlers.get(this).get("babel_plugins")
            }
        }
      , bundle: { enumerable: true,
            value: function(cb){
                cb = typeOf(cb) == "function" ? cb : Function.prototype

                return bundlers.get(this).get("ready")
                  .then(ready)
                  .then(() => new Promise((resolve, reject) => {
                      const substitutes = {}
                      this.subsitute.forEach((value, key) => substitutes[key] = `"${value}"` )
                      substitutes["process.env.NODE_ENV"] = `"${NODE_ENV}"`

                      const plugins = [
                            new webpack.DefinePlugin(substitutes)
                          , new ExtractTextPlugin(joinPath(relativePath(dirname(this.to_js), dirname(this.to_css)), basename(this.to_css)), { allchunks: true })
                          , new webpack.optimize.DedupePlugin()
                        ]

                      const wp_resolve = {
                          fallback: resolvePath(ROOT, "./node_modules")
                      }

                      if ( ippan_alias )
                        resolve.alias = { "ippankiban$": ippan_alias  }

                      if ( this.minify )
                        plugins.push(new BabiliPlugin({ comments: this.debug ? true : /@preserve|@license/ }))
                      if ( this.jsdoc )
                        plugins.push(new JsDocPlugin({ conf: this.jsdoc }))

                      webpack({
                          entry: resolvePath(ROOT, this.from)
                        , resolve: wp_resolve
                        , output: {
                              path: resolvePath(TMP, dirname(this.to_js))
                            , filename: basename(this.to_js)
                          }
                        , devtool: this.devtool || this.debug ? "source-map" : ""
                        , module: {
                              loaders: [
                                  {
                                      test: /\.js$/
                                    , loader: 'babel-loader'
                                    , query: {
                                          presets: [...this.babel_presets]
                                        , plugins: [...this.babel_plugins]
                                      }
                                  }
                                , { test: /\.css$/,
                                    loader: ExtractTextPlugin.extract('style-loader', `css-loader?modules&${this.postcss_configuration}!postcss-loader`)
                                  },
                              ]
                          }
                        , postcss: (webpack) => {
                               return [
                                  ...[...this.postcss_plugins].map(v => {
                                      if ( typeOf(v) == "string" )
                                        return require(v)()
                                      else
                                        return v
                                  })
                               ]
                            }
                          , plugins
                      }, (err, stats) => {
                          if ( err || stats.hasErrors() ) {
                              if ( err )
                                return reject([err])
                              return reject(stats.compilation.errors)
                          }
                          resolve()
                      })
                  })
                  .then(() => cb())
                  .catch((errors, ...args) => {
                      if ( typeOf(errors) != "array" )
                        errors = [errors]

                      cb.apply(null, errors)
                  }))
            }
        }
      , debug: { enumerable: true,
            get: function(){ return bundlers.get(this).get("debug") }
          , set: function(v){
                bundlers.get(this).set("debug", !!v)
            }
        }
      , devtool: { enumerable: true,
            get: function(){ return bundlers.get(this).devtool }
          , set: function(v){
                bundlers.get(this).set("devtool", v || false)
            }
        }
      , from: { enumerable: true,
            get: function(){ return bundlers.get(this).get("from") }
          , set: function(v){
                bundlers.get(this).set("from", typeof(v) == "string"
                                              ? (isAbsoluePath(v) ? `.${v}` : v)
                                              : void function(){ throw new TypeError("entry path (string) expected")  }())
            }
        }
      , jsdoc: { enumerable: true,
            get: function(){ return bundlers.get(this).get("jsdoc") || false }
          , set: function(v){
                bundlers.get(this).set("jsdoc", typeOf(v) == "string" ? v : false)
            }
        }
      , minify: { enumerable: true,
            get: function(){ return bundlers.get(this).get("minify") }
          , set: function(v){
                bundlers.get(this).set("minify", !!v)
            }
        }
      , postcss_configuration: { enumerable: true,
            get: function(){
                return serialize(bundlers.get(this).get("postcss_configuration"))
            }
          , set: function(v){
                if ( typeOf(v) !== "object" ) return

                bundlers.get(this).set("postcss_configuration", JSON.parse(JSON.stringify(v)))
            }
        }
      , postcss_plugins: { enumerable: true,
            get: function(){
                if ( !bundlers.get(this).has("postcss_plugins") )
                  bundlers.get(this).set("postcss_plugins", new Set)

                return bundlers.get(this).get("postcss_plugins")
            }
        }
      , subsitute: { enumerable: true,
            get: function(){
                if ( !bundlers.get(this).has("substitutes") )
                  bundlers.get(this).set("substitutes", new Map)

                return bundlers.get(this).get("substitutes")
              }
            }
      , to_js: { enumerable: true,
            get: function(){ return bundlers.get(this).get("to_js") }
          , set: function(v){
                bundlers.get(this).set("to_js", typeof(v) == "string"
                                              ? (isAbsoluePath(v) ? `.${v}` : v)
                                              : void function(){ throw new TypeError("js output, path (string) expected")  }())
            }
        }
      , to_css: {
            get: function(){ return bundlers.get(this).get("to_css") }
          , set: function(v){
                bundlers.get(this).set("to_css", typeof(v) == "string"
                                              ? (isAbsoluePath(v) ? `.${v}` : v)
                                              : void function(){ throw new TypeError("css output, path (string) expected")  }())
            }
        }
    }
})
<commit_msg><commit_after>"use strict"

const { NODE_ENV, ROOT, TMP, IPPAN_ALIAS, IPV4 } = process.env

const { class:klass } = require("ippankiban/lib/class")
const { basename, dirname, isAbsolute:isAbsoluePath, join:joinPath, relative:relativePath, resolve:resolvePath } = require("path")
const { type:typeOf } = require("ippankiban/lib/type")
const { nextTick } = process
const { Event } = require("ippankiban/lib/Event")
const { EventTarget } = require("ippankiban/lib/EventTarget")
const { realpath } = require("fs")
const { Serializer:{ stringify:serialize } } = require("ippankiban/lib/Serializer")

const combineLoaders = require('webpack-combine-loaders')
const webpack = require("webpack")
const BabiliPlugin = require("babili-webpack-plugin")
const JsDocPlugin = require('jsdoc-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports.WebpackBundler = klass(EventTarget, statics => {
    const bundlers = new WeakMap
    const empty = {}

    let ready = Promise.resolve()

    let ippan_alias = false
    if ( IPPAN_ALIAS )
      ready = ready.then(() => new Promise((resolve, reject) => {
          realpath(resolvePath(ROOT, "./node_modules/ippankiban"), (err, path) => {
              if ( err )
                ippan_alias = false,
                console.error(err)
              else
                ippan_alias = path

              resolve()
          })
      }))

    return {
        constructor: function(...args){
            bundlers.set(this, new Map)

            bundlers.get(this).set("ready",
                Promise.resolve(typeOf(args[0]) == "object" ? args.shift() : {})
                .then(dict => new Promise(resolve => {
                    nextTick(() => {
                      this.from = dict.from

                      this.to_js = dict.to_js
                      this.to_css = dict.to_css

                      this.debug = dict.debug
                      this.devtool = dict.devtool
                      this.jsdoc = dict.jsdoc || dict.jsDoc
                      this.minify = dict.minify

                      ;((dict.babel||empty).presets||[]).forEach(preset => {
                          if ( typeOf(preset) == "string" )
                            this.babel_presets.add(preset)
                      })
                      ;((dict.babel||empty).plugins||[]).forEach(plugin => {
                          if ( typeOf(plugin) == "string" )
                            this.babel_plugins.add(plugin)
                      })
                      ;((dict.postcss||empty).plugins||[]).forEach(plugin => {
                          if ( typeOf(plugin) == "string" )
                            this.postcss_plugins.add(plugin)
                      })

                      this.postcss_configuration = (dict.postcss||empty).configuration||{}

                      ;Object.keys(dict.substitutes||{}).forEach(key => {
                          if ( typeOf(dict.substitutes[key]) == "string" )
                            this.substitutes.set(key, dict.substitutes[key])
                      })

                      resolve()
                    })
                }))
                .catch(e => this.dispatchEvent("error", e)))
        }
      , babel_presets: { enumerable: true,
            get: function(){
                if ( !bundlers.get(this).has("babel_presets") )
                  bundlers.get(this).set("babel_presets", new Set)

                return bundlers.get(this).get("babel_presets")
            }
        }
      , babel_plugins: { enumerable: true,
            get: function(){
                if ( !bundlers.get(this).has("babel_plugins") )
                  bundlers.get(this).set("babel_plugins", new Set)

                return bundlers.get(this).get("babel_plugins")
            }
        }
      , bundle: { enumerable: true,
            value: function(cb){
                cb = typeOf(cb) == "function" ? cb : Function.prototype

                return bundlers.get(this).get("ready")
                  .then(ready)
                  .then(() => new Promise((resolve, reject) => {
                      const substitutes = {}
                      this.substitutes.forEach((value, key) => substitutes[key] = `"${value}"` )
                      substitutes["process.env.NODE_ENV"] = `"${NODE_ENV}"`

                      const plugins = [
                            new webpack.DefinePlugin(substitutes)
                          , new ExtractTextPlugin(joinPath(relativePath(dirname(this.to_js), dirname(this.to_css)), basename(this.to_css)), { allchunks: true })
                          , new webpack.optimize.DedupePlugin()
                        ]

                      const wp_resolve = {
                          fallback: resolvePath(ROOT, "./node_modules")
                      }

                      if ( ippan_alias )
                        resolve.alias = { "ippankiban$": ippan_alias  }

                      if ( this.minify )
                        plugins.push(new BabiliPlugin({ comments: this.debug ? true : /@preserve|@license/ }))
                      if ( this.jsdoc )
                        plugins.push(new JsDocPlugin({ conf: this.jsdoc }))

                      webpack({
                          entry: resolvePath(ROOT, this.from)
                        , resolve: wp_resolve
                        , output: {
                              path: resolvePath(TMP, dirname(this.to_js))
                            , filename: basename(this.to_js)
                          }
                        , devtool: this.devtool || this.debug ? "source-map" : ""
                        , module: {
                              loaders: [
                                  {
                                      test: /\.js$/
                                    , loader: 'babel-loader'
                                    , query: {
                                          presets: [...this.babel_presets]
                                        , plugins: [...this.babel_plugins]
                                      }
                                  }
                                , { test: /\.css$/,
                                    loader: ExtractTextPlugin.extract('style-loader', `css-loader?modules&${this.postcss_configuration}!postcss-loader`)
                                  },
                              ]
                          }
                        , postcss: (webpack) => {
                               return [
                                  ...[...this.postcss_plugins].map(v => {
                                      if ( typeOf(v) == "string" )
                                        return require(v)()
                                      else
                                        return v
                                  })
                               ]
                            }
                          , plugins
                      }, (err, stats) => {
                          if ( err || stats.hasErrors() ) {
                              if ( err )
                                return reject([err])
                              return reject(stats.compilation.errors)
                          }
                          resolve()
                      })
                  })
                  .then(() => cb())
                  .catch((errors, ...args) => {
                      if ( typeOf(errors) != "array" )
                        errors = [errors]

                      cb.apply(null, errors)
                  }))
            }
        }
      , debug: { enumerable: true,
            get: function(){ return bundlers.get(this).get("debug") }
          , set: function(v){
                bundlers.get(this).set("debug", !!v)
            }
        }
      , devtool: { enumerable: true,
            get: function(){ return bundlers.get(this).devtool }
          , set: function(v){
                bundlers.get(this).set("devtool", v || false)
            }
        }
      , from: { enumerable: true,
            get: function(){ return bundlers.get(this).get("from") }
          , set: function(v){
                bundlers.get(this).set("from", typeof(v) == "string"
                                              ? (isAbsoluePath(v) ? `.${v}` : v)
                                              : void function(){ throw new TypeError("entry path (string) expected")  }())
            }
        }
      , jsdoc: { enumerable: true,
            get: function(){ return bundlers.get(this).get("jsdoc") || false }
          , set: function(v){
                bundlers.get(this).set("jsdoc", typeOf(v) == "string" ? v : false)
            }
        }
      , minify: { enumerable: true,
            get: function(){ return bundlers.get(this).get("minify") }
          , set: function(v){
                bundlers.get(this).set("minify", !!v)
            }
        }
      , postcss_configuration: { enumerable: true,
            get: function(){
                return serialize(bundlers.get(this).get("postcss_configuration"))
            }
          , set: function(v){
                if ( typeOf(v) !== "object" ) return

                bundlers.get(this).set("postcss_configuration", JSON.parse(JSON.stringify(v)))
            }
        }
      , postcss_plugins: { enumerable: true,
            get: function(){
                if ( !bundlers.get(this).has("postcss_plugins") )
                  bundlers.get(this).set("postcss_plugins", new Set)

                return bundlers.get(this).get("postcss_plugins")
            }
        }
      , subsitutes: { enumerable: true,
            get: function(){
                if ( !bundlers.get(this).has("substitutes") )
                  bundlers.get(this).set("substitutes", new Map)

                return bundlers.get(this).get("substitutes")
              }
            }
      , to_js: { enumerable: true,
            get: function(){ return bundlers.get(this).get("to_js") }
          , set: function(v){
                bundlers.get(this).set("to_js", typeof(v) == "string"
                                              ? (isAbsoluePath(v) ? `.${v}` : v)
                                              : void function(){ throw new TypeError("js output, path (string) expected")  }())
            }
        }
      , to_css: {
            get: function(){ return bundlers.get(this).get("to_css") }
          , set: function(v){
                bundlers.get(this).set("to_css", typeof(v) == "string"
                                              ? (isAbsoluePath(v) ? `.${v}` : v)
                                              : void function(){ throw new TypeError("css output, path (string) expected")  }())
            }
        }
    }
})
<|endoftext|>


<commit_before>import Promise from 'bluebird';
import cheerio from 'cheerio';
import R from 'ramda';

import ChampionifyErrors from '../errors.js';
import { cl, request, shorthandSkills, trinksCon } from '../helpers';
import Log from '../logger';
import progressbar from '../progressbar';
import store from '../store';
import T from '../translate';

const default_schema = require('../../data/default.json');  //  Riot JSON schema

//  Item headings from lolalytics website
const item_block_names = ['Starting Items', 'First Item', 'Boots', 'Second Item', 'Third Item', 'Fourth Item', 'Fifth Item'];

export const source_info = {
  name: 'Lolalytics',
  id: 'lolalytics'
};

export function getVersion() {
  return request('http://current.lolalytics.com/')
    .then(body => {
      const $c = cheerio.load(body);
      const lolalytics_header = $c('body > div > h2').text();
      const patchRegex = new RegExp('League of Legends Patch ([0-9].[0-9]*)');
      const lolalytics_ver = patchRegex.exec(lolalytics_header)[1];
      store.set('lolalytics_ver', lolalytics_ver);
      return lolalytics_ver;
    })
    .catch(err => {
      throw new ChampionifyErrors.RequestError('Can\'t get Lolalytics Version').causedBy(err);
    });
}

function createChampionifyJson(riot_json, position, champion_name, split_sort) {
  if (split_sort) {
    position += `_${split_sort}`;
  }

  return {
    champ: champion_name,
    file_prefix: position,
    riot_json: riot_json,
    source: 'lolalytics'
  };
}

function createRiotJson(parsed_data, position, champion_name, split_sort) {
  const blocks = [];
  const item_names = store.get('item_names');
  const sortByWinRate = R.sortBy(R.prop('win'));
  const sortByPickRate = R.sortBy(R.prop('pick'));
  const build_sections = parsed_data.build_sections;
  const skills = parsed_data.skills;

  const build_sections_to_convert = [];

  R.forEach(function(x) { if (R.contains(x.title, item_block_names)) build_sections_to_convert.push(x); }, build_sections); //  Filter out the rows we don't care about (champion counters, etc.)

  function convertBuildSectionJsonToBlock(build_section_json, title) {
    const items = [];

    for (let k = 0; k < build_section_json.length; k++) {
      let id = parseInt(item_names[build_section_json[k].name], 10);

      id = (isNaN(id) ? 2003 : id); //  For biscuit

      items.push({
        count: 1,
        id: id.toString()
      });
    }

    const filtered_items = R.uniqBy(R.prop('id'), items); //  filter out duplicates, mainly just the second health pot from converting buscuits

    let block = {
      type: title,
      items: filtered_items
    };

    return block;
  }

  //  Iterate the sections
  for (let i = 0; i < build_sections_to_convert.length; i++) {
    //  Iterate the columns in that section
    const current_section = build_sections_to_convert[i];

    if (!split_sort) {
      let block = convertBuildSectionJsonToBlock(R.reverse(sortByWinRate(current_section.json)), `${T.t('highest_win', true)} ${T.t(current_section.title.split(' ').join('_'))}`);
      blocks.push(block);
      block = convertBuildSectionJsonToBlock(R.reverse(sortByPickRate(current_section.json)), `${T.t('most_freq', true)} ${T.t(current_section.title.split(' ').join('_'))}`);
      blocks.push(block);
    } else if (R.toLower(split_sort) === 'win') {
      let block = convertBuildSectionJsonToBlock(R.reverse(sortByWinRate(current_section.json)), `${T.t(current_section.title.split(' ').join('_'))}`);
      blocks.push(block);
    } else {
      let block = convertBuildSectionJsonToBlock(R.reverse(sortByPickRate(current_section.json)), `${T.t(current_section.title.split(' ').join('_'))}`);
      blocks.push(block);
    }
  }

  let riot_json = R.merge(R.clone(default_schema, true), {
    champion: champion_name,
    title: `Lolalytics ${champion_name} ${T.t(R.toLower(position), true)} ${store.get('lolalytics_ver')}`,
    blocks: trinksCon(blocks, skills)
  });

  if (split_sort) {
    if (R.toLower(split_sort) === 'win') {
      riot_json.title += ' ' + T.t('highest_win', true);
    } else {
      riot_json.title += ' ' + T.t('most_freq', true);
    }
  }

  if (store.get('settings').locksr) riot_json.map = 'SR';

  return createChampionifyJson(riot_json, position, champion_name, split_sort);
}

function parseSkillsData(cheerio_data) {
  let $c = cheerio_data;
  let skill_sections = [];
  $c('td.summarytitle').each(function(i, element) {
    if ($c(this).text() === 'Abilities') {
      let innerSkillsTable = $c(this).parent().find('table.summaryskillstable');
      let rows = $c(innerSkillsTable).find('tr');

      $c(rows).each(function(j, row) {
        if (j === 0)
          return; //  Skip the header row

        let skill_order = $c(row).find('td.summaryskills > div.summaryspellkey').text().split('').join('.');
        let win_rate = parseFloat($c(row).find('td.win').text());
        let pick_rate = parseFloat($c(row).find('td.popularity').text());

        let skill_section = {
          skills: skill_order,
          win: win_rate,
          pick: pick_rate
        };
        skill_sections.push(skill_section);
      }); //  end each row
    } //  end if abilities section
  }); //  end each td.summarytitle

  var highest_win_func = R.sortBy(R.prop('win'));
  var most_freq_func = R.sortBy(R.prop('pick'));

  let highest_win_skills = R.reverse(highest_win_func(skill_sections))[0];
  let most_freq_skills = R.reverse(most_freq_func(skill_sections))[0];

  let shorthand_bool = store.get('settings').skillsformat;

  let skills = {
    most_freq: shorthand_bool ? shorthandSkills(most_freq_skills.skills.split('.')) : most_freq_skills.skills,
    highest_win: shorthand_bool ? shorthandSkills(highest_win_skills.skills.split('.')) : highest_win_skills.skills
  };

  return skills;
}

function parseItemData(cheerio_data) {
  let build_sections = [];
  let $c = cheerio_data;

  $c('td.summarytitle').each(function(i, element) {
    let build_section = {
      title: $c(this).text(), //  name of the section
      json: []  //  json object w/ name, win, & pick values
    };

    let innerTable = $c(this).parent().find('table.summaryinner');
    let rows = $c(innerTable).find('tr');
    //  Store each column in the build_sections.json array

    $c(rows).each(function(j, row) {
      let rowName = $c(row).find('td.summarysubheading').text();
      if (rowName === '') { //  Items
        rowName = 'Items';
        $c(row).find('h1').each(function(z, itemName) {
          build_section.json.push({
            name: ($c(itemName).text()),
            win: null,
            pick: null
          });
        }); //  end each h1
      } else {
        if (rowName === 'Win') {
          $c(row).find('td.win.summarystats').each(function(z, winPercent) {
            build_section.json[z].win = parseFloat($c(winPercent).text());
          }); //  end find win
        }
        if (rowName === 'Pick') {
          $c(row).find('td.popularity.summarystats').each(function(z, pickPercent) {
            build_section.json[z].pick = parseFloat($c(pickPercent).text());
          }); //  end find popularity
        }
      } //  end else (not items)
    }); //  end each row
    build_sections.push(build_section);
  }); //  end each summarytitle

  return build_sections;
}

function parseChampionPage(cheerio_data, position, champion_name) {
  const build_sections = parseItemData(cheerio_data);
  const skills = parseSkillsData(cheerio_data);
  const parsed_data = {
    build_sections: build_sections,
    skills: skills
  };
  const builds = [];

  if (store.get('settings').splititems) {
    builds.push(createRiotJson(parsed_data, position, champion_name, 'Win'));
    builds.push(createRiotJson(parsed_data, position, champion_name, 'Pick'));
  } else {
    builds.push(createRiotJson(parsed_data, position, champion_name));
  }
  return builds;
}

function parseChampion(request_params, cheerio_data) {
  const $c = cheerio_data;
  const champion_name = request_params.champion_name;
  const position = request_params.position;
  let formatted_builds = [];

  const positions = $c('.lanebox > div.lanetitle');
  let position_names = [];
  let current_position = null;
  positions.each(function(i, pos) {
    $c(pos).children().remove(); // Remove the x.xx% after the lane name, it's a child in the div
    position_names.push($c(pos).text());
    if ($c(pos).parent().hasClass('selected'))
      current_position = $c(pos).text();
  });
  position_names = R.filter(role => (role !== position && role !== 'All Lanes'), position_names); //  Remove if exists

  if (position_names.length === 1 || position) { // Single position champ or we were passed a position
    formatted_builds = R.concat(formatted_builds, parseChampionPage(cheerio_data, current_position, champion_name));
  }

  if (position_names.length > 1 && !position) { //  More positions available and we werent passed one
    let extra_requests = [];
    extra_requests = R.map(position => ({champion_name, position}), position_names);
    return Promise.resolve(extra_requests)
    .map(request_params => getChampionPage(request_params)) // eslint-disable-line no-use-before-define
    .then(R.flatten)
    .then(R.concat(formatted_builds));
  }

  return formatted_builds;
}

function getChampionPage(request_params) {
  const { champion_name, position } = request_params;
  let url = `http://current.lolalytics.com/champion/${champion_name}/`;
  if (position)
    url += position + '/';
  else {
    cl(`${T.t('processing')} Lolalytics: ${T.t(champion_name)}`);
  }

  function markUndefined() {
    store.push('undefined_builds', {
      source: source_info.name,
      champion_name,
      position: request_params.position || 'All'
    });
    return;
  }

  return request(url).then(html => {
    console.timeEnd(champion_name + position);
    let $ = cheerio.load(html);
    return parseChampion(request_params, $);
  })
  .catch(err => {
    Log.warn(err);
    markUndefined();
    return;
  });
}

export function getSr() {
  const champs = store.get('champs'); //  Array of champ names

  return Promise.resolve(champs)
  .then(R.reverse)
  .map(champion_name => {
    progressbar.incrChamp();
    return getChampionPage({champion_name});
  }, {concurrency: 3})
  .then(data => {
    store.push('sr_itemsets', data);
  });
}
<commit_msg>PR change updates<commit_after>import Promise from 'bluebird';
import cheerio from 'cheerio';
import R from 'ramda';

import ChampionifyErrors from '../errors.js';
import { cl, request, shorthandSkills, trinksCon } from '../helpers';
import Log from '../logger';
import progressbar from '../progressbar';
import store from '../store';
import T from '../translate';

const default_schema = require('../../data/default.json');  //  Riot JSON schema

//  Item headings from lolalytics website
const item_block_names = ['Starting Items', 'First Item', 'Boots', 'Second Item', 'Third Item', 'Fourth Item', 'Fifth Item'];

const sort_by_win_rate = R.sortBy(R.prop('win'));
const sort_by_pick_rate = R.sortBy(R.prop('pick'));

export const source_info = {
  name: 'Lolalytics',
  id: 'lolalytics'
};

export function getVersion() {
  return request('http://current.lolalytics.com/')
    .then(body => {
      const $c = cheerio.load(body);
      const lolalytics_header = $c('body > div > h2').text();
      const patchRegex = new RegExp('League of Legends Patch ([0-9].[0-9]*)');
      const lolalytics_ver = patchRegex.exec(lolalytics_header)[1];
      store.set('lolalytics_ver', lolalytics_ver);
      return lolalytics_ver;
    })
    .catch(err => {
      throw new ChampionifyErrors.RequestError('Can\'t get Lolalytics Version').causedBy(err);
    });
}

function createChampionifyJson(riot_json, position, champion_name, split_sort) {
  if (split_sort) {
    position += `_${split_sort}`;
  }

  return {
    champ: champion_name,
    file_prefix: position,
    riot_json: riot_json,
    source: 'lolalytics'
  };
}

function createRiotJson(parsed_data, position, champion_name, split_sort) {
  const blocks = [];
  const item_names = store.get('item_names');
  const build_sections = parsed_data.build_sections;
  const skills = parsed_data.skills;

  const build_sections_to_convert = R.filter(R.propSatisfies(R.contains(R.__, item_block_names), 'title', R.__), build_sections);//  Filter out the rows we don't care about (champion counters, etc.)

  function convertBuildSectionJsonToBlock(build_section_json, title) {
    const items = [];

    for (let k = 0; k < build_section_json.length; k++) {
      let id = parseInt(item_names[build_section_json[k].name], 10);

      id = (isNaN(id) ? 2003 : id); //  For biscuit

      items.push({
        count: 1,
        id: id.toString()
      });
    }

    const filtered_items = R.uniqBy(R.prop('id'), items); //  filter out duplicates, mainly just the second health pot from converting buscuits

    let block = {
      type: title,
      items: filtered_items
    };

    return block;
  }

  R.forEach(current_section => {
    if (!split_sort) {
      let block = convertBuildSectionJsonToBlock(R.reverse(sort_by_win_rate(current_section.json)), `${T.t('highest_win', true)} ${T.t(current_section.title.split(' ').join('_'))}`);
      blocks.push(block);
      block = convertBuildSectionJsonToBlock(R.reverse(sort_by_pick_rate(current_section.json)), `${T.t('most_freq', true)} ${T.t(current_section.title.split(' ').join('_'))}`);
      blocks.push(block);
    } else if (R.toLower(split_sort) === 'win') {
      let block = convertBuildSectionJsonToBlock(R.reverse(sort_by_win_rate(current_section.json)), `${T.t(current_section.title.split(' ').join('_'))}`);
      blocks.push(block);
    } else {
      let block = convertBuildSectionJsonToBlock(R.reverse(sort_by_pick_rate(current_section.json)), `${T.t(current_section.title.split(' ').join('_'))}`);
      blocks.push(block);
    }
  }, build_sections_to_convert);

  let riot_json = R.merge(R.clone(default_schema, true), {
    champion: champion_name,
    title: `Lolalytics ${champion_name} ${T.t(R.toLower(position), true)} ${store.get('lolalytics_ver')}`,
    blocks: trinksCon(blocks, skills)
  });

  if (split_sort) {
    if (R.toLower(split_sort) === 'win') {
      riot_json.title += ' ' + T.t('highest_win', true);
    } else {
      riot_json.title += ' ' + T.t('most_freq', true);
    }
  }

  if (store.get('settings').locksr) riot_json.map = 'SR';

  return createChampionifyJson(riot_json, position, champion_name, split_sort);
}

function parseSkillsData($c) {
  let skill_sections = $c('td.summarytitle').map(function(i, el) {
    el = $c(el);
    if (el.text() === 'Abilities') {
      return el.parent().find('table.summaryskillstable').find('tr').map((idx, row) => {
        row = $c(row);
        if (idx === 0) return; // Skip the header row

        const skill_order = row.find('td.summaryskills > div.summaryspellkey').text().split('').join('.');
        const win_rate = parseFloat(row.find('td.win').text());
        const pick_rate = parseFloat(row.find('td.popularity').text());

        return {
          skills: skill_order,
          win: win_rate,
          pick: pick_rate
        };
      });
    }
  }).get();

  skill_sections = R.reject(R.isNil, R.flatten(skill_sections));

  let highest_win_skills = R.reverse(sort_by_win_rate(skill_sections))[0];
  let most_freq_skills = R.reverse(sort_by_pick_rate(skill_sections))[0];

  let shorthand_bool = store.get('settings').skillsformat;

  let skills = {
    most_freq: shorthand_bool ? shorthandSkills(most_freq_skills.skills.split('.')) : most_freq_skills.skills,
    highest_win: shorthand_bool ? shorthandSkills(highest_win_skills.skills.split('.')) : highest_win_skills.skills
  };

  return skills;
}

function parseItemData($c) {
  let build_sections = $c('td.summarytitle').map(function(i, el) {
    el = $c(el);
    let build_section = {
      title: el.text(), //  name of the section
      json: []  //  json object w/ name, win, & pick values
    };

    build_section.json = el.parent().find('table.summaryinner').map(function(j, table) {
      table = $c(table);
      let rows = table.children('tr');
      const item_name_row = $c(rows[0]);
      const win_rates = $c(rows[1]).find('td.win.summarystats');
      const pick_rates = $c(rows[2]).find('td.popularity.summarystats');
      return item_name_row.find('h1').map(function(idx, item_name) {
        const item_title = $c(item_name).text();
        const win_rate = parseFloat($c(win_rates[idx]).text());
        const pick_rate = parseFloat($c(pick_rates[idx]).text());

        return {
          name: item_title,
          win: win_rate,
          pick: pick_rate
        };
      });
    }).get();
    build_section.json = R.flatten(build_section.json);
    return build_section;
  }).get();
  return build_sections;
}

function parseChampionPage(cheerio_data, position, champion_name) {
  const build_sections = parseItemData(cheerio_data);
  const skills = parseSkillsData(cheerio_data);
  const parsed_data = {
    build_sections: build_sections,
    skills: skills
  };
  const builds = [];

  if (store.get('settings').splititems) {
    builds.push(createRiotJson(parsed_data, position, champion_name, 'Win'));
    builds.push(createRiotJson(parsed_data, position, champion_name, 'Pick'));
  } else {
    builds.push(createRiotJson(parsed_data, position, champion_name));
  }
  return builds;
}

function parseChampion(request_params, $c) {
  const champion_name = request_params.champion_name;
  const position = request_params.position;
  let formatted_builds = [];

  const positions = $c('.lanebox > div.lanetitle');
  let position_names = [];
  let current_position = null;
  positions.each(function(i, pos) {
    $c(pos).children().remove(); // Remove the x.xx% after the lane name, it's a child in the div
    position_names.push($c(pos).text());
    if ($c(pos).parent().hasClass('selected'))
      current_position = $c(pos).text();
  });
  position_names = R.filter(role => (role !== position && role !== 'All Lanes'), position_names); //  Remove if exists

  if (position_names.length === 1 || position) { // Single position champ or we were passed a position
    formatted_builds = R.concat(formatted_builds, parseChampionPage($c, current_position, champion_name));
  }

  if (position_names.length > 1 && !position) { //  More positions available and we werent passed one
    let extra_requests = [];
    extra_requests = R.map(position => ({champion_name, position}), position_names);
    return Promise.resolve(extra_requests)
    .map(request_params => getChampionPage(request_params)) // eslint-disable-line no-use-before-define
    .then(R.flatten)
    .then(R.concat(formatted_builds));
  }

  return formatted_builds;
}

function getChampionPage(request_params) {
  const { champion_name, position } = request_params;
  let url = `http://current.lolalytics.com/champion/${champion_name}/`;
  if (position)
    url += position + '/';
  else {
    cl(`${T.t('processing')} Lolalytics: ${T.t(champion_name)}`);
  }

  function markUndefined() {
    store.push('undefined_builds', {
      source: source_info.name,
      champion_name,
      position: request_params.position || 'All'
    });
    return;
  }

  return request(url).then(html => {
    let $ = cheerio.load(html);
    return parseChampion(request_params, $);
  })
  .catch(err => {
    Log.warn(err);
    markUndefined();
    return;
  });
}

export function getSr() {
  const champs = store.get('champs'); //  Array of champ names

  return Promise.resolve(champs)
  .then(R.reverse)
  .map(champion_name => {
    progressbar.incrChamp();
    return getChampionPage({champion_name});
  }, {concurrency: 3})
  .then(data => {
    store.push('sr_itemsets', data);
  });
}
<|endoftext|>


<commit_before>function validateEmail(email) {
    var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
    return re.test(email);
}
function lettersOnly(param){
    var letters = /^[a-zA-Z]*$/;
    return letters.test(param);
}
function onlyNumbers(num){
    var numbers = /^[0-9]*$/;
    return numbers.test(num);
}
function profileForm2() {
    var fname = document.forms["profileForm"]["firstName"].value;
    var lname = document.forms["profileForm"]["lastName"].value;
    var country = document.forms["profileForm"]["country"].value;
    var city = document.forms["profileForm"]["city"].value;
    var streetName = document.forms["profileForm"]["streetName"].value;
    var streetNumber = document.forms["profileForm"]["streetNumber"].value;
    var phoneNumber = document.forms["profileForm"]["phoneNumber"].value;
    var email = document.forms["profileForm"]["email"].value;
    var pass = document.forms["profileForm"]["password"].value;
    var passconf = document.forms["profileForm"]["passwordconf"].value;
    var antispam = document.forms["profileForm"]["antispam"].value;
    var validatedEmail = validateEmail(email);

    if (fname == null || fname == "") {
        alert("First Name must be filled in");
        return false;
    } else {
        if(!lettersOnly(fname)){
            alert ("Only letters and spaces allowed in first name");
            return false;
        }
        if(fname.length < 2){
            alert("First name too short");
            return false;
        }
    }
    if (lname == null || lname == "") {
        alert("Last Name must be filled");
        return false;
    } else {
        if(!lettersOnly(lname)){
            alert ("Only letters and spaces allowed in last name");
            return false;
        }
        if(lname.length < 2){
            alert("Last name too short");
            return false;
        }
    }
    if (country == null || country == "") {
        alert("Country name must be filled in");
        return false;
    } else {
        if(!lettersOnly(country)){
            alert ("Only letters and spaces allowedin country name");
            return false;
        }
        if(country.length < 2){
            alert("Country name too short");
            return false;
        }
    }
    if (city == null || city == "") {
        alert("City name must be filled in");
        return false;
    } else {
        if(!lettersOnly(city)){
            alert ("Only letters and spaces allowed in city name");
            return false;
        }
        if(city.length < 2){
            alert("City name too short");
            return false;
        }
    }
    if (streetNumber == null || streetNumber == "") {
        alert("Street Number must be filled in");
        return false;
    }

    if (streetName == null || streetName == "") {
        alert("Street Name must be filled");
        return false;
    } else {
        if(!lettersOnly(streetName)){
            alert ("Only letters and spaces allowed in street name");
            return false;
        }
        if(streetName.length < 2){
            alert("Street name too short");
            return false;
        }
    }
    if (phoneNumber == null || phoneNumber == "") {
        alert("Phone Number must be filled in");
        return false;
    } else {
        if(phoneNumber.length != 10){
            alert("Phone number must have 10 numbers");
            return false;
        }
        if(!onlyNumbers(phoneNumber)){
            alert("Please insert only numbers in phone number field");
            return false;
        }
    }
    if (!validatedEmail) {
        alert("Invalid email format");
        return false;
    }
    if (email == null || email == "") {
        alert("Email must be filled in");
        return false;
    }
    if (pass == null || pass == "") {
        alert("Password must be filled in");
        return false;
    }
    if (passconf == null || passconf == "") {
        alert("Password Confirm must be filled in");
        return false;
    }
    if (pass != passconf) {
        alert("Passwords do not match");
        return false;
    }
    if (antispam == null || antispam == "" || antispam != 6) {
        alert("Antispam must be filled in or value incorrect");
        return false;
    }
}<commit_msg>profileValidation debugged<commit_after>function validateEmail(email) {
    var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
    return re.test(email);
}
function lettersOnly(param){
    var letters = /^[a-zA-Z\s]*$/;
    return letters.test(param);
}
function onlyNumbers(num){
    var numbers = /^[0-9]*$/;
    return numbers.test(num);
}
function profileForm2() {
    var fname = document.forms["profileForm"]["firstName"].value;
    var lname = document.forms["profileForm"]["lastName"].value;
    var country = document.forms["profileForm"]["country"].value;
    var city = document.forms["profileForm"]["city"].value;
    var streetName = document.forms["profileForm"]["streetName"].value;
    var streetNumber = document.forms["profileForm"]["streetNumber"].value;
    var phoneNumber = document.forms["profileForm"]["phoneNumber"].value;
    var email = document.forms["profileForm"]["email"].value;
    var pass = document.forms["profileForm"]["password"].value;
    var passconf = document.forms["profileForm"]["passwordconf"].value;
    var antispam = document.forms["profileForm"]["antispam"].value;
    var validatedEmail = validateEmail(email);

    if (fname == null || fname == "") {
        alert("First Name must be filled in");
        return false;
    } else {
        if(!lettersOnly(fname)){
            alert ("Only letters and spaces allowed in first name");
            return false;
        }
        if(fname.length < 2){
            alert("First name too short");
            return false;
        }
    }
    if (lname == null || lname == "") {
        alert("Last Name must be filled");
        return false;
    } else {
        if(!lettersOnly(lname)){
            alert ("Only letters and spaces allowed in last name");
            return false;
        }
        if(lname.length < 2){
            alert("Last name too short");
            return false;
        }
    }
    if (country == null || country == "") {
        alert("Country name must be filled in");
        return false;
    } else {
        if(!lettersOnly(country)){
            alert ("Only letters and spaces allowedin country name");
            return false;
        }
        if(country.length < 2){
            alert("Country name too short");
            return false;
        }
    }
    if (city == null || city == "") {
        alert("City name must be filled in");
        return false;
    } else {
        if(!lettersOnly(city)){
            alert ("Only letters and spaces allowed in city name");
            return false;
        }
        if(city.length < 2){
            alert("City name too short");
            return false;
        }
    }
    if (streetNumber == null || streetNumber == "") {
        alert("Street Number must be filled in");
        return false;
    }

    if (streetName == null || streetName == "") {
        alert("Street Name must be filled");
        return false;
    } else {
        if(!lettersOnly(streetName)){
            alert ("Only letters and spaces allowed in street name");
            return false;
        }
        if(streetName.length < 2){
            alert("Street name too short");
            return false;
        }
    }
    if (phoneNumber == null || phoneNumber == "") {
        alert("Phone Number must be filled in");
        return false;
    } else {
        if(phoneNumber.length != 10){
            alert("Phone number must have 10 numbers");
            return false;
        }
        if(!onlyNumbers(phoneNumber)){
            alert("Please insert only numbers in phone number field");
            return false;
        }
    }
    if (!validatedEmail) {
        alert("Invalid email format");
        return false;
    }
    if (email == null || email == "") {
        alert("Email must be filled in");
        return false;
    }
    if (pass == null || pass == "") {
        alert("Password must be filled in");
        return false;
    }
    if (passconf == null || passconf == "") {
        alert("Password Confirm must be filled in");
        return false;
    }
    if (pass != passconf) {
        alert("Passwords do not match");
        return false;
    }
    if (antispam == null || antispam == "" || antispam != 6) {
        alert("Antispam must be filled in or value incorrect");
        return false;
    }
}<|endoftext|>