$(
    function() {
        var converter = new showdown.Converter();
        const loadedAttr = "loaded";
        const repoAttr = "repo";
        $("#load-md-btn-base").click(function () {
            var clickedElement = $(this);
            var loaded = clickedElement.attr(loadedAttr);
            if (loaded === "false") {
                var repositoryUrl = clickedElement.attr(repoAttr);
                $.get(
                    repositoryUrl + "/master/license-report.md",
                    function (data) {
                        var html = converter.makeHtml(data);
                        $("#md-destination-base").html(html);
                        clickedElement.attr(loadedAttr, "true");
                    }
                );
            }
        });
    }
);

$(
    function() {
        var converter = new showdown.Converter();
        const loadedAttr = "loaded";
        const repoAttr = "repo";

        $("#load-md-btn-base").click(function () {
            var clickedElement = $(this);
            var mdDestinationID = $("#md-destination-base");
            var loaded = clickedElement.attr(loadedAttr);

            if (loaded === "false") {
                var repositoryUrl = clickedElement.attr(repoAttr);
                $.get(
                    repositoryUrl + "/master/license-report.md",
                    function (data) {
                        var html = converter.makeHtml(data);
                        mdDestinationID.html(html);
                        clickedElement.attr(loadedAttr, "true");
                        makeCollapsibleTitle(mdDestinationID);
                    }
                );
            }
        });

        function makeCollapsibleTitle(mdDestinationID) {
            var h1Elements = mdDestinationID.find("h1");
            var h2Elements = mdDestinationID.find("h2");

            h1Elements.addClass("dependencies-title");

            h2Elements.each(function(index, element) {
                const titleID = this.id + "_1";
                $(element).addClass("collapse-link collapsed");
                $(element).attr("href", "#" + titleID);
                $(element).attr("data-toggle", "collapse");
                $(element).next("ol").addClass("dependencies-container collapse");
                $(element).next("ol").attr("id", titleID);
                $(element).next("ol").next("p").css("display", "none");
                $(element).next("ol").find("a").addClass("external");
                $(element).next("ol").find("a").attr("target", "_blank");
            });
        }
    }
);

Add needed classes and id to elements to make them collapsible


"use strict";

var socket = io();

var username;
$(window).load(function() {
    username = prompt("Please enter your name");
    socket.emit('log on', username);
});

$(window).on('beforeunload', function() {
  socket.emit('log off', username);
});

function userActivity(name, joinedOrLeft) {
  alert(name + " " + joinedOrLeft + " the game");
}
socket.on('log on', function(name) {
  userActivity(name, "joined");
});
socket.on('log off', function(name) {
  userActivity(name, "left");
});

function getCardID(targetNode) {
  console.log(targetNode);
  if (targetNode.className === 'card') {
    return targetNode.id;
  }
  else {
    return getCardID(targetNode.parentNode);
  }
}

$('.card').click(function(event) {
  var cardID = getCardID(event.target);

  console.log(username, "clicked card", cardID);
  socket.emit('card click', username, cardID);
});

"use strict";

var socket = io();

var username;
$(window).load(function() {
    username = prompt("Please enter your name");
    socket.emit('log on', username);
});

$(window).on('beforeunload', function() {
  socket.emit('log off', username);
});

function userActivity(name, joinedOrLeft) {
  alert(name + " " + joinedOrLeft + " the game");
}
socket.on('log on', function(name) {
  userActivity(name, "joined");
});
socket.on('log off', function(name) {
  userActivity(name, "left");
});

function getCardID(targetNode) {
  if (targetNode.className === 'card') {
    return targetNode.id;
  }
  else {
    return getCardID(targetNode.parentNode);
  }
}
$('.card').click(function(event) {
  var cardID = getCardID(event.target);

  console.log(username, "clicked card", cardID);
  socket.emit('card click', {'user':username, 'card':cardID});
});

Remove unnecessary logging, emit card click data as object


var express = require('express');
var http = require('http');
var socket = require('socket.io');
var SamsungRemote = require('samsung-remote');

var app = express();
var port = process.env.PORT || 8080;

app.disable('etag');

var server = http.createServer(app).listen(port, function() {
  console.log('Express server listening on port ' + port);
});

var io = socket.listen(server);

io.sockets.on('connection', function(socket){
  console.log('New client connected');
  socket.emit('welcome', 'hello! You are now connected');

  var remote = new SamsungRemote({
    ip: '192.168.1.1'
  });
});

var express = require('express');
var http = require('http');
var socket = require('socket.io');
var SamsungRemote = require('samsung-remote');

var app = express();
var port = process.env.PORT || 8080;

app.disable('etag');

var server = http.createServer(app).listen(port, function() {
  console.log('Express server listening on port ' + port);
});

var io = socket.listen(server);

io.sockets.on('connection', function(socket){
  console.log('New client connected');
  socket.emit('welcome', 'hello! You are now connected');

  var remote = new SamsungRemote({
    ip: '192.168.1.1'
  });

  socket.on('ip', function(ip){
    remote.config.ip = ip;
    console.log('New IP defined : ' + ip);
    socket.emit('ip', 'New IP defined : ' + ip);
  });
});

Add socket event : `ip`


var express = require('express');
var multiparty = require('multiparty');
var fs = require('fs');
var _ = require('underscore');

var app = express();

var steghide_embed = require('.').steghide_embed;

app.post('/embed', function(req, res) {
  var form = new multiparty.Form({
    uploadDir: '/tmp/stegosaurus',
  });
  form.parse(req, function(err, fields, files) {
    if(err) {
      res.status(401).send('401 Bad request');
      return false;
    }

    var steghidden_path = steghide_embed(
      files.the_image[0].path,
      files.the_secret[0].path,
      fields.the_password[0]
    );

    res.download(steghidden_path, 'steghidden-' + files.the_image[0].originalFilename);

    _(files.the_image).each(function(file) { fs.unlink(file.path); });
    _(files.the_secret).each(function(file) { fs.unlink(file.path); });
  });
});

app.use(express.static('public'));

var server = app.listen(8080, function() {
  var host = server.address().address;
  var port = server.address().port;
  console.log('Stegosaurus service listening at http://%s:%s', host, port);
});

var express = require('express');
var multiparty = require('multiparty');
var fs = require('fs');
var _ = require('underscore');

var app = express();

var steghide_embed = require('.').steghide_embed;

app.post('/embed', function(req, res) {
  var form = new multiparty.Form({
    uploadDir: '/tmp/stegosaurus',
  });
  form.parse(req, function(err, fields, files) {
    if(err) {
      res.status(401).send('401 Bad request');
      return false;
    }

    var image_path = files.the_image[0].path;
    var secret_path = files.the_secret[0].path;

    var steghidden_path = steghide_embed(
      image_path,
      secret_path,
      fields.the_password[0]
    );

    function cleanup(image_path, secret_path, steghidden_path) {
      _([image_path, secret_path, steghidden_path]).each(function(path) { fs.unlink(path); });
    }

    res.download(steghidden_path, 'steghidden-' + files.the_image[0].originalFilename, function(err) {
      cleanup(image_path, secret_path, steghidden_path);
    });
  });
});

app.use(express.static('public'));

var server = app.listen(8080, function() {
  var host = server.address().address;
  var port = server.address().port;
  console.log('Stegosaurus service listening at http://%s:%s', host, port);
});

Clean up temporary files properly


/**
 * React form server.The simplest server ever.
 *
 * This Express application serves the contact form with its
 * assets and processes the submission. A lot of aspects
 * of a real life application have been omitted here
 * for the sake of simplicity such as form validation and
 * security.
 */

var bodyParser = require('body-parser');
var fs = require('fs');
var express = require('express');
var app = express();

// Exposes public assets such as index.html and JavaScript files.
app.use(express.static('public'));

// Adds support for JSON-encoded bodies used in POST requests.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

// Processes a form submission.
app.post('/send', function (req, res) {
  console.log(req.body);
  return res.send({status: 'OK'});
});

// Starts the web application.
var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;
});

/**
 * React form server.The simplest server ever.
 *
 * This Express application serves the contact form with its
 * assets and processes the submission. A lot of aspects
 * of a real life application have been omitted here
 * for the sake of simplicity such as form validation and
 * security.
 */

var bodyParser = require('body-parser');
var express = require('express');
var app = express();

// Sets the port to use.
app.set('port', (process.env.PORT || 3000));

// Exposes public assets such as index.html and JavaScript files.
app.use(express.static('public'));

// Adds support for JSON-encoded bodies used in POST requests.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

// Processes a form submission.
app.post('/send', function (req, res) {
  console.log(req.body);
  return res.send({status: 'OK'});
});

// Starts the web application.
var server = app.listen(app.get('port'), function () {
  console.log('App is running at port', app.get('port'));
});

Set application port and remove fs dependency


var os = require('os')
  , http = require('http')

var start = new Date()

function secondsSince(when) {
  return (new Date() - when) / 1000
}

function uptime() {
  return '' + secondsSince(start)
}

http.createServer(function(req, res) {
  var body = os.hostname() + ' has been up for ' + uptime() + 's.'

  res.writeHead(200, {
    'Content-Type' : 'text/plain'
  , 'Content-Length' : body.length
  })

  res.end(body)
}).listen(80)

var os = require('os')
  , http = require('http')

var start = new Date()

function secondsSince(when) {
  return (new Date() - when) / 1000
}

function uptime() {
  return '' + secondsSince(start)
}

http.createServer(function(req, res) {
  var body = os.hostname() + ' has been up for ' + uptime() + 's.'

  res.writeHead(200, {
    'Content-Type' : 'text/plain'
  , 'Content-Length' : body.length
  })

  res.end(body)
}).on('error', function(err){
  console.log('error: ' + err)
}).listen(8080)

Update handler; handle error event


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

function WebService(currentUser) {
	this._currentUser = currentUser;
	this._dependencies = {};
	this.runRef = undefined;
}

WebService.prototype.runWrapper = function () {
	var self = this;

	return function (name, allowedTypeAccount, params) {
		name = name || 'accessDenied';
		allowedTypeAccount = allowedTypeAccount || [];
		params = params || {};

		return function (req, res) {
			params.req = req;
			params.res = res;
			self.runRef(name, allowedTypeAccount, params);
		};
	};
};

WebService.prototype.run = function (name, allowedTypeAccount, params) {
	allowedTypeAccount = allowedTypeAccount || [];
	params = params || {};

	var self = this;
	var permissionsInit = new PermissionConstructor(allowedTypeAccount, this._currentUser);
	var webServices = require('../ServiceDirectories/Web/Public');

	if (permissionsInit.check()) {
		webServices[name].call(undefined, self._dependencies, params);
	} else {
		webServices['accessDenied'].call(undefined, self._dependencies, params);
	}
};

WebService.prototype.addDependency = function (name, value) {
	this._dependencies[name] = value;
};

module.exports.WebService = WebService;

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

function WebService(currentUser) {
	this._currentUser = currentUser;
	this._dependencies = {};
	this.runRef = undefined;
}

WebService.prototype.runWrapper = function () {
	var self = this;

	return function (name, allowedTypeAccount, params) {
		name = name || 'accessDenied';
		allowedTypeAccount = allowedTypeAccount || [];
		params = params || {};

		return function (req, res) {
			params.req = req;
			params.res = res;
			self.runRef(name, allowedTypeAccount, params);
		};
	};
};

WebService.prototype.run = function (name, allowedTypeAccount, params) {
	allowedTypeAccount = allowedTypeAccount || [];
	params = params || {};

	var self = this;
	var permissionsInit = new PermissionConstructor(allowedTypeAccount, this._currentUser);
	var webServices = require('../ServiceDirectories/Web/Public');

	if (permissionsInit.check()) {
		webServices[name].call(undefined, self._dependencies, params);
	} else {
		webServices['accessDenied'].call(undefined, self._dependencies, params);
	}
};

WebService.prototype.addDependency = function (name, value) {
	if (!this._dependencies[name]) {
		this._dependencies[name] = value;
	}
};

module.exports.WebService = WebService;

Add condition which checking if dependency already exists.


const expect = require('chai').expect;
const fs = require('fs');
const path = require('path');
const pluginRunner = require('../lib/plugin_runner');

describe('goog.defineClass to ES6 class', () => {

  const convert = function(fileName) {
    const testFilePath = path.join(__dirname, fileName);
    // Add new line at the end to match the expected file.
    return pluginRunner.run(testFilePath);
  };

  const readFile = function(fileName) {
    return fs.readFileSync(path.join(__dirname, fileName), 'utf8');
  };

  it('converts file to es6', () => {
    expect(convert('with_statics_es5.js')).to.equal(
        readFile('with_statics_es6.js'));
  });

  it('converts file with parent', () => {
    expect(convert('inheritance_es5.js')).to.equal(
        readFile('inheritance_es6.js'));
  });

  it('converts statics', function() {
    expect(convert('static_functions_es5.js')).to.equal(
        readFile('static_functions_es6.js'));
  });
});

const expect = require('chai').expect;
const fs = require('fs');
const path = require('path');
const pluginRunner = require('../lib/plugin_runner');

describe('goog.defineClass to ES6 class', () => {

  const convert = function(fileName) {
    const testFilePath = path.join(__dirname, fileName);
    // Add new line at the end to match the expected file.
    return pluginRunner.run(testFilePath);
  };

  const readFile = function(fileName) {
    return fs.readFileSync(path.join(__dirname, fileName), 'utf8');
  };

  it('converts file to es6', () => {
    expect(convert('with_statics_es5.js')).to.equal(
        readFile('with_statics_es6.js'));
  });

  it('converts file with parent', () => {
    expect(convert('inheritance_es5.js')).to.equal(
        readFile('inheritance_es6.js'));
  });

  it('converts statics', function() {
    expect(convert('static_functions_es5.js')).to.equal(
        readFile('static_functions_es6.js'));
  });

  it('skips file without goog.defineClass', function() {
    // A file without goog.defineClass will be skipped.
    expect(convert('without_goog_define_class.js')).to.equal(
        readFile('without_goog_define_class.js'));
  });
});

Add test to ensure files without goog.defineClass are skipped


var Toolbelt = require('./lib/toolbelt').Toolbelt;
var entry = require('./lib/entry');

exports.init = function (config, job, jobContext, callback) {
  callback(null, {
    env: {},
    path: [],

    deploy: function (phaseContext, cb) {
      var toolbelt = new Toolbelt(config, job, jobContext, phaseContext);

      entry.prepareControlRepository(toolbelt, function (err) {
        cb(err, true);
      });
    }
  });
};

var Toolbelt = require('strider-deconst-common').Toolbelt;
var entry = require('./lib/entry');

exports.init = function (config, job, jobContext, callback) {
  callback(null, {
    env: {},
    path: [],

    deploy: function (phaseContext, cb) {
      var toolbelt = new Toolbelt(config, job, jobContext, phaseContext);

      if (hadError(toolbelt.connectToDocker()), cb) return
      if (hadError(toolbelt.connectToGitHub()), cb) return
      if (hadError(toolbelt.connectToContentService(true), cb) return

      entry.prepareControlRepository(toolbelt, function (err) {
        cb(err, true);
      });
    }
  });
};

var hadError = function (err, callback) {
  if (err) {
    err.type = 'exitCode';
    err.code = 1;

    if (callback) callback(err);
    return true
  }

  return false
}

Use the common package's Toolbelt.


// Casts a rating
var rate = function (event) {
  "use strict";
  event.preventDefault();
  var star = event.target;
  var post = star.parentElement.parentElement.parentElement.dataset.post;
  var starNum = event.target.dataset.num;
  var oldRating = $('div[data-post=' + post + ']').attr('data-rating');
  $('div[data-post=' + post + ']').attr('data-rating', starNum);
  var setStarHighlight = function () {
    console.log(oldRating);
    if ($(this).data("num") <= starNum) {
      $(this).removeClass('fa-star-o rate-' + oldRating).addClass('fa-star rate-' + starNum);
    } else {
      console.log(oldRating);
      $(this).removeClass('fa-star rate-' + oldRating).addClass('fa-star-o');
    }
  }
  $('div[data-post=' + post + '] .star').each(setStarHighlight);
};

Template.feed.events({
  'click .star': rate
});

// Casts a rating
var rate = function (event) {
  "use strict";
  event.preventDefault();
  var star = event.target;
  var post = star.parentElement.parentElement.parentElement.dataset.post;
  var starNum = event.target.dataset.num;
  var oldRating = $('div[data-post=' + post + ']').attr('data-rating');
  $('div[data-post=' + post + ']').attr('data-rating', starNum);
  var setStarHighlight = function () {
    console.log(oldRating);
    if ($(this).data("num") <= starNum) {
      $(this)
      .removeClass('fa-star-o rate-' + oldRating)
      .addClass('fa-star rate-' + starNum);
    } else {
      console.log(oldRating);
      $(this)
      .removeClass('fa-star rate-' + oldRating)
      .addClass('fa-star-o');
    }
  };
  $('div[data-post=' + post + '] .star').each(setStarHighlight);
};

Template.feed.events({
  'click .star': rate
});

Clean up code to appease jshint


import styled from 'styled-components';

const PaneRow = styled.div.withConfig({ displayName: 'PaneRow' })`
  display: flex;
  flex-direction: row;
  width: 100%;
  align-items: flex-start;

  & > * {
    flex: 1;
    border-right: ${({ theme }) => theme.pane.border};
  }

  & > *:last-child {
    border-right: none;
  }
`;

PaneRow.usage = `
# PaneRow

A composeable column. Lays out children horizontally. Applies a divider between children.

\`\`\`
<PaneRow>
  <Pane>Content</Pane>
  <Pane>Content</Pane>
</PaneRow>
\`\`\`
`;

export default PaneRow;

import styled from 'styled-components';

const PaneRow = styled.div.withConfig({ displayName: 'PaneRow' })`
  display: flex;
  flex-direction: row;
  width: 100%;
  align-items: flex-start;

  & > * {
    flex: 1;
    border-right: ${({ theme }) => theme.pane.border};
    border-left: ${({ theme }) => theme.pane.border};
    margin-left: -1px;
  }

  & > *:first-child {
    margin-left: 0;
    border-left: none;
  }

  & > *:last-child {
    border-right: none;
  }
`;

PaneRow.usage = `
# PaneRow

A composeable column. Lays out children horizontally. Applies a divider between children.

\`\`\`
<PaneRow>
  <Pane>Content</Pane>
  <Pane>Content</Pane>
</PaneRow>
\`\`\`
`;

export default PaneRow;

Improve separating borders on panes


'use strict'

var test = require('tape')
var Router = require('../')

test('global hook', function (t) {
  t.plan(2)

  var state = Router({
    path: '/packages/sour'
  })
  var value = null

  Router.route(state, {
    path: '/packages/:name',
    render: function () {
      return value
    }
  })

  Router.hook(state, 'enter.before', function (params, callback) {
    t.deepEqual(params, {name: 'sour'})
    value = 'hooked'
    callback()
  })

  state.active(function onChange () {
    t.equal(Router.render(state()), 'hooked')
  })

  Router.watch(state)
})

'use strict'

var test = require('tape')
var Router = require('../')

test('hooks', function (t) {
  t.test('global', function (t) {
    t.plan(2)

    var state = Router({
      path: '/packages/sour'
    })
    var values = []

    Router.route(state, {
      path: '/packages/:name',
      render: function () {
        return values.join(',')
      }
    })

    Router.hook(state, 'enter.before', function (params, callback) {
      t.deepEqual(params, {name: 'sour'})
      process.nextTick(function () {
        values.push(0)
        callback()
      })
    })

    Router.hook(state, 'enter.before', function (params, callback) {
      values.push(1)
      callback()
    })

    state.active(function onChange () {
      t.equal(Router.render(state()), '0,1')
    })

    Router.watch(state)
  })
})

Update hook test to test serial execution


import { extend } from 'flarum/extension-utils';
import ActionButton from 'flarum/components/action-button';
import PostComment from 'flarum/components/post-comment';

export default function() {
  extend(PostComment.prototype, 'actionItems', function(items) {
    var post = this.props.post;
    if (post.isHidden()) return;

    items.add('reply',
      ActionButton.component({
        icon: 'reply',
        label: 'Reply',
        onclick: () => {
          var component = post.discussion().replyAction();
          if (component) {
            var quote = window.getSelection().toString();
            var mention = '@'+post.user().username()+'#'+post.number()+' ';
            component.editor.insertAtCursor(quote ? '> '+mention+quote+'\n\n' : mention);

            // If the composer is empty, then assume we're starting a new reply.
            // In which case we don't want the user to have to confirm if they
            // close the composer straight away.
            if (!component.content()) {
              component.props.originalContent = mention;
            }
          }
        }
      })
    );
  });
}

import { extend } from 'flarum/extension-utils';
import ActionButton from 'flarum/components/action-button';
import PostComment from 'flarum/components/post-comment';

export default function() {
  extend(PostComment.prototype, 'actionItems', function(items) {
    var post = this.props.post;
    if (post.isHidden()) return;

    items.add('reply',
      ActionButton.component({
        icon: 'reply',
        label: 'Reply',
        onclick: () => {
          var component = post.discussion().replyAction();
          if (component) {
            var quote = window.getSelection().toString();
            var mention = '@'+post.user().username()+'#'+post.number()+' ';
            component.editor.insertAtCursor((component.editor.value() ? '\n\n' : '')+(quote ? '> '+mention+quote+'\n\n' : mention));

            // If the composer is empty, then assume we're starting a new reply.
            // In which case we don't want the user to have to confirm if they
            // close the composer straight away.
            if (!component.content()) {
              component.props.originalContent = mention;
            }
          }
        }
      })
    );
  });
}

Insert newlines into composer before post mentions


import { extend } from 'flarum/extension-utils';
import ActionButton from 'flarum/components/action-button';
import CommentPost from 'flarum/components/comment-post';

export default function() {
  extend(CommentPost.prototype, 'actionItems', function(items) {
    var post = this.props.post;
    if (post.isHidden()) return;

    items.add('reply',
      ActionButton.component({
        icon: 'reply',
        label: 'Reply',
        onclick: () => {
          var component = post.discussion().replyAction();
          if (component) {
            var quote = window.getSelection().toString();
            var mention = '@'+post.user().username()+'#'+post.number()+' ';

            // If the composer is empty, then assume we're starting a new reply.
            // In which case we don't want the user to have to confirm if they
            // close the composer straight away.
            if (!component.content()) {
              component.props.originalContent = mention;
            }

            component.editor.insertAtCursor((component.editor.value() ? '\n\n' : '')+(quote ? '> '+mention+quote+'\n\n' : mention));
          }
        }
      })
    );
  });
}

import { extend } from 'flarum/extension-utils';
import ActionButton from 'flarum/components/action-button';
import CommentPost from 'flarum/components/comment-post';

export default function() {
  extend(CommentPost.prototype, 'actionItems', function(items) {
    var post = this.props.post;
    if (post.isHidden()) return;

    function insertMention(component, quote) {
      var mention = '@'+post.user().username()+'#'+post.number()+' ';

      // If the composer is empty, then assume we're starting a new reply.
      // In which case we don't want the user to have to confirm if they
      // close the composer straight away.
      if (!component.content()) {
        component.props.originalContent = mention;
      }

      component.editor.insertAtCursor((component.editor.getSelectionRange()[0] > 0 ? '\n\n' : '')+(quote ? '> '+mention+quote.trim().replace(/\n/g, '\n> ')+'\n\n' : mention));
    }

    items.add('reply',
      ActionButton.component({
        icon: 'reply',
        label: 'Reply',
        onclick: () => {
          var quote = window.getSelection().toString();

          var component = app.composer.component;
          if (component && component.props.post && component.props.post.discussion() === post.discussion()) {
            insertMention(component, quote);
          } else {
            post.discussion().replyAction().then(component => insertMention(component, quote));
          }
        }
      })
    );
  });
}

Use new replyAction promise implementation


'use strict'

import test from 'tape'
import majors from '../'

test((t) => {
  t.deepEqual(majors('> 2 < 5'), ['3', '4'])
  t.deepEqual(majors('< 5 > 2'), ['3', '4'])
  t.deepEqual(majors('>= 2.3.0 < 5'), ['2', '3', '4'])

  t.throws(majors.bind(null, '> 2 > 10'), /unbounded/)
  t.throws(majors.bind(null, '> 2'), /unbounded/)
  t.deepEqual(majors('>= 2', '4.3.2'), ['2', '3', '4'], 'unbounded with maximum');

  t.end()
})

'use strict'

import test from 'tape'
import majors from '../'

test((t) => {
  t.deepEqual(majors('2'), ['2'])
  t.deepEqual(majors('> 2 < 5'), ['3', '4'])
  t.deepEqual(majors('< 5 > 2'), ['3', '4'])
  t.deepEqual(majors('>= 2.3.0 < 5'), ['2', '3', '4'])

  t.throws(majors.bind(null, '> 2 > 10'), /unbounded/)
  t.throws(majors.bind(null, '> 2'), /unbounded/)
  t.deepEqual(majors('>= 2', '4.3.2'), ['2', '3', '4'], 'unbounded with maximum');

  t.end()
})

Add test for = operator


var async = require("async");
var bay6 = require("../lib/");
var expect = require("chai").expect;
var mongoose = require("mongoose");
var request = require("supertest");

describe("Model", function() {
  var app;
  var server;
  var model;

  beforeEach(function() {
    app = bay6();
    app.options.prefix = "";
    model = app.model("Document", {
      title: String,
      contents: String
    });
  });

  describe("#limit", function() {
    it("should return a maximum of n documents", function(done) {
      model.limit(5);

      server = app.serve(9000);
      populateAndGet(function(err, res) {
        expect(res.body.length).to.equal(5);
        done();
      });
    });
  });

  afterEach(function(done) {
    app.mongoose.db.dropDatabase(done);
    server.close();
  });

  function populateAndGet(cb) {
    var Document = app.mongoose.model("Document");
    async.each([1, 2, 3, 4, 5, 6], function(useless, done2) {
      var doc = new Document({ title: "war and peace", contents: "yolo" });
      doc.save(done2);
    }, function(err) {
      if (err) {
        throw err;
      }
      request(server).get("/documents").end(cb);
    });
  }
});

var async = require("async");
var bay6 = require("../lib/");
var expect = require("chai").expect;
var mongoose = require("mongoose");
var request = require("supertest");

describe("Model", function() {
  var app;
  var server;
  var model;

  beforeEach(function() {
    app = bay6();
    app.options.prefix = "";
    model = app.model("Document", {
      title: String,
      contents: String
    });
  });

  describe("#limit", function() {
    it("should return a maximum of n documents", function(done) {
      model.limit(5);

      populateAndGet(function(err, res) {
        expect(res.body.length).to.equal(5);
        done();
      });
    });
  });

  afterEach(function(done) {
    app.mongoose.db.dropDatabase(done);
    server.close();
  });

  function populateAndGet(cb) {
    server = app.serve(9000);
    var Document = app.mongoose.model("Document");
    async.each([1, 2, 3, 4, 5, 6], function(useless, done2) {
      var doc = new Document({ title: "war and peace", contents: "yolo" });
      doc.save(done2);
    }, function(err) {
      if (err) {
        throw err;
      }
      request(server).get("/documents").end(cb);
    });
  }
});

Move defining the server into populateAndGet helper


define(function () {
  var self = {};

  self.distance = function distance(a, b) {
    return Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2);
  };

  self.distancePoint = function distancePoint(a, b) {
    return Math.sqrt(self.distance(a, b));
  };

  self.distanceLink = function distanceLink(p, a, b) {
    /* http://stackoverflow.com/questions/849211 */
    var l2 = self.distance(a, b);
    if (l2 === 0) {
      return self.distance(p, a);
    }
    var t = ((p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y)) / l2;
    if (t < 0) {
      return self.distance(p, a);
    } else if (t > 1) {
      return self.distance(p, b);
    }
    return self.distancePoint(p, {
      x: a.x + t * (b.x - a.x),
      y: a.y + t * (b.y - a.y)
    });
  };

  return self;
});

define(function () {
  var self = {};

  self.distance = function distance(a, b) {
    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
  };

  self.distancePoint = function distancePoint(a, b) {
    return Math.sqrt(self.distance(a, b));
  };

  self.distanceLink = function distanceLink(p, a, b) {
    /* http://stackoverflow.com/questions/849211 */
    var l2 = self.distance(a, b);
    if (l2 === 0) {
      return self.distance(p, a);
    }
    var t = ((p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y)) / l2;
    if (t < 0) {
      return self.distance(p, a);
    } else if (t > 1) {
      return self.distance(p, b);
    }
    return self.distancePoint(p, {
      x: a.x + t * (b.x - a.x),
      y: a.y + t * (b.y - a.y)
    });
  };

  return self;
});

Replace Math.pow to improve performance


import { assert } from 'chai';

import { expandNodesToLevel } from '../src';

const nestedTree = [{
    value: '0',
    label: 'Node 0',
    children: [{
        value: '0-0',
        label: 'Node 0-0',
    }, {
        value: '0-1',
        label: 'Node 0-1',
        children: [{
            value: '0-1-0',
            label: 'Node 0-1-0',
            children: [{
                value: '0-1-0-0',
                label: 'Node 0-1-0-0',
            }],
        }, {
            value: '0-1-1',
            label: 'Node 0-1-1',
            children: [{
                value: '0-1-1-0',
                label: 'Node 0-1-1-0',
            }],
        }],
    }, {
        value: '0-2',
        label: 'Node 0-2',
    }],
}, {
    value: '1',
    label: 'Node 1',
}];

describe('utils', () => {
    describe('expandNodesToLevel', () => {
        it('should recursively traverse a tree of nodes and return the key values of parents from the level specified', () => {
            const expected = ['0', '0-1'];

            assert.equal(expected, expandNodesToLevel(nestedTree, 1));
        });
    });
});

import { assert } from 'chai';

import { expandNodesToLevel } from '../src';

const nestedTree = [{
    value: '0',
    label: 'Node 0',
    children: [{
        value: '0-0',
        label: 'Node 0-0',
    }, {
        value: '0-1',
        label: 'Node 0-1',
        children: [{
            value: '0-1-0',
            label: 'Node 0-1-0',
            children: [{
                value: '0-1-0-0',
                label: 'Node 0-1-0-0',
            }],
        }, {
            value: '0-1-1',
            label: 'Node 0-1-1',
            children: [{
                value: '0-1-1-0',
                label: 'Node 0-1-1-0',
            }],
        }],
    }, {
        value: '0-2',
        label: 'Node 0-2',
    }],
}, {
    value: '1',
    label: 'Node 1',
}];

describe('utils', () => {
    describe('expandNodesToLevel', () => {
        it('should recursively traverse a tree of nodes and return the key values of parents from the level specified', () => {
            const expected = ['0', '0-1'];

            assert.deepEqual(expected, expandNodesToLevel(nestedTree, 1));
        });
    });
});

Fix stupid deep equal check


import React from 'react'
import { provideHooks } from 'redial'
import { reduxForm } from 'redux-form'
import Loader from 'react-loaders'
import { viewTodo } from '../actions';
import { connect } from 'react-redux';
import { TodoUpdateForm } from './TodoForm';
import { Link } from 'react-router'

@provideHooks({
  fetch: ({ dispatch, params: { id }, store }) => dispatch(
    viewTodo({
      id: id,
      reject: (e) => {alert(e.message);},
      store
    }))
})
@connect((state) => {
  return {
    viewedTodo: state.todo.viewedTodo,
    fetchState: state.todo.fetchState,
  };
})
export default class TodoDetail extends React.Component {
  render() {
    const { viewedTodo, fetchState, history } = this.props;
    if (fetchState[viewTodo].fetching) {
      return (

            <Loader type="line-scale" active="true"/>

      )
    }
    if (!viewedTodo) {
      return

    }
    return(

        <Link  className="back-link" to={"/todos"}>{"< Back"}</Link>

{viewedTodo.title}

        <TodoUpdateForm history={history}/>

    )
  }
}

import React from 'react'
import { provideHooks } from 'redial'
import { reduxForm } from 'redux-form'
import Loader from 'react-loaders'
import { viewTodo } from '../actions';
import { connect } from 'react-redux';
import { TodoUpdateForm } from './TodoForm';
import { Link } from 'react-router'

@provideHooks({
  fetch: ({ dispatch, params: { id }, store }) => dispatch(
    viewTodo({
      id: id,
      reject: (e) => {alert(e);},
      store
    }))
})
@connect((state) => {
  return {
    viewedTodo: state.todo.viewedTodo,
    fetchState: state.todo.fetchState,
  };
})
export default class TodoDetail extends React.Component {
  render() {
    const { viewedTodo, fetchState, history } = this.props;
    if (fetchState[viewTodo].fetching) {
      return (

            <Loader type="line-scale" active="true"/>

      )
    }
    if (!viewedTodo) {
      return

    }
    return(

        <Link  className="back-link" to={"/todos"}>{"< Back"}</Link>

{viewedTodo.title}

        <TodoUpdateForm history={history}/>

    )
  }
}

Fix error message on fetching in todo detail page


function MainMenu(options) {
  'use strict';
  var menu;
  menu = {
    title: {
      text: 'Yet Another Pong Clone',
      font: 'bold 65px Monaco, Courier New, monospace',
      colour: '#FFFFFF'
    },
      items: [
      {
        text: '1P',
        font: 'bold 45px Monaco, Courier New, monospace',
        colour: '#FFFFFF',
        newScreen: new Game({
          width: options.width,
          height: options.height,
          baseSpeed: 5,
          twoPlayer: false,
          players : {}
        })
      },
      {
        text: '2P',
        font: 'bold 45px Monaco, Courier New, monospace',
        colour: '#FFFFFF',
        newScreen: new Game({
          width: options.width,
          height: options.height,
          baseSpeed: 5,
          twoPlayer: true,
          players : {}
        })
      },
      {
        text: 'Settings',
        font: 'bold 45px Monaco, Courier New, monospace',
        colour: '#FFFFFF',
        newScreen: {}
      }
    ],
    selected: {
      font: 'bold 55px Monaco, Courier New, monospace',
      colour: '#FFCC33'
    },
    x: 0,
    y: 0,
    width: options.width || 1280,
    height: options.height || 640,
    backgroundColour: '#000000',
    itemSeparator: 100,
    callback: options.callback || function() {}
  };

  return new Menu(menu);
};

function MainMenu(options) {
  'use strict';
  var menu;
  menu = {
    title: {
      text: 'Yet Another Pong Clone',
      font: 'bold 65px Monaco, Courier New, monospace',
      colour: '#FFFFFF'
    },
      items: [
      {
        text: '1P',
        font: 'bold 45px Monaco, Courier New, monospace',
        colour: '#FFFFFF',
        newScreen: OnePlayerMenu({
          width: options.width,
          height: options.height,
          baseSpeed: options.baseSpeed,
          callback: options.callback
        })
      },
      {
        text: '2P',
        font: 'bold 45px Monaco, Courier New, monospace',
        colour: '#FFFFFF',
        newScreen: new Game({
          width: options.width,
          height: options.height,
          baseSpeed: 5,
          twoPlayer: true,
          players : {}
        })
      },
      {
        text: 'Settings',
        font: 'bold 45px Monaco, Courier New, monospace',
        colour: '#FFFFFF',
        newScreen: {}
      }
    ],
    selected: {
      font: 'bold 55px Monaco, Courier New, monospace',
      colour: '#FFCC33'
    },
    x: 0,
    y: 0,
    width: options.width || 1280,
    height: options.height || 640,
    backgroundColour: '#000000',
    itemSeparator: 100,
    callback: options.callback || function() {}
  };

  return new Menu(menu);
};

Call one player menu instead of going straight to the game


document.addEventListener('DOMContentLoaded', function() {
  // Custom Select2

  // Fix for Select2 v3.x using overlay mask to close any opened Select2 instances
  // The overlay mask stops you lowering the z-index of the opend Select2 instance
  // This is not needed if upgraded to Select2 v4.x
  window.addEventListener('click', function(e) {
    var select2Drop = document.getElementById('select2-drop')

    if (select2Drop) {
      if (select2Drop.contains(e.target)) {
        // Click in the Select2 dropdown and do nothing...
      } else {
        $('*').select2('close')
      }
    }
  })

  // Inititate Select2 on any select element with the class .select2
  $('select.select2').select2({
    allowClear: true
  })
})

document.addEventListener('DOMContentLoaded', function() {

  // Inititate Select2 on any select element with the class .select2
  $('select.select2').select2({
    allowClear: true
  })

  // BELOW: z-index fix for Select2 v3.x to lower the z-index of an opened Select2.
  // The javascript below is not needed if Spree is updated to use Select2 v4.x
  window.addEventListener('click', function(e) {
    var select2Drop = document.getElementById('select2-drop')

    if (select2Drop) {
      if (select2Drop.contains(e.target)) {
        // Clicking inside the Select2 dropdown does nothing...
      } else {
        // Clicking outside the Select2 dropdown close all open Select2 dropdowns.
        $('*').select2('close')
      }
    }
  })
})

Improve js for Select2 z-index fix


'use strict';
var params = require('./params');

function Fx(level) {
	this.level = level;
	this.group = level.add.group();
}

Fx.prototype = {
	spawn: function(type, px, py) {
		var sprite;
		sprite = this.group.getFirstDead();
		if (sprite) {
			sprite.x = px;
			sprite.y = py;
			sprite.revive();
		} else {
			sprite = this.group.create(px, py, 'fx', 0);
			sprite.anchor.setTo(0.5, 0.5);
		}
		sprite.animations.add('run', [0, 1, 2, 3], 15, false, true);
		sprite.play('run', 15, false, true);
	},
	update: function() {}
};

module.exports = {
	Fx: Fx
};

'use strict';
var params = require('./params');

function Fx(level) {
	this.level = level;
	this.group = level.add.group();
}

Fx.prototype = {
	spawn: function(type, px, py) {
		var sprite;
		sprite = this.group.getFirstDead();
		if (sprite) {
			sprite.reset(px, py);
		} else {
			sprite = this.group.create(px, py, 'fx', 0);
			sprite.anchor.setTo(0.5, 0.5);
		}
		sprite.animations.add('run', [0, 1, 2, 3], 15, false, true);
		sprite.play('run', 15, false, true);
	},
	update: function() {}
};

module.exports = {
	Fx: Fx
};

Fix same class of error from last commit


define(function(require) {

  var test = require('../../test')
  var assert = test.assert

  assert(seajs.log('seajs.log test', 'group') === undefined, 'group')

  assert(seajs.log('a') === undefined, 'log')
  assert(seajs.log('a', 'b') === undefined, 'log')
  assert(seajs.log('a', 'b', 1) === undefined, 'log')

  assert(seajs.log('a', 'warn') === undefined, 'warn')
  assert(seajs.log('a', 'info') === undefined, 'info')
  assert(seajs.log('a', 'error') === undefined, 'error')
  assert(seajs.log('a', 'time') === undefined, 'time')
  assert(seajs.log('a', 'timeEnd') === undefined, 'timeEnd')

  assert(seajs.log('a', 'dir') === undefined, 'dir')
  assert(seajs.log({ name: 'a' }, 'dir') === undefined, 'dir')

  assert(seajs.log('seajs.log test', 'groupEnd') === undefined, 'groupEnd')

  test.next()

});

define(function(require) {

  var test = require('../../test')
  var assert = test.assert

  assert(seajs.log('seajs.log test', 'group') === undefined, 'group')

  assert(seajs.log('a') === undefined, 'log')
  assert(seajs.log('a ' + 1) === undefined, 'log')

  assert(seajs.log('a', 'warn') === undefined, 'warn')
  assert(seajs.log('a', 'info') === undefined, 'info')
  assert(seajs.log('a', 'error') === undefined, 'error')
  assert(seajs.log('a', 'time') === undefined, 'time')
  assert(seajs.log('a', 'timeEnd') === undefined, 'timeEnd')

  assert(seajs.log('a', 'dir') === undefined, 'dir')
  assert(seajs.log({ name: 'a' }, 'dir') === undefined, 'dir')

  assert(seajs.log('seajs.log test', 'groupEnd') === undefined, 'groupEnd')

  test.next()

});

Modify spec for code modification


/**
 * @module sandbox-timers
 * This module's job is to expose stub timer functions that raise warning when called.
 * @type {Object}
 */

var timerFunctions = ['setTimeout', 'setInterval', 'clearTimeout', 'clearInterval', 'setImmediate'],
    MESSAGE = ' is not available inside sandbox and has no side-effect.',

    SandboxTimers;

SandboxTimers = function (console) {
    var notSupported = function (name) {
        console.info(name + MESSAGE);
    };

    timerFunctions.forEach(function (name) {
        this[name] = notSupported.bind(name);
    }.bind(this));
};

module.exports = SandboxTimers;

/**
 * @module sandbox-timers
 * This module's job is to expose stub timer functions that raise warning when called.
 * @type {Object}
 */

var timerFunctions = ['setTimeout', 'setInterval', 'clearTimeout', 'clearInterval', 'setImmediate'],
    MESSAGE = ' is not available inside sandbox and has no side-effect.',

    SandboxTimers;

SandboxTimers = function (console) {
    var notSupported = function (name) {
        console.info(name + MESSAGE);
    };

    timerFunctions.forEach(function (name) {
        this[name] = notSupported.bind({}, name);
    }.bind(this));
};

module.exports = SandboxTimers;

Fix binding issue of the stub timers.


import { NAMESPACES } from 'rotonde-core-messages';
import handleConnection from './handleConnection';

export function registerHandlers(io) {
  const core = io.of(NAMESPACES.ROTONDE_CORE);
  core.on('connection', handleConnection);
}

import { NAMESPACES } from 'rotonde-core-messages';
import handleConnection from './handleConnection';

export function registerHandlers(io) {
  const core = io.of(NAMESPACES.ROTONDE_CORE);
  core.on('connection', handleConnection);
  if (process.env.NODE_ENV === 'development') {
    const { ChatServerPlugin } = require('../../.rotonde_plugins/local/rotonde-plugin-chat');
    const { ChatClientPlugin } = require('../../.rotonde_plugins/local/rotonde-plugin-chat');
    const clientPlugin = new ChatClientPlugin('http://localhost:3000');
    const plugin = new ChatServerPlugin(io);
    setInterval(() => {
      plugin.sendMessage('maxdeviant', 'blah');
    }, 1000);
  }
}

Add testing code for chat plugin


import { Linking } from 'react-native'; // eslint-disable-line import/no-unresolved, max-len

let previousOnLinkChange;

export const dance = (authUrl) => {
  if (previousOnLinkChange) {
    Linking.removeEventListener('url', previousOnLinkChange);
  }

  return Linking.openURL(authUrl)
    .then(() => new Promise((resolve, reject) => {
      const handleUrl = (url) => {
        if (!url || url.indexOf('fail') > -1) {
          reject(url);
        } else {
          resolve(url);
        }
      };

      const onLinkChange = ({ url }) => {
        Linking.removeEventListener('url', onLinkChange);
        handleUrl(url);
      };

      Linking.addEventListener('url', onLinkChange);

      previousOnLinkChange = onLinkChange;
    }));
};

export const request = fetch;

import { Linking } from 'react-native'; // eslint-disable-line import/no-unresolved, max-len

let previousOnLinkChange;

export const dance = (authUrl) => {
  if (previousOnLinkChange) {
    Linking.removeEventListener('url', previousOnLinkChange);
  }

  return Linking.openURL(authUrl)
    .then(() => new Promise((resolve, reject) => {
      const handleUrl = (url) => {
        if (!url || url.indexOf('fail') > -1) {
          reject(url);
        } else {
          resolve(url);
        }
      };

      const onLinkChange = ({ url }) => {
        Linking.removeEventListener('url', onLinkChange);
        previousOnLinkChange = undefined;
        handleUrl(url);
      };

      Linking.addEventListener('url', onLinkChange);

      previousOnLinkChange = onLinkChange;
    }));
};

export const request = fetch;

Remove previous handler when listener unsubscribed


"use strict";

const Task = require('../Task'),
    gulp = require('gulp'),
    path = require('path'),
    ProjectType = require('../../ProjectType'),
    tsc = require('gulp-typescript');

class JSTask extends Task {

    constructor(buildManager, taskRunner) {
        super(buildManager, taskRunner);
        this.command = "js";
        this.availableTo = [ProjectType.FRONTEND_MODULE];
    }

    action() {
        var tsConfig = tsc.createProject("tsconfig.json");
        return gulp.src([
            this._buildManager.options.scripts + "/**/*.{ts,tsx}"
        ])
            .pipe(tsc(tsConfig))
            .on("error", function (error) {
                console.error(error);
                process.exit(1);
            })
            .pipe(gulp.dest(this._buildManager.options.distribution));
    }
}

module.exports = JSTask;

"use strict";

const Task = require('../Task'),
    gulp = require('gulp'),
    path = require('path'),
    ProjectType = require('../../ProjectType'),
    tsc = require('gulp-typescript');

class JSTask extends Task {

    constructor(buildManager, taskRunner) {
        super(buildManager, taskRunner);
        this.command = "js";
        this.availableTo = [ProjectType.FRONTEND_MODULE];
    }

    action() {
        var tsConfig = tsc.createProject("tsconfig.json");
        return gulp.src([
            this._buildManager.options.scripts + "/**/*.{ts,tsx}"
        ])
            .pipe(tsc(tsConfig))
            .on("error", function (error) {
                process.exit(1);
            })
            .pipe(gulp.dest(this._buildManager.options.distribution));
    }
}

module.exports = JSTask;

Remove unnecessary error log from js module bundle


import template from './appstore-field-select-openstack-tenant.html';

class AppstoreFieldSelectOpenstackTenantController {
  // @ngInject
  constructor(ncUtilsFlash, openstackTenantsService, currentStateService) {
    this.ncUtilsFlash = ncUtilsFlash;
    this.openstackTenantsService = openstackTenantsService;
    this.currentStateService = currentStateService;
  }

  $onInit() {
    this.loading = true;
    this.currentStateService.getProject().then(project => {
      this.openstackTenantsService.getAll({
        field: ['name', 'uuid'],
        project_uuid: project.uuid,
      }).then(tenants => {
        this.choices = tenants.map(tenant => ({
          display_name: tenant.name,
          value: `Tenant UUID: ${tenant.backend_id}. Name: ${tenant.name}`
        }));
        this.loading = false;
        this.loaded = true;
      })
      .catch(response => {
        this.ncUtilsFlash.errorFromResponse(response, gettext('Unable to get list of OpenStack tenants.'));
        this.loading = false;
        this.loaded = false;
      });
    });
  }
}

const appstoreFieldSelectOpenstackTenant = {
  template,
  bindings: {
    field: '<',
    model: '<'
  },
  controller: AppstoreFieldSelectOpenstackTenantController,
};

export default appstoreFieldSelectOpenstackTenant;

import template from './appstore-field-select-openstack-tenant.html';

class AppstoreFieldSelectOpenstackTenantController {
  // @ngInject
  constructor(ncUtilsFlash, openstackTenantsService, currentStateService) {
    this.ncUtilsFlash = ncUtilsFlash;
    this.openstackTenantsService = openstackTenantsService;
    this.currentStateService = currentStateService;
  }

  $onInit() {
    this.loading = true;
    this.currentStateService.getProject().then(project => {
      this.openstackTenantsService.getAll({
        field: ['name', 'backend_id'],
        project_uuid: project.uuid,
      }).then(tenants => {
        this.choices = tenants.map(tenant => ({
          display_name: tenant.name,
          value: `Tenant UUID: ${tenant.backend_id}. Name: ${tenant.name}`
        }));
        this.loading = false;
        this.loaded = true;
      })
      .catch(response => {
        this.ncUtilsFlash.errorFromResponse(response, gettext('Unable to get list of OpenStack tenants.'));
        this.loading = false;
        this.loaded = false;
      });
    });
  }
}

const appstoreFieldSelectOpenstackTenant = {
  template,
  bindings: {
    field: '<',
    model: '<'
  },
  controller: AppstoreFieldSelectOpenstackTenantController,
};

export default appstoreFieldSelectOpenstackTenant;

Fix filter for fields when displaying OpenStack select


import { expect } from 'chai';
import u from '../lib';

describe('u.reject', () => {
  it('can reject by index', () => {
    const result = u.reject((_, index) => index === 1, [3, 4, 5]);

    expect(result).to.eql([3, 5]);
  });

  it('freezes the result', () => {
    expect(Object.isFrozen(u.reject('a', []))).to.be.true;
  });
});

import { expect } from 'chai';
import u from '../lib';

describe('u.reject', () => {
  it('can reject by index', () => {
    const result = u.reject((_, index) => index === 1, [3, 4, 5]);

    expect(result).to.eql([3, 5]);
  });

  it('can reject with callback shorthand', () => {
    const result = u.reject('bad', [{ bad: true }, { bad: false }]);

    expect(result).to.eql([{ bad: false }]);
  });

  it('freezes the result', () => {
    expect(Object.isFrozen(u.reject('a', []))).to.be.true;
  });
});

Add shorthand syntax reject test


import React from 'react';
import { shallow, mount, render } from 'enzyme';
import Slider from '../src/slider.jsx';
import GoldTagLine from '../src/goldtagline.jsx'
import {expect} from 'chai';

describe("slider", function() {
  it("defaults to 10 pieces of gold", function() {
    expect(shallow(<Slider />).contains(<GoldTagLine goldPieces="10"/>)).to.be.true;
  });
  it("changes description when slider is moved", function(){
    const slider = mount(<Slider />);
    slider.find("input").simulate('change', {target: {value: 15}})
    expect(slider.contains(<GoldTagLine goldPieces="15"/>)).to.be.true;
  });
});

import React from 'react';
import { shallow, mount, render } from 'enzyme';
import Slider from '../src/slider.jsx';
import GoldTagLine from '../src/goldtagline.jsx'
import {expect} from 'chai';

describe("slider", function() {
  it("defaults to 10 pieces of gold", function() {
    expect(shallow(<Slider />).contains(<GoldTagLine goldPieces="10"/>)).to.be.true;
  });
  it("changes description when slider is moved", function(){
    const slider = shallow(<Slider />);
    slider.find("input").simulate('change', {target: {value: 15}})
    expect(slider.contains(<GoldTagLine goldPieces="15"/>)).to.be.true;
  });
});

Change full dom to shallow


"use strict";
var Anyfetch = require('anyfetch');

module.exports.get = function get(req, res, next) {
  var anyfetchClient = new Anyfetch(req.accessToken.token);
  anyfetchClient.postCompanyUpdate(function updated(err) {
    if(!err) {
      res.send(204);
    }
    next(err);
  });
};

"use strict";
var Anyfetch = require('anyfetch');

module.exports.get = function get(req, res, next) {
  var anyfetchClient = new Anyfetch(req.accessToken.token);
  anyfetchClient.postUserUpdate(function updated(err) {
    if(!err) {
      res.send(204);
    }
    next(err);
  });
};

Send userUpdate instead of companyUpdate


// ==UserScript==
// @name         SFcomic Viewer
// @namespace
// @version      0.2.1
// @description  Auto load comic picture.
// @author       AntonioTsai
// @match        http://comic.sfacg.com/*
// @include      http://comic.sfacg.com/*
// @grant        none
// @downloadURL  https://github.com/AntonioTsai/SFcomic-Viewer/raw/master/SFcomicViewer.user.js
// ==/UserScript==

/**
 * picAy: The array store all image's url of the volume
 * hosts: The array store possible host
 * getHost(): Get the current host index
 */
(() => {
	var imgTable = document.querySelector("table tbody");
	var tempTr = document.createElement("tr");
	var imgs = document.createElement("img");
	tempTr.appendChild(document.createElement("td"));
	tempTr.children[0].appendChild(imgs);

	// remove original image
	var tr = document.querySelector("tr");
	tr.parentElement.removeChild(tr);

	// generate all images
	for (var i = 0; i < picCount; i++) {
		var imgTr = tempTr.cloneNode(true);
		imgTr.appendChild(document.createElement("img"));
		imgTr.children[0].children[0].src = picAy[i];
		imgTable.appendChild(imgTr);
	}

})();

// ==UserScript==
// @name         SFcomic Viewer
// @namespace
// @version      0.2.1
// @description  Auto load comic picture.
// @author       AntonioTsai
// @match        http://comic.sfacg.com/*
// @include      http://comic.sfacg.com/*
// @grant        none
// @downloadURL  https://github.com/AntonioTsai/SFcomic-Viewer/raw/master/SFcomicViewer.user.js
// ==/UserScript==

/**
 * picAy: The array store all image's url of the volume
 * hosts: The array store possible host
 * getHost(): Get the current host index
 */
(() => {
	var imgTable = document.querySelector("table tbody");
	var tempTr = document.createElement("tr");

	// remove original image & social media icon
	var tr = document.querySelector("tr");
	tr.parentElement.removeChild(tr);

	// generate all images
	for (var i = 0; i < picCount; i++) {
		var imgTr = tempTr.cloneNode(true);
		imgTr.appendChild(document.createElement("img"));
		imgTr.children[0].children[0].src = picAy[i];
		imgTable.appendChild(imgTr);
	}

})();

Remove unnecessary code and add comment


/*global Promise:true*/
var workQueue = require('./workQueue');
var Promise = require('bluebird');
module.exports = function oathbreaker(value) {
    if (!value || typeof value.then !== 'function') {
        return value;
    }

    if (!value.isRejected) {
        // this is not a bluebird promise
        return value;
    }

    if (value.isFulfilled()) {
        return value;
    }

    if (value.isRejected()) {
        value.caught(function () {
            // Ignore - already handled
        });

        throw value.reason();
    }

    var onResolve = function () {};
    var onReject = function () {};

    var evaluated = false;
    var error;
    var resolvedValue;
    value.then(function (obj) {
        evaluated = true;
        resolvedValue = obj;
        onResolve(value);
    }, function (err) {
        evaluated = true;
        error = err;
        onReject(err);
    });

    workQueue.drain();

    if (evaluated && error) {
        throw error;
    } else if (evaluated) {
        return value;
    }

    return new Promise(function (resolve, reject) {
        onResolve = resolve;
        onReject = reject;
    });
};

/*global Promise:true*/
var workQueue = require('./workQueue');
var Promise = require('bluebird');
module.exports = function oathbreaker(value) {
    if (!value || typeof value.then !== 'function') {
        return value;
    }

    if (!value.isRejected) {
        // this is not a bluebird promise
        return value;
    }

    if (value.isFulfilled()) {
        return value;
    }

    if (value.isRejected()) {
        value.caught(function () {
            // Ignore - already handled
        });

        throw value.reason();
    }

    var onResolve = function () {};
    var onReject = function () {};

    var evaluated = false;
    var error;
    var resolvedValue;
    value.then(function (obj) {
        evaluated = true;
        resolvedValue = obj;
        onResolve(value);
    }, function (err) {
        evaluated = true;
        error = err;
        onReject(err);
    });

    workQueue.drain();

    if (evaluated && error) {
        if (Error.captureStackTrace) {
            Error.captureStackTrace(error);
        }
        throw error;
    } else if (evaluated) {
        return value;
    }

    return new Promise(function (resolve, reject) {
        onResolve = resolve;
        onReject = reject;
    });
};

Fix stack trace of errors that has been thrown when the work queue has been drained


/* eslint-disable */
const { resolve } = require('path');
const webpack = require('webpack');

module.exports = {
  context: resolve(__dirname, 'src'),

  entry: [
    './Fireworks.js'
    // the entry point of our app
  ],
  output: {
    filename: 'fireworks.bundle.js',
    // the output bundle

    path: resolve(__dirname, 'dist'),

  },

  module: {
    rules: [
      {
        enforce: "pre",
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: "eslint-loader",
        options: {
          emitError: true
        }
      },
      {
        test: /\.jsx?$/,
        use: [ 'babel-loader', ],
        exclude: /node_modules/
      },
    ],
  }
};

Disable linting for fireworks-react webpack


'use strict';

if (Neft.utils.isNode) {
    require('lib/module-cache').registerCoffeeScript();
}

Neft.utils.merge(global, require('lib/testing'));
global.assert = Neft.assert;

module.exports = function (runApp) {
    global.app = runApp();
    if (app != null) {
        global.environment = global.app.config.environment;
    }
    require('build/tests');
};

'use strict';

if (Neft.utils.isNode) {
    require('lib/module-cache').registerCoffeeScript();
}

Neft.utils.merge(global, require('lib/testing'));
global.assert = Neft.assert;

module.exports = function (runApp) {
    let initFunc;
    try {
        initFunc = require('init.js');
    } catch (error) {
        if (!Neft.utils.has(error.message, 'Cannot find module')) {
            throw error;
        }
    }

    global.app = initFunc ? initFunc(runApp) : runApp();

    if (app != null) {
        global.environment = global.app.config.environment;
    }

    require('build/tests');
    return global.app;
};

Support for init.js in testing


'use strict';

/**
* Uniformly distributed pseudorandom numbers.
*
* @module @stdlib/math/base/random/uniform
*
* @example
* var randu = require( '@stdlib/math/base/random/randu' );
*
* var v = randu();
* // returns <number>
*
* @example
* var factory = require( '@stdlib/math/base/random/randu' ).factory;
*
* var randu = factory({
*     'name': 'minstd',
*     'seed': 12345
* });
*
* var v = randu();
* // returns <number>
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );
var randu = require( './uniform.js' );
var factory = require( './factory.js' );

// METHODS //

setReadOnly( randu, 'factory', factory );

// EXPORTS //

module.exports = randu;

'use strict';

/**
* Uniformly distributed pseudorandom numbers.
*
* @module @stdlib/math/base/random/randu
*
* @example
* var randu = require( '@stdlib/math/base/random/randu' );
*
* var v = randu();
* // returns <number>
*
* @example
* var factory = require( '@stdlib/math/base/random/randu' ).factory;
*
* var randu = factory({
*     'name': 'minstd',
*     'seed': 12345
* });
*
* var v = randu();
* // returns <number>
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );
var randu = require( './uniform.js' );
var factory = require( './factory.js' );

// METHODS //

setReadOnly( randu, 'factory', factory );

// EXPORTS //

module.exports = randu;

Fix module name in JSDoc


// Keyboard keycodes
export const keyCodes = {
    ESCAPE: 27,
    ENTER: 13,
    SPACE: 32,
    LEFT_ARROW: 37,
    UP_ARROW: 38,
    RIGHT_ARROW: 39,
    DOWN_ARROW: 40
};

// Classnames likely to be shared across modules
export const defaultClassNames = {
    IS_ACTIVE: 'is-active',
    IS_HIDDEN: 'is-hidden',
    IS_READY: 'is-ready',
    NO_BACKDROP: 'no-backdrop',
    DIALOG_BACKDROP: 'dialog-backdrop'
};

export const NATIVELY_FOCUSABLE_ELEMENTS = [
    'a[href]',
    'area[href]',
    'input:not([disabled])',
    'select:not([disabled])',
    'textarea:not([disabled])',
    'button:not([disabled])',
    'iframe',
    'object',
    'embed',
    '[contenteditable]',
    '[tabindex]:not([tabindex^="-"])'
];

// Keyboard keycodes
export const keyCodes = {
    TAB: 9,
    ENTER: 13,
    ESCAPE: 27,
    SPACE: 32,
    LEFT_ARROW: 37,
    UP_ARROW: 38,
    RIGHT_ARROW: 39,
    DOWN_ARROW: 40
};

// Classnames likely to be shared across modules
export const defaultClassNames = {
    IS_ACTIVE: 'is-active',
    IS_HIDDEN: 'is-hidden',
    IS_READY: 'is-ready',
    NO_BACKDROP: 'no-backdrop',
    DIALOG_BACKDROP: 'dialog-backdrop'
};

export const NATIVELY_FOCUSABLE_ELEMENTS = [
    'a[href]',
    'area[href]',
    'input:not([disabled])',
    'select:not([disabled])',
    'textarea:not([disabled])',
    'button:not([disabled])',
    'iframe',
    'object',
    'embed',
    '[contenteditable]',
    '[tabindex]:not([tabindex^="-"])'
];

Add tab key to list of keycodes


import Em from 'ember';

var LlamaColumngroup = Em.View.extend({
	classNames: 'llama-columngroup',

	columns: null,

	updateTotalWidth: function () {
		var total = 0;
		this.get('childViews').forEach(function (view) {
			total += view.getWidth();
		});
		this.$().width(total);
	},

	onChildViewUpdate: function () {
		Em.run.later(this, this.updateTotalWidth, 0);
	}.observes('childViews'),

	didInsertElement: function () {
		this._super();
		Em.run.scheduleOnce('afterRender', this, this.updateTotalWidth);
	}
});

export default LlamaColumngroup;

import Em from 'ember';

var LlamaColumngroup = Em.View.extend({
	classNames: 'llama-columngroup',

	columns: null,

	updateTotalWidth: function () {
		var total = 0;
		this.get('childViews').forEach(function (view) {
			total += view.getWidth();
		});
		this.$().width(total);
	},

	onChildViewUpdate: function () {
		Em.run.next(this, this.updateTotalWidth);
	}.observes('childViews'),

	didInsertElement: function () {
		this._super();
		Em.run.scheduleOnce('afterRender', this, this.updateTotalWidth);
	}
});

export default LlamaColumngroup;

Use run next over run later


'use strict';

// Load our requirements
const i18n = require('i18n'),
      path = require('path'),
      logger = __require('libs/log');

// Variables
let localeDir = path.resolve(__base + '../locales');

// Configure the localization engine
i18n.configure({
  locales: require('./available-locales')(localeDir),
  defaultLocale: 'en',
  objectNotation: true,
  directory: localeDir,
  syncFiles: true,
  autoReload: true,
  register: global,
  api: {
    '__': 'lang',
    '__n': 'plural'
  }
});

// Export for future use
module.exports = i18n;

'use strict';

// Load our requirements
const i18n = require('i18n'),
      path = require('path');

// Load libraries
const logger = __require('libs/log'),
      settings = __require('libs/settings');

// Variables
let localeDir = path.resolve(__base + '../locales');

// Configure the localization engine
i18n.configure({
  locales: require('./available-locales')(localeDir),
  defaultLocale: 'en',
  objectNotation: true,
  directory: localeDir,
  syncFiles: true,
  autoReload: true,
  register: global,
  api: {
    '__': 'lang',
    '__n': 'plural'
  }
});

// Set the locale
if ( settings.language !== 'en' ) {
  i18n.setLocale(settings.language);
}

// Export for future use
module.exports = i18n;

Enable locale switching on load from settings


export default {
  entry: './src/index.js',
  output: {
    path: __dirname + './dist',
    filename: 'python-range.umd.js',
    library: 'pythonRange',
    libraryTarget: 'umd',
    umdNamedDefine: true,
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          babelrc: false,
          presets: [
            ['latest', {
              modules: false,
            }],
          ],
          plugins: ['transform-object-rest-spread', 'transform-runtime'],
        },
      },
    ],
  },
};

import path from 'path';

export default {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'python-range.umd.js',
    library: 'pythonRange',
    libraryTarget: 'umd',
    umdNamedDefine: true,
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          babelrc: false,
          presets: [
            ['latest', {
              modules: false,
            }],
          ],
          plugins: ['transform-object-rest-spread', 'transform-runtime'],
        },
      },
    ],
  },
};

Fix output path in webpack config


import webpack from 'webpack';
import HTMLWebpackPlugin from 'html-webpack-plugin';
import { resolve } from 'path';

module.exports = function config() {
  return {
    context: resolve(__dirname, '../src/browser'),
    module: {
      rules: [{
        test: /\.(graphql|gql)$/,
        exclude: /node_modules/,
        loader: 'graphql-tag/loader',
      }, {
        test: /\.css$/,
        exclude: /node_modules/,
        loaders: [
          'style-loader',
          'css-loader?modules&importLoaders=1',
          'postcss-loader',
        ],
      }],
    },
    output: {
      path: resolve(__dirname, '../dist/browser'),
      publicPath: '/',
    },
    plugins: [
      new webpack.NamedModulesPlugin(),
      new HTMLWebpackPlugin(),
    ],
    resolve: {
      alias: {
        '~': resolve(__dirname, '../src/common'),
      },
    },
  };
};

import webpack from 'webpack';
import HTMLWebpackPlugin from 'html-webpack-plugin';
import { resolve } from 'path';

module.exports = function config() {
  return {
    context: resolve(__dirname, '../src/browser'),
    module: {
      rules: [{
        test: /\.(graphql|gql)$/,
        exclude: /node_modules/,
        loader: 'graphql-tag/loader',
      }, {
        test: /\.css$/,
        exclude: /node_modules/,
        loaders: [
          'style-loader',
          'css-loader?modules&importLoaders=1',
          'postcss-loader',
        ],
      }, {
        test: /\.svg$/,
        loader: 'svg-url-loader',
        include: /img/,
      }, {
        test: /\.woff$/,
        loader: 'url-loader?mimetype=application/font-woff',
        include: /fonts/,
      }, {
        test: /\.woff2$/,
        loader: 'url-loader?mimetype=application/font-woff2',
        include: /fonts/,
      },
      { test: /\.[ot]tf$/,
        loader: 'url-loader?mimetype=application/octet-stream',
        include: /fonts/,
      },
      { test: /\.eot$/,
        loader: 'url-loader?mimetype=application/vnd.ms-fontobject',
        include: /fonts/,
      }],
    },
    output: {
      path: resolve(__dirname, '../dist/browser'),
      publicPath: '/',
    },
    plugins: [
      new webpack.NamedModulesPlugin(),
      new HTMLWebpackPlugin(),
    ],
    resolve: {
      alias: {
        '~': resolve(__dirname, '../src/common'),
        fonts: resolve(__dirname, '../fonts'),
        img: resolve(__dirname, '../img'),
      },
    },
  };
};

Add SVG and font loaders to webpack config


import Ember from 'ember';
import { moduleForComponent, test } from 'ember-qunit';

moduleForComponent( 'sl-calendar-year', 'Unit - component: sl-calendar-year' );

test( 'Default state is not active, new, or old', function( assert ) {
    let component  = this.subject(),
        $component = this.render();

    assert.strictEqual(
        component.get( 'active' ),
        false,
        'Default component is not active'
    );

    assert.strictEqual(
        component.get( 'new' ),
        false,
        'Default component is not in new state'
    );

    assert.strictEqual(
        component.get( 'old' ),
        false,
        'Default component is not in old state'
    );

    assert.strictEqual(
        $component.hasClass( 'active' ),
        false,
        'Default rendered component does not have class "active"'
    );

    assert.strictEqual(
        $component.hasClass( 'new' ),
        false,
        'Default rendered component does not have class "new"'
    );

    assert.strictEqual(
        $component.hasClass( 'old' ),
        false,
        'Default rendered component does not have class "old"'
    );
});

test( 'Click event sends action with year value', function( assert ) {
    let exampleYear = 2000,
        $component;

    assert.expect( 1 );

    this.subject({
        action: 'test',

        targetObject: {
            test: year => {
                assert.strictEqual( year, exampleYear, 'Received year' );
            }
        },

        year: exampleYear
    });

    $component = this.render();

    $component.trigger( 'click' );
});

import Ember from 'ember';
import { moduleForComponent, test } from 'ember-qunit';

moduleForComponent( 'sl-calendar-year', 'Unit - component: sl-calendar-year' );

test( 'Default state is not active, new, or old', function( assert ) {
    var component  = this.subject(),
        $component = this.render();

    assert.strictEqual(
        component.get( 'active' ),
        false,
        'Default component is not active'
    );

    assert.strictEqual(
        component.get( 'new' ),
        false,
        'Default component is not in new state'
    );

    assert.strictEqual(
        component.get( 'old' ),
        false,
        'Default component is not in old state'
    );

    assert.strictEqual(
        $component.hasClass( 'active' ),
        false,
        'Default rendered component does not have class "active"'
    );

    assert.strictEqual(
        $component.hasClass( 'new' ),
        false,
        'Default rendered component does not have class "new"'
    );

    assert.strictEqual(
        $component.hasClass( 'old' ),
        false,
        'Default rendered component does not have class "old"'
    );
});

test( 'Click event sends action with year value', function( assert ) {
    var exampleYear = 2000,
        $component;

    assert.expect( 1 );

    this.subject({
        action: 'test',

        targetObject: {
            test: year => {
                assert.strictEqual( year, exampleYear, 'Received year' );
            }
        },

        year: exampleYear
    });

    $component = this.render();

    $component.trigger( 'click' );
});

Revert assignments back to "var" from "let"


markdown_explorer = (function() {
    var isLocalHref = function(href) {
        return href.indexOf("://") === -1;
    };

    var isMarkdownHref = function(href) {
        return href.indexOf(".md") !== -1;
    };

    var makeLinksHandleMarkdown = function(element, directory) {
        element.find('a').click(function() {
            var linkHref = $(this).attr('href');
            if (isLocalHref(linkHref) && isMarkdownHref(linkHref)) {
                window.location = "?href=" + encodeURIComponent(directory + linkHref);
                return false;
            }
        });
    };

    var loadFromHref = function(element, href) {
        $.get(href, function(data) {
            element.html(markdown.toHTML(data));
            makeLinksHandleMarkdown(element, getCurrentDirectory(href));
        });
    };

    var getCurrentDirectory = function(href) {
        return href.substring(0, href.lastIndexOf("/") + 1);
    };

    var getQueryParameterHref = function() {
        return window.location.href.match(/href=([^&]*)/);
    };

    return {
        getCurrentDirectory: getCurrentDirectory,
        getQueryParameterHref: getQueryParameterHref,
        loadFromHref: loadFromHref
    }
})();

markdown_explorer = (function() {

    var isLocalHref = function(href) {
        return href.indexOf("://") === -1;
    };

    var isMarkdownHref = function(href) {
        return href.indexOf(".md") !== -1;
    };

    var makeLinksHandleMarkdown = function(element, directory) {
        element.find('a').click(function() {
            var linkHref = $(this).attr('href');
            if (isLocalHref(linkHref) && isMarkdownHref(linkHref)) {
                window.location = [location.protocol, '//', location.host, location.pathname].join('') + "?href=" + encodeURIComponent(directory + linkHref);
                return false;
            }
        });
    };

    var loadFromHref = function(element, href) {
        $.get(href, function(data) {
            element.html(markdown.toHTML(data));
            makeLinksHandleMarkdown(element, getCurrentDirectory(href));
        });
    };

    var getCurrentDirectory = function(href) {
        return href.substring(0, href.lastIndexOf("/") + 1);
    };

    var getQueryParameterHref = function() {
        return window.location.href.match(/href=([^&]*)/);
    };

    return {
        getCurrentDirectory: getCurrentDirectory,
        getQueryParameterHref: getQueryParameterHref,
        loadFromHref: loadFromHref
    }
})();

Fix markdown explorer for local links.


'use strict';

var tmpenv             = require('ember-cli-blueprint-test-helpers/lib/helpers/tmp-env');
var setupTestHooks     = require('ember-cli-blueprint-test-helpers/lib/helpers/setup');
var BlueprintHelpers   = require('ember-cli-blueprint-test-helpers/lib/helpers/blueprint-helper');
var generateAndDestroy = BlueprintHelpers.generateAndDestroy;

describe('Acceptance: ember generate and destroy instance-initializer-addon', function() {
  setupTestHooks(this, tmpenv);

  it('instance-initializer-addon foo', function() {
    // pass any additional command line options in the arguments array
    return generateAndDestroy(['instance-initializer-addon', 'foo'], {
      // define files to assert, and their contents
      target: 'addon',
      files: [
        {
          file: 'app/instance-initializers/foo.js',
          contains: "export { default, initialize } from 'my-addon/instance-initializers/foo';"
        }
      ]
    });
  });

});

'use strict';

var blueprintHelpers = require('ember-cli-blueprint-test-helpers/helpers');
var setupTestHooks = blueprintHelpers.setupTestHooks;
var emberNew = blueprintHelpers.emberNew;
var emberGenerateDestroy = blueprintHelpers.emberGenerateDestroy;

var chai = require('ember-cli-blueprint-test-helpers/chai');
var expect = chai.expect;

describe('Acceptance: ember generate and destroy instance-initializer-addon', function() {
  setupTestHooks(this);

  it('instance-initializer-addon foo', function() {
    var args = ['instance-initializer-addon', 'foo'];

    return emberNew({ target: 'addon' })
      .then(() => emberGenerateDestroy(args, _file => {
        expect(_file('app/instance-initializers/foo.js'))
          .to.contain("export { default, initialize } from 'my-addon/instance-initializers/foo';");
      }));
  });
});

Use alternative blueprint test helpers


'use strict';

/**
 * Module dependencies
 */

// Public node modules.
const _ = require('lodash');

module.exports = strapi => {
  return {
    beforeInitialize: function() {
      strapi.config.middleware.load.before.unshift('users-permissions');
    },

    initialize: function(cb) {
      _.forEach(strapi.config.routes, value => {
        if (_.get(value.config, 'policies')) {
          value.config.policies.unshift('plugins.users-permissions.permissions');
        }
      });

      if (strapi.plugins) {
        _.forEach(strapi.plugins, (plugin, name) => {
          _.forEach(plugin.config.routes, value => {
            if (_.get(value.config, 'policies')) {
              value.config.policies.unshift('plugins.users-permissions.permissions');
            }
          });
        });
      }

      cb();
    }
  };
};

'use strict';

/**
 * Module dependencies
 */

// Public node modules.
const _ = require('lodash');

module.exports = strapi => {
  return {
    beforeInitialize: function() {
      strapi.config.middleware.load.before.unshift('users-permissions');
    },

    initialize: function(cb) {
      _.forEach(strapi.admin.config.routes, value => {
        if (_.get(value.config, 'policies')) {
          value.config.policies.unshift('plugins.users-permissions.permissions');
        }
      });

      _.forEach(strapi.config.routes, value => {
        if (_.get(value.config, 'policies')) {
          value.config.policies.unshift('plugins.users-permissions.permissions');
        }
      });

      if (strapi.plugins) {
        _.forEach(strapi.plugins, (plugin, name) => {
          _.forEach(plugin.config.routes, value => {
            if (_.get(value.config, 'policies')) {
              value.config.policies.unshift('plugins.users-permissions.permissions');
            }
          });
        });
      }

      cb();
    }
  };
};

Apply users-permissions policy on the admin routes


$(document).ready(function(){
    $('.parallax').parallax();

    /* Adjust scrollto to compensate for the navbar */
    $('.scrollto').click(function(){
        var link = $(this).attr("href");
        $('html, body').animate({
            scrollTop: $(link).offset().top - $('#navbar').height()
        }, 200);
    });

    /* Move hamburger sideNav to right */
    $(".button-collapse").sideNav({
        edge: 'right', // Choose the horizontal origin
    });

    /* B&W effects */
    $(".featured-image").hover(
        function(){
            $(this).css("-webkit-filter", "grayscale(0%)");
            $(this).css("filter", "grayscale(0%)");
        },
        function(){
            $(this).css("-webkit-filter", "grayscale(100%)");
            $(this).css("filter", "grayscale(100%)");
        }
    );

    /* Prevent accidental google maps scrolling */
    $("#google-maps").click(function() {
        $("#google-maps iframe").css("pointer-events", "auto");
    });

    $("#google-maps").mouseleave(function() {
        $("#google-maps iframe").css("pointer-events", "none");
    });

    /* Fix scrolling when modals are opened */
    $.featherlight.defaults.afterOpen = function(event) {
        $("body").css("overflow", "hidden");
    };

    $.featherlight.defaults.afterClose = function(event) {
        $("body").css("overflow", "scroll");
    };
});

$(document).ready(function(){
    $('.parallax').parallax();

    /* Adjust scrollto to compensate for the navbar */
    $('.scrollto').click(function(){
        var link = $(this).attr("href");
        $('html, body').animate({
            scrollTop: $(link).offset().top - $('#navbar').height()
        }, 200);
    });

    /* Move hamburger sideNav to right */
    $(".button-collapse").sideNav({
        edge: 'right', // Choose the horizontal origin
    });

    /* B&W effects */
    $(".featured-image").hover(
        function(){
            $(this).css("-webkit-filter", "grayscale(0%)");
            $(this).css("filter", "grayscale(0%)");
        },
        function(){
            $(this).css("-webkit-filter", "grayscale(100%)");
            $(this).css("filter", "grayscale(100%)");
        }
    );

    /* Prevent accidental google maps scrolling */
    $("#google-maps").click(function() {
        $("#google-maps iframe").css("pointer-events", "auto");
    });

    $("#google-maps").mouseleave(function() {
        $("#google-maps iframe").css("pointer-events", "none");
    });

    /* Fix scrolling when modals are opened */
    $.featherlight.defaults.afterOpen = function(event) {
        $("body").css("position", "relative");
        $("body").css("overflow", "hidden");
    };

    $.featherlight.defaults.afterClose = function(event) {
        $("body").css("position", "static");
        $("body").css("overflow", "scroll");
    };
});

Add previous fix for iPhone


// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//= require react
//= require jquery
//= require_tree ./components
//= require ./jquery.jplayer.min

// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//= require rglossa/bundle
//= require jquery
//= require_tree ./components
//= require ./jquery.jplayer.min

Use webpack bundle from rglossa


import get from 'lodash/get'
import {useCallback, useEffect, useRef, useState} from 'react'

const noop = () => true

export default function useControlledInput(
  propValue,
  propOnChange,
  testValid = noop
) {
  const [inputValue, setInputValue] = useState(propValue)
  const ref = useRef()

  // Update the value from the external source on change unless the input is
  // currently the active element.
  useEffect(() => {
    if (ref.current !== document.activeElement) setInputValue(propValue)
  }, [propValue, ref, setInputValue])

  const onChange = useCallback(
    input => {
      // Is this the value itself or an event?
      const isEvent =
        input instanceof Event || get(input, 'nativeEvent') instanceof Event
      const value = isEvent ? input.target.value : input
      const isValid = testValid(value)
      // Ensure the displayed value syncs fast, even if it's not valid
      setInputValue(value)
      // Don't pass invalid changes through to the onChange function
      if (!isValid) return
      // Allow the sync to occur before propogating the change
      setImmediate(() => propOnChange(value))
    },
    [propOnChange, setInputValue, testValid]
  )

  return [inputValue, onChange, ref, testValid(inputValue)]
}

import get from 'lodash/get'
import {useCallback, useEffect, useRef, useState} from 'react'

const alwaysValid = () => true

export default function useControlledInput(
  propValue,
  propOnChange,
  testValid = alwaysValid
) {
  const [inputValue, setInputValue] = useState(propValue)
  const ref = useRef()

  // Update the value from the external source on change unless the input is
  // currently the active element.
  useEffect(() => {
    if (ref.current !== document.activeElement) setInputValue(propValue)
  }, [propValue, ref, setInputValue])

  const onChange = useCallback(
    input => {
      // Is this the value itself or an event?
      const isEvent =
        input instanceof Event || get(input, 'nativeEvent') instanceof Event
      const value = isEvent ? input.target.value : input
      const isValid = testValid(value)
      // Ensure the displayed value syncs fast, even if it's not valid
      setInputValue(value)
      // Don't pass invalid changes through to the onChange function
      if (!isValid) return
      // Allow the sync to occur before propogating the change
      setTimeout(() => propOnChange(value), 0)
    },
    [propOnChange, setInputValue, testValid]
  )

  return [inputValue, onChange, ref, testValid(inputValue)]
}

Use setTimeout(fn, 0) instead of setImmediate


const EventEmitter = require("events");
class DemoClient extends EventEmitter {}

const Client = new DemoClient();
exports.client = Client;

Client.connect = () => {
  Client.emit("ready");
};

Client.on("ready", () => {
  console.log("Demo client ready");
});
Client.emit("ready");

Client.exec = (command, callback) => {
  var response = "";
  if(command === "gettime") {
    response = "Day 1, 07:00\n6 days to next horde.";
  }
  else if(command === "version") {
    response = "Game version: Alpha 20 (b238) Compatibility Version: Alpha 20";
  }
  else if(command === "lp") {
    response = "Total of 0 in the game";
  }

  callback(void 0, response);
};

const EventEmitter = require("events");
class DemoClient extends EventEmitter {}

const Client = new DemoClient();
exports.client = Client;

Client.connect = () => {
  Client.emit("ready");
};

Client.on("ready", () => {
  console.log("Demo client ready");
});
Client.emit("ready");

Client.exec = (command, callback) => {
  var response = "";
  if(command === "gettime") {
    response = "Day 1, 07:00\n6 days to next horde.";
  }
  else if(command === "version") {
    response = "Game version: Alpha 20.1 (b6) Compatibility Version: Alpha 20.1";
  }
  else if(command === "lp") {
    response = "Total of 0 in the game";
  }

  callback(void 0, response);
};

Update demo server version output


var os = require('os');
var fs = require('fs');
var greenworks;
if (os.platform() == 'darwin')
  greenworks = require('../build/release/greenworks-osx');
else if (os.platform() == 'win32' || os.platform() == 'win64')
  greenworks = require('../build/release/greenworks-win');
else if (os.platform() == 'linux') {
  if (os.arch() == 'x64')
    greenworks = require('../build/release/greenworks-linux64');
  else if (os.arch() == 'ia32')
    greenworks = require('../build/release/greenworks-linux32');
}

// Greenworks Utils APIs implmentation.
greenworks.Utils.move = function(source_dir, target_dir) {
  fs.rename(source_dir, target_dir);
}

module.exports = greenworks;

var os = require('os');
var fs = require('fs');
var greenworks;
if (os.platform() == 'darwin')
  greenworks = require('../build/Release/greenworks-osx');
else if (os.platform() == 'win32' || os.platform() == 'win64')
  greenworks = require('../build/Release/greenworks-win');
else if (os.platform() == 'linux') {
  if (os.arch() == 'x64')
    greenworks = require('../build/Release/greenworks-linux64');
  else if (os.arch() == 'ia32')
    greenworks = require('../build/Release/greenworks-linux32');
}

// Greenworks Utils APIs implmentation.
greenworks.Utils.move = function(source_dir, target_dir) {
  fs.rename(source_dir, target_dir);
}

module.exports = greenworks;

Correct the greenwork addon path.


const fs = require('fs')
const express = require('express')
const app = express()

exports.addLocalPath = function addLocalPath(path) {
  fs.accessSync(path, fs.F_R_OK)
  app.use(express.static(path))
}

exports.start = function start(p, addr) {
  app.listen(p, addr)
}

const fs = require('fs')
const express = require('express')
const app = express()

exports.addLocalPath = function addLocalPath(path) {
  // FIXME: better error handling, until then: throw
  fs.accessSync(path, fs.F_R_OK)
  app.use(express.static(path))
}

exports.start = function start(p, addr) {
  app.listen(p, addr)
}

Add note on handling invalid local paths


Components.utils.import("resource://gre/modules/devtools/Console.jsm");
Components.utils.import("resource://gre/modules/Timer.jsm");
Components.utils.import('resource://gre/modules/Services.jsm');
// This module does not support all of es6 promise functionality.
// Components.utils.import("resource://gre/modules/Promise.jsm");
const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1", "nsIXMLHttpRequest");
Components.utils.importGlobalProperties(['URL']);

var hiddenWindow = Services.appShell.hiddenDOMWindow;
var mozRTCPeerConnection = hiddenWindow.mozRTCPeerConnection;
var mozRTCSessionDescription = hiddenWindow.mozRTCSessionDescription;
var mozRTCIceCandidate = hiddenWindow.mozRTCIceCandidate;

// Replace Blob with blob that has prototype defined.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1007318
var Blob = hiddenWindow.Blob;

var freedom;

function setupFreedom(manifest, debug) {
  if (this.freedom) {
    return this.freedom;
  }

  var lastSlash = manifest.lastIndexOf("/");
  var manifestLocation = manifest.substring(0, lastSlash + 1);
  //var manifestFilename = manifest.substring(lastSlash + 1);
  firefox_config = {
    isApp: false,
    manifest: manifest,
    portType: 'Worker',
    stayLocal: true,
    location: manifestLocation,
    debug: debug || false,
    moduleContext: false
  };

Components.utils.import("resource://gre/modules/devtools/Console.jsm");
Components.utils.import("resource://gre/modules/Timer.jsm");
Components.utils.import('resource://gre/modules/Services.jsm');
// This module does not support all of es6 promise functionality.
// Components.utils.import("resource://gre/modules/Promise.jsm");
const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1", "nsIXMLHttpRequest");
Components.utils.importGlobalProperties(['URL']);

var hiddenWindow = Services.appShell.hiddenDOMWindow;
var mozRTCPeerConnection = hiddenWindow.mozRTCPeerConnection;
var mozRTCSessionDescription = hiddenWindow.mozRTCSessionDescription;
var mozRTCIceCandidate = hiddenWindow.mozRTCIceCandidate;

// Replace Blob with blob that has prototype defined.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1007318
var Blob = hiddenWindow.Blob;

var firefoxExtension = true;

var freedom;

function setupFreedom(manifest, debug, freedomcfg) {
  if (this.freedom) {
    return this.freedom;
  }

  var lastSlash = manifest.lastIndexOf("/");
  var manifestLocation = manifest.substring(0, lastSlash + 1);
  //var manifestFilename = manifest.substring(lastSlash + 1);
  firefox_config = {
    isApp: false,
    manifest: manifest,
    portType: 'Worker',
    stayLocal: true,
    location: manifestLocation,
    debug: debug || false,
    moduleContext: false
  };

Allow freedomcfg to be passed in to setupFreedom.


const CoreView = require('backbone/core-view');
const template = require('./delete-mobile-app.tpl');
const checkAndBuildOpts = require('builder/helpers/required-opts');

const REQUIRED_OPTS = [
  'modalModel',
  'configModel',
  'authenticityToken',
  'needsPasswordConfirmation'
];

module.exports = CoreView.extend({
  events: {
    'submit .js-form': '_close',
    'click .js-cancel': '_close'
  },

  initialize: function (options) {
    checkAndBuildOpts(options, REQUIRED_OPTS, this);
  },

  render: function () {
    const mobileAppId = this.options.mobileApp.id;

    this.$el.html(
      template({
        formAction: `${this._configModel.prefixUrl()}/your_apps/mobile/${mobileAppId}`,
        authenticityToken: this._authenticityToken,
        passwordNeeded: this._needsPasswordConfirmation
      })
    );
  },

  _close: function () {
    this._modalModel.destroy();
  }
});

const CoreView = require('backbone/core-view');
const template = require('./delete-mobile-app.tpl');
const checkAndBuildOpts = require('builder/helpers/required-opts');

const REQUIRED_OPTS = [
  'modalModel',
  'configModel',
  'authenticityToken',
  'needsPasswordConfirmation'
];

module.exports = CoreView.extend({
  events: {
    'submit .js-form': '_close',
    'click .js-cancel': '_close'
  },

  initialize: function (options) {
    checkAndBuildOpts(options, REQUIRED_OPTS, this);
  },

  render: function () {
    const mobileAppId = this.options.mobileApp.id;

    this.$el.html(
      template({
        formAction: `${this._configModel.get('base_url')}/your_apps/mobile/${mobileAppId}`,
        authenticityToken: this._authenticityToken,
        passwordNeeded: this._needsPasswordConfirmation
      })
    );
  },

  _close: function () {
    this._modalModel.destroy();
  }
});

Change url to base url in mobile app delete


module.exports = function crawler(callback) {
	const request = require('request');
	const cheerio = require('cheerio');

	const URL = 'http://sarc.pucrs.br/Default/';

	var data = {};
	let requestHandler = (err, response, html) => {
		if(err) return callback(err);

		let $ = cheerio.load(html)('#ctl00_cphTitulo_UpdatePanel2 > div > table');

		for (let i = 0, l = $.length; i < l; i++) {
			let content    = cheerio.load($.eq(i).html());
			let time       = content('span').html();
			let table_data = content('.ms-btoolbar').children();
			let details = [];
			for (let j = 0, l = table_data.length; j < l; j+=3) {
				let detail = {
					'resource' : table_data.eq(j).text().trim(),
					'course'   : table_data.eq(j+1).text().trim(),
					'owner'    : table_data.eq(j+2).text().trim()
				};
				details.push(detail);
			}
			time = formatTime(time);
			if (details.length > 0) {
				data[time] = details;
			};
		}
		callback(null, data);
	}
	request(URL, requestHandler);
}

function formatTime(time) {
	var weekday = new Date().getDay() + 1
	return weekday + time
}

module.exports = function crawler(callback) {
	const request = require('request');
	const cheerio = require('cheerio');

	const URL = 'http://sarc.pucrs.br/Default/';

	var data = [];
	let requestHandler = (err, response, html) => {
		if(err) return callback(err);

		let $ = cheerio.load(html)('#ctl00_cphTitulo_UpdatePanel2 > div > table');

		for (let i = 0, l = $.length; i < l; i++) {
			let content    = cheerio.load($.eq(i).html());
			let time       = content('span').html();
			let table_data = content('.ms-btoolbar').children();
			for (let j = 0, l = table_data.length; j < l; j+=3) {
				let detail = {
					'time'     : formatTime(time),
					'resource' : table_data.eq(j).text().trim(),
					'course'   : table_data.eq(j+1).text().trim(),
					'owner'    : table_data.eq(j+2).text().trim()
				};
				data.push(detail);
			}
		}
		callback(null, data);
	}
	request(URL, requestHandler);
}

function formatTime(time) {
	var weekday = new Date().getDay() + 1
	return weekday + time
}

Change format of parsed data.


!function() {
  'use strict';

  angular.module('crumble', ['ngRoute'])
    .factory('crumble', function ($location, $route, $interpolate) {
      var context;
      var crumble = {
        trail: [],
      };

      crumble.setContext = function (ctx) {
        context = ctx;
        crumble.trail = build($location.path());
      };

      var build = function (path) {
        return !path ? [] : build(crumble.getParent(path)).concat(crumble.getCrumb(path));
      };

      crumble.getParent = function (path) {
        return path.replace(/[^\/]*\/?$/, '');
      };

      crumble.getCrumb = function (path) {
        var route = crumble.getRoute(path);
        return {
          path: path,
          label: $interpolate(route.label)(context),
        };
      };

      crumble.getRoute = function (path) {
        return find($route.routes, function (route) {
          return route.regexp && route.regexp.test(path);
        });
      };

      var find = function (obj, fn, thisArg) {
        for (var key in obj) {
          if (obj.hasOwnProperty(key) && fn.call(thisArg, obj[key], key, obj)) {
            return obj[key];
          }
        }
      };

      return crumble;
    });

}();

!function() {
  'use strict';

  angular.module('crumble', ['ngRoute'])
    .factory('crumble', function ($location, $route, $interpolate) {
      var crumble = {
        trail: [],
        context: {},
      };

      crumble.update = function (context) {
        crumble.context = context;
        crumble.trail = build($location.path());
      };

      var build = function (path) {
        return !path ? [] : build(crumble.getParent(path)).concat(crumble.getCrumb(path));
      };

      crumble.getParent = function (path) {
        return path.replace(/[^\/]*\/?$/, '');
      };

      crumble.getCrumb = function (path) {
        var route = crumble.getRoute(path);
        return {
          path: path,
          label: $interpolate(route.label)(crumble.context),
        };
      };

      crumble.getRoute = function (path) {
        return find($route.routes, function (route) {
          return route.regexp && route.regexp.test(path);
        });
      };

      var find = function (obj, fn, thisArg) {
        for (var key in obj) {
          if (obj.hasOwnProperty(key) && fn.call(thisArg, obj[key], key, obj)) {
            return obj[key];
          }
        }
      };

      return crumble;
    });

}();

Make context accessible, rename setContext to update


'use strict';
var _ = require('lodash');
var path = require('path');
var convert = require(path.resolve(__dirname, './convert.js'));

var context = {
  getDefaults: getDefaults
};

function getDefaults(name, module) {
  var folderName = convert.moduleToFolder(module);
  return _.clone({
    module: module,
    camelName: _.camelCase(name),
    controller: _.upperFirst(_.camelCase(name)) + 'Controller',
    directive: _.camelCase(name),
    directiveUrl: folderName + _.kebabCase(name) + '.directive.html',
    kebabName: _.kebabCase(name),
    moduleClass: _.kebabCase(module),
    route: _.camelCase(name) + 'Route',
    service: _.camelCase(name) + 'Service',
    state: module.replace('app.modules.', ''),
    templateUrl: folderName + _.kebabCase(name) + '.html'
  });
}

module.exports = context;

'use strict';
var _ = require('lodash');
var path = require('path');
var convert = require(path.resolve(__dirname, './convert.js'));

var context = {
  getDefaults: getDefaults
};

function getDefaults(name, module) {
  var folderName = convert.moduleToFolder(module);
  return _.clone({
    module: module,
    camelName: _.camelCase(name),
    controller: _getController(name, module),
    directive: _.camelCase(name),
    directiveUrl: folderName + _.kebabCase(name) + '.directive.html',
    kebabName: _.kebabCase(name),
    moduleClass: _.kebabCase(module),
    route: _.camelCase(name) + 'Route',
    service: _.camelCase(name) + 'Service',
    state: module.replace('app.modules.', ''),
    templateUrl: folderName + _.kebabCase(name) + '.html'
  });
}

function _getController(name, module) {
  module = module.replace(/app\..*?\./, '');
  return _.upperFirst(_.camelCase(module)) + 'Controller';
}

module.exports = context;

Set <controller> name scoped by modules 'namespace'