import when from 'when';

let
    openFiles = ['a.js', 'b.js', 'c.js'],
    saveFile = (file) => {
        console.log('saveFile', file);
        return new Promise((resolve, reject) => {
            setTimeout(
                () => {
                    console.log('timeout', file);
                    resolve(file);
                },
                2000
            );
        });
    };

let results = [];
openFiles.reduce(
    (promise, file) => {
        return promise
            .then(saveFile.bind(null, file))
            .then((result) => {
                results.push(result);
                return results;
            });
    },
    Promise.resolve()
)
    .then((...args) => {
        console.log('promise done', args);
    })
    .catch((error) => {
        console.log('promise error', error);
    });

when.reduce(openFiles, (results, file) => {
    return saveFile(file)
        .then((result) => {
                results.push(result);
                return results;
            });
}, [])
    .then((...args) => {
        console.log('when done', args);
    })
    .catch((error) => {
        console.log('when error', error);
    });

import when from 'when';

let
    openFiles = ['a.js', 'b.js', 'c.js'],
    saveFile = (file) => {
        console.log('saveFile', file);
        return new Promise((resolve, reject) => {
            setTimeout(
                () => {
                    console.log('timeout', file);
                    resolve(file);
                },
                2000
            );
        });
    };

openFiles.reduce(
    (promise, file) => promise.then((results) => {
        return saveFile(file)
            .then((result) => {
                results.push(result);
                return results;
            });
    }),
    Promise.resolve([])
)
    .then((...args) => {
        console.log('promise done', args);
    })
    .catch((error) => {
        console.log('promise error', error);
    });

when.reduce(openFiles, (results, file) => {
    return saveFile(file)
        .then((result) => {
                results.push(result);
                return results;
            });
}, [])
    .then((...args) => {
        console.log('when done', args);
    })
    .catch((error) => {
        console.log('when error', error);
    });

Update each series results to be embedded in the reduce


"use strict";

var db = require("./firebase");

// Ensure the updated timestamp is always accurate-ish
module.exports = function(ref) {
    ref.on("child_changed", function(snap) {
        var key = snap.key(),
            auth;

        // Avoid looping forever
        if(key === "updated_at" || key === "updated_by") {
            return;
        }

        auth = db.getAuth();

        // Clean up any old updated timestamps floating around
        ref.child("updated").remove();

        ref.child("updated_at").set(db.TIMESTAMP);
        ref.child("updated_by").set(auth.uid);
    });
};

"use strict";

var db = require("./firebase");

// Ensure the updated timestamp is always accurate-ish
module.exports = function(ref) {
    ref.on("child_changed", function(snap) {
        var key = snap.key(),
            auth;

        // Avoid looping forever
        if(key === "updated_at" || key === "updated_by") {
            return;
        }

        auth = db.getAuth();

        // Clean up any old updated timestamps floating around
        ref.child("updated").remove();

        ref.update({
            updated_at : db.TIMESTAMP,
            updated_by : auth.uid
        });
    });
};

Convert two .set() calls into one .update()


const eris = justcord.eris;
const config = justcord.config;
const chat = justcord.chat;

eris.on("ready", () => {
    console.log("Justcord ready!"); // TODO: Add logging utility functions
    eris.createMessage(config.eris.id, "Server connected to the guild successfully!")
});

eris.on("messageCreate", (message) => {
    if (message.channel.id == config.eris.id && message.member.id != eris.user.id) {
        chat.broadcast(`${message.member.nick}: ${message.content}`);
        console.log(`Discord: ${message.member.nick}: ${message.content}`);
    }
});

const eris = justcord.eris;
const config = justcord.config;
const chat = justcord.chat;

eris.on("ready", () => {
    console.log("Justcord ready!"); // TODO: Add logging utility functions
    eris.createMessage(config.eris.id, "Server connected to the guild successfully!")
});

eris.on("messageCreate", (message) => {
    if (message.channel.id == config.eris.id && message.member.id != eris.user.id) {
        let name = message.member.nick;
        if (!name) name = message.member.user.username;
        chat.broadcast(`${name}: ${message.content}`);
        console.log(`Discord: ${name}: ${message.content}`);
    }
});

Use username if nickname is null


'use strict';

var noop     = require('es5-ext/function/noop')
  , assign   = require('es5-ext/object/assign')
  , memoize  = require('memoizee')
  , ee       = require('event-emitter')
  , deferred = require('deferred')

  , isPromise = deferred.isPromise;

module.exports = function (fn/*, options*/) {
	var factory, memoized;
	if (fn.memoized) return fn;
	memoized = memoize(fn, assign(Object(arguments[1]), { refCounter: true }));
	factory = function () {
		var watcher, emitter, pipe, args, def;
		args = arguments;
		watcher = memoized.apply(this, arguments);
		if (isPromise(watcher)) {
			def = deferred();
			emitter = def.promise;
			def.resolve(watcher);
		} else {
			emitter = ee();
		}
		pipe = ee.pipe(watcher, emitter);
		emitter.close = function () {
			emitter.close = noop;
			pipe.close();
			if (memoized.clearRef.apply(this, args)) watcher.close();
		};
		return emitter;
	};
	factory.clear = memoized.clear;
	factory.memoized = true;
	return factory;
};

'use strict';

var noop     = require('es5-ext/function/noop')
  , assign   = require('es5-ext/object/assign')
  , memoize  = require('memoizee')
  , ee       = require('event-emitter')
  , eePipe   = require('event-emitter/lib/pipe')
  , deferred = require('deferred')

  , isPromise = deferred.isPromise;

module.exports = function (fn/*, options*/) {
	var factory, memoized;
	if (fn.memoized) return fn;
	memoized = memoize(fn, assign(Object(arguments[1]), { refCounter: true }));
	factory = function () {
		var watcher, emitter, pipe, args, def;
		args = arguments;
		watcher = memoized.apply(this, arguments);
		if (isPromise(watcher)) {
			def = deferred();
			emitter = def.promise;
			def.resolve(watcher);
		} else {
			emitter = ee();
		}
		pipe = eePipe(watcher, emitter);
		emitter.close = function () {
			emitter.close = noop;
			pipe.close();
			if (memoized.clearRef.apply(this, args)) watcher.close();
		};
		return emitter;
	};
	factory.clear = memoized.clear;
	factory.memoized = true;
	return factory;
};

Update up to changes in event-emitter package


#!/usr/bin/env node

// Must symlink the generator from xtc's modules up to the project's modules.
// Else Yeoman won't find it.

var path = require('path')
	fs = require('fs')
;

// process.cwd() == __dirname

if ('install' === process.env.npm_lifecycle_event) {

	try {
		fs.symlinkSync(path.join(process.cwd(), '/node_modules/generator-xtc'), path.join(process.cwd(), '../generator-xtc'), 'dir');
		console.log('symlink: generator-xtc into node_modules\n')
	} catch (e) {
		if (e.code === 'EEXIST') {
			console.info('symlink: generator-xtc already already exists node_modules\n');
		}
		else {
			throw e;
		}
	}

}

// And of course we remove it again before xtc is uninstalled

else if ('uninstall' === process.env.npm_lifecycle_event) {

	try {
		fs.unlinkSync(path.join(process.cwd(), '../generator-xtc'), 'dir');
		console.log('symlink: removed generator-xtc from node_modules\n')
	} catch (e) {
		if (e.code !== 'ENOENT') {
			console.info('symlink: Unable to remove generator-xtc from node_modules\n');
		}
		throw e;
	}
}

#!/usr/bin/env node

// Must symlink the generator from xtc's modules up to the project's modules.
// Else Yeoman won't find it.

var path = require('path')
	fs = require('fs')
;

// process.cwd() == __dirname

if ('install' === process.env.npm_lifecycle_event) {

	try {
		fs.symlinkSync(path.join(process.cwd(), '/node_modules/generator-xtc'), path.join(process.cwd(), '../generator-xtc'), 'dir');
		console.log('symlink: generator-xtc into node_modules\n')
	} catch (e) {
		if (e.code === 'EEXIST') {
			console.info('symlink: generator-xtc already exists in node_modules\n');
		}
		else {
			throw e;
		}
	}

}

// And of course we remove it again before xtc is uninstalled

else if ('uninstall' === process.env.npm_lifecycle_event) {

	try {
		fs.unlinkSync(path.join(process.cwd(), '../generator-xtc'), 'dir');
		console.log('symlink: removed generator-xtc from node_modules\n')
	} catch (e) {
		if (e.code !== 'ENOENT') {
			console.info('symlink: Unable to remove generator-xtc from node_modules\n');
		}
		throw e;
	}
}

Fix typo in error message


var ItemsRoute = Em.Route.extend({
  model: function (params) {
    return this.api.fetchAll('items', 'groups', params.group_id);
  },

  setupController: function (controller, model) {
    // allow sub-routes to access the GroupId since it seems the dynamic segment is not available otherwise
    controller.set('GroupId', model.get('firstObject.GroupId'));
    this._super(controller, model);
  },

  renderTemplate: function () {
    this.render('items', {
      into: 'application',
      outlet: 'items',
    });
  },

  actions: {
    refresh: function () {
      this.refresh();
      return true;
    }
  }
});

export default ItemsRoute;

var ItemsRoute = Em.Route.extend({
  model: function (params) {
    this.set('currentGroupId', parseInt(params.group_id, 10));
    return this.api.fetchAll('items', 'groups', params.group_id);
  },

  setupController: function (controller, model) {
    // allow sub-routes to access the GroupId since it seems the dynamic segment is not available otherwise
    controller.set('GroupId', this.get('currentGroupId'));
    this._super(controller, model);
  },

  renderTemplate: function () {
    this.render('items', {
      into: 'application',
      outlet: 'items',
    });
  },

  actions: {
    refresh: function () {
      this.refresh();
      return true;
    }
  }
});

export default ItemsRoute;

Fix setting GroupId on ItemsController when its model is empty


let RNVersionCheck;
if (process.env.RNVC_ENV === 'test') {
  RNVersionCheck = {
    country: 'ko',
    packageName: 'com.reactnative.versioncheck',
    currentBuildNumber: 1,
    currentVersion: '0.0.1',
  };
} else {
  const { Platform } = require('react-native');
  const { Constants, Util } = require('expo');

  const { manifest = {} } = Constants;
  const {
    version = null,
    android: { versionCode = null, package: androidPackageName = null } = {},
    ios: { bundleIdentifier = null, buildNumber = null } = {},
  } = manifest;

  RNVersionCheck = {
    currentVersion: version,
    country: Util.getCurrentDeviceCountryAsync(),
    currentBuildNumber: Platform.select({
      android: versionCode,
      ios: buildNumber,
    }),
    packageName: Platform.select({
      android: androidPackageName,
      ios: bundleIdentifier,
    }),
  };
}

const COUNTRY = RNVersionCheck.country;
const PACKAGE_NAME = RNVersionCheck.packageName;
const CURRENT_BUILD_NUMBER = RNVersionCheck.currentBuildNumber;
const CURRENT_VERSION = RNVersionCheck.currentVersion;

export default {
  getCountry: () => Promise.resolve(COUNTRY),
  getPackageName: () => PACKAGE_NAME,
  getCurrentBuildNumber: () => CURRENT_BUILD_NUMBER,
  getCurrentVersion: () => CURRENT_VERSION,
};

let RNVersionCheck;
if (process.env.RNVC_ENV === 'test') {
  RNVersionCheck = {
    country: 'ko',
    packageName: 'com.reactnative.versioncheck',
    currentBuildNumber: 1,
    currentVersion: '0.0.1',
  };
} else {
  const { Platform } = require('react-native');
  const { Constants, Localization, Util } = require('expo');

  const { manifest = {} } = Constants;
  const {
    version = null,
    android: { versionCode = null, package: androidPackageName = null } = {},
    ios: { bundleIdentifier = null, buildNumber = null } = {},
  } = manifest;

  RNVersionCheck = {
    currentVersion: version,
    country: `${Constants.expoVersion < 26 ? Util.getCurrentDeviceCountryAsync : Localization.getCurrentDeviceCountryAsync()}`,
    currentBuildNumber: Platform.select({
      android: versionCode,
      ios: buildNumber,
    }),
    packageName: Platform.select({
      android: androidPackageName,
      ios: bundleIdentifier,
    }),
  };
}

const COUNTRY = RNVersionCheck.country;
const PACKAGE_NAME = RNVersionCheck.packageName;
const CURRENT_BUILD_NUMBER = RNVersionCheck.currentBuildNumber;
const CURRENT_VERSION = RNVersionCheck.currentVersion;

export default {
  getCountry: () => Promise.resolve(COUNTRY),
  getPackageName: () => PACKAGE_NAME,
  getCurrentBuildNumber: () => CURRENT_BUILD_NUMBER,
  getCurrentVersion: () => CURRENT_VERSION,
};

Use `Localization.getCurrentDeviceCountryAsync` if its version of expo is over 26 since it's deprecated.


cinema.views.ViewportView = Backbone.View.extend({

    initialize: function () {
        this.$el.html(cinema.app.templates.viewport());

        this.camera = new cinema.models.CameraModel({
            info: this.model
        });

        this.renderView = new cinema.views.VisualizationCanvasWidget({
            el: this.$('.c-app-renderer-container'),
            model: this.model,
            camera: this.camera
        }).render();

        this.mouseInteractor = new cinema.utilities.RenderViewMouseInteractor({
            renderView: this.renderView,
            camera: this.camera
        }).enableMouseWheelZoom({
            maxZoomLevel: 10,
            zoomIncrement: 0.05,
            invertControl: false
        }).enableDragPan({
            keyModifiers: cinema.keyModifiers.SHIFT
        }).enableDragRotation({
            keyModifiers: null
        });

        this.listenTo(this.camera, 'change', this._refreshCamera);
    },

    updateQuery: function (query) {
        this.renderView.updateQuery(query);
    },

    _refreshCamera: function () {
        this.renderView.showViewpoint();
    },
});

cinema.views.ViewportView = Backbone.View.extend({

    initialize: function (opts) {
        this.$el.html(cinema.app.templates.viewport());

        this.camera = opts.camera || new cinema.models.CameraModel({
            info: this.model
        });

        this.renderView = new cinema.views.VisualizationCanvasWidget({
            el: this.$('.c-app-renderer-container'),
            model: this.model,
            camera: this.camera
        }).render();

        this.mouseInteractor = new cinema.utilities.RenderViewMouseInteractor({
            renderView: this.renderView,
            camera: this.camera
        }).enableMouseWheelZoom({
            maxZoomLevel: 10,
            zoomIncrement: 0.05,
            invertControl: false
        }).enableDragPan({
            keyModifiers: cinema.keyModifiers.SHIFT
        }).enableDragRotation({
            keyModifiers: null
        });

        this.listenTo(this.camera, 'change', this._refreshCamera);
    },

    updateQuery: function (query) {
        this.renderView.updateQuery(query);
    },

    _refreshCamera: function () {
        this.renderView.showViewpoint();
    }
});

Allow viewport to be initialized with a pre-existing camera model


/*global CodeMirror*/
$(function() {
  $('pre').each(function() {
    var preElement = $(this);
    var code = dedent(preElement.text()).trim();
    preElement.empty();
    CodeMirror(this, {
      value: code,
      mode: 'javascript',
      lineNumbers: !preElement.is('.inline'),
      readOnly: true
    });
  });

  $("a[href^='http']").attr("target", "_blank");
});

function getIndent(str) {
  var matches = str.match(/^[\s\\t]*/gm);
  var indent = matches[0].length;

  for (var i = 1; i < matches.length; i++) {
    indent = Math.min(matches[i].length, indent);
  }

  return indent;
}

function dedent(str, pattern) {
  var indent = getIndent(str);
  var reg;

  if (indent === 0) {
    return str;
  }

  if (typeof pattern === 'string') {
    reg = new RegExp('^' + pattern, 'gm');
  } else {
    reg = new RegExp('^[ \\t]{' + indent + '}', 'gm');
  }

  return str.replace(reg, '');
}

/*global CodeMirror*/
$(function() {
  $('pre').each(function() {
    var preElement = $(this);
    var code = dedent(preElement.text()).trim();
    preElement.empty();
    CodeMirror(this, {
      value: code,
      mode: 'javascript',
      lineNumbers: !preElement.is('.inline'),
      readOnly: true
    });
  });

  $("a[href^='http']").attr("target", "_blank");
  rewrite_urls();
});

/**
 * Our x-frame-options require that any page that is embedded
 * in an iframe include embedded as a query arg.
 */
function rewrite_urls() {
  var is_embedded = window.location.href.endsWith("embedded");

  if (!is_embedded) {
    return;
  }

  $('a').each(function () {
    var a = this;
    var href = $(a).attr('href');
    if (href.startsWith("/applab/docs")) {
      var new_href = href;
      if (href.indexOf("?") > -1) {
        new_href += "&embedded";
      } else {
        new_href += "?embedded";
      }
      $(a).attr('href', new_href);
    }
  });
}

function getIndent(str) {
  var matches = str.match(/^[\s\\t]*/gm);
  var indent = matches[0].length;

  for (var i = 1; i < matches.length; i++) {
    indent = Math.min(matches[i].length, indent);
  }

  return indent;
}

function dedent(str, pattern) {
  var indent = getIndent(str);
  var reg;

  if (indent === 0) {
    return str;
  }

  if (typeof pattern === 'string') {
    reg = new RegExp('^' + pattern, 'gm');
  } else {
    reg = new RegExp('^[ \\t]{' + indent + '}', 'gm');
  }

  return str.replace(reg, '');
}

Rewrite documentation urls to forward on the embedded flag


(function(global) {
    'use strict';

    (function(id) {
        var i, j;
        var tab = document.getElementById(id);
        var thead = tab.querySelector('thead');
        var tbody = tab.querySelector('tbody');
        var tr, th, td;
        // tr = document.createElement('tr');
        // th = document.createElement('td');
        // tr.appendChild(th);
        // for (i = 0; i < 30; i++) {
        //     th = document.createElement('th');
        //     th.textContent = i + 1;
        //     tr.appendChild(th);
        // }
        // thead.appendChild(tr);
        for (i = 0; i < 3; i++) {
            tr = document.createElement('tr');
            // th = document.createElement('th');
            // th.textContent = i + 1;
            // tr.appendChild(th);
            for (j = 0; j < 30; j++) {
                td = document.createElement('td');
                td.textContent = 0;
                tr.appendChild(td);
            }
            tbody.appendChild(tr);
        }
    })('rams');

})(this)

(function(global) {
    'use strict';

    (function(id) {
        var i, j;
        var tab = document.getElementById(id);
        var thead = tab.querySelector('thead');
        var tbody = tab.querySelector('tbody');
        var tr, th, td;
        // tr = document.createElement('tr');
        // th = document.createElement('td');
        // tr.appendChild(th);
        // for (i = 0; i < 30; i++) {
        //     th = document.createElement('th');
        //     th.textContent = i + 1;
        //     tr.appendChild(th);
        // }
        // thead.appendChild(tr);
        for (i = 0; i < 3; i++) {
            tr = document.createElement('tr');
            tr.id = "row-" + i;
            // th = document.createElement('th');
            // th.textContent = i + 1;
            // tr.appendChild(th);
            for (j = 0; j < 30; j++) {
                td = document.createElement('td');
                td.textContent = 0;
                td.id = "cell-" + (i * 30 + j);
                tr.appendChild(td);
            }
            tbody.appendChild(tr);
        }
    })('rams');

})(this)

Add ids to the markup


module.exports = {
  db: process.env.MONGODB || process.env.MONGOHQ_URL || 'mongodb://localhost:27017/gamekeller',
  sessionSecret: process.env.SESSION_SECRET || 'gkdevel'
}

module.exports = {
  db: process.env.MONGODB || 'mongodb://localhost:27017/gamekeller',
  sessionSecret: process.env.SESSION_SECRET || 'gkdevel'
}

Remove support for MONGOHQ_URL env variable


/* eslint-env node */
module.exports = {
  browsers: [
    'ie 9',
    'last 1 Chrome versions',
    'last 1 Firefox versions',
    'last 1 Safari versions'
  ]
};

/* eslint-env node */

// Which browsers are returned can be found at http://browserl.ist/
module.exports = {
  browsers: [
    'last 1 edge versions',
    'last 1 chrome versions',
    'firefox esr', //actually points to the last 2 ESR releases as they overlap
    'last 1 safari versions',
    'last 1 ios versions',
    'last 1 android versions',
  ]
};

Drop support for older browsers


var through = require('through2');

var choppa = function(chunkSize) {
  chunkSize = chunkSize === undefined ? 1 : chunkSize;
  var prev = new Buffer(0);

  var transform = function(chunk, enc, cb) {
    chunk = Buffer.concat([prev, chunk]);
    var self = this;
    if (chunkSize > 0) {
      while (chunk.length >= chunkSize) {
        self.push(chunk.slice(0, chunkSize));
        chunk = chunk.slice(chunkSize);
      }
      prev = chunk;
    } else {
      while (chunk.length) {
        var size = Math.floor(Math.random() * chunk.length) + 1;
        self.push(chunk.slice(0, size));
        chunk = chunk.slice(size);
      }
    }

    cb();
  };

  var flush = function(cb) {
    this.push(prev);
    cb();
  };

  return through(transform, flush);
};

module.exports = choppa;

var through = require('through2');

var choppa = function(chunkSize) {
  chunkSize = chunkSize === undefined ? 1 : chunkSize;
  var prev = new Buffer(0);

  var transform = function(chunk, enc, cb) {
    chunk = Buffer.concat([prev, chunk]);
    var self = this;
    if (chunkSize > 0) {
      while (chunk.length >= chunkSize) {
        self.push(chunk.slice(0, chunkSize));
        chunk = chunk.slice(chunkSize);
      }
      prev = chunk;
    } else {
      while (chunk.length) {
        var size = Math.floor(Math.random() * chunk.length) + 1;
        self.push(chunk.slice(0, size));
        chunk = chunk.slice(size);
      }
    }

    cb();
  };

  var flush = function(cb) {
    this.push(prev);
    cb();
  };

  return through.obj(transform, flush);
};

module.exports = choppa;

Fix async reads from the choppa.


var aglio = require('aglio');
var through2 = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;
var defaults = require('lodash.defaults');
var path = require('path');

module.exports = function (options) {
  'use strict';
  // Mixes in default options.
  options = defaults(options || {}, {
    compress: false,
    paths: []
  });

  function transform(file, enc, next) {
    var self = this;

    if (file.isNull()) {
      self.push(file); // pass along
      return next();
    }

    if (file.isStream()) {
      self.emit('error', new PluginError('gulp-aglio', 'Streaming not supported'));
      return next();
    }

    var str = file.contents.toString('utf8');

    // Clones the options object.
    var opts = defaults({
      theme: 'default'
    }, options);

    // Injects the path of the current file.
    opts.filename = file.path;

    // Inject includePath for relative includes
    opts.includePath = opts.includePath || path.dirname(opts.filename);

    aglio.render(str, opts, function (err, html) {
      if (err) {
        self.emit('error', new PluginError('gulp-aglio', err));
      } else {
        file.contents = new Buffer(html);
        file.path = gutil.replaceExtension(file.path, '.html');
        self.push(file);
      }
      next();
    });
  }

  return through2.obj(transform);
};

var aglio = require('aglio');
var through2 = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;
var defaults = require('lodash.defaults');
var path = require('path');

module.exports = function (options) {
  'use strict';
  // Mixes in default options.
  options = defaults(options || {}, {
    compress: false,
    paths: []
  });

  function transform(file, enc, next) {
    var self = this;

    if (file.isNull()) {
      self.push(file); // pass along
      return next();
    }

    if (file.isStream()) {
      self.emit('error', new PluginError('gulp-aglio', 'Streaming not supported'));
      return next();
    }

    var str = file.contents.toString('utf8');

    // Clones the options object.
    var opts = defaults({
      theme: 'default'
    }, options);

    // Injects the path of the current file.
    opts.filename = file.path;

    // Inject includePath for relative includes
    opts.includePath = opts.includePath || path.dirname(opts.filename);

    try {
      aglio.render(str, opts, function (err, html) {
        if (err) {
          self.emit('error', new PluginError('gulp-aglio', err));
        } else {
          file.contents = new Buffer(html);
          file.path = gutil.replaceExtension(file.path, '.html');
          self.push(file);
        }
        next();
      });
    } catch(err) {
      self.emit("error", new PluginError("gulp-aglio", err));
    }
  }

  return through2.obj(transform);
};

Fix error when files are not found


const getJSON = require('get-json');

const overpass = 'http://overpass-api.de/api/interpreter?data=';
const query = '[out:json];way[%22highway%22](around:50,51.424037,-0.148666);out;';

getJSON(`${overpass}${query}`, (err, result) => {
  if (err) console.log(err);
  console.log(result);
});

const getJSON = require('get-json');

const overpass = 'http://overpass-api.de/api/interpreter?data=';

const lat = 51.424037;
const long = -0.148666;
const distance = 50;

const query = `[out:json]; way["highway"](around:${distance},${lat},${long}); out;`;

getJSON(`${overpass}${query}`, (err, result) => {
  if (err) console.log(err);
  console.log(result);
});

Use templates to cleanup query


var qs = require('querystring')

module.exports = function (network, url, opts) {

  opts = opts || {}

  if (!linkfor[network]) throw new Error('Unsupported network ' + network)
  return linkfor[network](url, opts)

}

var linkfor = {
  facebook: function (url, opts) {
    var share = {
      u: url
    }
    if (opts.t) share.t = opts.t
    return 'https://www.facebook.com/sharer/sharer.php?' + qs.stringify(share)
  },
  googleplus: function (url, opts) {
    var share = {
      url: url
    }
    return 'https://plus.google.com/share?' + qs.stringify(share)
  },
  pinterest: function (url, opts) {
    var share = {
      url: url
    }
    if (opts.media) share.media = opts.media
    if (opts.description) share.description = opts.description
    return 'http://pinterest.com/pin/create/button/?' + qs.stringify(share)
  },
  twitter: function (url, opts) {
    var share = {
      source: url
    }
    if (opts.text) share.text = opts.text
    if (opts.via) share.via = opts.via
    return 'https://twitter.com/intent/tweet?' + qs.stringify(share)
  }
}

linkfor['google+'] = linkfor.googleplus

Add google+ as alias for googleplus


var _ = require('lodash');
var postcss = require('postcss');
var SEProperties = require('swedish-css-properties');
var SEValues = require('swedish-css-values');

module.exports = postcss.plugin('postcss-swedish-stylesheets', function (opts) {
    opts = opts || {
        properties: {},
        values:     {}
    };

    if (_.isObject(opts.properties)) {
        SEProperties = _.merge(SEProperties, opts.properties);
    }

    if (_.isObject(opts.values)) {
        SEValues = _.merge(SEValues, opts.values);
    }

    // Work with options here

    return function (css) {

        css.walkDecls(function transformDecl(decl) {
            // Properties
            _.forEach(SEProperties, function (value, key) {
                if (decl.prop === value) {
                    decl.prop = key;
                }
            });

            // Values
            _.forEach(SEValues, function (value, key) {
                decl.value = decl.value.replace(value, key);
            });

            // Important
            if (decl.value.indexOf('!viktigt') >= 0) {
                decl.value = decl.value.replace(/\s*!viktigt\s*/, '');
                decl.important = true;
            }
        });

    };
});

const _ = require('lodash');
const SEProperties = require('swedish-css-properties');
const SEValues = require('swedish-css-values');

const postcssSwedishStylesheets = (opts = {}) => {
  if (_.isObject(opts.properties)) {
    _.merge(SEProperties, opts.properties);
  }

  if (_.isObject(opts.values)) {
    _.merge(SEValues, opts.values);
  }

  return {
    postcssPlugin: 'postcss-swedish-stylesheets',
    Once(root) {
      root.walkDecls((decl) => {
        // Properties
        _.forEach(SEProperties, (value, key) => {
          if (decl.prop === value) {
            decl.prop = key;
          }
        });

        // Values
        _.forEach(SEValues, (value, key) => {
          decl.value = decl.value.replace(value, key);
        });

        // Important
        if (decl.value.indexOf('!viktigt') >= 0) {
          decl.value = decl.value.replace(/\s*!viktigt\s*/, '');
          decl.important = true;
        }
      });
    },
  };
};

module.exports.postcss = true;
module.exports = postcssSwedishStylesheets;

Update plugin to use PostCSS 8


var exec = require('child_process').exec;
module.exports = function sysPrefix() {
  return new Promise(function(resolve, reject) {
    exec('python -c \'import sys; print(sys.prefix)\'',
      function(err, stdout) {
        if (err !== null) {
          reject(err);
        }
        else {
          resolve(stdout.toString().trim());
        }
      });
  });
}

var exec = require('child_process').exec;
module.exports = function sysPrefix() {
  return new Promise(function(resolve, reject) {
    exec('python -c "import sys; print(sys.prefix)"',
      function(err, stdout) {
        if (err !== null) {
          reject(err);
        }
        else {
          resolve(stdout.toString().trim());
        }
      });
  });
}

Switch to double quotes inside the exec


require('dotenv').config();
const express = require('express');
const shortUrlController = require('./lib/short-url-controller.js');
const stubController = require('./lib/stub-controller.js');
const logger = require('winston');

const port = process.env.PORT || 5000;
const app = express();

app.set('view engine', 'pug');
app.use('/', stubController);
app.use('/new', shortUrlController);

const listener = app.listen(port, () => {
  logger.info(`Your app is listening on port ${listener.address().port}`);
});

Fix dotenv to work locally instead of just on heroku


/*!
 * array-last <https://github.com/jonschlinkert/array-last>
 *
 * Copyright (c) 2014 Jon Schlinkert, contributors.
 * Licensed under the MIT license.
 */

var isNumber = require('is-number');

module.exports = function last(arr, n) {
  if (!Array.isArray(arr)) {
    throw new Error('expected the first argument to be an array');
  }

  var len = arr.length;
  if (len === 0) {
    return null;
  }

  n = isNumber(n) ? +n : 1;
  if (n === 1 && len === 1) {
    return arr[0];
  }

  var res = new Array(n);
  while (n--) {
    res[n] = arr[--len];
  }
  return res;
};

/*!
 * array-last <https://github.com/jonschlinkert/array-last>
 *
 * Copyright (c) 2014 Jon Schlinkert, contributors.
 * Licensed under the MIT license.
 */

var isNumber = require('is-number');

module.exports = function last(arr, n) {
  if (!Array.isArray(arr)) {
    throw new Error('expected the first argument to be an array');
  }

  var len = arr.length;
  if (len === 0) {
    return null;
  }

  n = isNumber(n) ? +n : 1;
  if (n === 1) {
    return arr[len - 1];
  }

  var res = new Array(n);
  while (n--) {
    res[n] = arr[--len];
  }
  return res;
};

Return a single value when n=1


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

var fs = require('fs');

module.exports = {
  name: 'uncharted-describe-models',

  config: function(env, config) {
    if (env === 'test') {
      return;
    }

    if (!fs.existsSync('app/schema.json')) {
      throw new Error('You must include a schema.json in the root of app/');
    }

    var schema = JSON.parse(fs.readFileSync('app/schema.json', 'utf8'));
    config['model-schema'] = schema;
    return config;
  },

  includedCommands: function() {
    return {
      'update-models': require('./lib/commands/update-models')
    };
  }
};

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

var fs = require('fs');

module.exports = {
  name: 'uncharted-describe-models',

  config: function(env, config) {
    if (!fs.existsSync('app/schema.json')) {
      throw new Error('You must include a schema.json in the root of app/');
    }

    var schema = JSON.parse(fs.readFileSync('app/schema.json', 'utf8'));
    config['model-schema'] = schema;
    return config;
  },

  includedCommands: function() {
    return {
      'update-models': require('./lib/commands/update-models')
    };
  }
};

Make sure we always load the schema, even within a test


var restify = require('restify');

var messenger = require('./lib/messenger');
var session = require('./lib/session');

var server = restify.createServer();

server.use(restify.queryParser());
server.use(restify.bodyParser());
server.use(restify.authorizationParser());

server.get('/', function (req, res, next) {
  res.send(200, {status: 'ok'});
});

server.post('/messages', function (req, res, next) {
  var phoneNumber = req.params.From;

  session.get(phoneNumber, function(err, user) {
    if (err) messenger.send(phoneNumber, 'There was some kind of error.')
    if (user) {
      messenger.send(phoneNumber, 'Hello, old friend.');
    } else {
      session.set(phoneNumber, 'initial', function () {
        res.send(phoneNumber, 'Nice to meet you.')
      })
    }
  });

  res.send(200, {status: 'ok'});
});

server.listen(process.env.PORT || '3000', function() {
  console.log('%s listening at %s', server.name, server.url);
});

var restify = require('restify');

var messenger = require('./lib/messenger');
var session = require('./lib/session');

var server = restify.createServer();

server.use(restify.queryParser());
server.use(restify.bodyParser());
server.use(restify.authorizationParser());

server.get('/', function (req, res, next) {
  res.send(200, {status: 'ok'});
});

server.post('/messages', function (req, res, next) {
  var phoneNumber = req.params.From;

  session.get(phoneNumber, function(err, user) {
    if (err) {
      messenger.send(phoneNumber, 'There was some kind of error.');
      res.send(500, {error: 'Something went wrong.'});
    }
    if (user) {
      messenger.send(phoneNumber, 'Hello, old friend.');
      res.send(200);
    } else {
      session.set(phoneNumber, 'initial', function () {
        messenger.send(phoneNumber, 'Nice to meet you.');
        res.send(200);
      });
    }
  });

  res.send(200, {status: 'ok'});
});

server.listen(process.env.PORT || '3000', function() {
  console.log('%s listening at %s', server.name, server.url);
});

Send HTTP responses for all messages


// var http = require("http");
// app.set('view engine', 'html');
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/views'));
app.use(express.static(__dirname + '/scripts'));

app.listen(3000, function () {
  console.log('Example app listening on port 3000!')
})

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.post('/', function (req, res) {
  res.send('Got a POST request')
})

app.put('/user', function (req, res) {
  res.send('Got a PUT request at /user')
})

app.delete('/user', function (req, res) {
  res.send('Got a DELETE request at /user')
})

// Route path: /users/:userId/books/:bookId
// Request URL: http://localhost:3000/users/34/books/8989
// req.params: { "userId": "34", "bookId": "8989" }
// To define routes with route parameters, simply specify the route parameters in the path of the route as shown below.

app.get('/users/:userId/books/:bookId', function (req, res) {
  res.send(req.params)
})

Add info on setting parameters in route


module.exports = {
  handlebars: require('./lib/handlebars'),
  marked: require('./lib/marked'),
  componentTemplate: 'node_modules/foundation-docs/templates/component.html',
  handlebarsHelpers: 'node_modules/foundation-docs/helpers/'
}

var path = require('path');

var TEMPLATE_PATH = path.join(__dirname, 'templates/component.html');
var HELPERS_PATH = path.join(__dirname, 'helpers');

module.exports = {
  handlebars: require('./lib/handlebars'),
  marked: require('./lib/marked'),
  componentTemplate: path.relative(process.cwd(), TEMPLATE_PATH),
  handlebarsHelpers: path.relative(process.cwd(), HELPERS_PATH)
}

Use relative paths for componentTemplate and handlebarsHelpers paths


var Map = require('./lib/map'),
    Format = require('./lib/format'),
    safe64 = require('./lib/safe64');

module.exports = {
    Map: Map,
    Format: Format,
    safe64: safe64,
    pool: function(datasource) {
        return {
            create: function(callback) {
                var resource = new Map(datasource);
                resource.initialize(function(err) {
                    if (err) throw err;
                    callback(resource);
                });
            },
            destroy: function(resource) {
                resource.destroy();
            }
        };
    },
    serve: function(resource, options, callback) {
        resource.render(options, callback);
    }
};

var Map = require('./lib/map'),
    Format = require('./lib/format'),
    safe64 = require('./lib/safe64');

module.exports = {
    Map: Map,
    Format: Format,
    safe64: safe64,
    pool: function(datasource) {
        return {
            create: function(callback) {
                var resource = new Map(datasource);
                resource.initialize(function(err) {
                    callback(err, resource);
                });
            },
            destroy: function(resource) {
                resource.destroy();
            }
        };
    },
    serve: function(resource, options, callback) {
        resource.render(options, callback);
    }
};

Update tilelive pool factory create method to pass errors.


"use strict";

const util = require("gulp-util");
const through = require("through2");
const moment = require("moment");

module.exports = function(options) {
  options = options || {};

  function updateDate(file, options) {
    const now   = moment().format("YYYY/MM/DD"),
          regex = /Last updated: (\d{4}\/\d{2}\/\d{2})/i,
          prev  = regex.exec(file)[1];

    if (options.log) {
      util.log(
        `${util.colors.cyan("[gulp-update-humanstxt-date]")} ` +
        `Found the previous date to be: ${util.colors.red(prev)}. ` +
        `Replacing with ${util.colors.green(now)}.`
      );
    }

    file = file.replace(prev, now);
    return file;
  }

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

    if (file.isStream()) {
      cb(new util.PluginError("gulp-update-humanstxt-date", "Streaming not supported"));
      return;
    }

    try {
      file.contents = new Buffer(updateDate(file.contents.toString(), options));
      this.push(file);
    } catch (err) {
      this.emit("error", new util.PluginError("gulp-update-humanstxt-date", err));
    }

    cb();
  });
};

"use strict";

const util = require("gulp-util");
const through = require("through2");
const moment = require("moment");

module.exports = function(options) {
  options = options || {};

  function updateDate(file, options) {
    const now   = moment().format("YYYY/MM/DD"),
          regex = /Last updated?: ?(\d{4}\/\d{2}\/\d{2})/i,
          prev  = regex.exec(file)[1];

    if (options.log) {
      util.log(
        `${util.colors.cyan("[gulp-update-humanstxt-date]")} ` +
        `Found the previous date to be: ${util.colors.red(prev)}. ` +
        `Replacing with ${util.colors.green(now)}.`
      );
    }

    file = file.replace(prev, now);
    return file;
  }

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

    if (file.isStream()) {
      cb(new util.PluginError("gulp-update-humanstxt-date", "Streaming not supported"));
      return;
    }

    try {
      file.contents = new Buffer(updateDate(file.contents.toString(), options));
      this.push(file);
    } catch (err) {
      this.emit("error", new util.PluginError("gulp-update-humanstxt-date", err));
    }

    cb();
  });
};

Make the 'd' in 'updated' optional along with the space before the date


'use strict';

module.exports = {
  name: 'live-reload-middleware',

  serverMiddleware: function(options) {
    var app = options.app;
    options = options.options;

    if (options.liveReload === true) {
      var livereloadMiddleware = require('connect-livereload');

      app.use(livereloadMiddleware({
        port: options.liveReloadPort
      }));
    }
  }
};

'use strict';

module.exports = {
  name: 'live-reload-middleware',

  serverMiddleware: function(options) {
    var app = options.app;
    options = options.options;

    if (options.liveReload === true) {
      var livereloadMiddleware = require('connect-livereload');

      app.use(livereloadMiddleware({
        ignore: [
          /\.js(?:\?.*)?$/,
          /\.css(?:\?.*)$/,
          /\.svg(?:\?.*)$/,
          /\.ico(?:\?.*)$/,
          /\.woff(?:\?.*)$/,
          /\.png(?:\?.*)$/,
          /\.jpg(?:\?.*)$/,
          /\.jpeg(?:\?.*)$/,
          /\.ttf(?:\?.*)$/
        ],
        port: options.liveReloadPort
      }));
    }
  }
};

Fix ignore list to work with query string params.


import ReactGA from 'react-ga'
import {config} from 'config'

ReactGA.initialize(config.googleAnalyticsId);

exports.onRouteUpdate = (state, page, pages) => {
  ReactGA.pageview(state.pathname);
};

import ReactGA from 'react-ga'
import {config} from 'config'

ReactGA.initialize(config.googleAnalyticsId);
ReactGA.plugin.require('linkid');

exports.onRouteUpdate = (state, page, pages) => {
  ReactGA.pageview(state.pathname);
};

Add linkid to google analytics


import JobStatus from 'girder_plugins/jobs/JobStatus';

JobStatus.registerStatus({
    WORKER_FETCHING_INPUT: {
        value: 820,
        text: 'Fetching input',
        icon: 'icon-download',
        color: '#89d2e2'
    },
    WORKER_CONVERTING_INPUT: {
        value: 821,
        text: 'Converting input',
        icon: 'icon-shuffle',
        color: '#92f5b5'
    },
    WORKER_CONVERTING_OUTPUT: {
        value: 822,
        text: 'Converting output',
        icon: 'icon-shuffle',
        color: '#92f5b5'
    },
    WORKER_PUSHING_OUTPUT: {
        value: 823,
        text: 'Pushing output',
        icon: 'icon-upload',
        color: '#89d2e2'
    }
});

import JobStatus from 'girder_plugins/jobs/JobStatus';

JobStatus.registerStatus({
    WORKER_FETCHING_INPUT: {
        value: 820,
        text: 'Fetching input',
        icon: 'icon-download',
        color: '#89d2e2'
    },
    WORKER_CONVERTING_INPUT: {
        value: 821,
        text: 'Converting input',
        icon: 'icon-shuffle',
        color: '#92f5b5'
    },
    WORKER_CONVERTING_OUTPUT: {
        value: 822,
        text: 'Converting output',
        icon: 'icon-shuffle',
        color: '#92f5b5'
    },
    WORKER_PUSHING_OUTPUT: {
        value: 823,
        text: 'Pushing output',
        icon: 'icon-upload',
        color: '#89d2e2'
    },
    WORKER_CANCELING: {
        value: 824,
        text: 'Canceling',
        icon: 'icon-cancel',
        color: '#f89406'
    }
});

Add button to cancel job


import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

// Configure Enzyme
Enzyme.configure({ adapter: new Adapter() });

// Add RAF for React 16
global.requestAnimationFrame = function requestAnimationFrame(callback) {
  setTimeout(callback, 0);
};

const Enzyme = require('enzyme');
const Adapter = require('enzyme-adapter-react-16');

// Configure Enzyme
Enzyme.configure({ adapter: new Adapter() });

// Add RAF for React 16
global.requestAnimationFrame = function requestAnimationFrame(callback) {
  setTimeout(callback, 0);
};

Use require() instead of import().


class SearchBox extends React.Component {
  // constructor(){
  //   super();
  //   this.state = {
  //     searched:false;
  //   };
  // }
	render() {
		return (

        CLICK AND HIT ENTER TO SEARCH
        <form className="search-form" onSubmit={this._handleSubmit.bind(this)}>
          <input placeholder="search something" ref={input => this._search = input}/>
          <button type="submit">SEARCH HERE</button>
        </form>

    );
	}
  _handleSubmit(event) {
    event.preventDefault();
    let search = this._search.value;
    let parameters = '?action=opensearch&limit=10&namespace=0&format=json&search='
    var cb = '&callback=JSON_CALLBACK';
    let url = 'https://en.wikipedia.org/w/api.php'+parameters+search+cb
    // console.log(url);
    $.getJSON(url);
  }
}

class SearchContainer extends React.Component {
  // constructor(){
  //   super();
  //   this.state = {
  //     searches:{};
  //   };
  // }
  // render() {
  //   return (
  //

  //       {searches.map(search =>
  //

  //

  //        )}
  //
  //

  //   )
  // }
}

ReactDOM.render(
  <SearchBox />, document.getElementById('mainDiv')
);

Write first component and start first API call


const command = {
  command: "serve",
  description: "Start Truffle's GraphQL UI playground",
  builder: {},
  help: {
    usage: "truffle db serve",
    options: []
  },

  /* This command does starts an express derived server that invokes
   * `process.exit()` on SIGINT. As a result there is no need to invoke
   * truffle's own `process.exit()` which is triggered by invoking the `done`
   * callback.
   *
   * Todo: blacklist this command for REPLs
   */
  run: async function(argv) {
    const Config = require("@truffle/config");
    const { playgroundServer } = require("truffle-db");

    const config = Config.detect(argv);
    const port = (config.db && config.db.PORT) || 4444;

    const { url } = await playgroundServer(config).listen({ port });

    console.log(`🚀 Playground listening at ${url}`);
    console.log(`ℹ  Press Ctrl-C to exit`);
  }
};

module.exports = command;

const command = {
  command: "serve",
  description: "Start Truffle's GraphQL UI playground",
  builder: {},
  help: {
    usage: "truffle db serve",
    options: []
  },

  /* This command does starts an express derived server that invokes
   * `process.exit()` on SIGINT. As a result there is no need to invoke
   * truffle's own `process.exit()` which is triggered by invoking the `done`
   * callback.
   *
   * Todo: blacklist this command for REPLs
   */
  run: async function(argv) {
    const Config = require("@truffle/config");
    const { playgroundServer } = require("truffle-db");

    const config = Config.detect(argv);
    const port = (config.db && config.db.port) || 4444;

    const { url } = await playgroundServer(config).listen({ port });

    console.log(`🚀 Playground listening at ${url}`);
    console.log(`ℹ  Press Ctrl-C to exit`);
  }
};

module.exports = command;

Make the port attribute lowercase


import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import App from './containers/App'

ReactDOM.render(
  <AppContainer>
    <App/>
  </AppContainer>,
  document.getElementById('root')
)

if (module.hot) {
  module.hot.accept('./containers/App', () => {
    // If you use Webpack 2 in ES modules mode, you can
    // use <App /> here rather than require() a <NextApp />.
    const NextApp = require('./containers/App').default
    ReactDOM.render(
      <AppContainer>
        <NextApp/>
      </AppContainer>,
      document.getElementById('root')
    )
  })
}

Add line break at end of file


require('jquery')
require('expose?$!expose?jQuery!jquery')
require("bootstrap-webpack")
require('./less/index.less')

$.get('http://10.90.100.1:8080/signalk/v1/api/vessels/self/navigation/position')
  .then(res => $.get(`http://www.tuuleeko.fi:8000/nearest-station?lat=${res.latitude}&lon=${res.longitude}`))
  .then(station => {
    $.get(`http://www.tuuleeko.fi:8000/observations?geoid=${station.geoid}`)
      .then(stationObservations => {
        var obs = stationObservations.observations[stationObservations.observations.length - 1]
        var forecastHtml = `

${stationObservations.name} (${(station.distanceMeters / 1000).toFixed(1)} km)

Wind direction	Wind speed	Wind gusts

${obs.windDir}°	${obs.windSpeedMs} m/s	${obs.windGustMs} m/s

`
        $('body').append(forecastHtml)
      })
  })

Add POC for showing the closes weather observation data


import * as path from 'path';
import {fs} from 'node-promise-es6';
import * as fse from 'fs-extra-promise-es6';

export default class {
  constructor(basePath) {
    this.basePath = path.resolve(basePath);
  }

  async create() {
    await fse.mkdirs(this.basePath);
  }

  path(...components) {
    return path.resolve(this.basePath, ...components);
  }

  async remove() {
    await fse.remove(this.path());
  }

  async write(files) {
    for (const file of Object.keys(files)) {
      const filePath = this.path(file);
      const fileContents = files[file];

      await fse.ensureFile(filePath);

      if (typeof fileContents === 'object') {
        await fse.writeJson(filePath, fileContents);
      } else {
        const reindentedFileContents = fileContents
          .split('\n')
          .filter((line, index, array) =>
            index !== 0 && index !== array.length - 1 || line.trim() !== '')
          .reduce(({indentation, contents}, line) => {
            const whitespaceToRemove = Number.isInteger(indentation) ?
              indentation :
              line.match(/^\s*/)[0].length;
            return {
              indentation: whitespaceToRemove,
              contents: `${contents}${line.slice(whitespaceToRemove)}\n`
            };
          }, {contents: ''}).contents;
        await fs.writeFile(filePath, reindentedFileContents);
      }
    }
  }
}

import * as path from 'path';
import {fs} from 'node-promise-es6';
import * as fse from 'fs-extra-promise-es6';

export default class {
  constructor(basePath) {
    this.basePath = path.resolve(basePath);
  }

  async create() {
    await fse.mkdirs(this.basePath);
  }

  path(...components) {
    return path.resolve(this.basePath, ...components);
  }

  async remove() {
    await fse.remove(this.path());
  }

  async write(files) {
    for (const [filePath, fileContents] of Object.entries(files)) {
      const absoluteFilePath = this.path(filePath);

      await fse.ensureFile(absoluteFilePath);

      if (typeof fileContents === 'object') {
        await fse.writeJson(absoluteFilePath, fileContents);
      } else {
        const reindentedFileContents = fileContents
          .split('\n')
          .filter((line, index, array) =>
            index !== 0 && index !== array.length - 1 || line.trim() !== '')
          .reduce(({indentation, contents}, line) => {
            const whitespaceToRemove = Number.isInteger(indentation) ?
              indentation :
              line.match(/^\s*/)[0].length;
            return {
              indentation: whitespaceToRemove,
              contents: `${contents}${line.slice(whitespaceToRemove)}\n`
            };
          }, {contents: ''}).contents;
        await fs.writeFile(absoluteFilePath, reindentedFileContents);
      }
    }
  }
}

Use Object.entries instead of Object.keys


var notify = require("./notify");

module.exports = function notifyStyleLint (stdout) {
  var messages = stdout.split("\n");

  messages.pop(); // Remove last empty new message.

  if(0 < messages.length) {
    var message = "{{length}} lint warning(s) found.".replace(/{{length}}/g, messages.length);

    notify.showNotification({
      subtitle: "Task style:lint",
      message: message,
      appIcon: notify.appIcon.sass
    });
  }
};

var notify = require("./notify");
var util   = require("util");

module.exports = function notifyStyleLint (stdout) {
  var messages = stdout.split("\n");

  messages.pop(); // Remove last empty new message.

  if(0 < messages.length) {
    var message = util.format("%d lint warning(s) found.", messages.length);

    notify.showNotification({
      subtitle: "Task style:lint",
      message: message,
      appIcon: notify.appIcon.sass
    });
  }
};

Use built-in utils to format the string.


appRun();

function appRun() {

    $(document).ready(function() {
        console.log("READY");

        $(".loading").hide();
        $(".complete").show();

    //PAGE SWIPES
    $(document).on('pageinit', function(event){
        $('.pages').on("swipeleft", function () {
            var nextpage = $(this).next('div[data-role="page"]');
            if (nextpage.length > 0) {
                $.mobile.changePage(nextpage, {transition: "slide", changeHash:false });
            }
        });

        $('.pages').on("swiperight", function () {
            var prevpage = $(this).prev('div[data-role="page"]');
            if (prevpage.length > 0) {
                $.mobile.changePage(prevpage, { transition: "slide", reverse: true, changeHash: false });
            }
        });
    });

    });

}

appRun();

function appRun() {

    $(document).ready(function() {
        console.log("READY");

        $(".loading").hide();
        $(".complete").show();

    //PAGE SWIPES
    $(document).on('pageinit', function(event){
        $('.pages').on("swipeleft", function () {
            var nextpage = $(this).next('div[data-role="page"]');
            if (nextpage.length > 0) {
                $.mobile.changePage(nextpage, {transition: "slide", changeHash:false });
            }
        });

        $('.pages').on("swiperight", function () {
            var prevpage = $(this).prev('div[data-role="page"]');
            if (prevpage.length > 0) {
                $.mobile.changePage(prevpage, { transition: "slide", reverse: true, changeHash: false });
            }
        });
    });

    //DRAG AND DROP

    //initialize dragging
    $("#watercolor").draggable( {
        revert: true,
        cursor: 'move',
    } );
    $("#leaves").draggable( {
        revert: true,
        cursor: 'move',
    } );
    $("#bubbles").draggable( {
        revert: true,
        cursor: 'move',
    } );

    //initialize droppable callback
    $("#spritesheet").droppable({
        tolerance: "pointer",
        drop: sinbadChange
    });

    console.log("before droppable");

    //event handler for drop event
    function sinbadChange(event, ui) {
        var currentBrush = ui.draggable.attr('id');
        console.log(currentBrush);
        console.log("in droppable");
        if (currentBrush == "watercolor") {
            $("#spritesheet").removeClass();
            $("#spritesheet").addClass("brushfish");
            console.log("DROPPED");
        } else if (currentBrush == "leaves") {
            $("#spritesheet").removeClass();
            $("#spritesheet").addClass("leaffish");
            console.log("DROPPED LEAF");
        } else if (currentBrush == "bubbles") {
            $("#spritesheet").removeClass();
            $("#spritesheet").addClass("bubblefish");
            console.log("DROPPED BUBBLE");
        } else {
            $("#spritesheet").removeClass();
            $("#spritesheet").addClass("plainfish");
        }
    }

    // //add listener to drop event
    // $("spritesheet").on("drop", function(event, ui) {

    // })

    }); //end jquery

} //end appRun

Add jquery UI drag/drop functionality


// @flow
const promiseBindMiddleware = (
  { dispatch } : { dispatch : Function },
) => (next: Function) => (action: Object) => {
  if (action && action.promise && typeof action.promise === 'function') {
    const { type, metadata, promise, promiseArg } = action

    dispatch({
      type: `${type}_START`,
      metadata,
    })

    return promise(...(Array.isArray(promiseArg) ? promiseArg : [promiseArg]))
      .then((data) => {
        dispatch({
          type: `${type}_SUCCESS`,
          payload: data,
          metadata,
        })

        return data
      }, (ex) => {
        dispatch({
          type: `${type}_ERROR`,
          payload: ex,
          metadata,
        })

        return ex
      })
  }
  return next(action)
}

export default promiseBindMiddleware

// @flow

const extendBy = (object: Object, { metadata } : { metadata : any }) => {
  if (metadata) return { ...object, metadata }
  return object
}

const promiseBindMiddleware = (
  { dispatch } : { dispatch : Function },
) => (next: Function) => (action: Object) => {
  if (action && action.promise && typeof action.promise === 'function') {
    const { type, metadata, promise, promiseArg } = action

    dispatch(extendBy({
      type: `${type}_START`,
    }, { metadata }))

    return promise(...(Array.isArray(promiseArg) ? promiseArg : [promiseArg]))
      .then((data) => {
        dispatch(extendBy({
          type: `${type}_SUCCESS`,
          payload: data,
        }, { metadata }))

        return data
      }, (ex) => {
        dispatch(extendBy({
          type: `${type}_ERROR`,
          payload: ex,
        }, { metadata }))

        // TODO change to throw an error
        return ex
      })
  }
  return next(action)
}

export default promiseBindMiddleware

Add meted only if exist


/**
 * Internal dependencies
 */
import { DATA_LAYER } from './index.private';

/**
 * Returns a function which, when invoked will initialize the dataLayer and push data onto it.
 *
 * @param {Object} target Object to enhance with dataLayer data.
 * @return {Function} Function that pushes data onto the dataLayer.
 */
export default function createDataLayerPush( target ) {
	/**
	 * Pushes data onto the data layer.
	 *
	 * @param {...any} args Arguments to push onto the data layer.
	 */
	return function dataLayerPush( ...args ) {
		target[ DATA_LAYER ] = target[ DATA_LAYER ] || [];
		target[ DATA_LAYER ].push( args );
	};
}

/**
 * Internal dependencies
 */
import { DATA_LAYER } from './index.private';

/**
 * Returns a function which, when invoked will initialize the dataLayer and push data onto it.
 *
 * @param {Object} target Object to enhance with dataLayer data.
 * @return {Function} Function that pushes data onto the dataLayer.
 */
export default function createDataLayerPush( target ) {
	/**
	 * Pushes data onto the data layer.
	 * Must use `arguments` internally.
	 */
	return function dataLayerPush() {
		target[ DATA_LAYER ] = target[ DATA_LAYER ] || [];
		target[ DATA_LAYER ].push( arguments );
	};
}

Refactor dataLayerPush to use func.arguments.


export default function(state, ctx, model, helpers) {

	const ConcretizeIfNative = helpers.ConcretizeIfNative;

	//TODO: Test IsNative for apply, bind & call
	model.add(Function.prototype.apply, ConcretizeIfNative(Function.prototype.apply));
	model.add(Function.prototype.call, ConcretizeIfNative(Function.prototype.call));
	model.add(Function.prototype.bind, ConcretizeIfNative(Function.prototype.bind));

  model.add(Object.prototype.hasOwnProperty, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

    Function.prototype.hasOwnProperty.apply(state.getConcrete(base), args);
  });

  model.add(Object.prototype.keys, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

    return Object.prototype.keys.apply(this.getConcrete(base), args);
  });

  model.add(console.log, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

		console.log.apply(base, args);
	});
}

export default function(state, ctx, model, helpers) {

	const ConcretizeIfNative = helpers.ConcretizeIfNative;

	//TODO: Test IsNative for apply, bind & call
	model.add(Function.prototype.apply, ConcretizeIfNative(Function.prototype.apply));
	model.add(Function.prototype.call, ConcretizeIfNative(Function.prototype.call));
	model.add(Function.prototype.bind, ConcretizeIfNative(Function.prototype.bind));

  model.add(Object.prototype.hasOwnProperty, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

    Function.prototype.hasOwnProperty.apply(state.getConcrete(base), args);
  });

  model.add(Object.prototype.keys, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

    return Object.prototype.keys.apply(this.getConcrete(base), args);
  });

  model.add(Object.assign, (base, args) => {
    return Object.assign.call(base, this.getConcrete(args[0]), this.getConcrete(args[1]));
  });

  model.add(console.log, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

		console.log.apply(base, args);
	});
}

Add a model for Object.assign


var nconf = require('nconf');

nconf
  .env()
  .file({ file: './gateway.json' });

nconf.defaults({
  'RIPPLE_REST_API': 'http://localhost:5990',
  'DATABASE_URL': 'postgres://username:password@localhost/ripple_gateway'
});

module.exports = nconf;

var nconf = require('nconf');

nconf
  .env()
  .file({ file: './config/config.json' });

nconf.defaults({
  'RIPPLE_REST_API': 'http://localhost:5990',
  'DATABASE_URL': 'postgres://username:password@localhost/ripple_gateway'
});

module.exports = nconf;

Move config file from gateway to config/config


//onReady
$(function() {
  //temporary testing functionality
  $('#refreshBtn').on('click', function() {
    updateStreams();
  });
});

function updateStreams() {
  // Clear out the stale data
  $('#mainContainer').html("");
  // And fetch the fresh
  var streamList = $('#streamList').val().split('\n');
  for (var i = 0, len = streamList.length; i < len; i++) {
    fetchStreamData(streamList[i]);
  }
}

function fetchStreamData( streamName ) {
  $.getJSON('https://api.twitch.tv/kraken/streams/' + streamName + '?callback=?', function(data){
    var streamObj = {};
    streamObj.streamName = data.stream.channel.display_name;
    streamObj.preview = data.stream.preview.medium;
    streamObj.status = data.stream.channel.status;
    streamObj.logo = data.stream.channel.logo;
    streamObj.url = data.stream._links.self;

    displayStream(streamObj);
  });
}

function displayStream( streamObj ) {
  $('#mainContainer').append(
    '
' +
    '' +
    '
' + streamObj.streamName + '
' +
    '
' + streamObj.status + '
' +
    '
'
  );
}

//onReady
$(function() {
  //temporary testing functionality
  $('#refreshBtn').on('click', function() {
    updateStreams();
  });
});

function updateStreams() {
  // Clear out the stale data
  $('#mainContainer').html("");
  // And fetch the fresh
  var streamList = $('#streamList').val().split('\n');
  for (var i = 0, len = streamList.length; i < len; i++) {
    fetchStreamData(streamList[i]);
  }
}

function fetchStreamData( streamName ) {
  $.getJSON('https://api.twitch.tv/kraken/streams/' + streamName + '?callback=?', function(data){
    var streamObj = {};
    streamObj.streamName = data.stream.channel.display_name;
    streamObj.preview = data.stream.preview.medium;
    streamObj.status = data.stream.channel.status;
    streamObj.logo = data.stream.channel.logo;
    streamObj.url = data.stream.channel.url;

    displayStream(streamObj);
  });
}

function displayStream( streamObj ) {
  $('
' +
      '' +
      '
' + streamObj.streamName + '
' +
      '
' + streamObj.status + '
' +
      '
'
  )
  .css('background-image', 'url(' + streamObj.preview + ')')
  .on('click', function() {
    window.open(streamObj.url, '_blank');
  })
  .appendTo($('#mainContainer'));
}

Refactor displayStream. Add background-image and onClick


/**
 * Created by leojin on 3/20/16.
 */
import ReactDom from 'react-dom';
import React from 'react';
import App from './App';

ReactDom.render(<App/>, document.getElementById("examples"));

/**
 * Created by leojin on 3/20/16.
 */
import ReactDom from 'react-dom';
import React from 'react';
import App from './app';

ReactDom.render(<App/>, document.getElementById("examples"));

Fix file name case on example import


'use strict';

var assign = require('object-assign');
var Filter = require('broccoli-filter');
var Rework = require('rework');

/**
 * Initialize `ReworkFilter` with options
 *
 * @param {Object} inputTree
 * @param {Object} opts
 * @api public
 */

function ReworkFilter(inputTree, opts) {
    if (!(this instanceof ReworkFilter)) {
        return new ReworkFilter(inputTree, opts);
    }

    this.inputTree = inputTree;
    this.opts = opts || {};
}

/**
 * Create object
 */

ReworkFilter.prototype = Object.create(Filter.prototype);
ReworkFilter.prototype.constructor = ReworkFilter;

/**
 * Extensions
 */

ReworkFilter.prototype.extensions = ['css'];
ReworkFilter.prototype.targetExtension = 'css';

/**
 * Process CSS
 *
 * @param {String} str
 * @api public
 */

ReworkFilter.prototype.processString = function (str) {
    var rework = new Rework(str);

    if (this.opts.use) {
        this.opts.use(rework);
    }

    return rework.toString(this.opts);
};

/**
 * Module exports
 */

module.exports = ReworkFilter;

/**
 * Mixin the rework built-in plugins
 */

delete Rework.properties;
assign(module.exports, Rework);

'use strict';

var assign = require('object-assign');
var Filter = require('broccoli-filter');
var Rework = require('rework');

/**
 * Initialize `ReworkFilter` with options
 *
 * @param {Object} inputTree
 * @param {Object} opts
 * @api public
 */

function ReworkFilter(inputTree, opts) {
    if (!(this instanceof ReworkFilter)) {
        return new ReworkFilter(inputTree, opts);
    }

    this.inputTree = inputTree;
    this.opts = opts || {};
}

/**
 * Create object
 */

ReworkFilter.prototype = Object.create(Filter.prototype);
ReworkFilter.prototype.constructor = ReworkFilter;

/**
 * Extensions
 */

ReworkFilter.prototype.extensions = ['css'];
ReworkFilter.prototype.targetExtension = 'css';

/**
 * Process CSS
 *
 * @param {String} str
 * @api public
 */

ReworkFilter.prototype.processString = function (str, relativePath) {
    var rework = new Rework(str, {
      source: relativePath
    });

    if (this.opts.use) {
        this.opts.use(rework);
    }

    return rework.toString(this.opts);
};

/**
 * Module exports
 */

module.exports = ReworkFilter;

/**
 * Mixin the rework built-in plugins
 */

delete Rework.properties;
assign(module.exports, Rework);

Set rework `source` from `relativePath`


'use strict'

var document = require('global/document')
var Loop = require('main-loop')
var virtualDom = require('virtual-dom')
var assert = require('assert')
var partial = require('ap').partial
var Delegator = require('dom-delegator')

// Instantiate a DOM delegator once, since it caches itself
Delegator()

exports.createComponent = createComponent

function createComponent (Component, data, callback) {
  assert(Component, 'Component is required')
  if (arguments.length < 2) return partial(createComponent, Component)

  if (typeof data === 'function') {
    callback = data
    data = undefined
  }

  // Call the component constructor to get a new state
  var state = Component(data)

  // Add an element for later use
  var div = document.createElement('div')
  document.body.appendChild(div)

  // create a raf rendering loop and add the target element to the dom
  var loop = Loop(state(), Component.render, virtualDom)
  div.appendChild(loop.target)
  // update the loop whenever the state changes
  state(loop.update)

  return callback(state, loop.target, destroy)

  function destroy () {
    // remove the element from the DOM
    document.body.removeChild(div)
  }
}

'use strict'

var document = require('global/document')
var Loop = require('main-loop')
var virtualDom = require('virtual-dom')
var assert = require('assert')
var partial = require('ap').partial
var Delegator = require('dom-delegator')

// Instantiate a DOM delegator once, since it caches itself
Delegator()

exports.createComponent = createComponent

function createComponent (Component, data, callback) {
  assert(Component, 'Component is required')
  if (arguments.length < 2) return partial(createComponent, Component)

  if (typeof data === 'function') {
    callback = data
    data = undefined
  }

  // Call the component constructor to get a new state
  var state = Component(data)

  // Add an element for later use
  var div = document.createElement('div')
  div.style.height = '100%'
  document.body.appendChild(div)

  // create a raf rendering loop and add the target element to the dom
  var loop = Loop(state(), Component.render, virtualDom)
  div.appendChild(loop.target)
  // update the loop whenever the state changes
  state(loop.update)

  return callback(state, loop.target, destroy)

  function destroy () {
    // remove the element from the DOM
    document.body.removeChild(div)
  }
}

Set component div to 100% height


export class DecoratorUtils {
  static declarationType = [
    "CLASS",
    "CLASS_METHOD",
    "CLASS_ACCESSOR",
    "OBJECT_LITERAL_METHOD",
    "OBJECT_LITERAL_ACCESSOR"
  ].reduce((obj, name) => {
    return Object.defineProperty(obj, name, { value: Symbol(name) });
  }, {})

  static getDeclarationType(args) {
    let [target, name, descriptor] = Array.slice(args);

    if (args.length === 1 && typeof target === "function") {
      return DecoratorUtils.declarationType.CLASS;
    } else if (args.length === 3 && typeof target === "object" && typeof target.constructor === "function") {
      let isObjectLiteral = target.constructor.name === "Object";
      let isAccessor = descriptor.get || descriptor.set;
      return DecoratorUtils.declarationType[`${isObjectLiteral ? "OBJECT_LITERAL" : "CLASS"}_${isAccessor ? "ACCESSOR" : "METHOD"}`];
    }

    return null;
  }
};

export class DecoratorUtils {
  static declarationType = [
    "CLASS",
    "CLASS_METHOD",
    "CLASS_ACCESSOR",
    "OBJECT_LITERAL_METHOD",
    "OBJECT_LITERAL_ACCESSOR"
  ].reduce((obj, name) => {
    return Object.defineProperty(obj, name, { value: Symbol(name) });
  }, {})

  static getDeclarationType(args) {
    let [target, name, descriptor] = Array.slice(args);

    if (args.length === 1 && typeof target === "function") {
      return DecoratorUtils.declarationType.CLASS;
    } else if (args.length === 3 && typeof target === "object" && typeof target.constructor === "function") {
      let isObjectLiteral = target.constructor.name === "Object";
      let isAccessor = descriptor.get || descriptor.set;
      return DecoratorUtils.declarationType[`${isObjectLiteral ? "OBJECT_LITERAL" : "CLASS"}_${isAccessor ? "ACCESSOR" : "METHOD"}`];
    }

    throw new Error("Invalid declaration type.");
  }
};

Throw an error for invalid declaration types


/* Copyright (C) 2017 Canonical Ltd. */

'use strict';

const React = require('react');

const DropdownMenu = require('./dropdown-menu');
const Panel = require('../panel/panel');

const jsTestUtils = require('../../utils/component-test-utils');

describe('Dropdown Menu', function() {

  function renderComponent(options={}) {
    return jsTestUtils.shallowRender(
      <DropdownMenu.WrappedComponent
        handleClickOutside={options.handleClickOutside}>
        {options.children}
      </DropdownMenu.WrappedComponent>, true);
  }

  it('can render', () => {
    const handleClickOutside = sinon.stub();
    const renderer = renderComponent({
      children:
child
,
      handleClickOutside: handleClickOutside
    });
    const output = renderer.getRenderOutput();
    const expected = (
      <Panel instanceName="dropdown-menu" visible={true}>

child

      </Panel>
    );
    expect(output).toEqualJSX(expected);
  });
});

/* Copyright (C) 2017 Canonical Ltd. */

'use strict';

const React = require('react');
const enzyme = require('enzyme');

const DropdownMenu = require('./dropdown-menu');

describe('Dropdown Menu', function() {

  const renderComponent = (options = {}) => enzyme.shallow(
    <DropdownMenu.WrappedComponent
      handleClickOutside={options.handleClickOutside || sinon.stub()}>
      {options.children}
    </DropdownMenu.WrappedComponent>
  );

  it('can render', () => {
    const wrapper = renderComponent({
      children:
child

    });
    const expected = (

child

    );
    assert.compareJSX(wrapper.find('.dropdown-menu__list'), expected);
  });
});

Update dropdown menu tests to use enzyme.


var needle = require('needle');

function Client(base_url, token) {
  this.base_url = base_url
  this.token = token || {}
}

Client.prototype.get = function (path, body, callback) {
  this.__send('get', path, body, callback);
}
Client.prototype.post = function (path, body, callback) {
  this.__send('post', path, body, callback);
}

Client.prototype.put = function (path, body, callback) {
  this.__send('put', path, body, callback);
}

Client.prototype.delete = function (path, body, callback) {
  this.__send('delete', path, body, callback);
}

Client.prototype.__send = function (method, path, body, callback) {
  var headers = { 'X-Ticket-Sharing-Version': '1' }
  if (this.token) {
    headers['X-Ticket-Sharing-Token'] = this.token
  }

  var options = {
    'headers': headers
  , 'json': true
  }

  needle.request(method, this.base_url + path, body, options, callback)
}

module.exports = Client

var needle = require('needle');

function Client(base_url, token) {
  this.base_url = base_url
  this.token = token || null
}

Client.prototype.get = function (path, body, callback) {
  this.__send('get', path, body, callback);
}
Client.prototype.post = function (path, body, callback) {
  this.__send('post', path, body, callback);
}

Client.prototype.put = function (path, body, callback) {
  this.__send('put', path, body, callback);
}

Client.prototype.delete = function (path, body, callback) {
  this.__send('delete', path, body, callback);
}

Client.prototype.__send = function (method, path, body, callback) {
  var headers = { 'X-Ticket-Sharing-Version': '1' }
  if (this.token) {
    headers['X-Ticket-Sharing-Token'] = this.token
  }

  var options = {
    'headers': headers
  , 'json': true
  }

  needle.request(method, this.base_url + path, body, options, callback)
}

module.exports = Client

Use null instead of empty object as {} != false but null == false


(function(ext) {
    // Cleanup function when the extension is unloaded
    ext._shutdown = function() {};

    // Status reporting code
    // Use this to report missing hardware, plugin or unsupported browser
    ext._getStatus = function() {
        // Check for the various File API support.
        if (window.File && window.FileReader && window.FileList && window.Blob) {
            return {status: 1, msg: 'The File APIs are not fully supported by your browser.'};
            //return {status: 2, msg: 'Ready'};
        } else {
            return {status: 1, msg: 'The File APIs are not fully supported by your browser.'};
        }
    };

        // Block and block menu descriptions
    var descriptor = {
        blocks: [
			['', 'My First Block', 'my_first_block'],
			['r', '%n ^ %n', 'power', 2, 3],
            ['r', '%m.k', 'k', 'heady']
        ],

        menus: {
	    k: ['headx', 'heady']
    }
    };

	ext.my_first_block = function() {
        console.log("hello, world.");
    };

    ext.power = function(base, exponent) {
        return Math.pow(base, exponent);
    };

    ext.k = function(m) {
        switch(m){
            case 'headx': return 1;
            case 'heady': return 2;
        }
    };

    // Register the extension
    ScratchExtensions.register('Kinect2Scratch', descriptor, ext);
})({});

(function(ext) {
    // Cleanup function when the extension is unloaded
    ext._shutdown = function() {};

    // Status reporting code
    // Use this to report missing hardware, plugin or unsupported browser
    ext._getStatus = function() {
        // Check for the various File API support.
        if (window.File && window.FileReader && window.FileList && window.Blob) {
            return {status: 2, msg: 'Ready'};
        } else {
            return {status: 0, msg: 'The File APIs are not fully supported by your browser.'};
        }
    };

        // Block and block menu descriptions
    var descriptor = {
        blocks: [
			['', 'My First Block', 'my_first_block'],
			['r', '%n ^ %n', 'power', 2, 3],
            ['r', '%m.k', 'k', 'heady']
        ],

        menus: {
	    k: ['headx', 'heady']
    }
    };

	ext.my_first_block = function() {
        console.log("hello, world.");
    };

    ext.power = function(base, exponent) {
        return Math.pow(base, exponent);
    };

    ext.k = function(m) {
        switch(m){
            case 'headx': return 1;
            case 'heady': return 2;
        }
    };

    // Register the extension
    ScratchExtensions.register('Kinect2Scratch', descriptor, ext);
})({});

Put statuses back to correct, adjust unsupported status


(function(app){

  "use strict"

  /**
   * Creates a filter to convert a time in milliseconds to
   * an hours:minutes:seconds format.
   *
   * e.g.
   * {{60000 | millisecondsToTime}} // 01:00
   * {{3600000 | millisecondsToTime}} // 01:00:00
   */
  app.filter("millisecondsToTime", MillisecondsToTime);

  function MillisecondsToTime(){
    return function(time){
      if(time < 0 || isNaN(time))
        return "";

      var seconds = parseInt((time / 1000) % 60);
      var minutes = parseInt((time / (60000)) % 60);
      var hours = parseInt((time / (3600000)) % 24);

      hours = (hours < 10) ? "0" + hours : hours;
      minutes = (minutes < 10) ? "0" + minutes : minutes;
      seconds = (seconds < 10) ? "0" + seconds : seconds;

      return ((hours !== "00") ? hours + ":" : "") + minutes + ":" + seconds;
    }
  };

})(angular.module("ov.player"));

(function(app){

  "use strict"

  /**
   * Creates a filter to convert a time in milliseconds to
   * an hours:minutes:seconds format.
   *
   * e.g.
   * {{60000 | millisecondsToTime}} // 01:00
   * {{3600000 | millisecondsToTime}} // 01:00:00
   */
  app.filter("millisecondsToTime", MillisecondsToTime);

  function MillisecondsToTime(){
    return function(time){
      if(time < 0 || isNaN(time))
        return "";

      time = parseInt(time);

      var seconds = parseInt((time / 1000) % 60);
      var minutes = parseInt((time / (60000)) % 60);
      var hours = parseInt((time / (3600000)) % 24);

      hours = (hours < 10) ? "0" + hours : hours;
      minutes = (minutes < 10) ? "0" + minutes : minutes;
      seconds = (seconds < 10) ? "0" + seconds : seconds;

      return ((hours !== "00") ? hours + ":" : "") + minutes + ":" + seconds;
    }
  };

})(angular.module("ov.player"));

Add security on time filter to be sure this is an integer and not a float


/* global document window */
import { focusFirstEl } from '../../../../../packages/spark-core/utilities/elementState';

const hideMobileNav = (nav) => {
  document.body.classList.remove('sprk-u-OverflowHidden');
  nav.classList.remove('is-active');
};

const focusTrap = (nav, mainNav) => {
  if (nav.classList.contains('is-active')) {
    focusFirstEl(mainNav);
  }
};

const bindUIEvents = () => {
  const nav = document.querySelector('.drizzle-o-Layout__nav');
  const mainNav = nav.querySelector('.drizzle-c-Navigation__main');
  const mainLayout = document.querySelector('.drizzle-o-Layout__main');

  window.addEventListener('resize', () => {
    hideMobileNav(nav);
  });

  mainLayout.addEventListener('focusin', () => {
    focusTrap(nav, mainNav);
  });
};

const mobileNav = () => {
  bindUIEvents();
};

export { mobileNav, hideMobileNav, focusTrap };

/* global document window */
import { focusFirstEl } from '../../../../../packages/spark-core/utilities/elementState';

const hideMobileNav = (nav) => {
  document.body.classList.remove('sprk-u-OverflowHidden');
  nav.classList.remove('is-active');
};

const focusTrap = (nav, mainNav) => {
  if (nav.classList.contains('is-active')) {
    focusFirstEl(mainNav);
  }
};

const bindUIEvents = () => {
  const nav = document.querySelector('.drizzle-o-Layout__nav');
  if (nav === null) return;
  const mainNav = nav.querySelector('.drizzle-c-Navigation__main');
  const mainLayout = document.querySelector('.drizzle-o-Layout__main');

  window.addEventListener('resize', () => {
    hideMobileNav(nav);
  });

  mainLayout.addEventListener('focusin', () => {
    focusTrap(nav, mainNav);
  });
};

const mobileNav = () => {
  bindUIEvents();
};

export { mobileNav, hideMobileNav, focusTrap };

Add check for if mobilenav exists


'use strict';

const externalDeps = [
	'@angular/*',
	'angular',
	'angular-mocks',
	'rxjs/*',
	'lodash',
	'moment',
	'moment-timezone',
];

const map = {
	'@angular': 'node_modules/@angular',
	'angular': 'node_modules/angular/angular',
	'angular-mocks': 'node_modules/angular-mocks/angular-mocks',
	'rxjs': 'node_modules/rxjs',
	'lodash': 'node_modules/lodash/index',
	'node-uuid': 'node_modules/node-uuid/uuid',
	'moment': 'node_modules/moment/moment',
	'moment-timezone': 'node_modules/moment-timezone/builds/moment-timezone-with-data.min',
}

let meta = {};
externalDeps.forEach(dep => {
	meta[dep] = { build: false };
});

System.config({
	meta,
	map,
	paths: {
		'*': '*.js',
	},
});

'use strict';

const externalDeps = [
	'@angular/*',
	'angular',
	'angular-mocks',
	'rxjs/*',
	'lodash',
	'moment',
	'moment-timezone',
];

const map = {
	'@angular': 'node_modules/@angular',
	'angular': 'node_modules/angular/angular',
	'angular-mocks': 'node_modules/angular-mocks/angular-mocks',
	'rxjs': 'node_modules/rxjs',
	'lodash': 'node_modules/lodash/index',
	'node-uuid': 'node_modules/node-uuid/uuid',
	'moment': 'node_modules/moment/moment',
	'moment-timezone': 'node_modules/moment-timezone/builds/moment-timezone-with-data.min',
};

const meta = externalDeps.reduce((curMeta, dep) => {
	curMeta[dep] = { build: false };
	return curMeta;
}, {});

System.config({
	meta,
	map,
	paths: {
		'*': '*.js',
	},
});

Use reduce to avoid mutating the object unneededly.


// Karma configuration
// http://karma-runner.github.io/0.10/config/configuration-file.html

module.exports = function(config) {
  config.set({
    // base path, that will be used to resolve files and exclude
    basePath: '',

    // testing framework to use (jasmine/mocha/qunit/...)
    frameworks: ['mocha', 'chai'],

    // list of files / patterns to load in the browser
    files: [
      'app/bower_components/angular/angular.js',
      'app/bower_components/angular-mocks/angular-mocks.js',
      'app/scripts/*.js',
      'app/scripts/**/*.js',
      'test/mock/**/*.js',
      'test/spec/**/*.js'
    ],

    // list of files / patterns to exclude
    exclude: [],

    // web server port
    port: 8080,

    // level of logging
    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: ['Firefox'],

    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false
  });
};

// Karma configuration
// http://karma-runner.github.io/0.10/config/configuration-file.html

module.exports = function(config) {
  config.set({
    // base path, that will be used to resolve files and exclude
    basePath: '',

    // testing framework to use (jasmine/mocha/qunit/...)
    frameworks: ['mocha', 'chai'],

		// reporter style
		reporters: [ 'dots' ],

		// list of files / patterns to load in the browser
    files: [
      'app/bower_components/angular/angular.js',
      'app/bower_components/angular-mocks/angular-mocks.js',
      'app/scripts/*.js',
      'app/scripts/**/*.js',
      'test/mock/**/*.js',
      'test/spec/**/*.js'
    ],

    // list of files / patterns to exclude
    exclude: [],

    // web server port
    port: 8080,

    // level of logging
    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: ['Firefox'],

    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false
  });
};

Change reporter style in Karma.


import React from 'react';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import AppBar from 'material-ui/AppBar';
import IconButton from 'material-ui/IconButton';
import IconMenu from 'material-ui/IconMenu';
import MenuItem from 'material-ui/MenuItem';
import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert';

/*
  Header
  Top of the full App
*/

var Header = React.createClass({
  handleTitleTouch : function() {
    this.props.history.push('/');
  },
  render : function() {
    return (
    <MuiThemeProvider>
       <AppBar
        title={MetaSeek}
        onTitleTouchTap={this.handleTitleTouch}
        iconElementLeft={

}
        iconElementRight={
          <IconMenu
            iconButtonElement={
              <IconButton><MoreVertIcon /></IconButton>
            }
            targetOrigin={{horizontal: 'right', vertical: 'top'}}
            anchorOrigin={{horizontal: 'right', vertical: 'top'}}
          >
            <MenuItem primaryText="Help" />
            <MenuItem primaryText="Sign out" />
          </IconMenu>
        }
      />
     </MuiThemeProvider>
    )
  }
});

export default Header;

import React from 'react';

import { Link } from 'react-router';

import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import AppBar from 'material-ui/AppBar';
import IconButton from 'material-ui/IconButton';
import IconMenu from 'material-ui/IconMenu';
import MenuItem from 'material-ui/MenuItem';
import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert';

/*
  Header
  Top of the full App
*/

var Header = React.createClass({
  handleTitleTouch : function() {
    this.props.history.push('/');
  },
  render : function() {
    return (
    <MuiThemeProvider>
       <AppBar
        title={MetaSeek}
        onTitleTouchTap={this.handleTitleTouch}
        iconElementLeft={

}
        iconElementRight={
          <IconMenu
            iconButtonElement={
              <IconButton><MoreVertIcon /></IconButton>
            }
            targetOrigin={{horizontal: 'right', vertical: 'top'}}
            anchorOrigin={{horizontal: 'right', vertical: 'top'}}
          >
            <Link style={{'text-decoration':'none'}} to='/myaccount'>
              <MenuItem primaryText="My Account" />
            </Link>
          </IconMenu>
        }
      />
     </MuiThemeProvider>
    )
  }
});

export default Header;

Add my account to header


import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['organization-profile'],

  credentials: Ember.inject.service(),

  organizationMembers: Ember.computed.mapBy('organization.organizationMemberships', 'organization'),

  didReceiveAttrs() {
    this._super(...arguments);
    this.get('credentials').set('currentOrganization', this.get('organization'));
  },

});

import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['organization-profile'],

  credentials: Ember.inject.service(),

  organizationMembers: Ember.computed.mapBy('organization.organizationMemberships', 'member'),

  didReceiveAttrs() {
    this._super(...arguments);
    this.get('credentials').set('currentOrganization', this.get('organization'));
  },
});

Fix organization profile by changing computed property


/**
 *
 * @flow
 */

'use strict';

import {StyleSheet} from 'react-native';

 const GlobalStyles = {
     contentWrapper: {
         paddingLeft: 5,
         paddingRight: 5,
     },
     sectionHeader: {
         fontSize: 20,
         marginTop: 10,
     },
     thumbnail: {
         height: 45,
         width: 45,
         borderRadius: 22, // why dafuq is 22 circular??
     },
     buttonContainer: {
         padding:10,
         paddingTop: 11,
         height:45,
         overflow:'hidden',
         borderRadius:4,
         backgroundColor: '#ededed'
     },
     separator: {
         flex: 1,
         height: StyleSheet.hairlineWidth,
         backgroundColor: '#8E8E8E',
     },
 };

 module.exports = GlobalStyles;

/**
 *
 * @flow
 */

'use strict';

import {StyleSheet} from 'react-native';

const GlobalStyles = {
    contentWrapper: {
        paddingLeft: 5,
        paddingRight: 5,
    },
    sectionHeader: {
        fontSize: 20,
        marginTop: 10,
    },
    thumbnail: {
        height: 45,
        width: 45,
        borderRadius: 22, // why dafuq is 22 circular??
    },
    buttonContainer: {
        padding:10,
        paddingTop: 11,
        height:45,
        overflow:'hidden',
        borderRadius:4,
        backgroundColor: '#ededed'
    },
    separator: {
        flex: 1,
        height: StyleSheet.hairlineWidth,
        backgroundColor: '#8E8E8E',
    },
    backBtn: {
        title: "Back",
        layout: "icon",
        icon: "ios-arrow-back",
    }
};

module.exports = GlobalStyles;

Add backBtn styling, fix indentation


const puppeteer = require("puppeteer")
const defaults = require("../configurations/defaults")

const puppeteerArgs = [
  "--no-sandbox",
  "--disable-setuid-sandbox",
  "--disable-gpu"
]

const allowedOptions = [
  "scale",
  "printBackground",
  "margin"
]

const formatOptions = options => allowedOptions.reduce((filtered, key) => {
  if (options[key] == 'true') {
    filtered[key] = true
    return filtered
  }

  if (options[key] == 'false') {
    filtered[key] = false
    return filtered
  }

  if (!isNaN(options[key])) {
    filtered[key] = +options[key]
    return filtered
  }

  filtered[key] = options[key]
  return filtered
}, {})

const pageToPdf = options => page =>
  page
    .goto(options.uri, { waitUntil: "networkidle" })
    .then(() => page.pdf(Object.assign(defaults, formatOptions(options))))

const browserToPdf = options => browser =>
  browser
    .newPage()
    .then(pageToPdf(options))
    .then(pdf => {
      browser.close()
      return pdf
    })

const uriToPdf = options =>
  puppeteer
    .launch({ args: puppeteerArgs })
    .then(browserToPdf(options))

module.exports = {
  uriToPdf
}

const puppeteer = require("puppeteer")
const defaults = require("../configurations/defaults")

const puppeteerArgs = [
  "--no-sandbox",
  "--disable-setuid-sandbox",
  "--disable-gpu"
]

const allowedOptions = [
  "scale",
  "displayHeaderFooter",
  "printBackground",
  "format",
  "landscape",
  "pageRanges",
  "width",
  "height",
  "margin"
]

const formatOptions = options => allowedOptions.reduce((filtered, key) => {
  if (options[key] == 'true') {
    filtered[key] = true
    return filtered
  }

  if (options[key] == 'false') {
    filtered[key] = false
    return filtered
  }

  if (!isNaN(options[key])) {
    filtered[key] = +options[key]
    return filtered
  }

  filtered[key] = options[key]
  return filtered
}, {})

const pageToPdf = options => page =>
  page
    .goto(options.uri, { waitUntil: "networkidle" })
    .then(() => page.pdf(Object.assign(defaults, formatOptions(options))))

const browserToPdf = options => browser =>
  browser
    .newPage()
    .then(pageToPdf(options))
    .then(pdf => {
      browser.close()
      return pdf
    })

const uriToPdf = options =>
  puppeteer
    .launch({ args: puppeteerArgs })
    .then(browserToPdf(options))

module.exports = {
  uriToPdf
}

Allow almost all puppeteer pdf configurations


'use strict';

const Winston = require('winston');

function Logger(level) {
  const logLevel = level.toLowerCase() || 'info';

  const logger = new Winston.Logger({
    level: logLevel,
    transports: [
      new Winston.transports.Console({
        colorize: false,
        timestamp: true,
        json: true,
        stringify: true
      })
    ]
  });

  return logger;
}

exports.attach = Logger;

'use strict';

const Winston = require('winston');

function Logger(level) {
  const logLevel = (level || 'info').toLowerCase();

  const logger = new Winston.Logger({
    level: logLevel,
    transports: [
      new Winston.transports.Console({
        colorize: false,
        timestamp: true,
        json: true,
        stringify: true
      })
    ]
  });

  return logger;
}

exports.attach = Logger;

Handle null and undefined log levels properly


'use strict'

var fs = require('fs')
var path = require('path')
var existFile = require('exists-file')

var minimistPath = path.join(__dirname, '..', 'node_modules', 'meow', 'node_modules', 'minimist')
var minimist = require(minimistPath)

var trimNewlinesPath = path.join(__dirname, '..', 'node_modules', 'meow', 'node_modules', 'trim-newlines')
var trimNewlines = require(trimNewlinesPath)

var FILENAME = 'worker-farm.opts'

function readConfig (filepath) {
  var yargs = process.argv.slice(2)
  if (yargs.length === 0) return yargs

  var filepath = path.resolve(yargs[yargs.length - 1], FILENAME)
  if (!existFile(filepath)) return yargs

  var config = fs.readFileSync(filepath, 'utf8')
  config = trimNewlines(config).split('\n')

  return config.concat(yargs)
}

module.exports = readConfig()

'use strict'

var fs = require('fs')
var path = require('path')
var existFile = require('exists-file')

var minimistPath = path.join(__dirname, '..', 'node_modules', 'meow', 'node_modules', 'minimist')
var minimist = require(minimistPath)

var trimNewlinesPath = path.join(__dirname, '..', 'node_modules', 'meow', 'node_modules', 'trim-newlines')
var trimNewlines = require(trimNewlinesPath)

var FILENAME = 'worker-farm.opts'

function readConfig (filepath) {
  var yargs = process.argv.slice(2)
  if (yargs.length > 1) return yargs

  var filepath = path.resolve(yargs[0], FILENAME)
  if (!existFile(filepath)) return yargs

  var config = fs.readFileSync(filepath, 'utf8')
  config = trimNewlines(config).split('\n')

  return config.concat(yargs)
}

module.exports = readConfig()

Load file if params are not present


import { remote } from 'electron';
import { call, select, put, takeLatest } from 'redux-saga/effects';
import GIF from './constants';
import { result, error, clear } from './actions';
import request from '../../utils/request';

export function* requestGif(action) {
  const requestURL = `http://api.giphy.com/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag=${action.payload}`;

  try {
    const gif = yield call(request, requestURL);
    const state = yield select();

    // Only continue displaying this result if the window is visible to the user
    // and they haven't blanked out the search box
    if (remote.getCurrentWindow().isVisible() && state.gif.currentQuery.length) {
      yield put(result(gif));
    } else {
      yield put(clear());
    }
  } catch (err) {
    yield put(error(err));
  }
}

export function* watchRequestGif() {
  yield takeLatest([GIF.REQUEST, GIF.NEXT], requestGif);
}

import { remote } from 'electron';
import { call, select, put, takeLatest } from 'redux-saga/effects';
import GIF from './constants';
import { result, error, clear } from './actions';
import request from '../../utils/request';

export function* requestGif(action) {
  // If there is no query given, grab the latest one from state
  const tag = action.payload
    ? action.payload
    : yield select(state => state.gif.currentQuery);

  const requestURL = `http://api.giphy.com/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag=${tag}`;

  try {
    const gif = yield call(request, requestURL);
    const state = yield select();

    // Only continue displaying this result if the window is visible to the user
    // and they haven't blanked out the search box
    if (remote.getCurrentWindow().isVisible() && state.gif.currentQuery.length) {
      yield put(result(gif));
    } else {
      yield put(clear());
    }
  } catch (err) {
    yield put(error(err));
  }
}

export function* watchRequestGif() {
  yield takeLatest([GIF.REQUEST, GIF.NEXT], requestGif);
}

Fix down button to dp the same tag search


import { connect } from 'react-redux';
import ContactUs from '../components/ContactUs';
import { submitForm } from '../actions/contact';

const mapStateToProps = (state) => ({
  contactStatus: state.contactStatus,
  defaultUserName: state.user.loggedUser && state.user.loggedUser.displayName,
  defaultUserEmail: state.user.loggedUser && state.user.loggedUser.email
});

const mapDispatchToProps = (dispatch) => ({
  submitForm: (data, endpoint) => dispatch(submitForm(data, endpoint))
});
export default connect(mapStateToProps, mapDispatchToProps)(ContactUs);

import { connect } from 'react-redux';
import ContactUs from '../components/ContactUs';
import { submitForm } from '../actions/contact';

const mapStateToProps = (state) => ({
  contactStatus: state.contactStatus,
  defaultUserName: state.user.loggedUser ? state.user.loggedUser.displayName : '',
  defaultUserEmail: state.user.loggedUser ? state.user.loggedUser.email : ''
});

const mapDispatchToProps = (dispatch) => ({
  submitForm: (data, endpoint) => dispatch(submitForm(data, endpoint))
});
export default connect(mapStateToProps, mapDispatchToProps)(ContactUs);

Fix issue when logging out on contact page


var AJAX_LOADER = '';

$(document).bind('ajaxComplete', function () {
    $('.ajax_loader').remove();
});

var AJAX_LOADER = '';

$(document).bind('ajaxComplete', function () {
    $('.ajax_loader').remove();

    $('form').removeData('submitted');
});

Mark forms as not submitted after AJAX complete.


var fs = require('fs'),
	path = require('path'),
	util = require('../lib/util');

var Source = util.inherit(Object, {
		_initialize: function (root) {
			this._root = root;
		},

		travel: function (callback, pathname) {
			pathname = pathname || '';

			var root = this._root,
				node = path.join(root, pathname),
				stats = fs.statSync(node),
				self = this;

			if (stats.isFile()) {
				callback(pathname, fs.readFileSync(node));
			} else if (stats.isDirectory()) {
				fs.readdirSync(node).forEach(function (filename) {
					self.travel(callback, path.join(pathname, filename));
				});
			}
		}
	});

module.exports = Source;

var fs = require('fs'),
	path = require('path'),
	util = require('../lib/util');

var Source = util.inherit(Object, {
		_initialize: function (root) {
			this._root = root;
		},

		travel: function (callback, pathname) {
			pathname = pathname || '';

			var root = this._root,
				node = path.join(root, pathname),
				stats = fs.statSync(node),
				self = this;

			if (stats.isFile()) {
				callback(pathname, fs.readFileSync(node));
			} else if (stats.isDirectory() && pathname.charAt(0) != '.'){
				fs.readdirSync(node).forEach(function (filename) {
					self.travel(callback, path.join(pathname, filename));
				});
			}
		}
	});

module.exports = Source;

Fix read hidden directory error.