import Vue from 'vue';

export var version = '2.0.0';

var compatible = (/^2\./).test(Vue.version);
if (!compatible) {
  Vue.util.warn('VueFocus ' + version + ' only supports Vue 2.x, and does not support Vue ' + Vue.version);
}

export var focus = {
  inserted: function(el, binding) {
    if (binding.value) el.focus();
    else el.blur();
  },

  componentUpdated: function(el, binding) {
    if (binding.value) el.focus();
    else el.blur();
  },
};

export var mixin = {
  directives: {
    focus: focus,
  },
};

import Vue from 'vue';

export var version = '2.0.0';

var compatible = (/^2\./).test(Vue.version);
if (!compatible) {
  Vue.util.warn('VueFocus ' + version + ' only supports Vue 2.x, and does not support Vue ' + Vue.version);
}

export var focus = {
  inserted: function(el, binding) {
    if (binding.value) el.focus();
    else el.blur();
  },

  componentUpdated: function(el, binding) {
    if (binding.modifiers.lazy) {
      if (Boolean(binding.value) === Boolean(binding.oldValue)) {
        return;
      }
    }

    if (binding.value) el.focus();
    else el.blur();
  },
};

export var mixin = {
  directives: {
    focus: focus,
  },
};

Add a new `.lazy` modifier to mimic behavior of v1


var _ = require('lodash');

module.exports = function (data, options) {

  options = _.extend({
    mutator: function (val) {
      return val;
    }
  }, options);

  if (typeof data !== 'object') {
    throw new Error('[toxic] requires an object to mutate');
  }

  return _(data)
    .map(function (value, key) {

      // Which mutator to use
      var keyMutator = options.keyMutator || options.mutator;
      var valueMutator = options.valueMutator || options.mutator;

      return [
        keyMutator(key),
        valueMutator(value)
      ];
    })
    .filter(_.identity)
    .zipObject()
    .value();
};

var _ = require('lodash');

module.exports = function (data, options) {

  options = _.extend({
    mutator: function (val) {
      return val;
    }
  }, options);

  if (typeof data !== 'object') {
    throw new Error('[toxic] requires an object to mutate');
  }

  return _(data)
    .map(function (value, key) {
      // Which mutator to use
      var keyMutator = options.keyMutator || options.mutator;
      var valueMutator = options.valueMutator || options.mutator;

      return [
        keyMutator(key),
        valueMutator(value)
      ];
    })
    .filter(_.identity)
    .fromPairs()
    .value();
};

Use _.fromPairs instead of zipObject


module.exports = {
    core: {
        Product: require('./src/core/product'),
        Fabric: require('./src/core/fabric'),
        Buyer: require('./src/core/buyer'),
        Supplier: require('./src/core/supplier'),
        Textile: require('./src/core/textile'),
        Accessories: require('./src/core/accessories'),
        Sparepart: require('./src/core/sparepart'),
        UoM: require('./src/core/UoM').UoM,
        UoM_Template: require('./src/core/UoM').UoM_Template,
        GeneralMerchandise: require('./src/core/general-merchandise')
    },
    po: {
        PurchaseOrderItem: require('./src/po/purchase-order-item'),
        PurchaseOrder: require('./src/po/purchase-order'),
        PurchaseOrderGroup: require('./src/po/purchase-order-group'),

        POGarmentGeneral: require('./src/po/PO-garment-general'),
        POGroupGarmentGeneral: require('./src/po/purchase-order-group-garment-general'),

        POGarmentSparepart: require('./src/po/po-garment-sparepart')

    },
    map: require('./src/map'),
    validator: require('./src/validator')
}

module.exports = {
    core: {
        Product: require('./src/core/product'),
        Fabric: require('./src/core/fabric'),
        Buyer: require('./src/core/buyer'),
        Supplier: require('./src/core/supplier'),
        Textile: require('./src/core/textile'),
        Accessories: require('./src/core/accessories'),
        Sparepart: require('./src/core/sparepart'),
        UoM: require('./src/core/UoM').UoM,
        UoM_Template: require('./src/core/UoM').UoM_Template,
        GeneralMerchandise: require('./src/core/general-merchandise')
    },
    po: {
        PurchaseOrderItem: require('./src/po/purchase-order-item'),
        PurchaseOrder: require('./src/po/purchase-order'),
        PurchaseOrderGroup: require('./src/po/purchase-order-group'),

        POGarmentGeneral: require('./src/po/PO-garment-general'),
        POGroupGarmentGeneral: require('./src/po/purchase-order-group-garment-general'),

        POGarmentSparepart: require('./src/po/po-garment-sparepart'),
        POTextileJobOrder: require('./src/po/po-textile-job-order-external')

    },
    map: require('./src/map'),
    validator: require('./src/validator')
}

Update Index (Add PO Textile Job Order)


const { DataTypes } = require('sequelize');

module.exports = function (sequelize) {
  const ConnectionAccesses = sequelize.define(
    'ConnectionAccesses',
    {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
      },
      connectionId: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      connectionName: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      userId: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      userEmail: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      duration: {
        type: DataTypes.INTEGER,
        allowNull: false,
        validate: {
          min: 0,
          max: 86400,
        },
      },
      expiryDate: {
        type: DataTypes.DATE,
        allowNull: false,
      },
      createdAt: {
        type: DataTypes.DATE,
        allowNull: false,
      },
      updatedAt: {
        type: DataTypes.DATE,
        allowNull: false,
      },
    },
    {
      tableName: 'connection_accesses',
      underscored: true,
    }
  );

  return ConnectionAccesses;
};

const { DataTypes } = require('sequelize');

module.exports = function (sequelize) {
  const ConnectionAccesses = sequelize.define(
    'ConnectionAccesses',
    {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
      },
      connectionId: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      connectionName: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      userId: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      userEmail: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      // Number of seconds connection access is valid from creation
      // Used to set expiryDate
      duration: {
        type: DataTypes.INTEGER,
        allowNull: false,
        defaultValue: 0,
        validate: {
          min: 0,
          max: 86400,
        },
      },
      expiryDate: {
        type: DataTypes.DATE,
        allowNull: false,
      },
      createdAt: {
        type: DataTypes.DATE,
        allowNull: false,
      },
      updatedAt: {
        type: DataTypes.DATE,
        allowNull: false,
      },
    },
    {
      tableName: 'connection_accesses',
      underscored: true,
    }
  );

  return ConnectionAccesses;
};

Fix optional duration for connection accesses


module.exports=dataset;

/*global document*/

// replace namesLikeThis with names-like-this
function toDashed(name) {
  return name.replace(/([A-Z])/g, function(u) {
    return "-" + u.toLowerCase();
  });
}

var fn;

if (document.body.dataset) {
  fn = {
    set: function(node, attr, value) {
      node.dataset[attr] = value;
    },
    get: function(node, attr) {
      return node.dataset[attr];
    }
  };
} else {
  fn = {
    set: function(node, attr, value) {
      node.setAttribute('data-' + toDashed(attr), value);
    },
    get: function(node, attr) {
      return node.getAttribute('data-' + toDashed(attr));
    }
  };
}

function dataset(node, attr, value) {
  var self = {
    set: set,
    get: get
  };

  function set(attr, value) {
    fn.set(node, attr, value);
    return self;
  }

  function get(attr) {
    return fn.get(node, attr);
  }

  if (arguments.length === 3) {
    return set(attr, value);
  }
  if (arguments.length == 2) {
    return get(attr);
  }

  return self;
}

module.exports=dataset;

/*global document*/

// replace namesLikeThis with names-like-this
function toDashed(name) {
  return name.replace(/([A-Z])/g, function(u) {
    return "-" + u.toLowerCase();
  });
}

var fn;

if (document.head.dataset) {
  fn = {
    set: function(node, attr, value) {
      node.dataset[attr] = value;
    },
    get: function(node, attr) {
      return node.dataset[attr];
    }
  };
} else {
  fn = {
    set: function(node, attr, value) {
      node.setAttribute('data-' + toDashed(attr), value);
    },
    get: function(node, attr) {
      return node.getAttribute('data-' + toDashed(attr));
    }
  };
}

function dataset(node, attr, value) {
  var self = {
    set: set,
    get: get
  };

  function set(attr, value) {
    fn.set(node, attr, value);
    return self;
  }

  function get(attr) {
    return fn.get(node, attr);
  }

  if (arguments.length === 3) {
    return set(attr, value);
  }
  if (arguments.length == 2) {
    return get(attr);
  }

  return self;
}

Check if dataset exist on `head` node


const Server = require('./server/server');
const Login = require('./server/login');
const settings = require('./settings');

const server = new Server(new Login());
server.start(settings.port);

const Server = require('./server/server');
const Login = require('./server/login');
const settings = require('./settings');

const server = new Server(new Login());
server.start(process.env.PORT || settings.port);

Support for setting PORT from environment


var CodeMirror = require('codemirror/lib/codemirror.js')
var CmComponent = require('./codemirror.vue')

module.exports = {
  CodeMirror: CodeMirror,
  codemirror: CmComponent,
  install: function (Vue) {
    Vue.component('codemirror', CmComponent)
  }
}

var CodeMirror = require('codemirror/lib/codemirror.js')
import CmComponent from './codemirror.vue'

function install (Vue) {
  Vue.component('codemirror', CmComponent)
}

export default {
  install
}
export {
  CodeMirror,
  CmComponent as codemirror
}

Fix compatibility when vue-loader option `esModule` is true.


var ejs = require('ejs')
  , through = require('through')

module.exports = function(file, options) {
  if (!/\.ejs$/.test(file)) return through()

  options = options || {};

  var buffer = ""

  return through(function write(chunk) {
    buffer += chunk
  }, function end() {
    var template = ejs.compile(buffer, {
        client: true
      , debug: options.debug || false
      , compileDebug: options.compileDebug || false
      , filename: file
    })

    this.queue('module.exports = (' + template + ')')
    this.queue(null)
  })
}

var ejs = require('ejs')
  , through = require('through')

module.exports = function(file, options) {
  if (!/\.ejs$/.test(file)) return through()

  options = options || {}

  var buffer = ""

  return through(function write(chunk) {
    buffer += chunk
  }, function end() {
    var template = ejs.compile(buffer, {
        client: true
      , compileDebug: options.debug || false
      , filename: file
    })

    this.queue('module.exports = (' + template + ')')
    this.queue(null)
  })
}

Use --debug flag for compileDebug option.


// Start by requiring IOU to shim up the Promise constructor.

var
PROC    = require('child_process'),
Promise = require('iou').Promise;

exports.exec = function exec(command, options) {
  options = options || Object.create(null);
  var promise, child;
  promise = new Promise(function (resolve) {
    child = PROC.exec(command, function (err, stdout, stderr) {
      res = Object.create(null);
      Object.defineProperties(res, {
        stdout: {
          enumerable: true,
          value: stdout
        },
        stderr: {
          enumerable: true,
          value: stderr
        }
      });
      if (err) {
        Object.defineProperties(res, {
          errorMessage: {
            enumerable: true,
            value: err.message
          },
          exitCode: {
            enumerable: true,
            value: err.code
          },
          exitSignal: {
            enumerable: true,
            value: err.signal
          }
        });
      }
      return resolve(res);
    });
  });
  return promise;
};

// Start by requiring IOU to shim up the Promise constructor.

var
PROC    = require('child_process'),
Promise = require('iou').Promise;

exports.exec = function exec(command) {
  var promise, child;
  promise = new Promise(function (resolve) {
    child = PROC.exec(command, function (err, stdout, stderr) {
      res = Object.create(null);
      Object.defineProperties(res, {
        stdout: {
          enumerable: true,
          value: stdout
        },
        stderr: {
          enumerable: true,
          value: stderr
        }
      });
      if (err) {
        Object.defineProperties(res, {
          errorMessage: {
            enumerable: true,
            value: err.message
          },
          exitCode: {
            enumerable: true,
            value: err.code
          },
          exitSignal: {
            enumerable: true,
            value: err.signal
          }
        });
      }
      return resolve(res);
    });
  });
  return promise;
};

exports.spawn = function spawn() {
};

Remove options arg from exec.


var path = require("path");

// Export function to create new config (builder is passed in from outside)
module.exports = function(builder) {

    var bootstrapLess = require.resolve("bootstrap/less/bootstrap.less");

    return builder.merge({
        template: require.resolve("./template/template.hbs"),
        partials: path.resolve(__dirname,"template"),
        helpers: require("./src/handlebars-helper.js"),
        less: {
            main: [
                bootstrapLess,
                require.resolve("./less/main.less")
            ],
            paths: [
                path.dirname(bootstrapLess)
            ]
        },
        /**
         * A preprocessor that may return a modified json before entering the rendering process.
         * Access the inherited preprocessor is possible via this.previous(json)
         * @param obj the input object
         * @return a modified object or a promise for a modified object.
         */
        preprocessor: function(obj) { return obj; }
    })
};

// Add "package" to be used by bootprint-doc-generator
module.exports.package = require("./package");

var path = require("path");

// Export function to create new config (builder is passed in from outside)
module.exports = function(builder) {

    var bootstrapLess = require.resolve("bootstrap/less/bootstrap.less");

    return builder.merge({
        template: require.resolve("./handlebars/template.hbs"),
        partials: path.resolve(__dirname,"handlebars"),
        helpers: require("./src/handlebars-helper.js"),
        less: {
            main: [
                bootstrapLess,
                require.resolve("./less/main.less")
            ],
            paths: [
                path.dirname(bootstrapLess)
            ]
        },
        /**
         * A preprocessor that may return a modified json before entering the rendering process.
         * Access the inherited preprocessor is possible via this.previous(json)
         * @param obj the input object
         * @return a modified object or a promise for a modified object.
         */
        preprocessor: function(obj) { return obj; }
    })
};

// Add "package" to be used by bootprint-doc-generator
module.exports.package = require("./package");

Fix configured paths for partials


var createMiniHarp = function() {
  var connect = require('connect'),
      argv = require("minimist")(process.argv.slice(2)),
      app = connect(),
      port = argv.port || 4000;

  console.log("Starting mini-harp on http://localhost:" + port);
  app.listen(port);
}

module.exports = createMiniHarp;

var createMiniHarp = function() {
  var connect = require('connect'),
      argv = require("minimist")(process.argv.slice(2)),
      app = connect(),
      port = argv.port || 4000;

  app.use(function(req,res,next){
    var url = req.url.split("/");
    if (url[1] == "current-time" && url[2] === undefined)
      res.end((new Date()).toISOString()+"\n");
    else
      next();
    }).listen(port);

  console.log("Starting mini-harp on http://localhost:" + port);
}

module.exports = createMiniHarp;

Implement A Current Time Middleware


module.exports = exports = sseMiddleware;

/**
 * Middleware that adds support of Server Sent Events
 * @param __
 * @param res
 * @param next
 * @void
 */
function sseMiddleware(__, res, next) {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Access-Control-Allow-Origin': '*'
  });

  setInterval(() => {
    res.write(': sse-handshake');
  }, 3000);

  /**
   * Add function to response which allow to send events to the client
   * @param evt
   * @param json
   * @param [id]
   */
  res.sse = (evt, json, id) => {
    res.write('\n');

    if (id) {
      res.write(`id: ${id}\n`);
    }

    res.write(`retry: 3000\n`);
    res.write(`event: ${evt}\n`);
    res.write(`data: ${JSON.stringify(json)}\n\n`);
  };
  next();
}

module.exports = exports = sseMiddleware;

/**
 * Middleware that adds support of Server Sent Events
 * @param __
 * @param res
 * @param next
 * @void
 */
function sseMiddleware(__, res, next) {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Access-Control-Allow-Origin': '*'
  });

  const handshakeInterval = setInterval(() => {
    res.write(': sse-handshake');
  }, 3000);
  res.on('end', () => {
    clearInterval(handshakeInterval);
  });

  /**
   * Add function to response which allow to send events to the client
   * @param evt
   * @param json
   * @param [id]
   */
  res.sse = (evt, json, id) => {
    res.write('\n');

    if (id) {
      res.write(`id: ${id}\n`);
    }

    res.write(`retry: 3000\n`);
    res.write(`event: ${evt}\n`);
    res.write(`data: ${JSON.stringify(json)}\n\n`);
  };
  next();
}

Clear interval when response ends


const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  context: __dirname + '/src',
  entry: './bootstrapper',
  output: {
    path: __dirname + '/public',
    filename: 'bundle.js'
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  module: {
    loaders: [
      {
        test: /\.(png|jpg)$/,
        loader: 'url-loader?limit=100000'
      },
      {
        test: /\.styl$/,
        loader: 'style-loader!css-loader!stylus-loader',
        exclude: /node_modules/
      },
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.jsx?$/,
        loader: 'eslint-loader',
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      hash: true,
      inject: true,
      template: 'src/index.html'
    })
  ],
  devServer: {
    contentBase: __dirname + '/public'
  }
};

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  context: __dirname + '/src',
  entry: './bootstrapper',
  output: {
    path: __dirname + '/public',
    filename: 'bundle.js'
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  module: {
    loaders: [
      {
        test: /\.(png|jpg)$/,
        loader: 'url-loader?limit=100000'
      },
      {
        test: /\.styl$/,
        loader: 'style-loader!css-loader!stylus-loader?resolve url',
      },
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.jsx?$/,
        loader: 'eslint-loader',
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      hash: true,
      inject: true,
      template: 'src/index.html'
    })
  ],
  devServer: {
    contentBase: __dirname + '/public'
  }
};

Resolve URLs in Stylus files


/* jshint node: true */
'use strict';

var fs = require('fs');

module.exports = {
  name: 'ember-cli-sentry',

  included: function(app) {
    this._super.included(app);

    try {
      var stats = fs.statSync(app.bowerDirectory + '/raven-js/dist/raven.js');
      if (!stats.errno) {
        app.import(app.bowerDirectory + '/raven-js/dist/raven.js');
      }
    } catch (e) {
      console.log('ember-cli-sentry will not be loaded from bower installation');
    }
  },

  contentFor: function(type, config) {
    if (type === 'body-footer' && config.sentry && !config.sentry.development && config.sentry.cdn) {
      return '<script src="' + config.sentry.cdn + '"></script>';
    }
  }
};

/* jshint node: true */
'use strict';

var fs = require('fs');

module.exports = {
  name: 'ember-cli-sentry',

  included: function(app) {
    this._super.included(app);

    try {
      var stats = fs.statSync(app.bowerDirectory + '/raven-js/dist/raven.js');
      if (!stats.errno) {
        app.import(app.bowerDirectory + '/raven-js/dist/raven.js');
      }
    } catch (e) {
      this.ui.writeLine('ember-cli-sentry will not be loaded from bower installation');
    }
  },

  contentFor: function(type, config) {
    if (type === 'body-footer' && config.sentry && !config.sentry.development && config.sentry.cdn) {
      return '<script src="' + config.sentry.cdn + '"></script>';
    }
  }
};

Use ui.writeLine instead of console.log to respect --silent


'use strict';

var connect = require('readable-lists-api');
var run = require('./lib/run-bot.js');

var readers = {};
readers.pipermail = require('./lib/readers/pipermail');

var db = connect(process.env.DATABASE);

function onList(list) {
  console.log(list.source);
}
function onError(err) {
  console.error(err.stack || err);
}
function runBot() {
  db.getLists().then(function (lists) {
    function next() {
      if (lists.length === 0) return;
      var list = lists.pop();
      onList(list);
      var source = new readers[list.type](list._id, list.source);
      return run(source, db).then(null, onError).then(next);
    }
    return next();
  }).then(null, onError).done(runBot);
}
runBot();

'use strict';

var connect = require('readable-lists-api');
var run = require('./lib/run-bot.js');

var readers = {};
readers.pipermail = require('./lib/readers/pipermail');

var db = connect(process.argv[2] || process.env.DATABASE);

function onList(list) {
  console.log(list.source);
}
function onError(err) {
  console.error(err.stack || err);
}
function runBot() {
  db.getLists().then(function (lists) {
    function next() {
      if (lists.length === 0) return;
      var list = lists.pop();
      onList(list);
      var source = new readers[list.type](list._id, list.source);
      return run(source, db).then(null, onError).then(next);
    }
    return next();
  }).then(null, onError).done(runBot);
}
runBot();

Support passing database as an argument


require('dotenv').load();

var stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

exports.handler = function(event, context) {

  stripe.charges.create({
    amount:        event.amount,
    source:        event.source,
    currency:      event.currency || 'usd',
    description:   event.description || 'Stripe payment '+event.order_id,
    receipt_email: event.receipt_email || null
  }, function(err, charge) {
    if (err && err.type === 'card_error') {
      context.fail(new Error(err.message));
    } else if(err){
      context.fail(err);
    } else {
      context.succeed({ status: charge.status, success : true });
    }
  });
};

require('dotenv').load();

var stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

exports.handler = function(event, context, callback) {
  const chargeParams = {
    currency: 'usd',
    description: `Stripe payment ${event.order_id}`,
    receipt_email: null,
    ...event
  };

  stripe.charges.create(chargeParams, function(err, charge) {
    const status = charge ? charge.status : null;

    callback(err, { status, success: !err });
  });
};

Update handler signature to match node v4+ runtime


'use strict';

var assign = require('object-assign');
var chalk = require('chalk');
var lpad = require('lpad-align');
var ProgressBar = require('progress');

/**
 * Progress bar download plugin
 *
 * @param {Object} opts
 * @api public
 */

module.exports = function (opts) {
	return function (res, url, cb) {
		opts = opts || {};
		opts.stream = opts.stream || process.stderr;
		opts.indent = opts.indent || 2;

		if (res.headers['content-length']) {
			var words = [
				'fetch',
				'progress'
			];

			var fetch = chalk.cyan(lpad('fetch', words, opts.indent));
			var progress = chalk.cyan(lpad('progress', words, opts.indent));
			var str = progress + ' : [:bar] :percent :etas';

			var bar = new ProgressBar(str, assign({
				complete: '=',
				incomplete: ' ',
				width: 20,
				total: parseInt(res.headers['content-length'], 10)
			}, opts));

			opts.stream.write(fetch + ' : ' + url + '\n');

			res.on('data', function (data) {
				bar.tick(data.length);
			});

			res.on('end', function () {
				opts.stream.write('\n');
				cb();
			});
		}
	};
};

'use strict';

var assign = require('object-assign');
var chalk = require('chalk');
var lpad = require('lpad-align');
var ProgressBar = require('progress');

/**
 * Progress bar download plugin
 *
 * @param {Object} opts
 * @api public
 */

module.exports = function (opts) {
	return function (res, url, cb) {
		opts = opts || {};
		opts.stream = opts.stream || process.stderr;
		opts.indent = opts.indent || 2;

		if (res.headers['content-length']) {
			var words = [
				'fetch',
				'progress'
			];

			var fetch = chalk.cyan(lpad('fetch', words, opts.indent));
			var progress = chalk.cyan(lpad('progress', words, opts.indent));
			var str = progress + ' : [:bar] :percent :etas';

			var bar = new ProgressBar(str, assign({}, {
				complete: '=',
				incomplete: ' ',
				width: 20,
				total: parseInt(res.headers['content-length'], 10)
			}, opts));

			opts.stream.write(fetch + ' : ' + url + '\n');

			res.on('data', function (data) {
				bar.tick(data.length);
			});

			res.on('end', function () {
				opts.stream.write('\n');
				cb();
			});
		}
	};
};

Allow default options to be overridden


module.exports = function thirteen(number) {
  if (number !== undefined && typeof number !== "number") {
    // Can number be cast to a number?
    if (!isNaN(+number.toString())) {
      return +number.toString() * 13;
    } else if (!isNaN(+number.valueOf())) {
      return +number.valueOf() * 13;
    } else {
      return new Error("I can only deal with numbers");
    }
  } else {
    return number * 13;
  }
};

module.exports = function thirteen(number) {
  if (number !== undefined && typeof number !== "number") {
    // Can number be cast to a number?
    if (!isNaN(+number.toString())) {
      return +number.toString() * 13;
    } else if (!isNaN(+number.valueOf())) {
      return +number.valueOf() * 13;
    } else {
      return new Error("I can only deal with numbers");
    }
  } else {
    // Respond with great energy
    return number * 13  + "!!!";
  }
};

Enhance user experience with more energetic response


module.exports = {
  app:      require('./src/app'),
  cache:    require('./src/cache'),
  cls:      require('./src/cls'),
  config:   require('./src/config'),
  db:       require('./src/db/db'),
  dev:      require('./src/dev/index'),
  i18next:  require('i18next'),
  render:   require('consolidate').dust,
  logger:   require('winston'),
  mailer:   require('./src/mailer'),
  Model:    require('./src/db/Model')
};

module.exports = {
  app:      require('./src/app'),
  cache:    require('./src/cache'),
  cls:      require('./src/cls'),
  config:   require('./src/config'),
  db:       require('./src/db/db'),
  i18next:  require('i18next'),
  render:   require('consolidate').dust,
  logger:   require('winston'),
  mailer:   require('./src/mailer'),
  Model:    require('./src/db/Model')
};

if (!process.env.NODE_ENV || process.env.NODE_ENV === 'dev') {
  module.exports.dev = require('./src/dev/index');
}

Fix dependency for production env


var argv = require('minimist')(process.argv.slice(2));
var fs = require('fs');
var path = require('path');

module.exports = function (options) {
  options = options || {};
  var bases = options.base || './';
  var gulp = options.gulp || require('gulp');
  var tasks = argv._;

  if (typeof bases === 'string') {
    bases = [bases];
  }

  tasks.forEach(function (task) {
    bases.forEach(function (base) {
      var baseTask = path.join(process.cwd(), base, task);
      var baseTaskJs = baseTask + '.js';
      if (fs.existsSync(baseTaskJs)) {
        var taskFunc = require(baseTask);

        if (taskFunc.private) {
          return;
        }

        if (!taskFunc.dependencies) {
          taskFunc.dependencies = [];
        }

        gulp.task(task, taskFunc.dependencies, function () {
          return taskFunc(argv);
        });
      }
    });
  });
};

var argv = require('minimist')(process.argv.slice(2));
var path = require('path');

function loadTask (gulp, taskName, taskPath) {
  try {
    var taskFunc = require(taskPath);
  } catch (e) {
    throw new Error ('could not load task "' + taskName + '"');
  }

  if (taskFunc.private) {
    return;
  }

  if (!taskFunc.dependencies) {
    taskFunc.dependencies = [];
  }

  taskFunc.dependencies.forEach(function (depPath) {
    var depRealPath = path.join(path.dirname(taskPath), depPath);
    try {
      loadTask(gulp, depPath, depRealPath);
    } catch (e) {
      throw new Error('could not load task dependency "' + depPath + '" for "' + taskName + '"');
    }
  });

  gulp.task(taskName, taskFunc.dependencies, function () {
    return taskFunc(argv);
  });
}

module.exports = function (options) {
  options = options || {};
  var bases = options.base || './';
  var gulp = options.gulp || require('gulp');
  var tasks = argv._;

  if (typeof bases === 'string') {
    bases = [bases];
  }

  tasks.forEach(function (taskName) {
    bases.forEach(function (basePath) {
      var taskPath = path.join(process.cwd(), basePath, taskName);
      try {
        loadTask(gulp, taskName, taskPath);
      } catch (e) {
        throw e;
      }
    });
  });
};

Support loading and auto-tasking of task dependencies.


/*
 * @license MIT http://www.opensource.org/licenses/mit-license.php
 * @author  Hovhannes Babayan <bhovhannes at gmail dot com>
 */
var loaderUtils = require('loader-utils');

module.exports = function(content) {
	this.cacheable && this.cacheable();

	var query = loaderUtils.getOptions(this);

	var limit = query.limit ? parseInt(query.limit, 10) : 0;

	if (limit <= 0 || content.length < limit) {
		content = content.toString('utf8');

		if (query.stripdeclarations) {
			content = content.replace(/^\s*<\?xml [^>]*>\s*/i, "");
		}

		content = content.replace(/"/g, "'");
		content = content.replace(/\s+/g, " ");
		content = content.replace(/[{}\|\\\^~\[\]`"<>#%]/g, function(match) {
			return '%'+match[0].charCodeAt(0).toString(16).toUpperCase();
		});

		var data = 'data:image/svg+xml,' + content.trim();
		if (!query.noquotes) {
			data = '"'+data+'"';
		}

		return 'module.exports = ' + JSON.stringify(data);
	}
	else {
		var fileLoader = require('file-loader');
		return fileLoader.call(this, content);
	}
};

module.exports.raw = true;

/*
 * @license MIT http://www.opensource.org/licenses/mit-license.php
 * @author  Hovhannes Babayan <bhovhannes at gmail dot com>
 */
var loaderUtils = require('loader-utils');

module.exports = function(content) {
	this.cacheable && this.cacheable();

	var query = loaderUtils.getOptions(this) || {};

	var limit = query.limit ? parseInt(query.limit, 10) : 0;

	if (limit <= 0 || content.length < limit) {
		content = content.toString('utf8');

		if (query.stripdeclarations) {
			content = content.replace(/^\s*<\?xml [^>]*>\s*/i, "");
		}

		content = content.replace(/"/g, "'");
		content = content.replace(/\s+/g, " ");
		content = content.replace(/[{}\|\\\^~\[\]`"<>#%]/g, function(match) {
			return '%'+match[0].charCodeAt(0).toString(16).toUpperCase();
		});

		var data = 'data:image/svg+xml,' + content.trim();
		if (!query.noquotes) {
			data = '"'+data+'"';
		}

		return 'module.exports = ' + JSON.stringify(data);
	}
	else {
		var fileLoader = require('file-loader');
		return fileLoader.call(this, content);
	}
};

module.exports.raw = true;

Fix calling without query throws TypeError


'use strict';

const DAS = module.exports = {};

DAS.ActionHandler = require('./ActionHandler');
DAS.Dispatcher = require('./Dispatcher')

Add dispatcher to the library


;(function(window, document){
	document.addEventListener('touchmove', function(e) {
		isScrollElement(e.target) || e.preventDefault();
	}, false);
	document.addEventListener('touchstart', function(e){
		var elem = isScrollElement(e.target);
		if(elem) {
			var startTopScroll = elem.scrollTop;
			if(startTopScroll <= 0) { elem.scrollTop = 1; }
			if(startTopScroll + elem.offsetHeight >= elem.scrollHeight) {
				elem.scrollTop = elem.scrollHeight - elem.offsetHeight - 1;
			}
		}
	}, false);
	function isScrollElement(element) {
		while(element) {
			if (
				(window.getComputedStyle(element).overflow === 'scroll' ||
				window.getComputedStyle(element)["overflow-y"] === 'scroll' ||
				window.getComputedStyle(element)["overflow-x"] === 'scroll') &&
				element.scrollHeight > window.innerHeight
				) {
				return element;
			}
			element = element.parentElement;
		}
		return false;
	}
})(window, document);

;(function(window, document){
	document.addEventListener('touchmove', function(e) {
		isScrollElement(e.target) || e.preventDefault();
	}, false);
	document.addEventListener('touchstart', function(e){
		var elem = isScrollElement(e.target);
		var startTopScroll = 0;
		if(elem) {
			startTopScroll = elem.scrollTop;
			if(startTopScroll <= 0) { elem.scrollTop = 1; }
			if(startTopScroll + elem.clientHeight >= elem.scrollHeight) {
				elem.scrollTop = elem.scrollHeight - elem.clientHeight - 1;
			}
		}
	}, false);
	function isScrollElement(element) {
		while(element) {
			if (
				(window.getComputedStyle(element).overflow === 'scroll' ||
				window.getComputedStyle(element)["overflow-y"] === 'scroll' ||
				window.getComputedStyle(element)["overflow-x"] === 'scroll') &&
				element.scrollHeight > window.innerHeight
				) {
				return element;
			}
			element = element.parentElement;
		}
		return false;
	}
})(window, document);

Change detection to ignore borders


/**
 * bit.ly access library code.
 */
var Shortener = new JS.Singleton('Shortener', {
  initialize: function() {
    this.extend({
      CLIENT:    BitlyClient || null,
      NAMESPACE: BitlyCB     || null
    });
  },

	shorten: function() {
	  var uri, callback;

	  if (typeof arguments[0] == 'string') {
	    uri      = arguments[0];
	    callback = arguments[1];
	  } else {
	    uri      = window.location.href;
	    callback = arguments[0];
	  }

		var name = this._registerCallback(callback);

		if (!(name && this.CLIENT)) return;

		this.CLIENT.call('shorten', {
			'longUrl': uri
		}, 'BitlyCB.' + name);
	},

	_dispatcher: function(callback, data) {
		var result;

    // Results are keyed by longUrl, so we need to grab the first one.
    for (var r in data.results) {
			result = data.results[r];
			break;
    }

		callback(result, data);
	},

	_registerCallback: function(callback) {
	  if (!this.NAMESPACE) return false;

		var name = 'abbr' + this.callbackCount;
		this.callbackCount += 1;

		this.NAMESPACE[name] = function(data) {
			this._dispatcher(callback, data);
		}.bind(this);

		return name;
	},

	callbackCount: 0
});

/**
 * bit.ly access library code.
 */
var Shortener = new JS.Singleton('Shortener', {
	shorten: function() {
	  var uri, callback;

	  if (typeof arguments[0] == 'string') {
	    uri      = arguments[0];
	    callback = arguments[1];
	  } else {
	    uri      = window.location.href;
	    callback = arguments[0];
	  }

		var name = this._registerCallback(callback);

		if (!(name && this.CLIENT)) return;

		this.CLIENT.call('shorten', {
			'longUrl': uri
		}, 'BitlyCB.' + name);
	},

	_dispatcher: function(callback, data) {
		var result;

    // Results are keyed by longUrl, so we need to grab the first one.
    for (var r in data.results) {
			result = data.results[r];
			break;
    }

		callback(result, data);
	},

	_registerCallback: function(callback) {
	  if (!this.NAMESPACE) return false;

		var name = 'abbr' + this.callbackCount;
		this.callbackCount += 1;

		this.NAMESPACE[name] = function(data) {
			this._dispatcher(callback, data);
		}.bind(this);

		return name;
	},

	callbackCount: 0,

	CLIENT:        BitlyClient || null,
  NAMESPACE:     BitlyCB     || null
});

Clean up bitly API object references.


// Context for k-CFA analysis
//
// Assume a context is an array of numbers.
// A number in such list denotes a call site, that is @label of a CallExpression.
// We keep the most recent 'k' callsites.
// Equality on contexts should look into the numbers.

var callSiteContextParameter = {
    // maximum length of context
    maxDepthK: 0,
    // function list for sensitive analysis
    sensFuncs: {}
};

function CallSiteContext() {
    this.csList = [];
}

CallSiteContext.prototype.isEqual = function (other) {
    if (this.csList.length != other.csList.length) return false;
    for (var i = 0; i < this.csList.length; i++) {
        if (this.csList[i] != other.csList[i]) return false;
    }
    return true;
};

CallSiteContext.prototype.appendOne = function (callSite) {
    // use concat to create a new array
    // oldest one comes first
    var appended = this.csList.concat(callSite);
    if (appended.length > callSiteContextParameter.maxDepthK) {
        appended.shift();
    }
};

exports.callSiteContextParameter = callSiteContextParameter;
exports.CallSiteContext = CallSiteContext;

// Context for k-CFA analysis
//
// Assume a context is an array of numbers.
// A number in such list denotes a call site, that is @label of a CallExpression.
// We keep the most recent 'k' callsites.
// Equality on contexts should look into the numbers.

var callSiteContextParameter = {
    // maximum length of context
    maxDepthK: 0,
    // function list for sensitive analysis
    sensFuncs: {}
};

function CallSiteContext() {
    this.csList = [];
}

CallSiteContext.prototype.equals = function (other) {
    if (this.csList.length != other.csList.length) return false;
    for (var i = 0; i < this.csList.length; i++) {
        if (this.csList[i] != other.csList[i]) return false;
    }
    return true;
};

CallSiteContext.prototype.appendOne = function (callSite) {
    // use concat to create a new array
    // oldest one comes first
    var appended = this.csList.concat(callSite);
    if (appended.length > callSiteContextParameter.maxDepthK) {
        appended.shift();
    }
};

CallSiteContext.prototype.toString = function () {
    return this.csList.toString();
};

exports.callSiteContextParameter = callSiteContextParameter;
exports.CallSiteContext = CallSiteContext;

Add toString method for CallSiteContext


module.exports = function(sugar, models, assert) {
    return function updateMultipleAuthors(cb) {
        var firstAuthor = {name: 'foo'};
        var secondAuthor = {name: 'bar'};
        var authors = [firstAuthor, secondAuthor];

        sugar.create(models.Author, authors, function(err, d) {
            if(err) return cb(err);

            var name = 'joe';

            sugar.update(models.Author, authors, {name: name}, function(err, d) {
                if(err) return cb(err);

                assert.equal(d && d[0], name);
                assert.equal(d && d[1], name);

                cb();
            });
        });
    };
};

module.exports = function(sugar, models, assert) {
    return function updateMultipleAuthors(cb) {
        var firstAuthor = {name: 'foo'};
        var secondAuthor = {name: 'bar'};
        var authors = [firstAuthor, secondAuthor];

        sugar.create(models.Author, authors, function(err, d) {
            if(err) return cb(err);

            var name = 'joe';

            sugar.update(models.Author, [d && d[0]._id, d && d[1]._id], {name: name}, function(err, d) {
                if(err) return cb(err);

                assert.equal(d && d[0], name);
                assert.equal(d && d[1], name);

                cb();
            });
        });
    };
};

Make multiple update operate on ids


module.exports = {
	module: {
		loaders: [{
			test: /\.css$/,
			loader: "style!css"
		}, {
			test: /\.pug$/,
			loader: "pug?self"
		}]
	}
}

module.exports = {
	module: {
		loaders: [{
			test: /\.css$/,
			loader: "style-loader!css-loader"
		}, {
			test: /\.pug$/,
			loader: "pug-loader?self"
		}]
	}
}

Fix compatibility with webpack 2.1.0-beta.26


const path = require('path');
const webpack = require('webpack');
const nodeEnv = process.env.NODE_ENV || 'development';
const { VueLoaderPlugin } = require('vue-loader');

const config = {
  mode: nodeEnv,
  entry: "./src/entries/dist.js",
  output: {
    path: path.join(__dirname, 'dist'),
    filename: "h5p-audio-recorder.js",
    sourceMapFilename: '[file].map'
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    },
    modules: [
      path.resolve('./src'),
      path.resolve('./node_modules')
    ]
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          preserveWhitespace: false
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      },
      {
        test: /\.(s[ac]ss|css)$/,
        use: [
          'vue-style-loader',
          'css-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(svg)$/,
        include: path.join(__dirname, 'src/images'),
        type: 'asset/inline'
      }
    ]
  },
  plugins: [
    // make sure to include the plugin for the magic
    new VueLoaderPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify(nodeEnv)
      }
    }),
  ]
};

module.exports = config;

const path = require('path');
const webpack = require('webpack');
const nodeEnv = process.env.NODE_ENV || 'development';
const { VueLoaderPlugin } = require('vue-loader');

const config = {
  mode: nodeEnv,
  entry: "./src/entries/dist.js",
  devtool: (nodeEnv === 'production') ? undefined : 'inline-source-map',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: "h5p-audio-recorder.js",
    sourceMapFilename: '[file].map'
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    },
    modules: [
      path.resolve('./src'),
      path.resolve('./node_modules')
    ]
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          preserveWhitespace: false
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      },
      {
        test: /\.(s[ac]ss|css)$/,
        use: [
          'vue-style-loader',
          'css-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(svg)$/,
        include: path.join(__dirname, 'src/images'),
        type: 'asset/inline'
      }
    ]
  },
  plugins: [
    // make sure to include the plugin for the magic
    new VueLoaderPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify(nodeEnv)
      }
    }),
  ]
};

module.exports = config;

Stop including sourcemap for production mode


import { configure, addDecorator } from '@storybook/react';
import { setDefaults } from '@storybook/addon-info';
import { setOptions } from '@storybook/addon-options';
import backgroundColor from 'react-storybook-decorator-background';

// addon-info
setDefaults({
  header: false,
  inline: false,
  source: true,
  propTablesExclude: [],
});

setOptions({
  name: `Version ${process.env.__VERSION__}`,
  url: 'https://teamleader.design'
});

addDecorator(backgroundColor(['#ffffff', '#e6f2ff', '#ffeecc', '#d3f3f3', '#ffe3d9', '#e1edfa', '#f1f0ff', '#2a3b4d']));

const req = require.context('../stories', true, /\.js$/);

configure(() => {
  req.keys().forEach(filename => req(filename));
}, module);

import { configure, addDecorator } from '@storybook/react';
import { setDefaults } from '@storybook/addon-info';
import { setOptions } from '@storybook/addon-options';
import backgroundColor from 'react-storybook-decorator-background';

// addon-info
setDefaults({
  header: false,
  inline: true,
  source: true,
  propTablesExclude: [],
});

setOptions({
  name: `Version ${process.env.__VERSION__}`,
  url: 'https://teamleader.design'
});

addDecorator(backgroundColor(['#ffffff', '#e6f2ff', '#ffeecc', '#d3f3f3', '#ffe3d9', '#e1edfa', '#f1f0ff', '#2a3b4d']));

const req = require.context('../stories', true, /\.js$/);

configure(() => {
  req.keys().forEach(filename => req(filename));
}, module);

Enable inline info instead of hiding it after the blue button in the upper right corner


define([
	'underscore',
	'text!templates/grid-docs.html',
	'text!pages/grid-options-remoteScrollTime.html',
	'dobygrid',
	'js/sample-fetcher'
], function (_, template, page, DobyGrid, remotedata) {
	"use strict";

	return Backbone.DobyView.extend({

		events: function () {
			return _.extend({}, Backbone.DobyView.prototype.events, {
				"change #option-value":		"changeOption"
			});
		},

		initialize: function () {
			var html = _.template(template, {
				page: page
			});

			this.$el.append(html);
		},

		render: function () {
			new DobyGrid({
				columns: [{
					id: "id",
					name: "ID",
					field: "id"
				}, {
					id: "name",
					name: "Name",
					field: "name"
				}, {
					id: "age",
					name: "Age",
					field: "age"
				}],
				data: remotedata,
				rowHeight: 35
			}).appendTo('#demo-grid');
		},

		changeOption: function (event) {
			// Get value
			var value = $(event.currentTarget).val();

			// Set value
			this.grid.setOptions({remoteScrollTime: value});
		}
	});
});

define([
	'underscore',
	'text!templates/grid-docs.html',
	'text!pages/grid-options-remoteScrollTime.html',
	'dobygrid',
	'js/sample-fetcher'
], function (_, template, page, DobyGrid, remotedata) {
	"use strict";

	return Backbone.DobyView.extend({

		events: function () {
			return _.extend({}, Backbone.DobyView.prototype.events, {
				"change #option-value":		"changeOption"
			});
		},

		initialize: function () {
			var html = _.template(template, {
				page: page
			});

			this.$el.append(html);
		},

		render: function () {
			this.grid = new DobyGrid({
				columns: [{
					id: "id",
					name: "ID",
					field: "id"
				}, {
					id: "name",
					name: "Name",
					field: "name"
				}, {
					id: "age",
					name: "Age",
					field: "age"
				}],
				data: remotedata,
				rowHeight: 35
			}).appendTo('#demo-grid');
		},

		changeOption: function (event) {
			// Get value
			var value = $(event.currentTarget).val();

			// Set value
			this.grid.setOptions({remoteScrollTime: value});
		}
	});
});

Fix bug with remoteScrollTime docs changer.


const path = require("path");

function ResolverIntercept(resolver) {
  this.resolver = resolver;
  this.cache = {};
};

ResolverIntercept.prototype.require = function(import_path) {
  // Modify import_path so the cache key is consistently the same irrespective
  // of whether a user explicated .sol extension
  import_path = path.basename(import_path, ".sol");

  // TODO: Using the import path for relative files may result in multiple
  // paths for the same file. This could return different objects since it won't be a cache hit.
  if (this.cache[import_path]) {
    return this.cache[import_path];
  }

  // Note, will error if nothing is found.
  var resolved = this.resolver.require(import_path);

  this.cache[import_path] = resolved;

  // During migrations, we could be on a network that takes a long time to accept
  // transactions (i.e., contract deployment close to block size). Because successful
  // migration is more important than wait time in those cases, we'll synchronize "forever".
  resolved.synchronization_timeout = 0;

  return resolved;
};

ResolverIntercept.prototype.contracts = function() {
  var self = this;
  return Object.keys(this.cache).map(function(key) {
    return self.cache[key];
  });
};

module.exports = ResolverIntercept;

const path = require("path");

function ResolverIntercept(resolver) {
  this.resolver = resolver;
  this.cache = {};
};

ResolverIntercept.prototype.require = function(import_path) {
  // Modify import_path so the cache key is consistently the same irrespective
  // of whether a user explicated .sol extension
  import_path = import_path.replace(/\.sol$/i, '');

  // TODO: Using the import path for relative files may result in multiple
  // paths for the same file. This could return different objects since it won't be a cache hit.
  if (this.cache[import_path]) {
    return this.cache[import_path];
  }

  // Note, will error if nothing is found.
  var resolved = this.resolver.require(import_path);

  this.cache[import_path] = resolved;

  // During migrations, we could be on a network that takes a long time to accept
  // transactions (i.e., contract deployment close to block size). Because successful
  // migration is more important than wait time in those cases, we'll synchronize "forever".
  resolved.synchronization_timeout = 0;

  return resolved;
};

ResolverIntercept.prototype.contracts = function() {
  var self = this;
  return Object.keys(this.cache).map(function(key) {
    return self.cache[key];
  });
};

module.exports = ResolverIntercept;

Fix ResolverIntercept to maintain full import path while still normalizing the path; fixes npm support in truffle since bug >4.1.3


// @flow
export opaque type WideBar = "W"
export const WIDE_BAR: WideBar = "W"

export opaque type NarrowBar = "N"
export const NARROW_BAR: NarrowBar = "N"

export opaque type WideSpace = "w"
export const WIDE_SPACE: WideSpace = "w"

export opaque type NarrowSpace = "n"
export const NARROW_SPACE: NarrowSpace = "n"

export opaque type DiscreteSymbologySymbol = WideBar | NarrowBar | WideSpace | WideBar
export opaque type SymbologySymbol = DiscreteSymbologySymbol

Add union type for symbols of all symbologies


var fs = require('fs')
var mkdirp = require('mkdirp')

module.exports = function () {
  fill(4, 10, 2, __dirname + '/target')
}

if (module === require.main) {
  require('tap').pass('yes')
  return
}

function fill (depth, files, folders, target) {
  mkdirp.sync(target)
  var o = { flag: 'wx' }
  for (var f = files; f > 0; f--) {
    fs.writeFileSync(target + '/f-' + depth + '-' + f, '', o)
  }

  // valid symlink
  fs.symlinkSync('f-' + depth + '-1', target + '/link-' + depth + '-good', 'file')

  // invalid symlink
  fs.symlinkSync('does-not-exist', target + '/link-' + depth + '-bad', 'file')

  // file with a name that looks like a glob
  fs.writeFileSync(target + '/[a-z0-9].txt', '', o)

  depth--
  if (depth <= 0)
    return

  for (f = folders; f > 0; f--) {
    mkdirp.sync(target + '/folder-' + depth + '-' + f)
    fill(depth, files, folders, target + '/d-' + depth + '-' + f)
  }
}

var fs = require('fs')
var mkdirp = require('mkdirp')

module.exports = function () {
  fill(4, 10, 2, __dirname + '/target')
}

if (module === require.main) {
  require('tap').pass('yes')
  return
}

function fill (depth, files, folders, target) {
  mkdirp.sync(target)
  var o = { flag: 'wx' }
  if (process.version.match(/^v0\.8/))
    o = 'utf8'

  for (var f = files; f > 0; f--) {
    fs.writeFileSync(target + '/f-' + depth + '-' + f, '', o)
  }

  // valid symlink
  fs.symlinkSync('f-' + depth + '-1', target + '/link-' + depth + '-good', 'file')

  // invalid symlink
  fs.symlinkSync('does-not-exist', target + '/link-' + depth + '-bad', 'file')

  // file with a name that looks like a glob
  fs.writeFileSync(target + '/[a-z0-9].txt', '', o)

  depth--
  if (depth <= 0)
    return

  for (f = folders; f > 0; f--) {
    mkdirp.sync(target + '/folder-' + depth + '-' + f)
    fill(depth, files, folders, target + '/d-' + depth + '-' + f)
  }
}

Make tests pass on v0.8


/*jshint node:true*/
module.exports = {
  "framework": "qunit",
  "test_page": "tests/index.html?hidepassed",
  "disable_watching": true,
  "launch_in_ci": [
    "PhantomJS"
  ],
  "launch_in_dev": [
    "PhantomJS",
    "Chrome"
  ]
};

/*jshint node:true*/
module.exports = {
  "framework": "qunit",
  "test_page": "tests/index.html?hidepassed",
  "disable_watching": true,
  "launch_in_ci": [
    "Chrome"
  ],
  "launch_in_dev": [
    "PhantomJS",
    "Chrome"
  ]
};

Use Chrome for CI testing


// Licensed under the Apache License, Version 2.0 (the “License”); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import each from 'jest-each'
import { NORMAL as NORMAL_COMPONENT_THEME } from 'AwesomeComponentTheme'
import { NORMAL as NORMAL_THEME } from 'AwesomeTheme'
import { resolveFlair } from '..'
import { TEST_DATA } from 'data'

const RESOLVED_THEME = {
  componentTheme: NORMAL_COMPONENT_THEME,
  identifier: undefined,
  source: 'test-data',
  theme: NORMAL_THEME
}

describe('Function “resolveFlair”', () => {
  each(TEST_DATA)
    .test('using the pattern “%s”', (pattern, expectedFlair, expectedPresenter) => {
      const RESOLVED_FLAIR = resolveFlair(RESOLVED_THEME, pattern)
      expect(RESOLVED_FLAIR.flair).toBe(expectedFlair)
      expect(RESOLVED_FLAIR.presenter).toBe(expectedPresenter)
    })
})

// Licensed under the Apache License, Version 2.0 (the “License”); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import each from 'jest-each'
import resolveFlair from '../resolveFlair'
import { NORMAL as NORMAL_COMPONENT_THEME } from 'AwesomeComponentTheme'
import { NORMAL as NORMAL_THEME } from 'AwesomeTheme'
import { TEST_DATA } from 'data'

const RESOLVED_THEME = {
  componentTheme: NORMAL_COMPONENT_THEME,
  identifier: undefined,
  source: 'test-data',
  theme: NORMAL_THEME
}

describe.skip('Function “resolveFlair”', () => {
  each(TEST_DATA)
    .test('using the pattern “%s”', (pattern, expectedFlair, expectedPresenter) => {
      const RESOLVED_FLAIR = resolveFlair(RESOLVED_THEME, pattern)
      expect(RESOLVED_FLAIR.flair).toBe(expectedFlair)
      expect(RESOLVED_FLAIR.presenter).toBe(expectedPresenter)
    })
})

Change import and disable flair tests temporarily


/* global requirejs, require */
/**
 * app.js
 *
 * Distributed under terms of the MIT license.
 */

requirejs.config({
    paths: {
        "Vue": "https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue",
        "vue": ["require-vuejs", "https://rawgit.com/edgardleal/require-vuejs/master/dist/require-vuejs"],
        "alias": "using_alias"
    },
    shim: {
        "Vue": {"exports": "Vue"}
    }
});

require(["Vue", "vue!component", "vue!component.html", "vue!alias"], function(Vue){
    new Vue({
        el: "#app"
    });
});

/* global requirejs, require */
/**
 * app.js
 *
 * Distributed under terms of the MIT license.
 */

requirejs.config({
    paths: {
        "Vue": "https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue",
        "vue": ["require-vuejs", "https://rawgit.com/edgardleal/require-vuejs/master/dist/require-vuejs"],
        "alias": "using_alias"
    },
    shim: {
        "Vue": {"exports": "Vue"}
    }
});

require(["Vue", "vue!component", "vue!component.html", "vue!alias"], function(Vue){
    new Vue({
        el: "#app"
    });
});

Update Vuejs version on examples to 2.3.4


import './style.css!';
import 'bootstrap/css/bootstrap.css!';
import angular from 'angular';

import ShadertoyService from './shadertoy/service';

import ExportDirective from './export/directive';
import ExportingDirective from './exporting/directive';
import ExportErrorsDirective from './export-errors/directive';
import GoToURLDirective from './go-to-url/directive';
import PanelDirective from './panel/directive';
import ShadertoyDirective from './shadertoy/directive';

angular
	.module('app', [])
	.factory('shadertoy', ShadertoyService)
	.directive('export', ExportDirective)
	.directive('exporting', ExportingDirective)
	.directive('exportErrors', ExportErrorsDirective)
	.directive('goToUrl', GoToURLDirective)
	.directive('panel', PanelDirective)
	.directive('shadertoy', ShadertoyDirective)
;

import './style.css!';
import 'bootstrap/css/bootstrap.css!';
import angular from 'angular';

import ShadertoyService from './shadertoy/service';

import ExportDirective from './export/directive';
import ExportingDirective from './exporting/directive';
import ExportErrorsDirective from './export-errors/directive';
import GoToURLDirective from './go-to-url/directive';
import PanelDirective from './panel/directive';
import ShadertoyDirective from './shadertoy/directive';

angular
	.module('app', [])
	.factory('shadertoy', ShadertoyService)
	.directive('export', ExportDirective)
	.directive('exporting', ExportingDirective)
	.directive('exportErrors', ExportErrorsDirective)
	.directive('goToUrl', GoToURLDirective)
	.directive('panel', PanelDirective)
	.directive('shadertoy', ShadertoyDirective)
	.run(['$document', 'shadertoy', ($document, shadertoy) => {
		$document.bind('keydown', (event) => {
			if (event.which === 27) { // escape
				shadertoy.stop();
				event.preventDefault();
			}
		});
	}])
;

Add escape to stop export


import React from 'react'
import { Link } from 'react-router'
import Loader from 'react-loaders'

import { focusTodo, deleteTodo } from '../actions';

export default class TodoListItem extends React.Component {

  render() {
    const { todo, dispatch } = this.props;

    return (

        <input className="toggle" type="checkbox" />
         {dispatch(focusTodo(todo))}}>{todo.title}
        <button className="destroy" onClick={() => {dispatch(deleteTodo({id: todo.id}))}} />

    );
  }
}

import React from 'react'
import { Link } from 'react-router'
import Loader from 'react-loaders'

import { updateTodo, deleteTodo, focusTodo } from '../actions';

export default class TodoListItem extends React.Component {
  _onMarkChange() {
    const { todo, dispatch } = this.props;
    dispatch(updateTodo({
      id: todo.id,
      data: Object.assign({}, todo, {marked: !todo.marked ? 1 : 0}),
      resolve: null,
      reject: () => { alert('update failed!'); }
    }));
  }

  render() {
    const { todo, dispatch } = this.props;
    return (

        <input className="toggle" type="checkbox" checked={todo.marked}
          onChange={this._onMarkChange.bind(this)} />
         {dispatch(focusTodo(todo))}}>{todo.title}
        <button className="destroy" onClick={() => {dispatch(deleteTodo({id: todo.id}))}} />

    );
  }
}

Implement mark update for todos


var model = require('../models/index');

/* Sets a like in the Like table for a given artist and user (by Facebook ID number) */
exports.likeArtist = function(req, res) {
  return res.status(200).send('Success');
}

/* Retrieves the artist recommendations for the user */
exports.getArtistRecommendations = function(req, res) {
  return res.status(200).send('Success');
}

var model = require('../models/index');

/* Sets a like in the Like table for a given artist and user (by Facebook ID number) */
exports.likeArtist = function(req, res) {
  if (!req.user) return res.status(400).send('Not logged in');

  var facebookId = req.params.id;
  model.Artist.find({ where: { facebookId: facebookId } })
  .then(function(result) {
    if (result === null) {
      return res.status(400).send('No artist found');
    }
    else {
      model.Like.findOrCreate({ where: { user: req.user.id, artist: result.values.id } })
      .spread(function(user, created) {
        return res.status(200).send(user.values);
      })
      .catch(function(err) {
        return res.status(400).send(err);
      });
    }
  })
  .catch(function(err) {
    return res.status(400).send(err);
  });
}

/* Retrieves the artist recommendations for the user */
exports.getArtistRecommendations = function(req, res) {
  return res.status(200).send('Success');
}

Implement the API call to like artists in database


var MarkupLine = {
    HandlesType: function(type) {
        return type == 'line';
    },

    Paint: function(elementObject) {
        $('#' + elementObject.Handle).css({
            left: SizeCalculator.ToPixels(elementObject.x) + 'px',
            top: SizeCalculator.ToPixels(elementObject.y) + 'px',
            width: SizeCalculator.ToPixels(elementObject.width) + 'px',
            heigth: SizeCalculator.ToPixels(elementObject.heigth) + 'px',
            backgroundColor: elementObject.color
        });
    },

    Activate: function(elementObject) {

    },

    Update: function(elementObject) {
        this.Paint(elementObject);
    },

    New: function(markup) {
       markup.AddElement({
           type: "line",
           x: 10,
           y: 10,
           width: 190,
           height: 1,
           color: '#00000',
           properties: {
               x: {
                   label: 'Left (mm)',
                   component: 'number'
               },
               y: {
                   label: 'Top (mm)',
                   component: 'number'
               },
               width: {
                   label: 'Width (mm)',
                   component: 'number'
               },
               height: {
                   label: 'Height (mm)',
                   component: 'number'
               },
               color: {
                   label: 'Color',
                   component: 'select',
                   items: {
                       'Black': '#00000',
                       'Silver': '#C0C0C0',
                   }
               }
           }
       });
    }
};

var MarkupLine = {
    HandlesType: function(type) {
        return type == 'line';
    },

    Paint: function(elementObject) {
        $('#' + elementObject.Handle).css({
            left: SizeCalculator.ToPixels(elementObject.x) + 'px',
            top: SizeCalculator.ToPixels(elementObject.y) + 'px',
            width: SizeCalculator.ToPixels(elementObject.width) + 'px',
            height: SizeCalculator.ToPixels(elementObject.height) + 'px',
            backgroundColor: elementObject.color
        });
    },

    Activate: function(elementObject) {

    },

    Update: function(elementObject) {
        this.Paint(elementObject);
    },

    New: function(markup) {
       markup.AddElement({
           type: "line",
           x: 10,
           y: 10,
           width: 190,
           height: 1,
           color: '#00000',
           properties: {
               x: {
                   label: 'Left (mm)',
                   component: 'number'
               },
               y: {
                   label: 'Top (mm)',
                   component: 'number'
               },
               width: {
                   label: 'Width (mm)',
                   component: 'number'
               },
               color: {
                   label: 'Color',
                   component: 'select',
                   items: {
                       'Black': '#00000',
                       'Silver': '#C0C0C0',
                   }
               }
           }
       });
    }
};

Disable changing a line's height


/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import PropTypes from 'prop-types';
import React from 'react';
import { StyleSheet, VirtualizedList, VirtualizedListPropTypes } from 'react-native';

const DataTable = React.memo(({ renderRow, ...otherProps }) => (
  <VirtualizedList style={defaultStyles.virtualizedList} renderItem={renderRow} {...otherProps} />
));

DataTable.propTypes = {
  ...VirtualizedListPropTypes,
  renderRow: PropTypes.func.isRequired,
  getItem: PropTypes.func,
  getItemCount: PropTypes.func,
};

DataTable.defaultProps = {
  getItem: (items, index) => items[index],
  getItemCount: items => items.length,
};

const defaultStyles = StyleSheet.create({
  virtualizedList: {
    flex: 1,
  },
});

export default DataTable;

/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import PropTypes from 'prop-types';
import React from 'react';
import { StyleSheet, VirtualizedList, VirtualizedListPropTypes } from 'react-native';

const DataTable = React.memo(({ renderRow, renderHeader, ...otherProps }) => (
  <>
    {renderHeader()}
    <VirtualizedList style={defaultStyles.virtualizedList} renderItem={renderRow} {...otherProps} />
  </>
));

DataTable.propTypes = {
  ...VirtualizedListPropTypes,
  renderRow: PropTypes.func.isRequired,
  renderHeader: PropTypes.func,
  getItem: PropTypes.func,
  getItemCount: PropTypes.func,
};

DataTable.defaultProps = {
  getItem: (items, index) => items[index],
  getItemCount: items => items.length,
  renderHeader: null,
};

const defaultStyles = StyleSheet.create({
  virtualizedList: {
    flex: 1,
  },
});

export default DataTable;

Add header to data table


const i18n = require('i18next')
const _ = require('underscore')
const path = require('path')

module.exports = {
  setup(options = {}) {
    const subdomainLang = options.subdomainLang || {}
    const availableLngs = _.pluck(_.values(subdomainLang), 'lngCode')
    i18n.init({
      resGetPath: path.resolve(__dirname, '../../', 'locales/__lng__.json'),
      saveMissing: true,
      resSetPath: path.resolve(
        __dirname,
        '../../',
        'locales/missing-__lng__.json'
      ),
      sendMissingTo: 'fallback',
      fallbackLng: options.defaultLng || 'en',
      detectLngFromHeaders: true,
      useCookie: false,
      preload: availableLngs,
      supportedLngs: availableLngs
    })
    const setLangBasedOnDomainMiddlewear = function(req, res, next) {
      const { host } = req.headers
      if (host == null) {
        return next()
      }
      const parts = host.split(/[.-]/)
      const subdomain = parts[0]

      const lang = subdomainLang[subdomainLang]
        ? subdomainLang[subdomain].lngCode
        : null

      if (req.originalUrl.indexOf('setLng') === -1 && lang != null) {
        req.i18n.setLng(lang)
      }
      if (req.language !== req.lng) {
        req.showUserOtherLng = req.language
      }
      next()
    }

    return {
      expressMiddlewear: i18n.handle,
      setLangBasedOnDomainMiddlewear,
      i18n
    }
  }
}

const i18n = require('i18next')
const _ = require('underscore')
const path = require('path')

module.exports = {
  setup(options = {}) {
    const subdomainLang = options.subdomainLang || {}
    const availableLngs = _.pluck(_.values(subdomainLang), 'lngCode')

    i18n.init({
      resGetPath: path.resolve(__dirname, '../../', 'locales/__lng__.json'),
      saveMissing: true,
      resSetPath: path.resolve(
        __dirname,
        '../../',
        'locales/missing-__lng__.json'
      ),
      sendMissingTo: 'fallback',
      fallbackLng: options.defaultLng || 'en',
      detectLngFromHeaders: true,
      useCookie: false,
      preload: availableLngs,
      supportedLngs: availableLngs
    })

    const setLangBasedOnDomainMiddlewear = function(req, res, next) {
      // Determine language from subdomain
      const { host } = req.headers
      if (host == null) {
        return next()
      }
      const [subdomain] = host.split(/[.-]/)
      const lang = subdomainLang[subdomain]
        ? subdomainLang[subdomain].lngCode
        : null

      // Unless setLng query param is set, use subdomain lang
      if (!req.originalUrl.includes('setLng') && lang != null) {
        req.i18n.setLng(lang)
      }

      if (req.language !== req.lng) {
        req.showUserOtherLng = req.language
      }

      next()
    }

    return {
      expressMiddlewear: i18n.handle,
      setLangBasedOnDomainMiddlewear,
      i18n
    }
  }
}

Clean up & comment language determination


var imageStore = new FS.Store.GridFS('images')

Images = new FS.Collection('images', {
  stores: [imageStore]
});

Images.allow({
  'insert' : function(){
    return true;
  },
  'update' : function(){
    return true;
  }
});

Allow permissions for Images collection.


//$(document).ready(function(){
var ready = function(){
    $("#what").on('click', function(e){
        e.preventDefault();
        $('html, body').stop().animate({
            scrollTop: $(".block-2").offset().top
        }, 1000);
    });
    $("#how").on('click', function(e){
        e.preventDefault();
        $('html, body').stop().animate({
            scrollTop: $(".block-3").offset().top
        }, 1000);
    });
    $("#signup").on('click', function(e){
        e.preventDefault();
        $('html, body').stop().animate({
            scrollTop: $(".block-4").offset().top
        }, 1000);
    });
    $(window).scroll(function(){
        var docScroll = $(window).scrollTop(),
            almostBottom = $(".block-4").offset().top - 100;

        if(docScroll >= almostBottom) {
            $(".back-to-top").fadeIn(200);
        } else {
            $(".back-to-top").fadeOut(200);
        }
    });
    $(".back-to-top").on('click', function(e){
        e.preventDefault();
        $('html, body').stop().animate({
            scrollTop: 0
        }, 1000);
    });
};

// http://stackoverflow.com/questions/17600093/rails-javascript-not-loading-after-clicking-through-link-to-helper#17600195
$(document).ready(ready);
$(document).on('turbolinks:load', ready);

//$(document).ready(function(){
var ready = function(){
    $("#what").on('click', function(e){
        e.preventDefault();
        $('html, body').stop().animate({
            scrollTop: $(".block-2").offset().top
        }, 1000);
    });
    $("#how").on('click', function(e){
        e.preventDefault();
        $('html, body').stop().animate({
            scrollTop: $(".block-3").offset().top
        }, 1000);
    });
    $("#signup").on('click', function(e){
        e.preventDefault();
        $('html, body').stop().animate({
            scrollTop: $(".block-4").offset().top
        }, 1000);
    });
    $(window).scroll(function(){
        var docScroll = $(window).scrollTop(),
            almostBottom = $(".block-4").offset().top - 100;

        if(docScroll >= almostBottom) {
            $(".back-to-top").fadeIn(200);
        } else {
            $(".back-to-top").fadeOut(200);
        }
    });
    $(".back-to-top").on('click', function(e){
        e.preventDefault();
        $('html, body').stop().animate({
            scrollTop: 0
        }, 1000);
    });
};

$(document).ready(ready);
$(document).on('turbolinks:load', ready);

Revert "added link to error fix"


(function() {
	'use strict';
	angular.module('pagespeedApp').factory('pagespeedApi', pagespeedApi);

	pagespeedApi.$inject = ['$http'];

	function pagespeedApi($http) {
		var endpoint = 'https://www.googleapis.com/pagespeedonline/v2/runPagespeed';
		var options = {
			key: ''
		};
		var cache = {};

		var service = {
			cache: cache,
			endpoint: endpoint,
			options: options,
			get: get,
			run: run
		};

		return service;

		function get(url) {
			var host = new URL(url).host;
			return service.cache[host] ? Promise.resolve(service.cache[host]) : service.run(url);
		}

		function run(url, mobile, screenshot) {
			var params = {
				url: url,
				key: service.options.key
			};

			return $http.get(service.endpoint, {
				params: params
			}).then(cacheResponse(url));
		}

		function cacheResponse(url) {
			return function(data) {
				console.log(data);
				var requestHost = new URL(url).host;
				var resolveHost = new URL(data.data.id).host;

				service.cache[resolveHost] = data;

				if (requestHost != resolveHost) {
					service.cache[requestHost] = data;
				}

				return data;
			};
		}
	}
})();

(function() {
	'use strict';
	angular.module('pagespeedApp').factory('pagespeedApi', pagespeedApi);

	pagespeedApi.$inject = ['$http'];

	function pagespeedApi($http) {
		var endpoint = 'https://www.googleapis.com/pagespeedonline/v2/runPagespeed';
		var options = {
			key: ''
		};
		var cache = {};

		var service = {
			cache: cache,
			endpoint: endpoint,
			options: options,
			get: get,
			run: run
		};

		return service;

		function get(url) {
			var host = new URL(url).host;
			return service.cache[host] ? Promise.resolve(service.cache[host]) : service.run(url);
		}

		function run(url) {
			var params = {
				url: url,
				key: service.options.key
			};

			return $http.get(service.endpoint, {
				params: params
			}).then(cacheResponse(url));
		}

		function cacheResponse(url) {
			return function(data) {
				var requestHost = new URL(url).host;
				var resolveHost = new URL(data.data.id).host;

				service.cache[resolveHost] = data;

				if (requestHost != resolveHost) {
					service.cache[requestHost] = data;
				}

				return data;
			};
		}
	}
})();

Remove mobile option due to gold plating


'use babel';

import Controller from './controller.js';

export default {
  config: {
    grammars: {
      type   : 'array',
      default: ['source.gfm'],
      items  : {
        type: 'string'
      }
    },
    minimumContentWidth: {
      type   : 'integer',
      default: 3,
      minimum: 3
    },
    useEastAsianWidth: {
      type   : 'boolean',
      default: false
    }
  },

  controler: null,

  activate() {
    this.controller = new Controller();
  },

  deactivate() {
    this.controller.destroy();
  },

  serialize() {
  }
};

'use babel';

import Controller from './controller.js';

export default {
  config: {
    grammars: {
      type   : 'array',
      default: ['source.gfm'],
      items  : {
        type: 'string'
      }
    },
    minimumContentWidth: {
      type   : 'integer',
      default: 3,
      minimum: 3
    },
    useEastAsianWidth: {
      type       : 'boolean',
      default    : false,
      description: 'Compute character width'
        + ' based on the Unicode East Asian Width specification'
    }
  },

  controler: null,

  activate() {
    this.controller = new Controller();
  },

  deactivate() {
    this.controller.destroy();
  },

  serialize() {
  }
};

Add description for useEastAsianWidth option


/**
 * Created by thram on 16/01/17.
 */

import {getState, setState, resetState} from "./store";

let dicts = {}, middlewares = [];

export const register = (key, dict) => dicts[key] = dict;

export const addMiddleware = (middleware) => middlewares.push(middleware);

export const dispatch = (keyType, data) => {
  const [key, type]  = keyType.split(':'),
        dict         = dicts[key],
        action       = dict && dict[type];
  if (action) {
    const value     = action.map(data),
          nextValue = action.reducer(value);
    middlewares.forEach((middleware) => middleware({prev: getState(key), payload: value, next: nextValue}));
    setState(key, action.reducer(action.map(data)));
  }
};

export const state = getState;

export const clearState = resetState;

export const createDict = (map, reducer) => ({map, reducer});

/**
 * Created by thram on 16/01/17.
 */

import {getState, setState, resetState} from "./store";

let dicts = {}, middlewares = [];

export const register = (key, dict) => dicts[key] = dict;

export const addMiddleware = (middleware) => middlewares.push(middleware);

export const dispatch = (keyType, data) => {
  const [key, type]  = keyType.split(':'),
        dict         = dicts[key],
        action       = dict && dict[type];
  if (action) {
    const value     = action.map(data),
          nextValue = action.reducer(value);
    middlewares.forEach((middleware) => middleware({
      state  : key,
      action : type,
      prev   : getState(key),
      payload: value,
      next   : nextValue
    }));
    setState(key, action.reducer(action.map(data)));
  }
};

export const state = getState;

export const clearState = resetState;

export const createDict = (map, reducer) => ({map, reducer});

Add state name and action name to the middleware object


/**
 * @fileoverview Run the bootstrap service
 */

var port = 3020,
    system = require('system'),
    page = require('webpage').create(),
    serverObj = require('./server').create(port),
    util = require('./util'),
    module = system.args[1],
    config = system.args[2];

if (!module) {
    console.error('missing module');
    serverObj.close();
    phantom.exit(1);
}

if (!config) {
    console.error('missing config');
    serverObj.close();
    phantom.exit(1);
}

config = decodeURIComponent(config);
var url = 'http://localhost:' + port + '/' + module + '.html?config=' + config;
console.log('<!-- html generated by Livefyre -->');
page.open(url, function(status) {
    if (status !== 'success') {
        console.error('Page could not be opened');
        serverObj.close();
        phantom.exit(1);
    }

    // TODO(rrp): Generalize this bit
    // Wait for fyre-comment-stream el? (need to ensure 100% loaded somehow)
    util.waitFor(function() {
        return page.evaluate(function() {
            return document.getElementsByClassName('fyre-comment-stream').length > 0;
        });
    }, function() {
        var html = page.evaluate(function() {
            return document.getElementById('bs').innerHTML;
        });
        console.log(html);
        serverObj.close();
        phantom.exit();
    });
});

/**
 * @fileoverview Run the bootstrap service
 */

var port = 3020,
    system = require('system'),
    page = require('webpage').create(),
    serverObj = require('./server').create(port),
    util = require('./util'),
    module = system.args[1],
    config = system.args[2];

if (!module) {
    console.error('missing module');
    serverObj.close();
    phantom.exit(1);
}

if (!config) {
    console.error('missing config');
    serverObj.close();
    phantom.exit(1);
}

config = decodeURIComponent(config);
var url = 'http://localhost:' + port + '/' + module + '.html?config=' + config;
console.log('<!-- html generated by Livefyre -->');
page.open(url, function(status) {
    if (status !== 'success') {
        console.error('Page could not be opened');
        serverObj.close();
        phantom.exit(1);
    }

    // TODO(rrp): Generalize this bit
    // Wait for fyre-comment-stream el? (need to ensure 100% loaded somehow)
    util.waitFor(function() {
        return page.evaluate(function() {
            return document.getElementsByClassName('fyre-comment-stream').length > 0;
        });
    }, function() {
        var html = page.evaluate(function() {
            return document.getElementById('bs').innerHTML;
        });
        console.log(html);
        serverObj.close();
        phantom.exit();
    }, 30000);
});

Use 30s timeout in waitfor function in case things happen slower than they should


bookcrossing.handler = function(event, context, callback) {
	console.log("Batatas");
}

exports.handler = function(event, context, callback) {
	console.log("Batatas");
}

Fix the header of function for AWS Lambda.


// @flow

import mixin from "merge-descriptors";
import EventEmitter from "events";
import SpiderQueue from "./queue/promise";
import SpiderRouter from "./routing/router";
import SpiderRequest from "./routing/request";
import SpiderResponse from "./routing/response";

/**
 * @param  {string}     base
 * @param  {Object}     options
 * @return {Object}
 */
function createCrawler(base: string, options: Object = {}): Object {
  if (typeof base !== "string") {
    throw new Error(`Base must be a string, not ${typeof base}`);
  }

  const config: Object = {
    interval: 250,
    concurrency: 10,
    ...options
  };

  const crawler: Object = {
    base: base,
    opts: config,
    req: SpiderRequest,
    res: SpiderResponse
  };

  // Glues all the components together:
  mixin(crawler, SpiderQueue, false);
  mixin(crawler, SpiderRouter, false);
  mixin(crawler, EventEmitter.prototype, false);

  return crawler;
}

module.exports = createCrawler;
module.exports.request = SpiderRequest;
module.exports.response = SpiderResponse;

// @flow

import mixin from "merge-descriptors";
import EventEmitter from "events";
import SpiderQueue from "./queue/promise";
import SpiderRouter from "./routing/router";
import SpiderRequest from "./routing/request";
import SpiderResponse from "./routing/response";

/**
 * @param  {string}     base
 * @param  {Object}     options
 * @return {Object}
 */
function createCrawler(base: string, options: Object = {}): Object {
  if (typeof base !== "string") {
    throw new Error(`Base must be a string, not ${typeof base}`);
  }

  const config: Object = {
    interval: 250,
    concurrent: 10,
    ...options
  };

  const crawler: Object = {
    base: base,
    opts: config,
    req: SpiderRequest,
    res: SpiderResponse
  };

  // Glues all the components together:
  mixin(crawler, SpiderQueue, false);
  mixin(crawler, SpiderRouter, false);
  mixin(crawler, EventEmitter.prototype, false);

  return crawler;
}

module.exports = createCrawler;
module.exports.request = SpiderRequest;
module.exports.response = SpiderResponse;

Update default options to match new queue-promise API


require("./stylesheets/main.less");

var settings = require("./settings");
var StatusBar = require("./bar");

var commands = codebox.require("core/commands");
var dialogs = codebox.require("utils/dialogs");

// Create the bar and add it to the body
var bar = new StatusBar();
bar.appendTo(codebox.app.$el);

commands.register({
    id: "view.statusbar.toggle",
    title: "View: Toggle Status Bar",
    shortcuts: [
        "mod+b", "mod+k"
    ],
    run: function() {
        settings.data.set("visible", !settings.data.get("visible"));
        codebox.settings.save();
    }
});

// Exports statusbar
codebox.statusbar = bar;

require("./stylesheets/main.less");

var settings = require("./settings");
var StatusBar = require("./bar");

var commands = codebox.require("core/commands");
var dialogs = codebox.require("utils/dialogs");

// Create the bar and add it to the body
var bar = new StatusBar();
bar.appendTo(codebox.app.$el);

commands.register({
    id: "view.statusbar.toggle",
    title: "View: Toggle Status Bar",
    shortcuts: [
        "mod+b", "mod+k"
    ],
    run: function() {
        settings.data.set("visible", !settings.data.get("visible"));
        codebox.settings.save();
    }
});

// Add to View menu
if (codebox.menubar) {
    codebox.menubar.createMenu("view", {
        caption: "Toggle Status Bar",
        command: "view.statusbar.toggle"
    });
}

// Exports statusbar
codebox.statusbar = bar;

Add command to toggle statusbar in view menu


import React from 'react'
import ReactDOM from 'react-dom'
import 'normalize.css'

import {Analytics} from './lib/analytics'
import {Header} from './header'
import {Drone} from './lib/drone'
import webfont from './lib/webfont'
import styles from './styles'

(() => {
  webfont({
    families: ['Cinzel Decorative:400'],
    text: 'Langri-Sha'
  })

  const container = document.createElement('div')
  container.className = styles.container
  document.body.appendChild(container)

  ReactDOM.render((
    <div>
      <Header />
      <Analytics id={'UA-86127521-1'} />
      <Drone />
    </div>
  ), container)
})()

import React from 'react'
import ReactDOM from 'react-dom'
import 'normalize.css'

import {Analytics} from './lib/analytics'
import {Header} from './header'
import {Drone} from './lib/drone'
import webfont from './lib/webfont'
import styles from './styles'

(() => {
  webfont({
    families: ['Cinzel Decorative:400'],
    text: 'Langri-Sha'
  })

  const container = document.createElement('div')
  container.className = styles.container
  document.body.appendChild(container)

  try {
    ReactDOM.render((
      <div>
        <Header />
        <Analytics id={'UA-86127521-1'} />
        <Drone />
      </div>
    ), container)
  } catch (err) {
    ga('send', 'exception', {
      exDescription: err.message,
      exFatal: false
    })
  }
})()

Add exception tracking for initial render


'use strict';

const redis   = require('./lib/redis');
const jenkins = require('./lib/jenkins');
const gitter  = require('./lib/gitter');
const schedule = require('node-schedule');

const pkg = require('./package.json');
console.log(`Staring ${pkg.name} v${pkg.version}`);

schedule.scheduleJob(process.env.CRON_INTERVAL, function() {
  console.log('Running Cron Job...');

  console.log('Fetching Jenkins nodes...');
  jenkins.getComputers(function(err, nodes) {
    if (err) { throw err; }
    console.log(`Found ${nodes.length} Jenkins nodes.`);

    console.log('Checking changed Jenkins nodes...');
    redis.jenkinsChanged(nodes, function(err, changed) {
      if (err) { throw err; }
      console.log(`${changed.length} node(s) changed.`);

      console.log('Posting to Gitter...');
      gitter.post(changed, function(err) {
        if (err) { throw err; }
        console.log('Gitter: Ok!');
      });
    });
  });
});

'use strict';

const schedule = require('node-schedule');

const jenkins = require('./lib/jenkins');
const redis   = require('./lib/redis');

const gitter  = require('./lib/gitter');
const sendgrid = require('./lib/sendgrid');

const pkg = require('./package.json');
console.log(`Staring ${pkg.name} v${pkg.version}`);

schedule.scheduleJob(process.env.CRON_INTERVAL, function() {
  console.log('Running Cron Job...');

  console.log('Fetching Jenkins nodes...');
  jenkins.getComputers(function(err, nodes) {
    if (err) { throw err; }
    console.log(`Found ${nodes.length} Jenkins nodes.`);

    console.log('Checking changed Jenkins nodes...');
    redis.jenkinsChanged(nodes, function(err, changed) {
      if (err) { throw err; }

      console.log(`${changed.length} node(s) changed.`);

      if (changed.length > 0) {
        console.log('Posting to Gitter...');
        gitter.post(changed, function(err) {
          if (err) { throw err; }
          console.log('Gitter: Ok!');
        });

        console.log('Notifying via Sendgrid...');
        sendgrid.notify(changed, function(err) {
          if (err) { throw err; }
          console.log('Sendgrid: Ok!');
        });
      }
    });
  });
});

Send email notification of important changes


'use strict';
const {URL} = require('url');
const got = require('got');
const registryUrl = require('registry-url');

const npmEmail = async username => {
	if (typeof username !== 'string') {
		throw new TypeError('Username required');
	}

	const url = new URL(`${registryUrl()}-/user/org.couchdb.user:${username}`);

	try {
		const {body} = await got(url, {json: true});
		return body.email;
	} catch (error) {
		if (error && error.statusCode === 404) {
			throw new Error(`User ${username} doesn't exist`);
		}

		throw error;
	}
};

module.exports = npmEmail;
// TODO: Remove this for the next major release
module.exports.default = npmEmail;

'use strict';
const {URL} = require('url');
const got = require('got');
const getRegistryUrl = require('registry-url');

const npmEmail = async username => {
	if (typeof username !== 'string') {
		throw new TypeError('Username required');
	}

	let registryUrl = getRegistryUrl();

	// `npmjs.com` no longer supports the endpoint we need, so we use a mirror.
	if (registryUrl.trim().replace(/\/$/, '') === 'https://registry.npmjs.org') {
		registryUrl = 'https://r.cnpmjs.org/';
	}

	const url = new URL(`${registryUrl}-/user/org.couchdb.user:${username}`);

	try {
		const {body} = await got(url, {json: true});
		return body.email;
	} catch (error) {
		if (error && error.statusCode === 404) {
			throw new Error(`User ${username} doesn't exist`);
		}

		throw error;
	}
};

module.exports = npmEmail;
// TODO: Remove this for the next major release
module.exports.default = npmEmail;

Fix the package being broken from npm API changes


const createPolobxMixin = function(stores) {
  let appState = {};

  Object.keys(stores).forEach( key => {
    const store = mobx.observable(stores[key].store);
    const actions = stores[key].actions;

    appState[key] = {
      store,
      actions
    };
  });

  function dispatch({store, action, payload}) {
    if (appState[store] && appState[store].actions && appState[store].actions[action]) {
      const storeAction = appState[store].actions[action];

      mobx.action(storeAction.bind(appState[store], [payload]))();

      return appState[store];
    }

    console.warn(`No action "${action}" for "${store}" store`);
  };

  mobx.useStrict(true);

  return subclass => class extends subclass {

    constructor() {
      super();

      this._appState = appState;
      this.dispatch = dispatch;
    }

    connectedCallback() {
      super.connectedCallback();

      const properties = this.constructor.config.properties;

      if (properties) {
        for (let property in properties) {
          const statePath = properties[property].statePath;

          if (statePath && this._appState[statePath.store]) {
            mobx.autorun(() => {
              const store = this._appState[statePath.store].store;
              this[property] = store[statePath.path];
            });
          }
        }
      }

    }
  };
};

const createPolobxBehavior = function(stores) {
  let appState = {};

  Object.keys(stores).forEach( key => {
    const store = mobx.observable(stores[key].store);
    const actions = stores[key].actions;

    appState[key] = {
      store,
      actions
    };
  });

  function dispatch({store, action, payload}) {
    if (appState[store] && appState[store].actions && appState[store].actions[action]) {
      const storeAction = appState[store].actions[action];

      mobx.action(storeAction.bind(appState[store], [payload]))();

      return appState[store];
    }

    console.warn(`No action "${action}" for "${store}" store`);
  };

  mobx.useStrict(true);

  return {

    created() {
      this._appState = appState;
      this.dispatch = dispatch;
    }

    attached() {
      const properties = this.constructor.config.properties;

      if (properties) {
        for (let property in properties) {
          const statePath = properties[property].statePath;

          if (statePath && this._appState[statePath.store]) {
            mobx.autorun(() => {
              const store = this._appState[statePath.store].store;
              this[property] = store[statePath.path];
            });
          }
        }
      }

    }
  };
};

Use behavior instead mixin to Polymer 1.x compatibility


'use strict'

/**
 * Mixes reducers in order. The resulting reducer function will try all
 * available reducers until a new state is obtained, thus it is recommended
 * to keep the state object immutable.
 * @param {Array.<Function>} reducers functions that accept `state, action`
 * arguments and return new state.
 * @return {Function} a new reducer function
 */
function mixn (_reducers) {
  const reducers = Array.isArray(_reducers) ? _reducers : Array.from(arguments)

  if (reducers.length === 0) {
    throw new Error('The reducers array needs at least one function')
  }

  reducers.forEach(function (reducer) {
    if (typeof reducer !== 'function') {
      throw new TypeError('All reducers must be a function')
    }
  })

  function reduce (state, action) {
    let newState
    reducers.some(function (fn) {
      newState = fn(state, action)
      return newState !== state
    })
    return newState
  }

  return reduce
}

module.exports = mixn

'use strict'

/**
 * Mixes reducers in order. The resulting reducer function will try all
 * available reducers until a new state is obtained, thus it is recommended
 * to keep the state object immutable.
 * @param {Array.<Function>} reducers functions that accept `state, action`
 * arguments and return new state.
 * @return {Function} a new reducer function
 */
function mixn (_reducers) {
  const reducers = Array.isArray(_reducers) ? _reducers : Array.from(arguments)

  if (reducers.length === 0) {
    throw new Error('The reducers array needs at least one function')
  }

  reducers.forEach(function (reducer) {
    if (typeof reducer !== 'function') {
      throw new TypeError('All reducers must be a function')
    }
  })

  function reduce (state, action) {
    var newState
    reducers.some(function (fn) {
      newState = fn(state, action)
      return newState !== state
    })
    return newState
  }

  return reduce
}

module.exports = mixn

Use let instead of var for max compatibility


'use stirct'

var opbeat = require('opbeat').start()
var uuid = require('node-uuid')
var AWS = require('aws-sdk')
var Printer = require('ipp-printer')

var port = process.env.PORT || 3000

var s3 = new AWS.S3()
var printer = new Printer({ name: 'printbin', port: port, zeroconf: false })

printer.on('job', function (job) {
  var key = uuid.v4() + '.ps'

  console.log('processing job %d (key: %s)', job.id, key)

  job.on('end', function () {
    console.log('done reading job %d (key: %s)', job.id, key)
  })

  var params = {
    Bucket: 'watson-printbin',
    Key: key,
    Body: job
  }

  s3.upload(params, function (err, data) {
    if (err) return opbeat.captureError(err)
    console.log('done uploading job %d (key: %s)', job.id, key)
  })
})

'use stirct'

var opbeat = require('opbeat').start()
var uuid = require('node-uuid')
var AWS = require('aws-sdk')
var Printer = require('ipp-printer')

var port = process.env.PORT || 3000

var s3 = new AWS.S3()
var printer = new Printer({ name: 'printbin', port: port, zeroconf: false })

printer.on('job', function (job) {
  var key = uuid.v4() + '.ps'

  console.log('processing job %d (key: %s)', job.id, key)

  job.on('end', function () {
    console.log('done reading job %d (key: %s)', job.id, key)
  })

  var params = {
    Bucket: 'watson-printbin',
    ACL: 'public-read',
    ContentType: 'application/postscript',
    Key: key,
    Body: job
  }

  s3.upload(params, function (err, data) {
    if (err) return opbeat.captureError(err)
    console.log('done uploading job %d (key: %s)', job.id, key)
  })
})

Allow public download from S3


var net = require('net')
var once = require('once')

/**
 * Detect if the network is up (do we have connectivity?)
 * @return {boolean}
 */
module.exports = function (cb) {
  var socket = net.connect({
    port: 80,
    host: 'google.com'
  })

  // If no 'error' or 'connect' event after 5s, assume network is down
  var timer = setTimeout(function () {
    done(new Error('timeout'))
  }, 5000)

  var done = once(function (err) {
    clearTimeout(timer)
    socket.unref()
    socket.end()
    cb(!err)
  })

  socket.on('error', done)
  socket.on('connect', done)
}

var net = require('net')
var once = require('once')

/**
 * Detect if the network is up (do we have connectivity?)
 * @return {boolean}
 */
module.exports = function (cb) {
  var socket = net.connect({
    port: 80,
    host: 'example.com'
  })

  // If no 'error' or 'connect' event after 5s, assume network is down
  var timer = setTimeout(function () {
    done(new Error('timeout'))
  }, 5000)

  var done = once(function (err) {
    clearTimeout(timer)
    socket.unref()
    socket.end()
    cb(!err)
  })

  socket.on('error', done)
  socket.on('connect', done)
}

Use example.com instead of google.com


'use strict';

var through = require('through2');
var gutil = require('gulp-util');
var ejs = require('ejs');

module.exports = function (options, settings) {
    settings = settings || {};
    options = options || {};
    settings.ext = settings.ext || '.html';

    return through.obj(function (file, enc, cb) {
        if (file.isNull()) {
            this.push(file);
            return cb();
        }

        if (file.isStream()) {
            this.emit(
                'error',
                new gutil.PluginError('gulp-ejs', 'Streaming not supported')
            );
        }

        options.filename = options.filename || file.path;
        try {
            file.contents = new Buffer(ejs.render(file.contents.toString(), options));
            file.path = gutil.replaceExtension(file.path, settings.ext);
        } catch (err) {
            this.emit('error', new gutil.PluginError('gulp-ejs', err.toString()));
        }

        this.push(file);
        cb();
    });
};

'use strict';

var through = require('through2');
var gutil = require('gulp-util');
var ejs = require('ejs');

module.exports = function (options, settings) {
    settings = settings || {};
    options = options || {};
    settings.ext = typeof settings.ext === "undefined" ? ".html" : settings.ext;

    return through.obj(function (file, enc, cb) {
        if (file.isNull()) {
            this.push(file);
            return cb();
        }

        if (file.isStream()) {
            this.emit(
                'error',
                new gutil.PluginError('gulp-ejs', 'Streaming not supported')
            );
        }

        options.filename = options.filename || file.path;
        try {
            file.contents = new Buffer(ejs.render(file.contents.toString(), options));
            file.path = gutil.replaceExtension(file.path, settings.ext);
        } catch (err) {
            this.emit('error', new gutil.PluginError('gulp-ejs', err.toString()));
        }

        this.push(file);
        cb();
    });
};

Allow to set empty settings.ext with null value


/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-cli-chartist',

  included: function included(app) {
    this.app = app;
    this._super.included(app);

    app.import('vendor/chartist/chartist.js');
    app.import('vendor/chartist/chartist.min.css');
  }
};

/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-cli-chartist',

  included: function included(app) {
    this.app = app;
    this._super.included(app);

    app.import('vendor/chartist/chartist.js');
    app.import('vendor/chartist/chartist.css');
  }
};

Correct the name of the css file


/* jshint node: true */
'use strict';

module.exports = {
  name: '@upsilon/ember-range-slider',
  included: function(app) {
    if (!process.env.EMBER_CLI_FASTBOOT) {
      app.import('node_modules/' + 'hammerjs/hammer.js');
    }
  }
};

/* jshint node: true */
"use strict";

module.exports = {
  name: "@upsilon/ember-range-slider",

  included(app) {
    if (typeof FastBoot !== 'undefined') {
      app.import('node_modules/hammerjs/hammer.js');
    }
  },
};

Fix breaking changes in FastBoot