import Command from './Command.js';

/**
 * Table Command
 */
export default class TableCommand extends Command {
    /**
     * @inheritDoc
     */
    execute() {
        const figure = this.editor.document.createElement('figure');
        const table = this.editor.document.createElement('table');
        const figcaption = this.editor.document.createElement('figcaption');

        figure.classList.add('table');
        figure.appendChild(table);
        figure.appendChild(figcaption);

        ['thead', 'tbody', 'tfoot'].forEach(part => {
            const item = this.editor.document.createElement(part);
            const tr = this.editor.document.createElement('tr');
            table.appendChild(item);
            item.appendChild(tr);

            for (let i = 0; i < 2; ++i) {
                let cell = this.editor.document.createElement(part === 'thead' ? 'th' : 'td');
                tr.appendChild(cell);
            }
        });

        this.editor.insert(figure);
    }
}

import Command from './Command.js';

/**
 * Table Command
 */
export default class TableCommand extends Command {
    /**
     * @inheritDoc
     */
    execute() {
        const figure = this.editor.document.createElement('figure');
        const table = this.editor.document.createElement('table');
        const figcaption = this.editor.document.createElement('figcaption');

        figure.classList.add('table');
        figure.appendChild(table);
        figure.appendChild(figcaption);

        ['thead', 'tbody', 'tfoot'].forEach(section => {
            const item = this.editor.document.createElement(section);
            const tr = this.editor.document.createElement('tr');
            table.appendChild(item);
            item.appendChild(tr);

            for (let i = 0; i < 2; ++i) {
                let cell = this.editor.document.createElement(section === 'thead' ? 'th' : 'td');
                tr.appendChild(cell);
            }
        });

        this.editor.insert(figure);
    }
}

Rename param to be consistent


'use strict';

// @ngInject
var authorsDirective = function() {
  return {
    scope: {
      authors: '='
    },
    template: require('./authorstemplate.html'),
    //@ngInject
    controller: function($scope) {
      $scope.fullnames = function (authors) {
        return authors.reduce((m, a, i) => m + a.first_name + ' ' + a.last_name + (i < authors.length-1 ? ', ':''), '');
      };
    }
  };
};

module.exports = authorsDirective;

'use strict';

// @ngInject
var authorsDirective = function() {
  return {
    scope: {
      authors: '='
    },
    template: require('./authorstemplate.html'),
    //@ngInject
    controller: function($scope) {
      $scope.fullnames = function (authors) {
        return authors.reduce((m, a, i) => {
          return m +
            (a.first_name ? a.first_name + ' ' + a.last_name : a.name) +
            (i < authors.length-1 ? ', ':'');
        }, '');
      };
    }
  };
};

module.exports = authorsDirective;

Support first_name, last_name and name


var Minionette = (function(global, _, $, Backbone) {
    'use strict';

    // Define and export the Minionette namespace
    var Minionette = {};
    Backbone.Minionette = Minionette;

    // @include ../jquery.cleanData.js

    // @include ../view.js
    // @include ../region.js
    // @include ../model_view.js
    // @include ../collection_view.js

    return Minionette;
})(this, _, jQuery, Backbone);

var Minionette = (function(global, _, $, Backbone) {
    'use strict';

    // Define and export the Minionette namespace
    var Minionette = {};
    Backbone.Minionette = Minionette;

    // @include ../jquery.cleanData.js

    // @include ../region.js
    // @include ../view.js
    // @include ../model_view.js
    // @include ../collection_view.js

    return Minionette;
})(this, _, jQuery, Backbone);

Make sure Region is included before View


var gulp  = require('gulp')
var shell = require('./')

var paths = {
  js: ['*.js', 'test/*.js']
}

gulp.task('test', shell.task('mocha -R spec -r should'))

gulp.task('coverage', ['test'], shell.task('istanbul cover _mocha -- -R spec'))

gulp.task('coveralls', ['coverage'], shell.task('cat coverage/lcov.info | coveralls'))

gulp.task('lint', shell.task([
  'jshint ' + paths.js.join(' '),
  'jscs '   + paths.js.join(' '),
]))

gulp.task('default', ['coverage', 'lint'])

gulp.task('watch', function () {
  // Keep watch running on errors.
  gulp.on('err', function () {})

  gulp.watch(paths.js, ['default'])
})

var gulp  = require('gulp')
var shell = require('./')

var paths = {
  js: ['*.js', 'test/*.js']
}

gulp.task('test', shell.task('mocha -R spec -r should'))

gulp.task('coverage', ['test'], shell.task('istanbul cover _mocha -- -R spec'))

gulp.task('coveralls', ['coverage'], shell.task('cat coverage/lcov.info | coveralls'))

gulp.task('lint', shell.task([
  'jshint ' + paths.js.join(' '),
  'jscs '   + paths.js.join(' '),
]))

gulp.task('default', ['coverage', 'lint'])

gulp.task('watch', function () {
  gulp.watch(paths.js, ['default'])
})

Remove dirty hack for keeping watch running on errors


/**
 * @file Etherscan API client.
 * @module client/etherscan
 */

'use strict'

/**
 * Etherscan API client.
 * @static
 */
class Client {

}

// Expose
module.exports = Client

/**
 * @file Etherscan API client.
 * @module client/etherscan
 */

'use strict'

/**
 * Private members store.
 * @private
 */
const privs = new WeakMap()

/**
 * Etherscan API client.
 * @static
 */
class Client {
  /**
   * No parameters.
   */
  constructor () {
    const priv = {}
    privs.set(this, priv)
  }
}

// Expose
module.exports = Client

Add private members store to Etherscan client


var gulp = require('gulp');
var $ = require('gulp-load-plugins')({
  camelize: true
});

var config = {
  source: {
    scripts: {
      path: 'app/',
      files: './app/**/*.js'
    }
  },
  build: {
    scripts: 'build/scrips/'
  }
}

gulp.task('build-scripts', function() {
  return gulp.src(config.source.scripts.files)
    .pipe($.concat('app-build.js'))
    .pipe($.uglify({mangle: false }))
    .pipe(gulp.dest(config.build.scripts));

});

gulp.task('default', function() {
  // place code for your default task here
});

var gulp = require('gulp');
var $ = require('gulp-load-plugins')({
  camelize: true
});

var config = {
  source: {
    scripts: {
      path: 'app/',
      files: './app/**/*.js'
    },
    markup: {
      path: 'app/',
      files: './app/**/*.html'
    }
  },
  build: {
    scripts: 'build/scrips/',
    markup: 'build/'
  }
}

gulp.task('build-scripts', function() {
  return gulp.src(config.source.scripts.files)
    .pipe($.concat('app-build.js'))
    .pipe($.uglify({mangle: false }))
    .pipe(gulp.dest(config.build.scripts));
});

gulp.task('build-markup', function() {
  return gulp.src(config.source.markup.files)
    .pipe(gulp.dest(config.build.markup));
});

gulp.task('default', function() {
  // place code for your default task here
});

Add gulp task build markup


var gulp = require('gulp')
var sass = require('gulp-sass')
var browserSync = require('browser-sync').create()

gulp.task('sass', function () {
  return gulp.src('./scss/**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest('./css'))
})

gulp.task('browser-sync', function() {
  browserSync.init({
    server: {
      baseDir: './'
    }
  })
})

gulp.task('default', ['sass', 'browser-sync'], function() {
  gulp.watch('./sass/**/*.scss', ['sass'])
})

var gulp = require('gulp')
var sass = require('gulp-sass')
var browserSync = require('browser-sync').create()

gulp.task('sass', function () {
  return gulp.src('./scss/**/*.scss')
    .pipe(sass())
    .pipe(gulp.dest('./css'))
    .pipe(browserSync.stream())
})

gulp.task('browser-sync', function() {
  browserSync.init({
    server: {
      baseDir: './'
    }
  })

  gulp.watch('./**/*.scss', ['sass'])
  gulp.watch('./index.html').on('change', browserSync.reload)
})

gulp.task('default', ['browser-sync'], function() {
  gulp.watch('./sass/**/*.scss', ['sass'])
})

Fix gulfile not watching Sass changes


import StoriesItemType from '../types/StoriesItemType'
import RankingInputItemType from '../types/RankingInputItemType'
import {Story, User, Ranking} from '../models'

const addRanking = {
  name: 'addRanking',
  type: StoriesItemType,
  args: {
    story: {type: RankingInputItemType}
  },
  async resolve (value, {story}) {
    let userId = value.request.user.id
    let storyId = story.id
    let ranking = await Ranking.findOne({where: {userId, storyId}})
    if (! ranking){
      Ranking.create({userId, storyId})
    }
    let result = await Story.findById(storyId, {
      include: [{
        model: User,
        as: 'user'
      },{
        model: Ranking,
        as: 'rankings'
      }]
    })
    return result
  }
}

export default addRanking

import StoriesItemType from '../types/StoriesItemType'
import RankingInputItemType from '../types/RankingInputItemType'
import {Story, User, Ranking} from '../models'

const addRanking = {
  name: 'addRanking',
  type: StoriesItemType,
  args: {
    story: {type: RankingInputItemType}
  },
  async resolve (value, {story}) {
    let userId = value.request.user.id
    let storyId = story.id
    let user = await User.findById(userId)
    if (user){
      let ranking = await Ranking.findOne({where: {userId, storyId}})
      if (! ranking){
        Ranking.create({userId, storyId})
      }
      let result = await Story.findById(storyId, {
        include: [{
          model: User,
          as: 'user'
        },{
          model: Ranking,
          as: 'rankings'
        }]
      })
      return result
    }else{
      throw 'Invalid user!'
    }
  }
}

export default addRanking

Add user check to add ranking


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

/*
 * Hide the password. Uses the password to form authorization strings,
 * but provides no interface for exporting it.
 */
function user_credentials(username,password) {
  if (username.is_user_credentials &&
    typeof username.basic === 'function' &&
    typeof username.digest === 'function'
  ) {
    return username;
  }

  var basic_string= !password && password !== '' ?
    new Buffer(username, "ascii").toString("base64")
  :
    new Buffer(username+':'+password, "ascii").toString("base64")
  ;
  function basic()
  {
    return basic_string;
  }
  function digest(realm) {
    return !password && password !== '' ?
        md5(username+':'+realm)
        :
        md5(username+':'+realm+':'+password)
  }
  return {
    basic: basic,   // basic() returns a hash of username:password
    digest: digest, // digest(realm) returns a u & p hash for that realm
    username: username,
    is_user_credentials: true
  }
}

module.exports= user_credentials;

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

/*
 * Hide the password. Uses the password to form authorization strings,
 * but provides no interface for exporting it.
 */
function user_credentials(username,password) {
  if (username.is_user_credentials &&
    typeof username.basic === 'function' &&
    typeof username.digest === 'function'
  ) {
    return username;
  }

  var basic_string= !password && password !== '' ?
    new Buffer(username, "ascii").toString("base64")
  :
    new Buffer(username+':'+password, "ascii").toString("base64")
  ;

  function Credentials()
  {
    this.username= username;
  }
  Credentials.prototype.basic= function()
  {
    return basic_string;
  }
  Credentials.prototype.digest= function(realm)
  {
    return !password && password !== '' ?
        md5(username+':'+realm)
        :
        md5(username+':'+realm+':'+password)
  }
  Credentials.prototype.is_user_credentials= function()
  {
    return true;
  }

  return new Credentials;
}

module.exports= user_credentials;

Refactor user credentials as a prototyped object.


var gulp = require('gulp');
var nodemon = require('nodemon');
var webpack = require('webpack');
var clientConfig = require('./webpack.config');
var path = require('path');

function onBuild(cb) {
  return function(err, stats) {
    if (err)
      console.log('Error', err);
    else
      console.log(stats.toString());

    if (cb) cb();
  }
}

// Serverside (backend) tasks group
// Nothing so far!

// Clientside (frontend) tasks
gulp.task('client-watch', function() {
  // Changes within 100 ms = one rebuild
  webpack(clientConfig).watch(100, onBuild);
});

gulp.task('client-build', function(cb) {
  webpack(clientConfig).run(onBuild(cb));
});

// Group tasks

// For development - rebuilds whenever something changes
gulp.task('watch', ['client-watch']);

// For production - builds everything
gulp.task('build', ['client-build']);

// Nodemon is used. Maybe it's better to use gulp's own watch system?
gulp.task('run', ['client-watch'], function() {
  nodemon({
    execMap: {
      js: 'node'
    },
    script: path.join(__dirname, 'server/main.js'),
    ext: 'js json'
  }).on('restart', function() {
    console.log('Restarted!');
  });
});

var gulp = require('gulp');
var nodemon = require('nodemon');
var webpack = require('webpack');
var clientConfig = require('./webpack.config');
var path = require('path');

var wpCompiler = webpack(clientConfig);

function onBuild(cb) {
  return function(err, stats) {
    if (err)
      console.log('Error', err);
    else
      console.log(stats.toString());

    if (cb) cb();
  }
}

// Serverside (backend) tasks group
// Nothing so far!

// Clientside (frontend) tasks
gulp.task('client-watch', function() {
  // Changes within 100 ms = one rebuild
  wpCompiler.watch({
      aggregateTimeout: 100
    },
    onBuild());
});

gulp.task('client-build', function(cb) {
  wpCompiler.run(onBuild(cb));
});

// Group tasks

// For development - rebuilds whenever something changes
gulp.task('watch', ['client-watch']);

// For production - builds everything
gulp.task('build', ['client-build']);

// Nodemon is used. Maybe it's better to use gulp's own watch system?
gulp.task('run', ['client-watch'], function() {
  nodemon({
    execMap: {
      js: 'node'
    },
    script: path.join(__dirname, 'server/main.js'),
    ext: 'js json'
  }).on('restart', function() {
    console.log('Restarted!');
  });
});

Fix onBuild callback for webpack watch mode, now it properly outputs what it should to the log (screen). Also microrefactor the webpack calling code.


/*
Copyright 2014 Spotify AB

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* global require */

var gulp = require('gulp');
var qunit = require('gulp-qunit');
var jshint = require('gulp-jshint');
var htmlhint = require("gulp-htmlhint");
var csslint = require("gulp-csslint");

gulp.task('test', function() {
    return gulp.src('./test.html').pipe(qunit());
});

gulp.task('jslint', function() {
    return gulp.src('*.js')
        .pipe(jshint())
        .pipe(jshint.reporter('default'))
        .pipe(jshint.reporter('fail'));
});

gulp.task('htmllint', function() {
    return gulp.src(["*.html", "!test.html"])
        .pipe(htmlhint())
        .pipe(htmlhint.reporter())
        .pipe(htmlhint.failReporter());
});

gulp.task('csslint', function() {
    gulp.src('*.css')
        .pipe(csslint())
        .pipe(csslint.reporter())
        .pipe(csslint.failReporter());
});

/*
Copyright 2014 Spotify AB

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* global require */

var gulp = require('gulp');
var qunit = require('gulp-qunit');
var jshint = require('gulp-jshint');
var htmlhint = require("gulp-htmlhint");
var csslint = require("gulp-csslint");

gulp.task('test', function() {
    return gulp.src('file://test.html').pipe(qunit());
});

gulp.task('jslint', function() {
    return gulp.src('*.js')
        .pipe(jshint())
        .pipe(jshint.reporter('default'))
        .pipe(jshint.reporter('fail'));
});

gulp.task('htmllint', function() {
    return gulp.src(["*.html", "!test.html"])
        .pipe(htmlhint())
        .pipe(htmlhint.reporter())
        .pipe(htmlhint.failReporter());
});

gulp.task('csslint', function() {
    gulp.src('*.css')
        .pipe(csslint())
        .pipe(csslint.reporter())
        .pipe(csslint.failReporter());
});

Fix headless unit test running


const fs = require("fs");
const path = require("path");
const { src, dest, task, watch, series } = require('gulp');
const Gitdown = require('@gnd/gitdown');
const rename = require("gulp-rename");
const debug = require("gulp-debug");
const pandoc = require("gulp-pandoc");

task('gitdown', async () => {
  if (!fs.existsSync("dist")) {
    fs.mkdirSync("dist");
  }

  const gitdown = Gitdown.readFile(path.join(__dirname, "src", "index.md"));

  gitdown.registerHelper("scroll-up", {
    compile: (config) => {
      return "<sup>[ [^](#user-content-contents) _Back to contents_ ]</sup>";
    }
  });

  await gitdown.writeFile('dist/_merged.md');
});

task('pandoc', () => {
  return src("dist/_merged.md")
    .pipe(debug({ title: "merged" }))
    .pipe(pandoc({
      from: "gfm",
      to: "gfm",
      args: ['--wrap=none'],
      ext: "md"
    }))
    .pipe(debug({ title: "pandoc output:" }))
    .pipe(rename("output.md"))
    .pipe(dest("dist"));
});

task('build', series("gitdown", "pandoc"));

task('watch', series(["build", () => {
  watch('./src', series(['build']));
}]));

task('default', series('build'));

const fs = require("fs");
const path = require("path");
const { src, dest, task, watch, series } = require('gulp');
const Gitdown = require('@gnd/gitdown');
const rename = require("gulp-rename");
const debug = require("gulp-debug");
const pandoc = require("gulp-pandoc");

task('gitdown', async () => {
  if (!fs.existsSync("dist")) {
    fs.mkdirSync("dist");
  }

  const gitdown = Gitdown.readFile(path.join(__dirname, "src", "index.md"));

  gitdown.registerHelper("scroll-up", {
    compile: (config) => {
      if (config.downRef) {
        return `<sup>[ [∧](#user-content-contents) _Back to contents_ | _${config.downTitle}_ [∨](${config.downRef}) ]</sup>`;
      } else {
        return "<sup>[ [∧](#user-content-contents) _Back to contents_ ]</sup>";
      }
    }
  });

  await gitdown.writeFile('dist/_merged.md');
});

task('pandoc', () => {
  return src("dist/_merged.md")
    .pipe(debug({ title: "merged" }))
    .pipe(pandoc({
      from: "gfm",
      to: "gfm",
      args: ['--wrap=none'],
      ext: "md"
    }))
    .pipe(debug({ title: "pandoc output:" }))
    .pipe(rename("output.md"))
    .pipe(dest("dist"));
});

task('build', series("gitdown", "pandoc"));

task('watch', series(["build", () => {
  watch('./src', series(['build']));
}]));

task('default', series('build'));

Make scroll-up thingy support scroll-down thingy


var gulp = require("gulp");
var sass = require("gulp-sass");

gulp.task('sass', function () {
    gulp.src('src/hipster-grid-system.scss')
        .pipe(sass())
        .pipe(gulp.dest('dist'));
});

var gulp = require("gulp");
var sass = require("gulp-sass");
var rename = require("gulp-rename");
var autoprefixer = require("gulp-autoprefixer");

gulp.task('sass', function () {
    gulp.src('src/hipster-grid-system.scss')
        .pipe(sass())
        .pipe(autoprefixer())
        .pipe(gulp.dest('dist'));
    gulp.src('src/hipster-grid-system.scss')
        .pipe(sass({outputStyle: 'compressed'}))
        .pipe(autoprefixer())
        .pipe(rename({
            suffix: ".min"
        }))
        .pipe(gulp.dest('dist'));
});

Add support autoprefixer for cross-browser. Add support minify dist file.


'use strict';

// DEV TIME CODE
if (FAKE_SERVER) {
    require('fake');
}
// DEV TIME CODE

require('./index.scss');

var $ = require('$jquery');
var util = require('lib/util');
var state = require('./state');
var repository = require('./repository');
var sections = require('./sections/section');

//var details = args.newData.hud;
var setup = state.current();

// only load things when we have the data ready to go
repository.getData(function(details) {
	// generate the html needed for the sections
	var html = sections.render(details, setup);
	html = '

' + html + '

';

	// insert the html into the dom
	var holder = $(html).appendTo('body')

	// force the correct state from previous load
	state.setup(holder);

	// setup events that we need to listen to
	sections.postRender(holder);

	// TODO: need to find a better place for this
	$('.glimpse-icon').click(function() {
		window.open(util.resolveClientUrl(util.currentRequestId(), true), 'GlimpseClient');
	});
});

'use strict';

// DEV TIME CODE
if (FAKE_SERVER) {
    require('fake');
}
// DEV TIME CODE

require('./index.scss');

var $ = require('$jquery');
var util = require('lib/util');
var state = require('./state');
var repository = require('./repository');
var sections = require('./sections/section');

//var details = args.newData.hud;
var setup = state.current();

// only load things when we have the data ready to go
repository.getData(function(details) {
	$(function() { setTimeout(function() {
		// generate the html needed for the sections
		var html = sections.render(details, setup);
		html = '

' + html + '

';

		// insert the html into the dom
		var holder = $(html).appendTo('body')

		// force the correct state from previous load
		state.setup(holder);

		// setup events that we need to listen to
		sections.postRender(holder);

		// TODO: need to find a better place for this
		$('.glimpse-icon').click(function() {
			window.open(util.resolveClientUrl(util.currentRequestId(), true), 'GlimpseClient');
		});
	}, 0); });
});

Fix bug where Navigation Timing info could be accessed to quickly and hence produce weird values


const Redis = require('ioredis');

module.exports = url => {
  const redis = new Redis(url);

  redis.setJSON = async (...arguments) => {
    arguments[1] = JSON.stringify(arguments[1]);
    if (typeof arguments[2] === 'object' && arguments[2].asSeconds) {
      arguments[2] = parseInt(arguments[2].asSeconds());
    }
    if (typeof arguments[2] === 'number') {
      arguments[3] = parseInt(arguments[2]);
      arguments[2] = 'EX';
    }
    return await redis.set.apply(redis, arguments);
  }

  redis.getJSON = async key => {
    const value = await redis.get(key);
    if (value) {
      return JSON.parse(value);
    }
    return value;
  }

  return redis;
};

const Redis = require('ioredis');

module.exports = url => {
  const redis = new Redis(url);

  redis.setJSON = async (...arguments) => {
    arguments[1] = JSON.stringify(arguments[1]);
    if (typeof arguments[2] === 'object' && arguments[2].asSeconds) {
      arguments[2] = parseInt(arguments[2].asSeconds());
    }
    if (typeof arguments[2] === 'number') {
      arguments[3] = parseInt(arguments[2]);
      arguments[2] = 'EX';
    }
    if (typeof arguments[2] === 'undefined') {
      arguments = [arguments[0], arguments[1]];
    }
    return await redis.set.apply(redis, arguments);
  }

  redis.getJSON = async key => {
    const value = await redis.get(key);
    if (value) {
      return JSON.parse(value);
    }
    return value;
  }

  return redis;
};

Fix redis syntax error if third argument is undefined


const Command = require('../structures/command.js');
const request = require('request');

module.exports = class TogetherTube extends Command {

  constructor(client) {
    super(client);
    this.name = "togethertube";
    this.aliases ["ttube", "ttb"];
  }

  run(message, args, commandLang) {
    let embed = this.client.getDekuEmbed(message);
    message.channel.startTyping();
    request('https://togethertube.com/room/create', (error, response) => {
      if (error) {
        embed.setColor(this.client.config.colors.error);
        embed.setTitle(commandLang.error_title);
        embed.setDescription(commandLang.error_description);
      } else {
        embed.setDescription(response.request.uri.href);
        embed.setAuthor('TogetherTube', 'https://togethertube.com/assets/img/favicons/favicon-32x32.png', 'https://togethertube.com/');
        message.channel.stopTyping();
        message.channel.send({embed});
      }
    });
  }

}

const Command = require('../structures/command.js');
const request = require('request');

module.exports = class TogetherTube extends Command {

  constructor(client) {
    super(client);
    this.name    = "togethertube";
    this.aliases = ["ttube", "ttb"];
  }

  run(message, args, commandLang) {
    let embed = this.client.getDekuEmbed(message);
    message.channel.startTyping();
    request('https://togethertube.com/room/create', (error, response) => {
      if (error) {
        embed.setColor(this.client.config.colors.error);
        embed.setTitle(commandLang.error_title);
        embed.setDescription(commandLang.error_description);
      } else {
        embed.setDescription(response.request.uri.href);
        embed.setAuthor('TogetherTube', 'https://togethertube.com/assets/img/favicons/favicon-32x32.png', 'https://togethertube.com/');
      }
      message.channel.stopTyping();
        message.channel.send({embed});
    });
  }

}

Fix aliases and error message.g


import DS from 'ember-data';
import OsfModel from 'ember-osf/models/osf-model';

/**
 * @module ember-preprints
 * @submodule models
 */

/**
 * Model for OSF APIv2 preprints. This model may be used with one of several API endpoints. It may be queried directly. In the future, there will be multiple taxonomy endpoints under the same namespace.
 * For field and usage information, see:
 * https://api.osf.io/v2/docs/#!/v2/Plos_Taxonomy_GET
 * @class Taxonomy
 */
export default OsfModel.extend({
    type: DS.attr('string'),
    text: DS.attr('string'),
    // TODO: Api implements this as a list field for now. This should be a relationship field in the future, when API supports it
    parentIds: DS.attr(),
});

import DS from 'ember-data';
import OsfModel from 'ember-osf/models/osf-model';

/**
 * @module ember-preprints
 * @submodule models
 */

/**
 * Model for OSF APIv2 preprints. This model may be used with one of several API endpoints. It may be queried directly. In the future, there will be multiple taxonomy endpoints under the same namespace.
 * For field and usage information, see:
 * https://api.osf.io/v2/docs/#!/v2/Plos_Taxonomy_GET
 * @class Taxonomy
 */
export default OsfModel.extend({
    type: DS.attr('string'),
    text: DS.attr('string'),
    parents: DS.attr(),
});

Update field name -remove TODO


/**
 * Created by jonathan on 3/7/15.
 */

var CameraApp = function() {};

CameraApp.prototype = {
    framesPerSecond: 1,

    setup: function() {
        this.image = document.getElementById('CameraImage');
        this.imageSource = 'http://104.206.193.11:49709/dcnvr/video/live/image/2?w=320&h=240';
        this.loadImage();
    },

    loadImage: function() {
        var calculatedDelay = 1000 / this.framesPerSecond;
        var currentTime = new Date().getTime();
        if (this.lastLoadTime != undefined){
            calculatedDelay = calculatedDelay - (currentTime - this.lastLoadTime);
        }

        this.lastLoadTime = currentTime;

        if (calculatedDelay <= 0) {
            this.image.src = this.imageSource + '&random=' + Math.random();
        } else {
            var cameraApp = this;
            this.timer = setTimeout(function() {
                cameraApp.image.src = cameraApp.imageSource + '&random=' + Math.random();
            }, calculatedDelay);
        }
    }
};

var cameraApp = null;

$(document).ready(function () {
    cameraApp = new CameraApp();

    $('#CameraImage').load(function() {
        cameraApp.loadImage();
    });

    cameraApp.setup();
});

/**
 * Created by jonathan on 3/7/15.
 */

var CameraApp = function() {};

CameraApp.prototype = {
    framesPerSecond: 1,
    timeoutInMinutes: 1,

    setup: function() {
        this.startTime = new Date().getTime();
        this.image = document.getElementById('CameraImage');
        this.imageSource = 'http://104.206.193.11:49709/dcnvr/video/live/image/2?w=320&h=240';
        this.loadImage();
    },

    loadImage: function() {
        var calculatedDelay = 1000 / this.framesPerSecond;
        var currentTime = new Date().getTime();

        if (currentTime - this.startTime > this.timeoutInMinutes * 60000)
        {
            if (!confirm('Live video viewing has timed out. Do you want to continue viewing?'))
            {
                return;
            } else {
                this.startTime = new Date().getTime();
            }
        }

        if (this.lastLoadTime != undefined){
            calculatedDelay = calculatedDelay - (currentTime - this.lastLoadTime);
        }

        this.lastLoadTime = currentTime;

        if (calculatedDelay <= 0) {
            this.image.src = this.imageSource + '&random=' + Math.random();
        } else {
            var cameraApp = this;
            this.timer = setTimeout(function() {
                cameraApp.image.src = cameraApp.imageSource + '&random=' + Math.random();
            }, calculatedDelay);
        }
    }
};

var cameraApp = null;

$(document).ready(function () {
    cameraApp = new CameraApp();

    $('#CameraImage').load(function() {
        cameraApp.loadImage();
    });

    cameraApp.setup();
});

Add live video feed timeout


import patchNode from '../node/patch';
import Transaction from '../transaction';
import { CreateNodeHookCache, VTree } from '../util/types';
import globalThis from '../util/global';

/**
 * Processes a set of patches onto a tracked DOM Node.
 *
 * @param {Transaction} transaction
 * @return {void}
 */
export default function patch(transaction) {
  const { mount, state, patches } = transaction;
  const { mutationObserver, measure, scriptsToExecute } = state;

  measure('patch node');

  const { ownerDocument } = /** @type {HTMLElement} */ (mount);
  const promises = transaction.promises || [];

  state.ownerDocument = ownerDocument || globalThis.document;

  // Always disconnect a MutationObserver before patching.
  if (mutationObserver) {
    mutationObserver.disconnect();
  }

  // Hook into the Node creation process to find all script tags, and mark them
  // for execution.
  const collectScripts = (/** @type {VTree} */vTree) => {
    if (vTree.nodeName === 'script') {
      scriptsToExecute.set(vTree, vTree.attributes.type);
    }
  };

  CreateNodeHookCache.add(collectScripts);

  // Skip patching completely if we aren't in a DOM environment.
  if (state.ownerDocument) {
    promises.push(...patchNode(patches, state));
  }

  CreateNodeHookCache.delete(collectScripts);

  transaction.promises = promises;
  measure('patch node');
}

import patch from '../node/patch';
import Transaction from '../transaction';
import { CreateNodeHookCache, VTree } from '../util/types';
import globalThis from '../util/global';

/**
 * Processes a set of patches onto a tracked DOM Node.
 *
 * @param {Transaction} transaction
 * @return {void}
 */
export default function patchNode(transaction) {
  const { mount, state, patches } = transaction;
  const { mutationObserver, measure, scriptsToExecute } = state;

  measure('patch node');

  const { ownerDocument } = /** @type {HTMLElement} */ (mount);
  const promises = transaction.promises || [];

  state.ownerDocument = ownerDocument || globalThis.document;

  // Always disconnect a MutationObserver before patching.
  if (mutationObserver) {
    mutationObserver.disconnect();
  }

  // Hook into the Node creation process to find all script tags, and mark them
  // for execution.
  const collectScripts = (/** @type {VTree} */vTree) => {
    if (vTree.nodeName === 'script') {
      scriptsToExecute.set(vTree, vTree.attributes.type);
    }
  };

  CreateNodeHookCache.add(collectScripts);

  // Skip patching completely if we aren't in a DOM environment.
  if (state.ownerDocument) {
    promises.push(...patch(patches, state));
  }

  CreateNodeHookCache.delete(collectScripts);

  transaction.promises = promises;
  measure('patch node');
}

Rename public function to match task name


var url = require("url");
var qs = require("qs");

/**
 * getNextLink
 * @function
 * @param {Object} response A response object returned from calling 'client.makeRequest'
 * @returns A parsed version of the link to the subsequent page, or null if no such page exists.
 */
var getNextLink = function (response) {
	if (response.headers.link) {
		var links = response.headers.link.split(",");
		for (var elem in links) {
			if (links[elem].includes("rel=\"next\"")) {
				var linkRegex = /<(.*)>/;
				var link = linkRegex.exec(links[elem])[1];
				var parsedUrl = url.parse(link);
				return qs.parse(parsedUrl.query);
			}
		}
	}
	return null;
};

module.exports.getNextLink = getNextLink;

var url = require("url");
var qs = require("qs");

/**
 * getNextLink
 * @function
 * @param {Object} response A response object returned from calling 'client.makeRequest'
 * @returns A parsed version of the link to the subsequent page, or null if no such page exists.
 */
var getNextLink = function (response) {
	if (response.headers.link) {
		var links = response.headers.link.split(",");
		for (var elem in links) {
			if (links[elem].indexOf("rel=\"next\"") !== -1) {
				var linkRegex = /<(.*)>/;
				var link = linkRegex.exec(links[elem])[1];
				var parsedUrl = url.parse(link);
				return qs.parse(parsedUrl.query);
			}
		}
	}
	return null;
};

module.exports.getNextLink = getNextLink;

Switch string.incluldes() to string.indexOf() for compatibility reasons


// Remove duplicate elements from array

function removeDups(arr){
  var dupes ={},
      returnArray = [],
      el;

  for(var i =0; i<arr.length; i++){
    el = arr[i];
    if(!dupes[el]){
      returnArray.push(el);
      dupes[el] = true;
   }
  }
  return returnArray;
}

removeDups([1,3,3,3,1,5,6,7,8,1]);

// Remove duplicate elements from array

function removeDups(arr){
  var dupes ={},
      returnArray = [],
      el;

  for(var i =0; i<arr.length; i++){
    el = arr[i];
    if(!dupes[el]){
      returnArray.push(el);
      dupes[el] = true;
   }
  }
  return returnArray;
}

removeDups([10,30,3,30,3,10,5,6,7,8,1,1, 'test', 'test']);

Remove duplicate elements in an array (FIX)


import webpack from 'webpack';
import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer';
import config from '../webpack.config.prod';

config.plugins.push(new BundleAnalyzerPlugin());

const compiler = webpack(config);

compiler.run((error, stats) => {
  if (error) {
    throw new Error(error);
  }

  console.log(stats); // eslint-disable-line no-console
});

import webpack from 'webpack';
import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer';
import config from '../webpack.config.prod';

config.plugins.push(new BundleAnalyzerPlugin());

process.env.NODE_ENV = 'production';

const compiler = webpack(config);

compiler.run((error, stats) => {
  if (error) {
    throw new Error(error);
  }

  console.log(stats); // eslint-disable-line no-console
});

Set prod env when analyzing bundle


import $ from 'jquery';
import Router from './util/router';
import common from './routes/Common';
import home from './routes/Home';
import about_us from './routes/About';

// Import Bootstrap
import 'bootstrap/dist/js/umd/util.js';
import 'bootstrap/dist/js/umd/alert.js';
import 'bootstrap/dist/js/umd/button.js';
import 'bootstrap/dist/js/umd/carousel.js';
import 'bootstrap/dist/js/umd/collapse.js';
import 'bootstrap/dist/js/umd/dropdown.js';
import 'bootstrap/dist/js/umd/modal.js';
import 'bootstrap/dist/js/umd/scrollspy.js';
import 'bootstrap/dist/js/umd/tab.js';
import 'bootstrap/dist/js/umd/tooltip.js';
import 'bootstrap/dist/js/umd/popover.js';

// Use this variable to set up the common and page specific functions. If you
// rename this variable, you will also need to rename the namespace below.
const routes = {
  // All pages
  common,
  // Home page
  home,
  // About us page, note the change from about-us to about_us.
  about_us
};

// Load Events
$(document).ready(() => new Router(routes).loadEvents());

import $ from 'jquery';
import Router from './util/router';
import common from './routes/Common';
import home from './routes/Home';
import about_us from './routes/About';

// Import npm dependencies
import 'bootstrap/dist/js/umd/util.js';
import 'bootstrap/dist/js/umd/alert.js';
import 'bootstrap/dist/js/umd/button.js';
import 'bootstrap/dist/js/umd/carousel.js';
import 'bootstrap/dist/js/umd/collapse.js';
import 'bootstrap/dist/js/umd/dropdown.js';
import 'bootstrap/dist/js/umd/modal.js';
import 'bootstrap/dist/js/umd/scrollspy.js';
import 'bootstrap/dist/js/umd/tab.js';
import 'bootstrap/dist/js/umd/tooltip.js';
import 'bootstrap/dist/js/umd/popover.js';

// Use this variable to set up the common and page specific functions. If you
// rename this variable, you will also need to rename the namespace below.
const routes = {
  // All pages
  common,
  // Home page
  home,
  // About us page, note the change from about-us to about_us.
  about_us
};

// Load Events
$(document).ready(() => new Router(routes).loadEvents());

Update comment for importing deps


var geocoder = require('node-geocoder') ("google", "https", {
	apiKey: '<YOUR-KEY>'
});
var csv = require('csv');

process.stdin
	.pipe(csv.parse())
	.pipe(csv.transform(function(data, callback){
		setImmediate(function(){
			geocoder.geocode(data[1])
		    .then(function(res) {
				data.push(res[0].latitude);
				data.push(res[0].longitude);
				callback(null, data);
		    })
		    .catch(function(err) {
		        console.log(data[0] + " " + err);
		    });
		});}, {parallel: 20}))
	.pipe(csv.stringify({quotedString: true}))
	.pipe(process.stdout);

var apiKey = "<YOUR-KEY>";
var geocoder = require('node-geocoder') ("google", "https", { apiKey: apiKey });
var csv = require('csv');

process.stdin
	.pipe(csv.parse())
	.pipe(csv.transform(function(data, callback){
		setImmediate(function(){
			geocoder.geocode(data[1])
		    .then(function(res) {
				data.push(res[0].latitude);
				data.push(res[0].longitude);
				callback(null, data);
		    })
		    .catch(function(err) {
		        console.log(data[0] + " " + err);
		    });
		});}, {parallel: 20}))
	.pipe(csv.stringify({quotedString: true}))
	.pipe(process.stdout);

Relocate the key to be able to find it eaven easier


'use strict';

var gulp = require('gulp');

var files = ['manifest.json', 'background.js'];
var xpiName = 'catgifs.xpi';

gulp.task('default', function () {
  console.log(files, xpiName)
});

'use strict';

var gulp = require('gulp');
var zip = require('gulp-zip');

var files = ['manifest.json', 'background.js'];
var xpiName = 'catgifs.xpi';

gulp.task('default', function () {
  gulp.src(files)
    .pipe(zip(xpiName))
    .pipe(gulp.dest('.'));
});

Use gulp to create the xpi.


var gulp = require('gulp');
var shell = require('gulp-shell');
var tsc = require('gulp-tsc');

gulp.task('build', function () {
  return gulp.src([
      './**/*.ts',
      '!./node_modules/**/*.ts'
    ])
    .pipe(tsc({
      target: 'ES5',
      removeComments: true,
      sourceMap: true
    }))
    .pipe(gulp.dest('.'));
});

gulp.task('run', [ 'build' ], shell.task([
  'node main.js'
]));

var gulp = require('gulp');
var shell = require('gulp-shell');
var tsc = require('gulp-tsc');

gulp.task('build', function () {
  return gulp.src([
      './**/*.ts',
      '!./node_modules/**/*.ts'
    ])
    .pipe(tsc({
      target: 'ES5',
      removeComments: true,
      sourceMap: true
    }))
    .pipe(gulp.dest('.'));
});

gulp.task('run', [ 'build' ], shell.task([
  'NODE_PATH=$NODE_PATH:./lib node main.js'
]));

Add lib to NODE_PATH when running the app.


'use strict';

var gulp = require('gulp');

var options = {
  name: 'ec2prices',
  dependantFiles: ['node_modules/babel/browser-polyfill.js'],
  mainFiles: [
    'app/scripts/app.es6',
    'app/scripts/**/!(*.spec|*.mock).{js,es6}'
  ],
  templateFiles: ['app/scripts/**/*.htm{,l}'],
  specFiles: ['app/scripts/**/*.{spec,mock}.es6'],

  views: {
    src: ['app/views/{,*/}*.htm{,l}'],
    base: 'app/views/'
  },
  normalFiles: ['app/instances.json'],
  buildDir: 'build',
  version: false,
};

require('./gulp/copy.js')(options);
require('./gulp/css.js')(options);
require('./gulp/deploy.js')(options);
require('./gulp/html.js')(options);
require('./gulp/js.js')(options);
require('./gulp/lint.js')(options);
require('./gulp/serve.js')(options);
require('./gulp/tests.js')(options);

gulp.task('default', ['lint', 'js', 'html', 'copy', 'css']);

'use strict';

var gulp = require('gulp');

var options = {
  name: 'ec2prices',
  dependantFiles: ['node_modules/babel/browser-polyfill.js'],
  mainFiles: [
    'app/scripts/app.es6',
    'app/scripts/**/!(*.spec|*.mock).{js,es6}'
  ],
  templateFiles: ['app/scripts/**/*.htm{,l}'],
  specFiles: ['app/scripts/**/*.{spec,mock}.es6'],

  views: {
    src: ['app/views/{,*/}*.htm{,l}'],
    base: 'app/views/'
  },
  normalFiles: ['app/instances.json'],
  buildDir: 'build',
  version: false,
};

require('./gulp/copy.js')(options);
require('./gulp/css.js')(options);
require('./gulp/deploy.js')(options);
require('./gulp/html.js')(options);
require('./gulp/js.js')(options);
require('./gulp/lint.js')(options);
require('./gulp/serve.js')(options);
require('./gulp/tests.js')(options);

gulp.task('default', ['lint', 'test', 'js', 'html', 'copy', 'css']);

Add the test task dependency back to the default gulp task


var parse = require('./parse');
var clean = require('./clean');

module.exports = Engine = {};

var pythons = [];
var outputs = [];
var pythonNum = 0;

Engine.runPython = function(operation, a, b, cb) {
  if (operation === 'local' || operation === 'global') {
    var cleanup = clean.cleanMin(operation, a, b, cb);
    a   = cleanup.func;
    b   = cleanup.options;
    cb  = cleanup.callback;
    b = JSON.stringify(b);
  } else if (operation === 'nnls') {
    cb = clean.cleanCB(cb);
    a = JSON.stringify(a);
    b = JSON.stringify(b);
  }

  // immediately invoked function in case user invokes runPython multiple times,
  // starting multiple child processes, causing race condition,
  // causing stdouts to potentially overlap.
  (function (num){
    pythons[num] = require('child_process').spawn(
      'python',
      [__dirname + '/../py/exec.py', operation, a, b]);
    outputs[num] = '';
    pythons[num].stdout.on('data', function(data){
      outputs[num] += data;
    });
    pythons[num].stdout.on('close', function(){
      // cb(outputs[num]);
      cb(JSON.parse(outputs[num]));
    });
  })(pythonNum++)
}

var parse = require('./parse');
var clean = require('./clean');

module.exports = Engine = {};

var pythons = [];
var outputs = [];
var pythonNum = 0;

Engine.runPython = function(operation, a, b, cb, xData, yData) {
  if (operation === 'local' || operation === 'global') {
    var cleanup = clean.cleanMin(operation, a, b, cb);
    a   = cleanup.func;
    b   = cleanup.options;
    cb  = cleanup.callback;
    b = JSON.stringify(b);
  } else if (operation === 'nnls') {
    cb = clean.cleanCB(cb);
    a = JSON.stringify(a);
    b = JSON.stringify(b);
  } else if (operation === 'fit') {
    var cleanup = clean.cleanFit(a, b, cb, xData, yData);
    a = cleanup.func;
    b = cleanup.options;
    cb = cleanup.callback;
    b = JSON.stringify(b);
  }

  // immediately invoked function in case user invokes runPython multiple times,
  // starting multiple child processes, causing race condition,
  // causing stdouts to potentially overlap (otherwise).
  (function (num){
    pythons[num] = require('child_process').spawn(
      'python',
      [__dirname + '/../py/exec.py', operation, a, b]);
    outputs[num] = '';
    pythons[num].stdout.on('data', function(data){
      outputs[num] += data;
    });
    pythons[num].stdout.on('close', function(){
      // cb(outputs[num]);
      cb(JSON.parse(outputs[num]));
    });
  })(pythonNum++)
}

Add specification for fit operation


import { Mongo } from 'meteor/mongo';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';

class ModuleFulfilmentCollection extends Mongo.Collection {
  insert(fulfilmentData, callBack){
    const fulfilmentDoc = fulfilmentData;
    let result;
    //validate document
    return super.insert( fulfilmentDoc, callBack);
  };
  update(selector, modifier){
    const result = super.update(selector, modifier);

    return result;
  };

  remove(selector){
    const result = super.remove(selector);
    return result;
  };
}

export const ModuleFulfilments = new ModuleFulfilmentCollection("modfulfilment");

/*
 * moduleMapping type,
 * @key academicYear
 * @value moduleMapping object
 */
const fulfilmentSchema = {
  moduleCode: {
    type: String
  },
  moduleMapping: {
    type: object,
    blackbox: true
  }
}

ModuleFulfilments.attachSchema(fulfilmentSchema);

import { Mongo } from 'meteor/mongo';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';

class ModuleFulfilmentCollection extends Mongo.Collection {
  insert(fulfilmentData, callBack){
    const fulfilmentDoc = fulfilmentData;
    let result;
    //validate document
    return super.insert( fulfilmentDoc, callBack);
  };
  update(selector, modifier){
    const result = super.update(selector, modifier);

    return result;
  };

  remove(selector){
    const result = super.remove(selector);
    return result;
  };
}

export const ModuleFulfilments = new ModuleFulfilmentCollection("modfulfilment");

/*
 * moduleMapping type,
 * @key academicYear
 * @value moduleMapping object
 */
const fulfilmentSchema = {
  moduleCode: {
    type: String
  },
  moduleMapping: {
    type: Object,
    blackbox: true
  }
}

ModuleFulfilments.attachSchema(fulfilmentSchema);

FIX wrong db schema declaration


var config = {
    /** app mode **/
    mode: 'DEV',

    /** db name **/
    db: 'tiapp-exercise',

    /** android tablet minimum form factor **/
    tablet: {
        width: 899,
        height: 899
    },

    /** Actions **/
    action: [
        {module: 'Try',     name: 'doSave',         path: 'Como.Controller.Try.doSave'},
        {module: 'Try',     name: 'showLogin',      path: 'Como.Controller.Try.showLogin'},
        {module: 'Try',     name: 'doLogin',        path: 'Como.Controller.Try.doLogin'},
        {module: 'Try',     name: 'doLogout',       path: 'Como.Controller.Try.doLogout'}
    ]
};

module.exports = config;

var config = {
    /** app mode **/
    mode: 'DEV',

    /** db name **/
    db: 'tiapp-como',

    /** android tablet minimum form factor **/
    tablet: {
        width: 899,
        height: 899
    },

    /** Actions **/
    action: [
        {module: 'Try',     name: 'doSave',         path: 'Como.Controller.Try.doSave'},
        {module: 'Try',     name: 'showLogin',      path: 'Como.Controller.Try.showLogin'},
        {module: 'Try',     name: 'doLogin',        path: 'Como.Controller.Try.doLogin'},
        {module: 'Try',     name: 'doLogout',       path: 'Como.Controller.Try.doLogout'}
    ]
};

module.exports = config;

Update to change db name on config


'use strict';

var grunt = require('grunt');

/*
 ======== A Handy Little Nodeunit Reference ========
 https://github.com/caolan/nodeunit

 Test methods:
 test.expect(numAssertions)
 test.done()
 Test assertions:
 test.ok(value, [message])
 test.equal(actual, expected, [message])
 test.notEqual(actual, expected, [message])
 test.deepEqual(actual, expected, [message])
 test.notDeepEqual(actual, expected, [message])
 test.strictEqual(actual, expected, [message])
 test.notStrictEqual(actual, expected, [message])
 test.throws(block, [error], [message])
 test.doesNotThrow(block, [error], [message])
 test.ifError(value)
 */

exports.autoprefixer = {
    setUp: function (done) {
        // setup here if necessary
        done();
    },
    default_options: function (test) {
        test.expect(1);

        var actual = grunt.file.read('tmp/default_options.css');
        var expected = grunt.file.read('test/expected/default_options.css');
        test.strictEqual(actual, expected, 'should describe what the default behavior is.');

        test.done();
    },
    custom_options: function (test) {
        test.expect(1);

        var actual = grunt.file.read('tmp/custom_options.css');
        var expected = grunt.file.read('test/expected/custom_options.css');
        test.strictEqual(actual, expected, 'should describe what the custom option(s) behavior is.');

        test.done();
    },
};

'use strict';

var grunt = require('grunt');

/*
 ======== A Handy Little Nodeunit Reference ========
 https://github.com/caolan/nodeunit

 Test methods:
 test.expect(numAssertions)
 test.done()
 Test assertions:
 test.ok(value, [message])
 test.equal(actual, expected, [message])
 test.notEqual(actual, expected, [message])
 test.deepEqual(actual, expected, [message])
 test.notDeepEqual(actual, expected, [message])
 test.strictEqual(actual, expected, [message])
 test.notStrictEqual(actual, expected, [message])
 test.throws(block, [error], [message])
 test.doesNotThrow(block, [error], [message])
 test.ifError(value)
 */

exports.autoprefixer = {
    setUp: function (done) {
        // setup here if necessary
        done();
    },
    custom_options: function (test) {
        test.expect(1);

        var actual = grunt.file.read('tmp/custom_options.css');
        var expected = grunt.file.read('test/expected/custom_options.css');
        test.strictEqual(actual, expected, 'should describe what the custom option(s) behavior is.');

        test.done();
    },
};

Remove test for default options


/* jshint node: true */

module.exports = function(environment) {
  return {};
};

/* jshint node: true */

/* ==================
 * USAGE INSTRUCTIONS
 * ==================
 *
 * If you'd like to make a local change to this file, you need
 * to tell git to ignore any changes to this file. You can do
 * this by running:
 *
 * git update-index --skip-worktree [file-path]
 *
 * If you want to undo the ignore and actually commit changes:
 *
 * git update-index --no-skip-worktree [file-path]
 *
 */

module.exports = function(environment) {
  return {};
};

Add usage instructions to config blueprint


// Basic idea from Bojan Mihelac -
// http://source.mihelac.org/2010/02/19/django-time-widget-custom-time-shortcuts/

// Django imports jQuery into the admin site using noConflict(True)
// We wrap this in an anonymous function to stick to jQuery's $ idiom
// and ensure we're using the admin version of jQuery, rather than
// anything else pulled in

(function($) {
   var Schedule = {
      init: function() {
         time_format = get_format('TIME_INPUT_FORMATS')[0];
         $(".timelist").each(function(num) {
            // Clear existing list
            $( this ).empty();
            // Fill list with time values
            for (i=8; i < 20; i++) {
               var time = new Date(1970,1,1,i,0,0);
               quickElement("a", quickElement("li", this, ""),
                  time.strftime(time_format), "href",
                  "javascript:DateTimeShortcuts.handleClockQuicklink(" + num +
                  ", " + i + ");");
            }
         });
      }
   }

   // We need to be called after django's DateTimeShortcuts.init, which
   // is triggered by a load event
   $( window ).bind('load', Schedule.init);
}(django.jQuery));

// Override the default setting on the django admin DateTimeShortcut
// Django 2 nicely does make this overridable, but we need to
// set it up before the DateTimeShortcuts init is called by
// window.onload, so we attach it to DOMContentLoaded
//
// The names of the input fields are also a bit opaque, and
// unfornately not something we can easily pass in

document.addEventListener("DOMContentLoaded", function() {
   console.log(window.DateTimeShortcuts);
   // These are for the single admin pages
   window.DateTimeShortcuts.clockHours.end_time_1 = [];
   window.DateTimeShortcuts.clockHours.start_time_1 = [];
   for (let hour = 8; hour <= 20; hour++) {
       let verbose_name = new Date(1970, 1, 1, hour, 0, 0).strftime('%H:%M');
       window.DateTimeShortcuts.clockHours.end_time_1.push([verbose_name, hour])
       window.DateTimeShortcuts.clockHours.start_time_1.push([verbose_name, hour])
   }
   // This is for the inline options - we define 30, which is hopefully sane
   for (let inline = 0; inline < 30; inline++) {
      let name = 'form-' + inline + '-end_time_1';
      console.log('computed name: ' + name);
      window.DateTimeShortcuts.clockHours[name] = [];
      for (let hour = 8; hour <= 20; hour++) {
          let verbose_name = new Date(1970, 1, 1, hour, 0, 0).strftime('%H:%M');
          window.DateTimeShortcuts.clockHours[name].push([verbose_name, hour])
      }
   }
});

Rework the scheduletime helper to work with later admintimewidget helper code


var expect = require('chai').expect,
    request = require('superagent').agent(),
    PrettyCSS = require('PrettyCSS'),
    testhost = require('../src/server').testhost();

describe('fields.css', function() {
    var res;
    before(function (done) {
        request.get(testhost + '/css/fields.css').end(function(r) {
            res = r;
            done();
        });
    });
    it('has text/css content-type', function() {
        expect(res.type).to.equal('text/css');
    });

    it('is valid CSS', function() {
        expect(PrettyCSS.parse(res.text).errors.length).to.equal(0);
    });
});

/*describe('svc/bndb_initializer', function() {
    var res;
    before(function (done) {
        request.get(testhost + '/svc/bndb_initializer.js').end(function(r) {
            res = r;
            done();
        });
    });
    it('has text/javascript content-type', function() {
        expect(res.type).to.equal('text/javascript');
    });

    it('valid JS', function() {
        expect(jshint(res.text)).to.equal(true);
    });
});*/

var expect = require('chai').expect,
    request = require('superagent').agent(),
    PrettyCSS = require('PrettyCSS'),
    Q = require('q'),
    connect = Q.defer(),
    environment = require('./lib/environment').default;

require('../src/server').harness(function (url) {
    connect.resolve(url);
});

describe('fields.css', function() {
    var res;
    before(function (done) {
        connect.promise.done(function (testhost) {
            request.get(testhost + '/css/fields.css').end(function(r) {
                res = r;
                done();
            });
        });
    });
    it('has text/css content-type', function() {
        expect(res.type).to.equal('text/css');
    });

    it('is valid CSS', function() {
        expect(PrettyCSS.parse(res.text).errors.length).to.equal(0);
    });
});

/*describe('svc/bndb_initializer', function() {
    var res;
    before(function (done) {
        request.get(testhost + '/svc/bndb_initializer.js').end(function(r) {
            res = r;
            done();
        });
    });
    it('has text/javascript content-type', function() {
        expect(res.type).to.equal('text/javascript');
    });

    it('valid JS', function() {
        expect(jshint(res.text)).to.equal(true);
    });
});*/

Use new harness in generated assets unit test


import normalizeArgs, { __RewireAPI__ as rewireAPI } from '../../../src/server/process/normalizeArgs';

describe('normalizeArgs', () => {
    afterEach(() => {
        rewireAPI.__ResetDependency__('process');
    });

    it('should normalize for Windows with no COMSPEC', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'win32',
            env: {}
        });

        const result = normalizeArgs('echo Hello world');
        expect(result).toEqual({
            file: 'cmd.exe',
            args: ['/s', '/c', '"echo Hello world"'],
            options: { windowsVerbatimArguments: true }
        });
    });

    it('should normalize for Windows with COMSPEC defined', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'win32',
            env: { comspec: 'command.com' }
        });

        const result = normalizeArgs('echo Hello again');
        expect(result).toEqual({
            file: 'command.com',
            args: ['/s', '/c', '"echo Hello again"'],
            options: { windowsVerbatimArguments: true }
        });
    });

    it('should normalize for Unix-like systems', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'darwin'
        });

        const result = normalizeArgs('echo Hello from the other side');
        expect(result).toEqual({
            file: '/bin/sh',
            args: ['-c', 'echo Hello from the other side'],
            options: {}
        });
    });
});

import normalizeArgs, { __RewireAPI__ as rewireAPI } from '../../../src/server/process/normalizeArgs';

describe('normalizeArgs', () => {
    afterEach(() => {
        rewireAPI.__ResetDependency__('process');
    });

    it('should normalize for Windows with no COMSPEC', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'win32',
            env: {}
        });

        const result = normalizeArgs('echo Hello world');
        expect(result).toEqual({
            file: 'cmd.exe',
            args: ['/s', '/c', 'echo Hello world'],
            options: { windowsVerbatimArguments: true }
        });
    });

    it('should normalize for Windows with COMSPEC defined', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'win32',
            env: { comspec: 'command.com' }
        });

        const result = normalizeArgs('echo Hello again');
        expect(result).toEqual({
            file: 'command.com',
            args: ['/s', '/c', 'echo Hello again'],
            options: { windowsVerbatimArguments: true }
        });
    });

    it('should normalize for Unix-like systems', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'darwin'
        });

        const result = normalizeArgs('echo Hello from the other side');
        expect(result).toEqual({
            file: '/bin/sh',
            args: ['-c', 'echo Hello from the other side'],
            options: {}
        });
    });
});

Remove quotes from tests in normalizeArgs


import App from './app';
import 'babel-polyfill';
common.app = new App(common);
common.app.start();

import App from './app';
common.app = new App(common);
common.app.start();

Remove babel-polyfill import in man.js


"use strict";

const apiRequest = require( "../../src/token/api-request" );
const storeToken = require( "../../src/token/store-token" );
const Promise = require( "bluebird" );
const expect = require( "expect.js" );
const sinonSandbox = require( "sinon" ).sandbox.create();

describe.only( "Generative testing", function() {
  ["SOME", "RANDOM", "STRINGS"].forEach(function( randomString ) {
    describe( `Given the token '${randomString}'`, function() {
      let fakeToken;

      beforeEach(function() {
        fakeToken = randomString
      });

      describe( `When storing the token '${randomString}'`, function() {
        let promiseToStoreToken;
        let mockedApiRequest;

        beforeEach(function() {
          mockedApiRequest = sinonSandbox
            .mock( apiRequest )
            .expects( "post" )
            .withExactArgs( "/store-token", fakeToken );
          promiseToStoreToken = storeToken( fakeToken, apiRequest );
        });

        afterEach(function() {
          sinonSandbox.restore();
        });

        it( "persists", function() {
          return Promise.try(function() {
            return promiseToStoreToken;
          }).then(function() {
            mockedApiRequest.verify();
          });
        });
      });
    });
  });
});

"use strict";

const apiRequest = require( "../../src/token/api-request" );
const storeToken = require( "../../src/token/store-token" );
const Promise = require( "bluebird" );
const expect = require( "expect.js" );
const sinonSandbox = require( "sinon" ).sandbox.create();

describe( "Generative testing", function() {
  ["SOME", "RANDOM", "STRINGS"].forEach(function( randomString ) {
    describe( `Given the token '${randomString}'`, function() {
      let fakeToken;

      beforeEach(function() {
        fakeToken = randomString
      });

      describe( `When storing the token '${randomString}'`, function() {
        let promiseToStoreToken;
        let mockedApiRequest;

        beforeEach(function() {
          mockedApiRequest = sinonSandbox
            .mock( apiRequest )
            .expects( "post" )
            .withExactArgs( "/store-token", fakeToken );
          promiseToStoreToken = storeToken( fakeToken, apiRequest );
        });

        afterEach(function() {
          sinonSandbox.restore();
        });

        it( "persists", function() {
          return Promise.try(function() {
            return promiseToStoreToken;
          }).then(function() {
            mockedApiRequest.verify();
          });
        });
      });
    });
  });
});

Remove the .only from the generative test


formsAngular.filter('titleCase',[function() {
    return function(str, stripSpaces) {
        var value = str.replace(/(_|\.)/g, ' ').replace(/[A-Z]/g, ' $&').replace(/\w\S*/g, function (txt) {
            return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
        });
        if (stripSpaces) {
            value = value.replace(/\s/g,'');
        }
        return value;
    }
}]);

formsAngular.filter('titleCase',[function() {
    return function(str, stripSpaces) {
        var value = str.replace(/(_|\.)/g, ' ').replace(/[a-z][A-Z]/g, ' $&').replace(/\w\S*/g, function (txt) {
            return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
        });
        if (stripSpaces) {
            value = value.replace(/\s/g,'');
        }
        return value;
    }
}]);

Stop titleCase introducing double spaces


import Em from 'ember';
import LlamaBodyCell from 'llama-table/components/llama-body-cell/component';
import layout from 'dummy/templates/components/button-cell';
var computed = Em.computed;
var gt = computed.gt;
var not = computed.not;

var ButtonCell = LlamaBodyCell.extend({
	layout: layout,
	showButton: not('isFooter'),
	actions: {
		click: function () {
			var controller = this.get('root');
			var rows = controller.get('rows');
			var row = this.get('content');
			var index = rows.indexOf(row);
			controller.sendAction(this.get('actionName'), index);
		},
	},
});

export default ButtonCell;

import Em from 'ember';
import LlamaBodyCell from 'llama-table/components/llama-body-cell/component';
import layout from 'dummy/templates/components/button-cell';
var computed = Em.computed;
var gt = computed.gt;
var not = computed.not;

var ButtonCell = LlamaBodyCell.extend({
	layout: layout,
	showButton: not('isFooter'),
	actions: {
		click: function () {
			var controller = this.get('root');
			var rows = controller.get('rows');
			var rowController = this.get('content');
			var row = Em.get(rowController, 'content');
			var index = rows.indexOf(row);
			controller.sendAction(this.get('actionName'), index);
		},
	},
});

export default ButtonCell;

Fix remove button in demo table


module.exports = function (grunt) {

    grunt.initConfig({
        nodewebkit: {
            options: {
                platforms: ['win', 'osx'],
                buildDir: './build',
                version: '0.12.1'
            },
            src: [
                'index.html',
                'package.json',
                './components/**/*',
                './css/**/*',
                './images/**/*',
                './js/**/*',
                './node_module/**/*'
            ]
        }
    });

    grunt.loadNpmTasks('grunt-node-webkit-builder');

    grunt.registerTask('build', ['nodewebkit']);

};

module.exports = function (grunt) {

    grunt.initConfig({
        nodewebkit: {
            options: {
                platforms: ['win', 'osx', 'linux'],
                buildDir: './build',
                version: '0.12.1'
            },
            src: [
                'index.html',
                'package.json',
                './components/**/*',
                './css/**/*',
                './images/**/*',
                './js/**/*',
                './node_module/**/*'
            ]
        }
    });

    grunt.loadNpmTasks('grunt-node-webkit-builder');

    grunt.registerTask('build', ['nodewebkit']);

};

Add linux in build options


'use strict';

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    jshint: {
      files: ['Gruntfile.js', 'lib/**/*.js'],
      options: {
        globalstrict: true,
        node: true,
        globals: {
          jQuery: true,
          console: false,
          module: true,
          document: true
        }
      }
    },
    mochaTest: {
      test: {
        options: {
          reporter: 'spec'
        },
        src: ['test/**/*.js'],
        env: {
          NODE_ENV: "test"
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-mocha-test');

  grunt.registerTask('test-env', function() {process.env.NODE_ENV = "test";});
  grunt.registerTask('test', ['test-env', 'jshint', 'mochaTest' ]);
  grunt.registerTask('default', ['test']);

};

'use strict';

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    jshint: {
      options: {
        globalstrict: true,
        node: true,
        globals: {
          jQuery: true,
          console: false,
          module: true,
          document: true
        }
      }
    },
    mochaTest: {
      test: {
        options: {
          reporter: 'spec'
        },
        src: ['test/**/*.js'],
        env: {
          NODE_ENV: "test"
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-mocha-test');

  grunt.registerTask('test-env', function() {process.env.NODE_ENV = "test";});
  grunt.registerTask('test', ['test-env', 'jshint', 'mochaTest' ]);
  grunt.registerTask('default', ['test']);

};

Remove `file` field from jshint configuration.


'use strict';

module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        jshint: {
            allFiles: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js', 'index.js'],
            options: {
                jshintrc: '.jshintrc',
            }
        },
        mochacli: {
            all: ['test/**/*.js'],
            options: {
                reporter: 'spec',
                ui: 'tdd'
            }
        },
        'mocha_istanbul': {
            coveralls: {
                src: [ 'test/lib', 'test/lib/utils' ],
                options: {
                    coverage: true,
                    legend: true,
                    check: {
                        lines: 100,
                        statements: 99
                    },
                    root: './lib',
                    reportFormats: ['lcov']
                }
            }
        }
    })

    grunt.event.on('coverage', function(lcov, done){
        require('coveralls').handleInput(lcov, function(error) {
            if (error) {
                console.log(error)
                return done(error)
            }
            done()
        })
    })

    // Load the plugins
    grunt.loadNpmTasks('grunt-contrib-jshint')
    grunt.loadNpmTasks('grunt-mocha-cli')
    grunt.loadNpmTasks('grunt-mocha-istanbul')

    // Configure tasks
    grunt.registerTask('coveralls', ['mocha_istanbul:coveralls'])
    grunt.registerTask('default', ['test'])

    grunt.registerTask('test', ['mochacli', 'jshint', 'coveralls'])
}

'use strict';

module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        jshint: {
            allFiles: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js', 'index.js'],
            options: {
                jshintrc: '.jshintrc',
            }
        },
        mochacli: {
            all: ['test/**/*.js'],
            options: {
                reporter: 'spec',
                ui: 'tdd'
            }
        },
        'mocha_istanbul': {
            coveralls: {
                src: [ 'test/lib', 'test/lib/utils' ],
                options: {
                    coverage: true,
                    legend: true,
                    check: {
                        lines: 100,
                        statements: 100
                    },
                    root: './lib',
                    reportFormats: ['lcov']
                }
            }
        }
    })

    grunt.event.on('coverage', function(lcov, done){
        require('coveralls').handleInput(lcov, function(error) {
            if (error) {
                console.log(error)
                return done(error)
            }
            done()
        })
    })

    // Load the plugins
    grunt.loadNpmTasks('grunt-contrib-jshint')
    grunt.loadNpmTasks('grunt-mocha-cli')
    grunt.loadNpmTasks('grunt-mocha-istanbul')

    // Configure tasks
    grunt.registerTask('coveralls', ['mocha_istanbul:coveralls'])
    grunt.registerTask('default', ['test'])

    grunt.registerTask('test', ['mochacli', 'jshint', 'coveralls'])
}

Update coverage values to match current


module.exports = function(grunt) {

    // TODO: platforms shouldn't be hardcoded here
    var platforms = ['win64'];

    // Build up array of destinations for Twister deamon files
    var destinations = {files: []};
    platforms.forEach(function (platform) {
        destinations.files.push({
                expand: true,
                src: ['./twister-data/**'],
                dest: './builds/Twisting/' + platform + '/'
        });
    });

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        nodewebkit: {
            options: {
                platforms: platforms,
                buildDir: './builds'
            },
            src: './src/**/*'
        },
        copy: {
            twister: destinations
        },
        less: {
            development: {
                files: {
                    "./src/app/styles/style.css": "./src/app/styles/main.less"
                }
            }
        },
        auto_install: {
            subdir: {
                options: {
                    cwd: 'src',
                    stdout: true,
                    stderr: true,
                    failOnError: true,
                }
            }
        },
    });

    grunt.loadNpmTasks('grunt-node-webkit-builder');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-auto-install');

    grunt.registerTask('build', ['less', 'nodewebkit', 'copy:twister']);
    grunt.registerTask('compile', ['less']);
    grunt.registerTask('postinstall', ['auto_install']);
};

module.exports = function(grunt) {

    // TODO: platforms shouldn't be hardcoded here
    var platforms = ['win64'];

    // Build up array of destinations for Twister deamon files
    var destinations = {files: []};
    platforms.forEach(function (platform) {
        destinations.files.push({
                expand: true,
                src: ['./twister-data/**'],
                dest: './builds/Twisting/' + platform + '/'
        });
    });

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        nodewebkit: {
            options: {
                platforms: platforms,
                buildDir: './builds'
            },
            src: ['./src/**/*', '!./src/twister-data/**/*', '!./src/*.exe', '!./src/*.pak', '!./src/*.dll']
        },
        copy: {
            twister: destinations
        },
        less: {
            development: {
                files: {
                    "./src/app/styles/style.css": "./src/app/styles/main.less"
                }
            }
        },
        auto_install: {
            subdir: {
                options: {
                    cwd: 'src',
                    stdout: true,
                    stderr: true,
                    failOnError: true,
                }
            }
        },
    });

    grunt.loadNpmTasks('grunt-node-webkit-builder');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-auto-install');

    grunt.registerTask('build', ['less', 'nodewebkit', 'copy:twister']);
    grunt.registerTask('compile', ['less']);
    grunt.registerTask('postinstall', ['auto_install']);
};

Fix Grunt file for local testing


import React from 'react';

import styles from 'stylesheets/components/common/typography';

const Rectangle = () => (

Rechteck

Eingabe

      <form>

          a:
            <input type="text" />

          b:
            <input type="text" />

      </form>

Flächeninhalt

      0

);

export default Rectangle;

import React from 'react';

import styles from 'stylesheets/components/common/typography';

class Rectangle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      edgeA: 0,
      edgeB: 0,
      area: 0
    };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    const name = event.target.name;
    const value = event.target.value;
    const area =
        name === 'edgeA' ?
        this.computeArea(value, this.state.edgeB):
        this.computeArea(this.state.edgeA, value);

    this.setState({
      [event.target.name]: value,
      area: area
    });
  }

  computeArea(edgeA, edgeB) {
    return edgeA * edgeB;
  }

  render() {
    return (

Rechteck

Eingabe

          <form>

              Seite a:
                <input
                  type="text"
                  name="edgeA"
                  value={this.state.edgeA}
                  onChange={this.handleChange}
                />

              Seite b:
                <input
                  type="text"
                  name="edgeB"
                  value={this.state.edgeB}
                  onChange={this.handleChange}
                />

          </form>

Flächeninhalt

          {this.state.area}

    );
  }
}

export default Rectangle;

Implement computation of rectangle's area


import React from 'react';

class ImageCardComponent extends React.Component {
  static propTypes = {
    uri: React.PropTypes.string.isRequired,
    uploadedAt: React.PropTypes.string.isRequired
  };

  render() {
    return (

            {this.props.uri}

              <time dateTime={this.props.uploadedAt}>{this.props.ploadedAt}</time>

    );
  }
}

export default ImageCardComponent;

import React from 'react';

class ImageCardComponent extends React.Component {
  static propTypes = {
    uri: React.PropTypes.string.isRequired,
    uploadedAt: React.PropTypes.string.isRequired
  };

  render() {
    return (

            {this.props.uri}

              <time dateTime={this.props.uploadedAt}>{this.props.uploadedAt}</time>

    );
  }
}

export default ImageCardComponent;

Fix typo 'ploadedAt' => 'uploadedAt'


var canihaz = require('canihaz'),
  fs = require('fs'),
  p = require('path');

/**
 * Install dependency modules that are not yet installed, and needed for executing the tasks.
 *
 * @param {Array} depNames: an array of dependency module names
 * @param {String} dir: application directory where node_modules dir is located
 * @param {Function} cb: standard cb(err, result) callback
 */
function install(depNames, dir, cb) {
  fs.readdir(p.join(dir, 'node_modules'), function(err, installed) {
    var uninstalled = [];
    depNames.forEach(function (depName) {
      if (installed.indexOf(depName) === -1) {
        uninstalled.push(depName);
      }
    });
    if (uninstalled.length > 0) {
      console.log('[deps] Installing modules: %s (might take a while, once-off only)', uninstalled .join(', '));
      canihaz({ key: 'optDependencies' }).apply(this, depNames.concat(cb));
    } else {
      cb();
    }
  });
}

exports.install = install;

var canihaz = require('canihaz'),
  fs = require('fs'),
  p = require('path');

const GLOBALS = ['npm'];

/**
 * Install dependency modules that are not yet installed, and needed for executing the tasks.
 * Global modules (like npm) are assumed to already exist.
 *
 * @param {Array} depNames: an array of dependency module names
 * @param {String} dir: application directory where node_modules dir is located
 * @param {Function} cb: standard cb(err, result) callback
 */
function install(depNames, dir, cb) {
  fs.readdir(p.join(dir, 'node_modules'), function(err, installed) {
    var uninstalled = [];
    depNames.forEach(function (depName) {
      if (installed.indexOf(depName) === -1 && GLOBALS.indexOf(depName) === -1) {
        uninstalled.push(depName);
      }
    });
    if (uninstalled.length > 0) {
      console.log('[deps] Installing modules: %s (might take a while, once-off only)', uninstalled .join(', '));
      canihaz({ key: 'optDependencies' }).apply(this, depNames.concat(cb));
    } else {
      cb();
    }
  });
}

exports.install = install;

Add global modules list, to be excluded from lazy installation.


function setupLinkHandling() {
    window.history.pushState({"html": document.documentElement.outerHTML}, "", window.location.href);

    var anchors = document.getElementsByTagName("a");

    for (var i = 0; i < anchors.length; i++) {
        if (anchors[i].href.startsWith("http://localhost") || anchors[i].href.startsWith("https://atomhacks.github.io")) {
            anchors[i].onclick = function() {
                var href = this.href;
                var xhttp = new XMLHttpRequest();
                xhttp.onreadystatechange = function() {
                    if (this.readyState == 4 && this.status == 200) {
                        window.history.pushState({"html": this.responseText}, "", href);
                        document.getElementsByTagName("html")[0].innerHTML = this.responseText;
                        setupLinkHandling();
                        setupNavigation();
                        generateShapes();
                    }
                };
                xhttp.open("GET", href, true);
                xhttp.send();

                return false;
            };
        }
    }

    window.onpopstate = function(e) {
        if (e.state) {
            document.getElementsByTagName("html")[0].innerHTML = e.state.html;
        }
    };
}

setupLinkHandling();

function setupLinkHandling() {
    window.history.pushState({"html": document.documentElement.outerHTML}, "", window.location.href);

    var anchors = document.getElementsByTagName("a");

    for (var i = 0; i < anchors.length; i++) {
        if (["localhost", "atomhacks.github.io", "bxhackers.club"].includes(window.location.hostname)) {
            anchors[i].onclick = function() {
                var href = this.href;
                var xhttp = new XMLHttpRequest();
                xhttp.onreadystatechange = function() {
                    if (this.readyState == 4 && this.status == 200) {
                        window.history.pushState({"html": this.responseText}, "", href);
                        document.getElementsByTagName("html")[0].innerHTML = this.responseText;
                        setupLinkHandling();
                        setupNavigation();
                        generateShapes();
                    }
                };
                xhttp.open("GET", href, true);
                xhttp.send();

                return false;
            };
        }
    }

    window.onpopstate = function(e) {
        if (e.state) {
            document.getElementsByTagName("html")[0].innerHTML = e.state.html;
        }
    };
}

setupLinkHandling();

Fix custom page loading with new domain


'use strict';

/**
	Application-wide metadata is stored here for reuse
*/
module.exports = {
	FRONTEND_VERSION: 31
};

'use strict';

/**
	Application-wide metadata is stored here for reuse
*/
module.exports = {
	FRONTEND_VERSION: 32
};

Increment version to force refresh


import GameStateManager from "./GameStates/GameStateManager";
import CommandParser from "./Commands/CommandParser";
import GenerateName from "./Generators/NameGenerator";

export default {
  install: (Vue) => {
    Vue.prototype.$game = {
      startGame() {
        return GameStateManager.StartGame();
      },
      generateName() {
        return GenerateName();
      },
      parseCommand(command) {
        return CommandParser.ParseCommand(command);
      }
    }
  }
}

import GameStateManager from "./GameStates/GameStateManager";
// import CommandParser from "./Commands/CommandParser";
import GenerateName from "./Generators/NameGenerator";

export default {
  install: (Vue) => {
    Vue.prototype.$game = {
      startGame() {
        return GameStateManager.StartGame();
      },
      generateName() {
        return GenerateName();
      },
      parseCommand(command) {
        // return CommandParser.ParseCommand(command);
        console.log("Parsing " + command);
      }
    }
  }
}

Stop using command parser file


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

var codeBlocks = document.querySelectorAll('code[data-path]')
Array.prototype.forEach.call(codeBlocks, function (code) {
  code.textContent = fs.readFileSync(path.join(__dirname, code.dataset.path))
})

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

var codeBlocks = document.querySelectorAll('code[data-path]')
Array.prototype.forEach.call(codeBlocks, function (code) {
  var codePath = code.dataset.path
  code.textContent = fs.readFileSync(path.join(__dirname, '..', codePath))
})

Use new path based on changed __dirname


const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  entry: {
    login: './public/src/js/login.js',
    register: './public/src/js/register.js',
    'admin-search': './public/src/js/admin-search.js',
    'admin-users': './public/src/js/admin-users.js',
    'admin-user': './public/src/js/admin-user.js',
    'manage-admin': './public/src/js/manage-admin.js',
    'manage-device': './public/src/js/manage-device.js',
    manage: './public/src/js/manage.js',
    captcha: './public/src/js/captcha.js'
  },

  plugins: [
    new CleanWebpackPlugin(['public/dist/js'])
  ],

  output: {
    filename: '[name].min.js',
    path: path.resolve(__dirname, 'public/dist/js')
  },

  resolve: {
    modules: [
      path.resolve(__dirname, "public/src/modules"),
      "node_modules"
    ]
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  }
};

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  entry: {
    login: './public/src/js/login.js',
    register: './public/src/js/register.js',
    'admin-search': './public/src/js/admin-search.js',
    'admin-users': './public/src/js/admin-users.js',
    'admin-user': './public/src/js/admin-user.js',
    'manage-admin': './public/src/js/manage-admin.js',
    'manage-device': './public/src/js/manage-device.js',
    manage: './public/src/js/manage.js',
    captcha: './public/src/js/captcha.js'
  },

  plugins: [
    new CleanWebpackPlugin(['public/dist/js'])
  ],

  output: {
    filename: '[name].min.js',
    path: path.resolve(__dirname, 'public/dist/js')
  },

  resolve: {
    modules: [
      path.resolve(__dirname, 'public/src/modules'),
      'node_modules'
    ]
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  }
};

Use single quotes in webpack config


w/**
 * Latvian translation for foundation-datepicker
 * Artis Avotins <artis@apit.lv>
 */

;(function($){
    $.fn.fdatepicker.dates['lv'] = {
        days: ["Svētdiena", "Pirmdiena", "Otrdiena", "Trešdiena", "Ceturtdiena", "Piektdiena", "Sestdiena", "Svētdiena"],
        daysShort: ["Sv", "P", "O", "T", "C", "Pk", "S", "Sv"],
        daysMin: ["Sv", "Pr", "Ot", "Tr", "Ce", "Pk", "St", "Sv"],
        months: ["Janvāris", "Februāris", "Marts", "Aprīlis", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"],
        monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jūn", "Jūl", "Aug", "Sep", "Okt", "Nov", "Dec."],
        today: "Šodien",
        weekStart: 1
    };
}(jQuery));

Remove stray character breaking scripts.


var argv = require('cmdenv')('micromono')

/**
 * Parse commmand line and environment options
 */
argv
  .allowUnknownOption()
  .option('-s --service [services]', 'Names of services to require. Use comma to separate multiple services. (e.g. --service account,cache) Env name: MICROMONO_SERVICE')
  .option('-d --service-dir [dir]', 'Directory of locally available services. Env name: MICROMONO_SERVICE_DIR')
  .option('-w --allow-pending', 'White list mode - allow starting the balancer without all required services are loaded/probed.')
  .option('-p --port [port]', 'The http port which balancer/service binds to.')
  .option('-H --host [host]', 'The host which balancer/service binds to.')
  .option('-r --rpc [type]', 'Type of rpc to use.', 'axon')
  .option('--rpc-port [port]', 'The port which service binds the rpc server to.')
  .option('-b --bundle-asset', 'Bundle production ready version of asset files.')

module.exports = argv

var argv = require('cmdenv')('micromono')

/**
 * Parse commmand line and environment options
 */
argv
  .allowUnknownOption()
  .option('-s --service [services]', 'Names of services to require. Use comma to separate multiple services. (e.g. --service account,cache) Env name: MICROMONO_SERVICE')
  .option('-d --service-dir [dir]', 'Directory of locally available services. Env name: MICROMONO_SERVICE_DIR')
  .option('-p --port [port]', 'The http port which balancer/service binds to.')
  .option('-H --host [host]', 'The host which balancer/service binds to.')
  .option('-r --rpc [type]', 'Type of rpc to use.', 'axon')
  .option('--rpc-port [port]', 'The port which service binds the rpc server to.')
  .option('--rpc-host [host]', 'The host which service binds the rpc server to.')
  .option('-b --bundle-asset', 'Bundle production ready version of asset files.')

module.exports = argv

Add rpc host and remove --allow-pending.


/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

( function() {

win = null;

module.exports = {
    show: function() {
        if ( win === null ) {
            win = window.open('splashscreen.html');
        }
    },

    hide: function() {
        if ( win !== null ) {
            win.close();
            win = null;
        }
    }
};

require("cordova/tizen/commandProxy").add("SplashScreen", module.exports);

})();

Add license headers to Tizen code


'use strict';

// Configuration for the New Relic Node.js agent

exports.config = {
    app_name: process.env.NEW_RELIC_APP_NAME || 'app',
    logging: {
        filepath: process.env.NEW_RELIC_LOG || 'stdout'
    }
};

'use strict';

// Configuration for the New Relic Node.js agent

module.exports.config = {
    app_name: process.env.NEW_RELIC_APP_NAME || 'app',
    logging: {
        filepath: process.env.NEW_RELIC_LOG || 'stdout'
    }
};

Use always "module.exports", not the alias "exports"


const yeoman = require( 'yeoman-generator' );
const description = require( './description' );

module.exports = yeoman.Base.extend({
  constructor: function constructor( ...args ) {
    yeoman.Base.apply( this, args );
    this.argument( 'name', {
      type: String, required: false,
      desc: description.name,
    });
    this.option( 'debug', {
      type: Boolean, required: false, alias: 'd', defaults: false,
      desc: 'Debug mode',
    });
  },
  initialize: function initialize() {
    if ( this.options.debug ) {
      this.log( `ARGUMENT: name ${ this.name }` );
    }
  },
});

const yeoman = require( 'yeoman-generator' );
const description = require( './description' );

module.exports = yeoman.Base.extend({
  constructor: function constructor( ...args ) {
    yeoman.Base.apply( this, args );
    this.argument( 'name', {
      type: String, required: false,
      desc: description.name,
    });
    this.option( 'debug', {
      type: Boolean, required: false, alias: 'd', defaults: false,
      desc: 'Debug mode',
    });
  },
  initializing: function initializing() {
    if ( this.options.debug ) {
      this.log( `ARGUMENT: name ${ this.name }` );
    }
  },
});

Rename init method according to the spec.


Fix uri in secto_identifier js


'use strict';

const NODE_ENV = process.env.NODE_ENV || 'development';
const webpack = require('webpack');
const path = require('path');

const PATHS = {
    app: path.join(__dirname, 'app'),
    build: path.join(__dirname, 'build')
};

module.exports = {
    entry: {
        app: PATHS.app
    },
    output: {
        path: PATHS.build,
        filename: 'bundle.js'
    },
    watch: NODE_ENV === 'development',
    watchOptions: {
        aggregateTimeout: 100
    },
    devtool: NODE_ENV === 'development' ? 'cheap-module-inline-source-map' : null,
    plugins: [
        new webpack.NoErrorsPlugin(),
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify('production')
            }
        })
    ],
    resolve: {
        modulesDirectories: ['node_modules'],
        extensions: ['', '.js']
    },
    resolveLoader: {
        modulesDirectories: ['node_modules'],
        modulesTemplates: ['*-loader', '*'],
        extensions: ['', '.js']
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel',
                query: {
                    presets: ['es2015', 'react']
                }
            }
        ]
    }
};

'use strict';

const NODE_ENV = process.env.NODE_ENV || 'development';
const webpack = require('webpack');
const path = require('path');

const PATHS = {
    app: path.join(__dirname, 'app'),
    build: path.join(__dirname, 'build')
};

module.exports = {
    entry: {
        app: PATHS.app
    },
    output: {
        path: PATHS.build,
        filename: 'bundle.js'
    },
    watch: NODE_ENV === 'development',
    watchOptions: {
        aggregateTimeout: 100
    },
    devtool: NODE_ENV === 'development' ? 'cheap-module-inline-source-map' : null,
    plugins: [
        new webpack.NoErrorsPlugin(),
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify('production')
            }
        })
    ],
    resolve: {
        modulesDirectories: ['node_modules'],
        extensions: ['', '.js']
    },
    resolveLoader: {
        modulesDirectories: ['node_modules'],
        modulesTemplates: ['*-loader', '*'],
        extensions: ['', '.js']
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel',
                query: {
                    presets: ['es2015', 'react']
                },
                include: [
                    PATHS.app
                ]
            }
        ]
    }
};

Add include property to babel loader


var serviceName         = "facebook";

var request             = require("request");
var serviceConfig       = require("./../config/services.config.json");

var result = {
    service: serviceName,
    status: false
}

function facebook (cb) {

    request({
        url: serviceConfig[serviceName],
        method: "GET",
        headers: {
            "User-Agent": 'request'
        }
    }, function(error, response, body) {
        if(error) {
            result["message"]       = "Problem with the connection.";
            result["data"]          = error;
            return cb(result);
        }

        if(body) {
            try {
                body = JSON.parse(body);
            } catch (e) {
                result["message"]    = "Could not parse the response.";
                return cb(result);
            }

            if(body.current.health != 1) {
                result["status"]    = false;
                result["message"]   = body.current.subject;
                return cb(result);
            }

            result["status"]        = true;
            result["message"]       = body.current.subject;
            return cb(result);
        }

        result["message"]   = "Empty response. Try Again.";
        return cb(result);

    });
}

module.exports = facebook;

var serviceName         = "facebook";

var request             = require("request");
var serviceConfig       = require("./../config/services.config.json");

function facebook (cb) {
    var result = {
        service: serviceName,
        status: false
    };

    request({
        url: serviceConfig[serviceName],
        method: "GET",
        headers: {
            "User-Agent": 'request'
        }
    }, function(error, response, body) {
        if(error) {
            result["message"]       = "Problem with the connection.";
            result["data"]          = error;
            return cb(result);
        }

        if(body) {
            try {
                body = JSON.parse(body);
            } catch (e) {
                result["message"]    = "Could not parse the response.";
                return cb(result);
            }

            if(body.current.health != 1) {
                result["message"]   = body.current.subject;
                return cb(result);
            }

            result["status"]        = true;
            result["message"]       = body.current.subject;
            return cb(result);
        }

        result["message"]   = "Empty response. Try Again.";
        return cb(result);

    });
}

module.exports = facebook;

Make result object local to function


'use strict';

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

var Context = function () {
    var rawContext = contextify();

    rawContext.globals = rawContext.getGlobal();

    return {
        run: function (source, filename) {
            rawContext.run(source, filename);
        },

        runFile: function (fileName, callback) {
            fs.readFile(
                fileName,
                'utf8',
                function (err, data) {
                    if (err) {
                        callback(undefined, err);
                    }
                    else {
                        callback(rawContext.run(data, fileName));
                    }
                }
            );
        },

        hasAngular: function () {
            return typeof rawContext.angular === 'object';
        },

        getAngular: function () {
            return rawContext.angular;
        },

        module: function () {
            return rawContext.angular.module.apply(
                rawContext.angular.module,
                arguments
            );
        },

        injector: function (modules) {
            return rawContext.angular.inject(modules);
        },

        dispose: function () {
            rawContext.dispose();
        }
    };
};

exports.Context = Context;

'use strict';

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

var Context = function () {
    var rawContext = contextify();

    rawContext.globals = rawContext.getGlobal();

    return {
        run: function (source, filename) {
            rawContext.run(source, filename);
        },

        runFile: function (fileName, callback) {
            fs.readFile(
                fileName,
                'utf8',
                function (err, data) {
                    if (err) {
                        callback(undefined, err);
                    }
                    else {
                        callback(rawContext.run(data, fileName));
                    }
                }
            );
        },

        hasAngular: function () {
            return typeof rawContext.angular === 'object';
        },

        getAngular: function () {
            return rawContext.angular;
        },

        module: function () {
            return rawContext.angular.module.apply(
                rawContext.angular.module,
                arguments
            );
        },

        injector: function (modules) {
            return rawContext.angular.injector(modules);
        },

        dispose: function () {
            rawContext.dispose();
        }
    };
};

exports.Context = Context;

Correct typo of 'injector' method name as 'inject'.