module.exports = function(grunt) {
  'use strict';
  grunt.initConfig({
    benchmark: {
      singleTest: {
        src: ['benchmarks/singleTest.js'],
        dest: 'results/singleTest.csv'
      },
      loneFunction: {
        src: ['benchmarks/loneFunction.js'],
        dest: 'results/loneFunction.csv'
      },
      suites: {
        src: ['benchmarks/suites.js'],
        dest: 'results/suites.csv'
      },
      mixedSuite: {
        src: ['benchmarks/mixedSuite.js'],
        dest: 'results/mixedSuite.csv'
      },
      fibonacci: {
        src: ['benchmarks/fibonacci.js'],
        dest: 'results/fibonacci.csv'
      }
    },
    jshint: {
      options: { jshintrc: true },
      all: {
        src: ['Gruntfile.js', 'lib/**/*.js', 'tasks/**/*.js', 'benchmarks/*.js']
      }
    },
    nodeunit: {
      files: ['test/**/*_test.js']
    },
    watch: {
      all: {
        files: ['<%= jshint.all.src %>', '<%= nodeunit.files %>'],
        tasks: ['default']
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-nodeunit');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadTasks('tasks');
  grunt.registerTask('default', ['jshint', 'nodeunit']);
};

module.exports = function(grunt) {
  'use strict';
  grunt.initConfig({
    benchmark: {
      singleTest: {
        src: ['benchmarks/singleTest.js'],
        dest: 'results/singleTest.csv'
      },
      loneFunction: {
        src: ['benchmarks/loneFunction.js'],
        dest: 'results/loneFunction.csv'
      },
      suites: {
        src: ['benchmarks/suites.js'],
        dest: 'results/suites.csv'
      },
      mixedSuite: {
        src: ['benchmarks/mixedSuite.js'],
        dest: 'results/mixedSuite.csv'
      },
      fibonacci: {
        src: ['benchmarks/fibonacci.js'],
        dest: 'results/fibonacci.csv'
      }
    },
    jshint: {
      options: { jshintrc: true },
      all: {
        src: ['Gruntfile.js', 'lib/**/*.js', 'tasks/**/*.js', 'benchmarks/*.js']
      }
    },
    nodeunit: {
      files: ['test/**/*_test.js']
    },
    watch: {
      all: {
        files: ['<%= jshint.all.src %>', '<%= nodeunit.files %>'],
        tasks: ['default']
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-nodeunit');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadTasks('tasks');
  grunt.registerTask('default', ['jshint']);
};

Remove nodeunit as that test is bad


import React, { Component } from 'react'
import { Carousel, Well } from 'react-bootstrap'

import design1 from './Noah-Fagan-portfolio-oct-14-4.jpg'
import design2 from './Noah-Fagan-portfolio-oct-14-5.jpg'
import design3 from './Noah-Fagan-portfolio-oct-14-6.jpg'
import design4 from './Noah-Fagan-portfolio-oct-14-7.jpg'

class OurDesigns extends Component {
  render () {
    return (
      <Well>

Our Designs

        <Carousel>
          <Carousel.Item>

          </Carousel.Item>
          <Carousel.Item>

          </Carousel.Item>
          <Carousel.Item>

          </Carousel.Item>
          <Carousel.Item>

          </Carousel.Item>
        </Carousel>
      </Well>
    )
  }
}

export default OurDesigns

import React, { Component } from 'react'
import { Carousel, Well } from 'react-bootstrap'

import design1 from './Noah-Fagan-portfolio-oct-14-4.jpg'
import design2 from './Noah-Fagan-portfolio-oct-14-5.jpg'
import design3 from './Noah-Fagan-portfolio-oct-14-6.jpg'
import design4 from './Noah-Fagan-portfolio-oct-14-7.jpg'

class OurDesigns extends Component {
  render () {
    return (
      <Well>

Our Designs

          Wouldn’t it be cool if we could show you floor plans of your ideal home? We’re working on it, but until then why not check out some of our standard designs.

        <Carousel>
          <Carousel.Item>

          </Carousel.Item>
          <Carousel.Item>

          </Carousel.Item>
          <Carousel.Item>

          </Carousel.Item>
          <Carousel.Item>

          </Carousel.Item>
        </Carousel>
      </Well>
    )
  }
}

export default OurDesigns

Update our designs section text


'use strict';

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
	simplemocha: {
		app: {
			src: ['test/test.js']
		}
	},
	jshint: {
		options: {
			jshintrc: '.jshintrc'
		},
		lib: ['lib/**/*.js', 'tasks/**/*.js', 'Gruntfile.js']
	},
	release: {},
	"steal-build": {
		"test-webworker": {
			options: {
				system: {
					configMain: "@empty",
					main: "worker",
					baseUrl: __dirname + "/test/browser/webworker"
				},
				buildOptions: {
					bundleSteal: true,
					quiet: true
				}
			}
		}
	},
	testee: {
		tests: {
			options: {
				browsers: [ "firefox" ]
			},
			src: [ "test/browser/test.html" ]
		}
	}
  });

  grunt.registerTask('default', 'test');
  grunt.registerTask('test', [ 'jshint', 'simplemocha' ]);
  grunt.registerTask("test:browser", [ "steal-build", "testee" ]);

  grunt.loadNpmTasks('grunt-simple-mocha');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-release');
  grunt.loadNpmTasks('testee');
  grunt.loadTasks("tasks");
};

'use strict';

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
	simplemocha: {
    options: {
      timeout: 30000
    },
		app: {
			src: ['test/test.js']
		}
	},
	jshint: {
		options: {
			jshintrc: '.jshintrc'
		},
		lib: ['lib/**/*.js', 'tasks/**/*.js', 'Gruntfile.js']
	},
	release: {},
	"steal-build": {
		"test-webworker": {
			options: {
				system: {
					configMain: "@empty",
					main: "worker",
					baseUrl: __dirname + "/test/browser/webworker"
				},
				buildOptions: {
					bundleSteal: true,
					quiet: true
				}
			}
		}
	},
	testee: {
		tests: {
			options: {
				browsers: [ "firefox" ]
			},
			src: [ "test/browser/test.html" ]
		}
	}
  });

  grunt.registerTask('default', 'test');
  grunt.registerTask('test', [ 'jshint', 'simplemocha' ]);
  grunt.registerTask("test:browser", [ "steal-build", "testee" ]);

  grunt.loadNpmTasks('grunt-simple-mocha');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-release');
  grunt.loadNpmTasks('testee');
  grunt.loadTasks("tasks");
};

Set a very large timeout for AppVeyor slowness


import React from 'react'
import i18n from '../../i18n'

const MapFooter = () => (

          ernte-teilen.org

          {i18n.t('nav.privacy')}

          {i18n.t('nav.imprint')}

    {i18n.t('nav.map_data')}

      © MapBox

     |

      © OpenStreetMap

)

export default MapFooter

Update links to privacy and contact page


import createStore from './createStore'
import combineReducers from './combineReducers'
import bindActionCreators from './bindActionCreators'
import applyMiddleware from './applyMiddleware'
import compose from './compose'

/*
* This is a dummy function to check if the function name has been altered by minification.
* If the function has been minified and NODE_ENV !== 'production', warn the user
*/
function isCrushed() {}

if (isCrushed.name !== 'isCrushed' && process.env.NODE_ENV !== 'production') {
  /*eslint-disable no-console */
  console.error(
    'You are currently using minified code outside of NODE_ENV === \'production\'. ' +
    'This means that you are running a slower development build of Redux. ' +
    'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' +
    'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' +
    'to ensure you have the correct code for your production build.'
  )
  /*eslint-enable */
}

export {
  createStore,
  combineReducers,
  bindActionCreators,
  applyMiddleware,
  compose
}

import createStore from './createStore'
import combineReducers from './combineReducers'
import bindActionCreators from './bindActionCreators'
import applyMiddleware from './applyMiddleware'
import compose from './compose'

/*
* This is a dummy function to check if the function name has been altered by minification.
* If the function has been minified and NODE_ENV !== 'production', warn the user.
*/
function isCrushed() {}

if (isCrushed.name !== 'isCrushed' && process.env.NODE_ENV !== 'production') {
  /*eslint-disable no-console */
  console.error(
    'You are currently using minified code outside of NODE_ENV === \'production\'. ' +
    'This means that you are running a slower development build of Redux. ' +
    'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' +
    'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' +
    'to ensure you have the correct code for your production build.'
  )
  /*eslint-enable */
}

export {
  createStore,
  combineReducers,
  bindActionCreators,
  applyMiddleware,
  compose
}

Add period on line 9


// Copyright (c) Rotorz Limited. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root.

/** @module webreed */

// Copyright (c) Rotorz Limited. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root.

/** @module webreed-core */

Correct main module name in jsdoc comment.


import Tree from './data/Tree';
import Trie from './data/Trie';
import BinarySearchTree from './data/BinarySearchTree';
import Graph from './data/Graph';
import MinHeap from './data/MinHeap';
import LinkedList from './data/LinkedList';

export default { Tree, Trie, BinarySearchTree, Graph, MinHeap }

import Tree from './data/Tree';
import Trie from './data/Trie';
import BinarySearchTree from './data/BinarySearchTree';
import Graph from './data/Graph';
import MinHeap from './data/MinHeap';
import LinkedList from './data/LinkedList';

export { Tree, Trie, BinarySearchTree, Graph, MinHeap, LinkedList }

Remove default export to pure export


import ReactMapboxGl from "./map";

import Layer from "./layer";
import Feature from "./feature";
import ZoomControl from "./zoom-control";
import Popup from "./popup";

export { ReactMapboxGl };
export { Layer };
export { Feature };
export { ZoomControl };
export { Popup };

export default ReactMapboxGl;

import Map from "./map";
import Layer from "./layer";
import Feature from "./feature";
import ZoomControl from "./zoom-control";
import Popup from "./popup";

export {
  Feature,
  Layer,
  Map,
  Popup,
  ZoomControl
};

export default Map;

Change Map export to just be named "Map"


'use strict';
(() => {
  module.exports = (gulp, plugins, config) => {
    return () => {
      console.log(`${config.patternsPath}/**/*.js`);
      return gulp.src([`${config.patternsPath}/**/*.js`, `!${config.patternsPath}/**/*.min.js`])
        .pipe(plugins.changed(config.buildPath))
        .pipe(plugins.plumber({
          errorHandler: plugins.notify.onError('Error: <%= error.message %>')
        }))
        .pipe(plugins.rename({ suffix: '.min' }))
        .pipe(plugins.sourcemaps.init())
        .pipe(plugins.babel({
          presets: [
            ['env', { 'modules': false }]
          ],
          ignore: [
            // Keep these files from breaking until they're refactored to ES6 code.
            `${config.patternsPath}/components/dialogs/**/*.js`
          ]
        }))
        .pipe(plugins.uglify())
        .pipe(plugins.size(config.sizeOptions))
        .pipe(plugins.sourcemaps.write('.', { sourceRoot: '.' }))
        .pipe(gulp.dest(config.buildPath))
      ;
    };
  };
})();

'use strict';
(() => {
  module.exports = (gulp, plugins, config) => {
    return () => {
      console.log(`${config.patternsPath}/**/*.js`);
      return gulp.src([`${config.patternsPath}/**/*.js`, `!${config.patternsPath}/**/*.min.js`])
        .pipe(plugins.changed(config.buildPath))
        .pipe(plugins.plumber({
          errorHandler: plugins.notify.onError('Error: <%= error.message %>')
        }))
        .pipe(plugins.rename({ suffix: '.min' }))
        .pipe(plugins.sourcemaps.init())
        .pipe(plugins.babel({
          presets: [
            ['env', { 'modules': false }]
          ],
          ignore: [
            // Keep these files from breaking until they're refactored to ES6 code.
            `${config.patternsPath}/components/dialogs/**/*.js`,
            `${config.patternsPath}/components/buttons/rocketbelt.dynamic-button.js`
          ]
        }))
        .pipe(plugins.uglify())
        .pipe(plugins.size(config.sizeOptions))
        .pipe(plugins.sourcemaps.write('.', { sourceRoot: '.' }))
        .pipe(gulp.dest(config.buildPath))
      ;
    };
  };
})();

Exclude dynamic buttons from ES6ification.


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

var port = process.env.PORT || 3000

app.use(bodyParser.urlencoded({ extended: true }))

app.get('/api/days/:day', function(request, response, next){
  var daysOfWeek = {
    monday: 1,
    tuesday:2,
    wednesday: 3,
    thursday: 4,
    friday: 5,
    saturday: 6,
    sunday: 7
  }
  var day = request.params.day.toLowerCase()

  response.set('Content-Type', 'application/text')

  if(!daysOfWeek.hasOwnProperty(day)) {
    response.status(400)
    response.send(`'${day}' is not a valid day!`)
  } else {
    response.status(200)
    response.send(String(daysOfWeek[day]))
  }
})

app.post('/api/array/concat', function(request, response, next){
  response.set('Content-Type', 'application/json')
  var bodyObj = request.body
  var arrays = []
  for(item in bodyObj){
    try {
      arrays.push(JSON.parse(bodyObj[item]))
    } catch(error) {
        if(error instanceof SyntaxError) {
          response.status(400)
          return response.json({"error": "Input data should be of type Array."})
        }
      }
  }
  var result = [].concat.apply([], arrays)
  response.json({"result": result})
})

app.listen(port, function(){
  console.log(`Listening on port ${port}`)
})

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

var port = process.env.PORT || 3000

app.use(bodyParser.json())

app.get('/api/days/:day', function(request, response, next){
  var daysOfWeek = {
    monday: 1,
    tuesday:2,
    wednesday: 3,
    thursday: 4,
    friday: 5,
    saturday: 6,
    sunday: 7
  }
  var day = request.params.day.toLowerCase()

  response.set('Content-Type', 'application/text')

  if(!daysOfWeek.hasOwnProperty(day)) {
    response.status(400)
    response.send(`'${day}' is not a valid day!`)
  } else {
    response.status(200)
    response.send(String(daysOfWeek[day]))
  }
})

app.post('/api/array/concat', function(request, response, next){
  response.set('Content-Type', 'application/json')
  var result = []
  var bodyObj = request.body
  for (item in bodyObj){
    if(!Array.isArray(bodyObj[item])){
      response.status(400)
      return response.json({"error": "Input data should be of type Array."})
    } else {
    result = result.concat(bodyObj[item])
    }
  }
  response.json({"result": result})
})

app.listen(port, function(){
  console.log(`Listening on port ${port}`)
})

Update POST route request to be JSON


Iago.ThemesController = Ember.ArrayController.extend({
  needs: 'use_case',
  actions: {
    create: function() {
      var name = this.get('newThemeName'),
          controller = this;
      if (!name.trim()) { return; }

      var theme = Iago.Theme.create({
        org: 'iago',
        name: name,
        version: 'master'
      });

      if (!Iago.ThemeModel.find(name)) {
        Ember.$.post('/themes', { name: name }, function(data) {
          console.log(controller.content);
        });
      }

      controller.content.addObject(theme);

      Iago.UseCaseModel.addTheme(this.get('controllers.use_case.name'), name);
      Iago.UseCaseModel.save(this.get('controllers.use_case'));
    }
  }
});

Iago.ThemesController = Ember.ArrayController.extend({
  needs: 'use_case',
  actions: {
    create: function() {
      var name = this.get('newThemeName'),
          controller = this;
      if (!name.trim()) { return; }

      var theme = Iago.Theme.create({
        org: 'iago',
        name: name,
        version: 'master'
      });

      if (!Iago.ThemeModel.find(name)) {
        Ember.$.post('/themes', { name: name }, function(data) {
          console.log(controller.content);
        });
        Iago.ThemeModel.push(theme);
      }

      controller.content.addObject(theme);

      Iago.UseCaseModel.addTheme(this.get('controllers.use_case.name'), name);
      Iago.UseCaseModel.save(this.get('controllers.use_case'));
    }
  }
});

Add theme to ThemeModel if it does not exist


import loadZips from '../shared/load-zips'
import importData from '../shared/import-data'

exports.seed = async function(knex, Promise) {
  let zipCodes = loadZips('./seeds/shared/zip-codes.csv')
  await knex('zip_codes').del()
  await importData('zip_codes', zipCodes)
};

import loadZips from '../shared/load-zips'
import importData from '../shared/import-data'

exports.seed = async function(knex, Promise) {
  let zipCodes = loadZips('./seeds/shared/zip-codes.csv')
  await knex('zip_codes').del()
  await importData(knex, 'zip_codes', zipCodes)
};

Fix another thing that is bad


import React from 'react';
import Helmet from 'react-helmet';

class About extends React.Component {
	render() {
		return (

				<Helmet
  			title="About | Staytube"
  			meta={[{ property: 'og:title', content: 'About' }]}
				/>

About

Dedicated to great full length concerts on YouTube.

);
	}
}

export default About;

import React from 'react';
import Helmet from 'react-helmet';

class About extends React.Component {
	render() {
		return (

				<Helmet
  			title="About | Staytube"
  			meta={[{ property: 'og:title', content: 'About' }]}
				/>

About

Dedicated to great full length concerts. Exploring the concept of using "Youtube as a CMS". Made by Urban Sandén (@urre)

Tools

ReactJS

Babel

Webpack

PostCSS

Basscss

YouTube API

);
	}
}

export default About;

Add a list of tools


importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.0.0/workbox-sw.js')

const staticCache = 'react-base-static-v1'
const dynamicCache = 'react-base-dynamic-v1'
const timeCache = 30 * 24 * 60 * 60

self.workbox.skipWaiting()
self.workbox.clientsClaim()

workbox.core.setCacheNameDetails({
  precache: staticCache,
  runtime:  dynamicCache
})

workbox.routing.registerRoute(
  /\.(?:js|css)$/,
  workbox.strategies.cacheFirst({
    cacheName: staticCache
  }),
)

workbox.routing.registerRoute(
  new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'),
  workbox.strategies.cacheFirst({
    cacheName: staticCache,
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 10,
      }),
    ],
  }),
)

workbox.routing.registerRoute(
  new RegExp('/content/(.*)'),
  workbox.strategies.staleWhileRevalidate({
    cacheName: dynamicCache,
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 60,
        maxAgeSeconds: timeCache
      }),
    ],
  }),
)

importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.0.0/workbox-sw.js')

const staticCache = 'react-base-static-v1'
const dynamicCache = 'react-base-dynamic-v1'
const timeCache = 30 * 24 * 60 * 60

self.workbox.skipWaiting()
self.workbox.clientsClaim()

workbox.core.setCacheNameDetails({
  precache: staticCache,
  runtime:  dynamicCache
})

workbox.routing.registerRoute(
  /\.(?:js|css)$/,
  workbox.strategies.cacheFirst({
    cacheName: staticCache,
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 20,
        maxAgeSeconds: timeCache
      }),
    ],
  }),
)

workbox.routing.registerRoute(
  new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'),
  workbox.strategies.cacheFirst({
    cacheName: staticCache,
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 10,
      }),
    ],
  }),
)

workbox.routing.registerRoute(
  new RegExp('/content/(.*)'),
  workbox.strategies.staleWhileRevalidate({
    cacheName: dynamicCache,
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 60,
        maxAgeSeconds: timeCache
      }),
    ],
  }),
)

Add time cache to static cache


'use strict';

/**
 * @ngdoc directive
 * @name vlui.directive:bookmarkList
 * @description
 * # bookmarkList
 */
angular.module('vlui')
  .directive('bookmarkList', function (Bookmarks, consts, Logger) {
    return {
      templateUrl: 'bookmarklist/bookmarklist.html',
      restrict: 'E',
      replace: true,
      scope: {
        highlighted: '='
      },
      link: function postLink(scope, element, attrs, modalController) {
        // The bookmark list is designed to render within a modal overlay.
        // Because modal contents are hidden via ng-if, if this link function is
        // executing it is because the directive is being shown. Log the event:
        Logger.logInteraction(Logger.actions.BOOKMARK_OPEN);
        scope.logBookmarksClosed = function() {
          Logger.logInteraction(Logger.actions.BOOKMARK_CLOSE);
        };

        scope.Bookmarks = Bookmarks;
        scope.consts = consts;
      }
    };
  });

'use strict';

/**
 * @ngdoc directive
 * @name vlui.directive:bookmarkList
 * @description
 * # bookmarkList
 */
angular.module('vlui')
  .directive('bookmarkList', function (Bookmarks, consts, Logger) {
    return {
      templateUrl: 'bookmarklist/bookmarklist.html',
      restrict: 'E',
      replace: true,
      scope: {
        highlighted: '='
      },
      link: function postLink(scope /*, element, attrs*/) {
        // The bookmark list is designed to render within a modal overlay.
        // Because modal contents are hidden via ng-if, if this link function is
        // executing it is because the directive is being shown. Log the event:
        Logger.logInteraction(Logger.actions.BOOKMARK_OPEN);
        scope.logBookmarksClosed = function() {
          Logger.logInteraction(Logger.actions.BOOKMARK_CLOSE);
        };

        scope.Bookmarks = Bookmarks;
        scope.consts = consts;
      }
    };
  });

Fix lint warnings. cc @kadamwhite


import mongoose from 'mongoose'
var Schema = mongoose.Schema

var athleticsSchema = new Schema({
  id: String,
  date: Date,
  events: [{
    title: String,
    location: String,
    building_id: String,
    start_time: Date,
    end_time: Date
  }]
})

athleticsSchema.index({ id: 'text', date: 'text', campus: 'text', 'events.location': 'text', 'events.title': 'text' })

export default mongoose.model('athletics', athleticsSchema)

import mongoose from 'mongoose'
var Schema = mongoose.Schema

var athleticsSchema = new Schema({
  id: String,
  date: Date,
  campus: String,
  events: [{
    title: String,
    location: String,
    building_id: String,
    start_time: Date,
    end_time: Date
  }]
})

athleticsSchema.index({ id: 'text', date: 'text', campus: 'text', 'events.title': 'text' })

export default mongoose.model('athletics', athleticsSchema)

Remove date from text indices


var models = require('../models');
var GameController = require("./GameController");

var playerQueue = [];

exports.startGame = function(req, res) {

  var player1 = req.body.username;

  var game = GameController.findGame(player1).then(function(game) {
    // player has ongoing game
    if (game != null) {
      res.json({'game': game});
    }

    // Start a new game if opponent exists and opponent is not the same player. Pops the last element in queue.
    else if (playerQueue.length > 0 && playerQueue.indexOf(player1) === -1) {
      GameController.startGame(player1, playerQueue.pop()).then(function(game) {
        models.Game.find({
          include: [models.Board],
          where: {id: game.id}
        }).then(function(game) {
          res.json({'game': game});
        });
      });
    }

    // Put the player in the queue if the player isn't already there
    else if(playerQueue.indexOf(player1) === -1)  {
      playerQueue.unshift(player1);
      res.json({'game': null});
    }
  })
};

exports.cancelWaitForGame = function(req, res) {

  var player = req.body.username;
  var index = playerQueue.indexOf(player);

  if (index > -1) {
    playerQueue.splice(index, 1);
  }
};

var models = require('../models');
var GameController = require("./GameController");

var playerQueue = [];

exports.startGame = function(req, res) {

  var player1 = req.body.username;

  var game = GameController.findGame(player1).then(function(game) {
    // player has ongoing game
    if (game != null) {
      res.json({'game': game});
    }

    // Start a new game if opponent exists and opponent is not the same player. Pops the last element in queue.
    else if (playerQueue.length > 0 && playerQueue.indexOf(player1) === -1) {
      GameController.startGame(player1, playerQueue.pop()).then(function(game) {
        models.Game.find({
          include: [models.Board],
          where: {id: game.id}
        }).then(function(game) {
          res.json({'game': game});
        });
      });
    }

    // Put the player in the queue if the player isn't already there
    else if(playerQueue.indexOf(player1) === -1)  {
      playerQueue.unshift(player1);
      res.json({'game': null});
    }
    // If a game doesn't exit yet
    else {
      res.json({'game': null});
    }
  })
};

exports.cancelWaitForGame = function(req, res) {

  var player = req.body.username;
  var index = playerQueue.indexOf(player);

  if (index > -1) {
    playerQueue.splice(index, 1);
  }
};

Fix sending a null game object in the base case


const addPaintOptions = (options, layer) => {
  if (layer.isPoint) {
    options['type'] = 'circle'
    options['paint'] = {
      'circle-radius': [
        'interpolate',
        ['exponential', 1],
        ['zoom'],
        0, 1.5,
        6, 4
      ],
      'circle-color': layer.color,
      'circle-opacity': 0.7
    }
  } else {
    options['type'] = 'fill'
    options['paint'] = {
      'fill-color': layer.color,
      'fill-opacity': 0.8,
    }
  }
}

export default {
  methods: {
    addRasterTileLayer (layer) {
      this.map.addLayer({
        id: layer.id,
        type: 'raster',
        minzoom: 0,
        maxzoom: 22,
        source: {
          type: 'raster',
          tiles: [layer.url],
          tileSize: 256,
        },
        layout: {
          visibility: 'visible'
        }
      }, this.firstForegroundLayerId)
    },

    addRasterDataLayer(layer) {
      const options = {
        id: layer.id,
        source: {
          type: 'geojson',
          data: layer.url
        },
        layout: {
          visibility: 'visible'
        }
      }

      addPaintOptions(options, layer)
      console.log('Adding data layer:', layer, options, this.firstForegroundLayerId)
      this.map.addLayer(options, this.firstForegroundLayerId)
    },
  },
}

const addPaintOptions = (options, layer) => {
  if (layer.isPoint) {
    options['type'] = 'circle'
    options['paint'] = {
      'circle-radius': [
        'interpolate',
        ['exponential', 1],
        ['zoom'],
        0, 1.5,
        6, 4
      ],
      'circle-color': layer.color,
      'circle-opacity': 0.7
    }
  } else {
    options['type'] = 'fill'
    options['paint'] = {
      'fill-color': layer.color,
      'fill-opacity': 0.8,
    }
  }
}

export default {

  methods: {
    addRasterTileLayer (layer) {
      if(!this.hasExistingMapLayer(layer.id)) {
        this.map.addLayer({
          id: layer.id,
          type: 'raster',
          minzoom: 0,
          maxzoom: 22,
          source: {
            type: 'raster',
            tiles: [layer.url],
            tileSize: 256,
          },
          layout: {
            visibility: 'visible'
          }
        }, this.firstForegroundLayerId)
      }
    },

    addRasterDataLayer(layer) {
      if(!this.hasExistingMapLayer(layer.id)) {
        const options = {
          id: layer.id,
          source: {
            type: 'geojson',
            data: layer.url
          },
          layout: {
            visibility: 'visible'
          }
        }

        addPaintOptions(options, layer)

        this.map.addLayer(options, this.firstForegroundLayerId)
      }
    },

    hasExistingMapLayer (id) {
      const existingMapLayer = this.map.getLayer(id)

      return typeof existingMapLayer !== 'undefined'
    }
  },
}

Check whether a layer existing on the map before trying to add it


var assert = require("assert");
var parseApk = require("..");

describe("APK V24", function () {
    var output = null;

    before(function (done) {
        parseApk(__dirname + "/samples/test_v24.apk", function (err, out) {
            if (err) {
                return done(err);
            }
            output = out;
            done();
        });
    });

    it("Parses correctly", function () {
        assert.notEqual(null, output);
    });

    it("Starts with a manifest tag", function () {
        assert.equal(output.manifest.length, 1);
    });

    it("Has a package name", function () {
        assert.equal(output.manifest[0]["@package"], "com.idotools.bookstore");
    });

    it("Has a package version", function () {
        assert.equal(output.manifest[0]["@platformBuildVersionCode"], "24");
    });

    it("Has an application tag", function () {
        var manifest = output.manifest[0];
        assert.equal(manifest.application.length, 1);
    });
});

var assert = require("assert");
var parseApk = require("..");

describe("APK V24", function () {
    var output = null;

    before(function (done) {
        parseApk(__dirname + "/samples/test_v24.apk", function (err, out) {
            if (err) {
                return done(err);
            }
            output = out;
            done();
        });
    });

    it("Parses correctly", function () {
        assert.notEqual(null, output);
    });

    it("Starts with a manifest tag", function () {
        assert.equal(output.manifest.length, 1);
    });

    it("Has a package name", function () {
        assert.equal(output.manifest[0]["@package"], "com.idotools.bookstore");
    });

    it("Has a package version", function () {
        assert.equal(output.manifest[0]["@platformBuildVersionCode"], "24");
    });

    it("Parses platformBuildVersionName", function () {
        assert.equal(output.manifest[0]["@platformBuildVersionName"], "7.0");
    });

    it("Has an application tag", function () {
        var manifest = output.manifest[0];
        assert.equal(manifest.application.length, 1);
    });
});

Verify that type 4 fields are parsed correctly


var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
  if (xhr.readyState === 4) {
    if (xhr.status === 200){
      var employees = JSON.parse(xhr.responseText);
      var statusHTML = '
';
      for (var i = 0; i < employees.length; i++) {
      	if (employees[i].inoffice === true) {
      		statusHTML += '
';
      	} else {
      		statusHTML += '
';
      	}
      	statusHTML += employees[i].name + '
';
      }
      statusHTML += '
';
      document.getElementById('employeeList').innerHTML = statusHTML;
    }
  }
};

xhr.open('GET', 'data/employee-status.json');
xhr.send();

function getJSON(url) {
   // set up a new Promise
   // @resolve -> then
   // @reject  -> catch
   return new Promise(function(resolve, reject){
      let xhr = new XMLHttpRequest();
      xhr.open('GET', url);
      xhr.onreadystatechange = handleResponse;
      xhr.onerror = function(error){
         reject(error); // ajaxPromise 'catch'
      };
      xhr.send();

      // handle the ajax response
      function handleResponse() {
         if (xhr.readyState === 4) {
            if (xhr.status === 200){
               let employees = JSON.parse(xhr.responseText);
               resolve(employees); // ajaxPromise 'then'
            } else {
               reject(this.statusText); // ajaxPromise 'catch'
            }
         }
      }
   });
}

// cycle through each employee and create listItems
function createListItems(employees) {
   let i,
       statusHTML = '';

   for (i = 0; i < employees.length; i++) {
      if (employees[i].inoffice === true) {
         statusHTML += '
';
      } else {
         statusHTML += '
';
      }
      statusHTML += employees[i].name + '
';
   }
   return statusHTML;
}

// wrap listItems in a UL
function createUnordedList(listItems) {
   return '
' + listItems + '
';
}

// append the UL to the dom
function appendToDom(unordedList) {
   document.getElementById('employeeList').innerHTML = unordedList;
}

const ajaxPromise = getJSON('data/employee-status.json');

ajaxPromise
   .then(createListItems)
   .then(createUnordedList)
   .then(appendToDom)
   .catch(function(error){
      console.log(error);
   });

Add Promise | Modulize into functions | add ES2016 let and const


me.canvas = document.querySelector('#area');
me.ctx = me.canvas.getContext('2d');
me.ctx.lineWidth = 5;
me.arena = game.createArena('white', /*230*/me.canvas.height/2-10, me.canvas.width/2, me.canvas.height/2);

//Set up socket events --Ha Andrew don't look at this --You can't stop me
socket.on('player join', function(data){
  var x = me.canvas.width/2, y = me.canvas.height/2;
  me.players[data.id] = new game.Player(data.id, data.color, x, y);
  me.playerIDs.push(data.id);
});

socket.on('player leave', function(data){
  me.playerIDs.splice(me.playerIDs.indexOf(data.id),1);
  delete me.players[data.id];
});

socket.on('charge start', function(data){
  me.players[data.id].beginCharge();
});

socket.on('charge end', function(data){
  me.players[data.id].endCharge();
});

socket.on('phone tilt', function(data) {
  if(me.players[data.id]) {
    me.players[data.id].updateAcceleration(data.yAcc/300, -data.xAcc/300);
  } //my eyes are everywhere --I will gouge your eyes out
});

"use strict";
var game = game || {};

game.socketHandlers = {
  init : function(app) {
    /*me.canvas = document.querySelector('#area');
    me.ctx = me.canvas.getContext('2d');
    me.ctx.lineWidth = 5;
    me.arena = game.createArena('white', me.canvas.height/2-10, me.canvas.width/2, me.canvas.height/2);*/

    //Set up socket events --Ha Andrew don't look at this --You can't stop me
    socket.on('player join', function(data){
      var x = app.canvas.width/2, y = app.canvas.height/2;
      app.players[data.id] = new game.Player(data.id, data.color, x, y);
      app.playerIDs.push(data.id);
    });

    socket.on('player leave', function(data){
      app.playerIDs.splice(app.playerIDs.indexOf(data.id),1);
      delete app.players[data.id];
    });

    socket.on('charge start', function(data){
      app.players[data.id].beginCharge();
    });

    socket.on('charge end', function(data){
      app.players[data.id].endCharge();
    });

    socket.on('phone tilt', function(data) {
      if(app.players[data.id]) {
        app.players[data.id].updateAcceleration(data.yAcc/300, -data.xAcc/300);
      } //my eyes are everywhere --I will gouge your eyes out
    });
  }
}

Call all socket functions in socket handler


/*
 * Methods for fetching pasted html before it gets inserted into content
**/

/* Modern event.clipboardData driven approach.
 * Advantage is that it does not have to loose selection or modify dom to catch the data.
 * IE does not support though.
**/
wysihtml5.dom.getPastedHtml = function(event) {
  var html;
  if (event.clipboardData) {
    if (wysihtml5.lang.array(event.clipboardData.types).contains('text/html')) {
      html = event.clipboardData.getData('text/html');
    } else if (wysihtml5.lang.array(event.clipboardData.types).contains('text/plain')) {
      html = wysihtml5.lang.string(event.clipboardData.getData('text/plain')).escapeHTML(true, true);
    }
  }
  return html;
};

/* Older temprorary contenteditable as paste source catcher method for fallbacks */
wysihtml5.dom.getPastedHtmlWithDiv = function (composer, f) {
  var selBookmark = composer.selection.getBookmark(),
      cleanerDiv = document.createElement('DIV'),
      doc = composer.element.ownerDocument;

  cleanerDiv.setAttribute('contenteditable', 'true');
  doc.body.appendChild(cleanerDiv);
  cleanerDiv.focus();

  setTimeout(function () {
    composer.selection.setBookmark(selBookmark);
    f(cleanerDiv.innerHTML);
    cleanerDiv.parentNode.removeChild(cleanerDiv);
  }, 0);
};

/*
 * Methods for fetching pasted html before it gets inserted into content
**/

/* Modern event.clipboardData driven approach.
 * Advantage is that it does not have to loose selection or modify dom to catch the data.
 * IE does not support though.
**/
wysihtml5.dom.getPastedHtml = function(event) {
  var html;
  if (event.clipboardData) {
    if (wysihtml5.lang.array(event.clipboardData.types).contains('text/html')) {
      html = event.clipboardData.getData('text/html');
    } else if (wysihtml5.lang.array(event.clipboardData.types).contains('text/plain')) {
      html = wysihtml5.lang.string(event.clipboardData.getData('text/plain')).escapeHTML(true, true);
    }
  }
  return html;
};

/* Older temprorary contenteditable as paste source catcher method for fallbacks */
wysihtml5.dom.getPastedHtmlWithDiv = function (composer, f) {
  var selBookmark = composer.selection.getBookmark(),
      doc = composer.element.ownerDocument,
      cleanerDiv = coc.createElement('DIV');

  cleanerDiv.style.width = "1px";
  cleanerDiv.style.height = "1px";
  cleanerDiv.style.visibility = "hidden";
  cleanerDiv.style.overflow = "hidden";

  cleanerDiv.setAttribute('contenteditable', 'true');
  doc.body.appendChild(cleanerDiv);
  cleanerDiv.focus();

  setTimeout(function () {
    composer.selection.setBookmark(selBookmark);
    f(cleanerDiv.innerHTML);
    cleanerDiv.parentNode.removeChild(cleanerDiv);
  }, 0);
};

Make fallback paste catcher a bit less obtrusive.


/**
 * JavaScript SwatCheckboxList component
 *
 * @param id string Id of the matching {@link SwatCheckboxList} object.
 */
function SwatCheckboxList(id)
{
	this.check_list = document.getElementsByName(id + '[]');
	this.check_all = null; // a reference to a check-all js object

	for (i = 0; i < this.check_list.length; i++) {
		YAHOO.util.Event.addListener(this.check_list[i], 'change',
			SwatCheckboxList.clickHandler, this);
	}
}

SwatCheckboxList.clickHandler = function(event, object)
{
	object.checkAllInit();
}

SwatCheckboxList.prototype.checkAllInit = function ()
{
	if (this.check_all == null)
		return;

	var count = 0;
	for (i = 0; i < this.check_list.length; i++)
		if (this.check_list[i].checked)
			count++;
		else if (count > 0)
			break; // can't possibly be all checked or none checked

	this.check_all.setState(count == this.check_list.length);
}

SwatCheckboxList.prototype.checkAll = function(checked)
{
	for (i = 0; i < this.check_list.length; i++)
		this.check_list[i].checked = checked;
}

/**
 * JavaScript SwatCheckboxList component
 *
 * @param id string Id of the matching {@link SwatCheckboxList} object.
 */
function SwatCheckboxList(id)
{
	this.check_list = document.getElementsByName(id + '[]');
	this.check_all = null; // a reference to a check-all js object

	for (i = 0; i < this.check_list.length; i++) {
		YAHOO.util.Event.addListener(this.check_list[i], 'click',
			SwatCheckboxList.clickHandler, this);
	}
}

SwatCheckboxList.clickHandler = function(event, object)
{
	object.checkAllInit();
}

SwatCheckboxList.prototype.checkAllInit = function ()
{
	if (this.check_all == null)
		return;

	var count = 0;
	for (i = 0; i < this.check_list.length; i++)
		if (this.check_list[i].checked)
			count++;
		else if (count > 0)
			break; // can't possibly be all checked or none checked

	this.check_all.setState(count == this.check_list.length);
}

SwatCheckboxList.prototype.checkAll = function(checked)
{
	for (i = 0; i < this.check_list.length; i++)
		this.check_list[i].checked = checked;
}

Use click event instead of change event for checkbox list so it works in IE


var amok = require('../');
var test = require('tape');
var fs = require('fs');

test('compile with browserify', function(t) {
  var args = [
    'test/fixture/bundle.js'
  ];

  var exe = amok.compile('browserify', args);
  exe.stderr.on('data', function(data) {
    data = data.toString();
    t.fail(data);
  });

  exe.on('ready', function(scripts) {
    var filenames = Object.keys(scripts);
    t.equal(filenames.length, 1);

    var stats = fs.statSync(filenames[0]);
    t.ok(stats.size > 1);

    var pathnames = filenames.map(function(filename) {
      return scripts[filename];
    });

    t.equal(pathnames.length, 1);
    t.equal(pathnames[0], 'test/fixture/bundle.js');
  });

  exe.on('close', function(code, signal) {
    t.end();
  });
});

var amok = require('../');
var test = require('tape');
var fs = require('fs');

test('compile with browserify', function(t) {
  var args = [
    'test/fixture/bundle.js'
  ];

  var exe = amok.compile('browserify', args);
  exe.stderr.on('data', function(data) {
    data = data.toString();
    t.fail(data);
  });

  exe.on('ready', function(scripts) {
    var filenames = Object.keys(scripts);
    t.equal(filenames.length, 1);

    var stats = fs.statSync(filenames[0]);
    t.ok(stats.size > 1);

    var pathnames = filenames.map(function(filename) {
      return scripts[filename];
    });

    t.equal(pathnames.length, 1);
    t.equal(pathnames[0], 'test/fixture/bundle.js');

    exe.kill();
  });

  exe.on('close', function(code, signal) {
    t.end();
  });
});

Kill process to end browserify compile test


const editTextarea = {
  init() {
    // get all textarea elements with a maxlength attr
    const textAreaEls = document.querySelectorAll("textarea[data-max-length]");

    if (textAreaEls.length < 1) return;

    textAreaEls.forEach(el => {
      const limit = el.getAttribute("data-max-length");

      // create and insert counter element
      const counterEl = document.createElement("div");
      counterEl.innerText = `${el.innerHTML.length}/${limit}`;
      counterEl.className = "textarea-counter";
      el.insertAdjacentElement("afterend", counterEl);
      this.generateClass(counterEl, el.innerHTML.length, limit);

      // update count on every character change
      el.addEventListener("keyup", e => {
        const count = e.target.value.length;
        counterEl.innerText = `${count}/${limit}`;
        this.generateClass(counterEl, count, limit);
      });
    });
  },
  generateClass(counterEl, count, limit) {
    if (count > limit) {
      counterEl.classList.add("textarea-counter-over-limit");
    } else {
      counterEl.classList.remove("textarea-counter-over-limit");
    }
  }
};

export default editTextarea;

const editTextarea = {
  init() {
    // get all textarea elements with a maxlength attr
    const textAreaEls = document.querySelectorAll("textarea[data-max-length]");

    if (textAreaEls.length < 1) return;

    textAreaEls.forEach(el => {
      const limit = el.getAttribute("data-max-length");

      // create and insert counter element
      const counterEl = document.createElement("div");
      counterEl.innerText = `${el.innerHTML.length}/${limit}`;
      counterEl.className = "textarea-counter";
      el.insertAdjacentElement("afterend", counterEl);
      this.generateClass(counterEl, el.innerHTML.length, limit);

      // update count on every character change
      el.addEventListener("keyup", e => {
        const count = e.target.value.length;
        counterEl.innerText = `${count}/${limit}`;
        this.generateClass(counterEl, count, limit);
      });
    });
  },
  generateClass(counterEl, count, limit) {
    const textareaCounterClass = 'textarea-counter-over-limit';
    if (count > limit) {
      counterEl.classList.add(textareaCounterClass);
    } else {
      counterEl.classList.remove(textareaCounterClass);
    }
  }
};

export default editTextarea;

Put textarea counter class in variable


/*
 *  Test illustrating GH-1684 and GH-1726.
 *
 *  Run with debugger attached, and:
 *
 *  - StepOut from test1 and test2.
 *
 *  - StepOver the 'return' statement in test1 and test2.
 *
 *  - StepInto anotherFunction in test1 and test2.
 */

/*===
entered test1
entered anotherFunction
entered test2
entered anotherFunction
done
===*/

function anotherFunction() {
    var ret;
    print('entered anotherFunction');
    ret = 'foo' + 123;
    return ret;
}

function test1() {
    print('entered test1');
    return anotherFunction();
}

function test2() {
    var ret;

    print('entered test2');
    ret = anotherFunction();
    return ret;
}

try {
    test1();
    test2();
} catch (e) {
    print(e.stack || e);
}

print('done');

/*
 *  Test illustrating GH-1684, GH-1726, GH1786.
 */

/*===
entered test1
entered anotherFunction
entered test2
entered anotherFunction
===*/

/*
 *  Run with debugger attached, and:
 *
 *  - StepOut from test1 and test2.
 *
 *  - StepOver the 'return' statement in test1 and test2.
 *
 *  - StepInto anotherFunction in test1 and test2.
 */

function anotherFunction() {
    var ret;
    print('entered anotherFunction');
    ret = 'foo' + 123;
    return ret;
}

function test1() {
    print('entered test1');
    return anotherFunction();
}

function test2() {
    var ret;

    print('entered test2');
    ret = anotherFunction();
    return ret;
}

try {
    test1();
    test2();
} catch (e) {
    print(e.stack || e);
}

/*===
before bar
after bar
===*/

/*
 *  Nested case.  The tailcall in a nested call (not occurring in the
 *  function where stepping starts) shouldn't affect line pausing.
 */

function foo() {
    return 1;
}
function bar() {
    return foo();
}
function test() {
    print('before bar');
    bar();  // step over this
    print('after bar');
}

try {
    test();
} catch (e) {
    print(e.stack || e);
}

/*===
done
===*/

print('done');

Add nested tailcall to debugger step test


'use babel'

/* @flow */

export type Atom$Point = [number, number]
export type Atom$Range = [Atom$Point, Atom$Point] |
  {start: {row: number, column: number}, end: {row: number, column: number}}
export type Linter$Message = {
  key: string,
  type: string,
  text?: string,
  html?: string,
  name?: ?string,
  range?: Atom$Range,
  trace?: Array<Linter$Message>,
  severity: 'error' | 'warning' | 'info',
  filePath?: string
}
export type Linter$State = {}
export type Linter$Linter = {
  name?: string,
  number: number,
  deactivated: boolean,
  scope: 'file' | 'project',
}
export type Linter$Regular = Linter$Linter & {
  grammarScopes: Array<string>,
  lint: Function
}
export type Linter$Indie = Linter$Linter & {

}
export type Linter$Difference = {
  added: Array<Linter$Message>,
  removed: Array<Linter$Message>,
  messages: Array<Linter$Message>
}
export type Linter$UI = {
  name?: string,
  activate(): void,
  didCalculateMessages(difference: Linter$Difference): void,
  didBeginLinting(linter: Linter$Regular, filePath: ?string): void,
  didFinishLinting(linter: Linter$Regular, filePath: ?string): void,
  dispose(): void
}

'use babel'

/* @flow */

export type Atom$Point = [number, number]
export type Atom$Range = [Atom$Point, Atom$Point] |
  {start: {row: number, column: number}, end: {row: number, column: number}}
export type Linter$Message = {
  key: string,
  type: string,
  text?: string,
  html?: string,
  name?: ?string,
  range?: Atom$Range,
  trace?: Array<Linter$Message>,
  severity: 'error' | 'warning' | 'info',
  filePath?: string,
  selected?: ((message: Linter$Message) => void)
}
export type Linter$State = {}
export type Linter$Linter = {
  name?: string,
  number: number,
  deactivated: boolean,
  scope: 'file' | 'project',
}
export type Linter$Regular = Linter$Linter & {
  grammarScopes: Array<string>,
  lint: Function
}
export type Linter$Indie = Linter$Linter & {

}
export type Linter$Difference = {
  added: Array<Linter$Message>,
  removed: Array<Linter$Message>,
  messages: Array<Linter$Message>
}
export type Linter$UI = {
  name?: string,
  activate(): void,
  didCalculateMessages(difference: Linter$Difference): void,
  didBeginLinting(linter: Linter$Regular, filePath: ?string): void,
  didFinishLinting(linter: Linter$Regular, filePath: ?string): void,
  dispose(): void
}

Add selected attribute to message type


document.body.innerHTML = document.body.innerHTML.replace(new RegExp("(?!.*\")(0[xX][0-9a-fA-F]{40})(?!\")(!?<\s|\<|$)", "g"), `<a href="https://etherscan.io/address/$1" class="ext-etheraddresslookup-link">$1</a>$2`);

(function() {
    document.body.innerHTML = document.body.innerHTML.replace(
        new RegExp("(?!.*\")(0[xX][0-9a-fA-F]{40})(?!\")(!?<\s|\<|$)", "g"),
        `<a href="https://etherscan.io/address/$1" class="ext-etheraddresslookup-link">$1</a>$2`
    );
})();

Split logic on separate lines


var os = Npm.require('os');
var uvmon = Npm.require('nodefly-uvmon');

var SYSTEM_METRICS_FIELDS = ['testfield'];

SystemModel = function () {
  var self = this;
  this.lastGetData = new Date().getTime();
}

_.extend(SystemModel.prototype, ApmModel.prototype);

SystemModel.prototype.getEventLoopData = function() {
  var data = uvmon.getData();
  var time = new Date().getTime();
  data.time = time - this.lastGetData;
  this.lastGetData = time;
  return data;
};

SystemModel.prototype.buildPayload = function() {
  var metrics = {};
  var uvData = this.getEventLoopData();
  metrics.sessions = Meteor.default_server.sessions.length;
  metrics.rssBytes = process.memoryUsage().rss;
  metrics.loadAverage = os.loadavg()[0];
  metrics.eventLoopTime = uvData.sum_ms;
  metrics.eventLoopCount = uvData.count;
  metrics.totalTime = uvData.time;
  return {systemMetrics: metrics};
};

var os = Npm.require('os');
var uvmon = Npm.require('nodefly-uvmon');

var SYSTEM_METRICS_FIELDS = ['testfield'];

SystemModel = function () {
  var self = this;
  this.lastGetData = Date.now();
}

_.extend(SystemModel.prototype, ApmModel.prototype);

SystemModel.prototype.getEventLoopData = function() {
  var data = uvmon.getData();
  var time = Date.now();
  data.time = time - this.lastGetData;
  this.lastGetData = time;
  return data;
};

SystemModel.prototype.buildPayload = function() {
  var metrics = {};
  var uvData = this.getEventLoopData();
  metrics.startTime = Date.now();
  metrics.sessions = Meteor.default_server.sessions.length;
  metrics.rssBytes = process.memoryUsage().rss;
  metrics.loadAverage = os.loadavg()[0];
  metrics.eventLoopTime = uvData.sum_ms;
  metrics.eventLoopCount = uvData.count;
  metrics.totalTime = uvData.time;
  return {systemMetrics: metrics};
};

Use Date.now() and add startTime


import React from 'react';
import ReactDOM from 'react-dom';
import { expect } from 'chai';
import MarkupFrame from '../src';

function mount( component ) {
	const contentArea = window.document.querySelector( '#content' );
	ReactDOM.render( component, contentArea );
}

describe( '<MarkupFrame />', function() {
	it( 'renders an iframe', function() {
		mount( <MarkupFrame markup="" /> );
		const iframes = window.document.querySelectorAll( 'iframe' );
		expect( iframes ).to.have.length( 1 );
	} );

	it( 'injects props.markup into the iframe', function() {
		mount( <MarkupFrame markup="
Hello World
" /> );
		const iframe = window.document.querySelector( 'iframe' );
		expect( iframe.contentWindow.document.body.innerHTML ).to.eql( '
Hello World
' )
	} );

	it( 'calls props.onLoad with the iframe document', function( done ) {
		const onLoad = function( doc ) {
			doc.querySelector( 'h1' ).innerHTML = 'greetings';
			const iframe = window.document.querySelector( 'iframe' );
			expect( iframe.contentWindow.document.body.innerHTML ).to.eql( '
greetings
' );
			done();
		};
		mount( <MarkupFrame markup="
Hello World
" onLoad={ onLoad } /> );
	} );
} );

import React from 'react';
import ReactDOM from 'react-dom';
import { expect } from 'chai';
import MarkupFrame from '../src';

function mount( component ) {
	const contentArea = window.document.querySelector( '#content' );
	ReactDOM.render( component, contentArea );
}

describe( '<MarkupFrame />', function() {
	it( 'renders an iframe', function() {
		mount( <MarkupFrame markup="" /> );
		const iframes = window.document.querySelectorAll( 'iframe' );
		expect( iframes ).to.have.length( 1 );
	} );

	it( 'injects props.markup into the iframe', function() {
		mount( <MarkupFrame markup="
Hello World
" /> );
		const iframe = window.document.querySelector( 'iframe' );
		expect( iframe.contentWindow.document.body.innerHTML ).to.eql( '
Hello World
' )
	} );

	it.skip( 'calls props.onLoad with the iframe document', function( done ) {
		const onLoad = function( doc ) {
			doc.querySelector( 'h1' ).innerHTML = 'greetings';
			const iframe = window.document.querySelector( 'iframe' );
			expect( iframe.contentWindow.document.body.innerHTML ).to.eql( '
greetings
' );
			done();
		};
		mount( <MarkupFrame markup="
Hello World
" onLoad={ onLoad } /> );
	} );
} );

Add skip to failing test


#!/usr/bin/env node
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @noflow
 * @format
 */

'use strict';

var bin = require('./');
var spawn = require('child_process').spawn;

var input = process.argv.slice(2);

if (bin !== null) {
  spawn(bin, input, {stdio: 'inherit'}).on('exit', process.exit);
} else {
  throw new Error('Platform not supported.');
}

#!/usr/bin/env node
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @noflow
 * @format
 */

'use strict';

var bin = require('./');
var spawn = require('child_process').spawn;

var input = process.argv.slice(2);

if (bin !== null) {
  spawn(bin, input, {stdio: 'inherit'}).on('exit', process.exit);
} else {
  throw new Error(
    `Platform "${process.platform} (${process.arch})" not supported.`,
  );
}

Include platform and arch in the compiler error message


(function(angular, $, RepeaterUtilities) {

    'use strict';

    var module = angular.module('table.empty-table', []);
    module.directive('tableEmptyMessage', function($timeout, $log) {

        return {
            link: function(scope, el, attrs) {
                var msg = (attrs.tableEmptyMessage !== '') ? attrs.tableEmptyMessage : 'No items.';
                var tr = $('

' + msg + '

');
                var emptyToggleFn = function(val) {
                    if (!val || val.length === 0) {
                        tr.show();
                    } else {
                        tr.hide();
                    }
                };
                $timeout(function() {
                    var modelData = RepeaterUtilities.extractCollection(el);
                    if( modelData === undefined ) {
                        $log.warn("no model data found.");
                    }
                    var tbody = el.find("tbody");
                    var rowCount = tbody.find("tr").length;
                    tr.hide();
                    tbody.append(tr);
                    if( rowCount === 0 ) {
                        tr.show();
                    }
                    if( modelData ) {
                        scope.$watchCollection(modelData, emptyToggleFn);
                    }
                },0, false);
            }
        };
    });
})(angular, jQuery, RepeaterUtilities);

(function(angular, $, RepeaterUtilities) {

    'use strict';

    var module = angular.module('table.empty-table', []);
    module.directive('tableEmptyMessage', function($timeout, $log) {

        return {
            link: function(scope, el, attrs) {
                var msg = (attrs.tableEmptyMessage !== '') ? attrs.tableEmptyMessage : 'No items.';
                var tr = $('

' + msg + '

');
                var emptyToggleFn = function(val) {
                    if (!val || val.length === 0) {
                        tr.show();
                    } else {
                        tr.hide();
                    }
                };
                $timeout(function() {
                    var modelData = RepeaterUtilities.extractCollection(el);
                    if( modelData === undefined ) {
                        $log.warn("no model data found.");
                    }
                    var tbody = el.find("tbody");
                    var rowCount = tbody.find("tr").length;
                    tbody.append(tr);
                    if( rowCount > 0) {
                        tr.hide();
                    }
                    if( modelData ) {
                        scope.$watchCollection(modelData, emptyToggleFn);
                    }
                },0, false);
            }
        };
    });
})(angular, jQuery, RepeaterUtilities);

Fix empty table not showing up


const Sequelize = require('sequelize');

const Database = require('../postgreSQL');

const database = new Database();

let Money = database.db.define('money', {
	userID: Sequelize.STRING,
	money: {
		type: Sequelize.INTEGER,
		defaultValue: 0
	}
});

Money.sync();

module.exports = Money;

const Sequelize = require('sequelize');

const Database = require('../postgreSQL');

const database = new Database();

let Money = database.db.define('money', {
	userID: Sequelize.STRING,
	money: {
		type: Sequelize.INTEGER,
		defaultValue: 0
	}
});

Money.sync();

Money.find({ where: { userID: 'SLOTMACHINE' } }).then(slotmachine => {
	if (!slotmachine) {
		Money.create({
			userID: 'SLOTMACHINE',
			money: 10000
		});
	}
});

module.exports = Money;

Add db entry for slotmachine


/*
 * File to store and export reusable constant values
 */

/*
 * Teaser length is constrained to 156 characters so
 * that the teaser is not cut off by search engines
 */
export const MAX_TEASER_LENGTH = 156;

/*
 * File to store and export reusable constant values
 */

/*
 * Teaser length is constrained to 250 characters so
 * that the teaser is not cut off by search engines
 */
export const MAX_TEASER_LENGTH = 250;

Change max teaser length to 250


import { LitElement, html } from '@polymer/lit-element/lit-element.js'
import { repeat } from 'lit-html/directives/repeat.js'
import { shared } from '../../styles/shared.js'

/*
 * Show keyframes in a grid
 */
class KeyframeGrid extends LitElement {
  static get properties() {
    return { keyframes: { type: Object } }
  }

  _toArray(object) {
    const array = []

    for (const step in object) {
      array.push({
        step: parseFloat(step),
        value: object[step]
      })
    }

    array.sort((a, b) => a.step - b.step)

    return array
  }

  render() {
    const { keyframes } = this

    return html`
      ${shared}

        ${repeat(this._toArray(keyframes), keyframe => html`

${keyframe.step}: ${JSON.stringify(keyframe.value)}

        `)}

    `
  }

}

customElements.define('keyframe-grid', KeyframeGrid)

import { LitElement, html } from '@polymer/lit-element/lit-element.js'
import { repeat } from 'lit-html/directives/repeat.js'
import { shared } from '../../styles/shared.js'

/*
 * Show keyframes in a grid
 */
class KeyframeGrid extends LitElement {
  static get properties() {
    return { keyframes: { type: Object } }
  }

  _toArray(object) {
    const array = []

    for (const step in object) {
      array.push({
        step: parseFloat(step),
        value: object[step]
      })
    }

    array.sort((a, b) => a.step - b.step)

    return array
  }

  render() {
    const { keyframes } = this

    return html`
      ${shared}

        ${repeat(this._toArray(keyframes), keyframe => html`

${keyframe.step}: ${JSON.stringify(keyframe.value, null, '\t')}

        `)}

    `
  }

}

customElements.define('keyframe-grid', KeyframeGrid)

Make all keyframes visible via scroll


(function (angular) {
  'use strict';

  var StoredItem = function (storage, itemName, defaultValueFactory, log) {

    var value = defaultValueFactory();

    var storedValue = storage.getItem(itemName);
    if (_.isString(storedValue)) {
      try {
        _.merge(value, angular.fromJson(storedValue));
      } catch (e) {
        log.warn('Caught exception when loading filters from local storage item', itemName, ':', e);
      }
    }

    this.get = function () {
      return value;
    };

    this.save = function (newValue) {
      value = newValue;
      storage.setItem(itemName, angular.toJson(value));
    };

    this.reset = function () {
      value = defaultValueFactory();
      storage.removeItem(itemName);
    };

  };

  var BrowserObjectStorage = function (storage, log) {

    this.getItem = function (itemName, defaultValueFactory) {
      return new StoredItem(storage, itemName, defaultValueFactory, log);
    };

  };

  angular.module('zucchini-ui-frontend')
    .factory('BrowserSessionStorage', function ($window, $log) {
      return new BrowserObjectStorage($window.sessionStorage, $log);
    })
    .factory('BrowserLocalStorage', function ($window, $log) {
      return new BrowserObjectStorage($window.localStorage, $log);
    });

})(angular);

(function (angular) {
  'use strict';

  var StoredItem = function (storage, itemName, defaultValueFactory, log) {

    var value = defaultValueFactory();

    this.get = function () {
      return value;
    };

    this.save = function (newValue) {
      value = newValue;
      storage.setItem(itemName, angular.toJson(value));
    };

    this.reset = function () {
      value = defaultValueFactory();
      storage.removeItem(itemName);
    };

    var storedValue = storage.getItem(itemName);
    if (_.isString(storedValue)) {
      try {
        _.merge(value, angular.fromJson(storedValue));
      } catch (e) {
        log.warn('Caught exception when loading filters from local storage item', itemName, ':', e);
      }
    }
    this.save(value);

  };

  var BrowserObjectStorage = function (storage, log) {

    this.getItem = function (itemName, defaultValueFactory) {
      return new StoredItem(storage, itemName, defaultValueFactory, log);
    };

  };

  angular.module('zucchini-ui-frontend')
    .factory('BrowserSessionStorage', function ($window, $log) {
      return new BrowserObjectStorage($window.sessionStorage, $log);
    })
    .factory('BrowserLocalStorage', function ($window, $log) {
      return new BrowserObjectStorage($window.localStorage, $log);
    });

})(angular);

Save value in storage on init


import Ember from 'ember';

const FormControl = Ember.Component.extend({
  intl: Ember.inject.service(),

  showErrors: false,

  classNames: "form-field",

  classNameBindings: ['hasErrors:has-errors'],

  inputId: Ember.computed("elementId", {
    get() {
      return `${this.get("elementId")}-input`;
    }
  }),

  label: Ember.computed("data", "field", {
    get() {
      let modelName =
        this.get("data.content.constructor.modelName") ||
        this.get("data.constructor.modelName");

      if (!modelName) {
        return;
      }

      let fieldName = this.get("field");

      if (!fieldName) {
        return;
      }

      modelName = Ember.String.underscore(modelName);
      fieldName = Ember.String.underscore(fieldName);

      return this.get("intl").t(
        `models.attributes.${modelName}.${fieldName}`);
    }
  }),

  init() {
    this._super(...arguments);

    this.hasErrors = Ember.computed.notEmpty(
      `data.validations.attrs.${this.get('field')}.errors`);
  }
});

FormControl.reopenClass({
  positionalParams: ["field"]
});

export default FormControl;

import Ember from 'ember';

const FormControl = Ember.Component.extend({
  intl: Ember.inject.service(),
  classNames: "form-field",
  classNameBindings: ['hasErrors:has-errors', 'focused'],

  showErrors: false,

  focusIn() {
    this.set('focused', true);
  },

  focusOut() {
    this.set('focused', false);
  },

  inputId: Ember.computed("elementId", {
    get() {
      return `${this.get("elementId")}-input`;
    }
  }),

  label: Ember.computed("data", "field", {
    get() {
      let modelName =
        this.get("data.content.constructor.modelName") ||
        this.get("data.constructor.modelName");

      if (!modelName) {
        return;
      }

      let fieldName = this.get("field");

      if (!fieldName) {
        return;
      }

      modelName = Ember.String.underscore(modelName);
      fieldName = Ember.String.underscore(fieldName);

      return this.get("intl").t(
        `models.attributes.${modelName}.${fieldName}`);
    }
  }),

  init() {
    this._super(...arguments);

    this.hasErrors = Ember.computed.notEmpty(
      `data.validations.attrs.${this.get('field')}.errors`);
  }
});

FormControl.reopenClass({
  positionalParams: ["field"]
});

export default FormControl;

Add class when an input receives focus


/* eslint-env jasmine, mocha */

import helperFixture from './lib/fixture';

if (!document.registerElement && !window.customElements) {
  require('skatejs-web-components');
}

mocha.setup({ timeout: 10000 }); // eslint-disable-line no-undef

afterEach(() => {
  // Ensure perf tests have enough time to cleanup after themselves.
  mocha.timeout(120000); // eslint-disable-line no-undef
  helperFixture('');
});

/* eslint-env jasmine, mocha */

import helperFixture from './lib/fixture';

if (!window.customElements) {
  require('skatejs-web-components');
}

mocha.setup({ timeout: 10000 }); // eslint-disable-line no-undef

afterEach(() => {
  // Ensure perf tests have enough time to cleanup after themselves.
  mocha.timeout(120000); // eslint-disable-line no-undef
  helperFixture('');
});

Update tests so that it will polyfill v0 supported browsers up to v1.


/* See license.txt for terms of usage */

define([
    "firebug/lib/trace"
],
function(FBTrace) {

// ********************************************************************************************* //
// Constants

const Cc = Components.classes;
const Ci = Components.interfaces;

var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci["nsIConsoleService"]);

// ********************************************************************************************* //
// Module implementation

var Deprecated = {};
Deprecated.deprecated = function(msg, fnc)
{
    return function deprecationWrapper()
    {
        if (!this.nagged)
        {
            // drop frame with deprecated()
            var caller = Components.stack.caller;
            var explain = "Deprecated function, " + msg;

            if (typeof(FBTrace) !== undefined)
            {
                FBTrace.sysout(explain, getStackDump());

                //if (exc.stack)
                //    exc.stack = exc.stack.split("\n");

                FBTrace.sysout(explain + " " + caller.toString());
            }

            if (consoleService)
                consoleService.logStringMessage(explain + " " + caller.toString());

            this.nagged = true;
        }

        return fnc.apply(this, arguments);
    }
}

// ********************************************************************************************* //
// Local helpers

function getStackDump()
{
    var lines = [];
    for (var frame = Components.stack; frame; frame = frame.caller)
        lines.push(frame.filename + " (" + frame.lineNumber + ")");

    return lines.join("\n");
};

// ********************************************************************************************* //
// Registration

return Deprecated;

// ********************************************************************************************* //
});

/* See license.txt for terms of usage */

define([
    "firebug/lib/trace"
],
function(FBTrace) {

// ********************************************************************************************* //
// Constants

const Cc = Components.classes;
const Ci = Components.interfaces;

var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci["nsIConsoleService"]);

// ********************************************************************************************* //
// Module implementation

var Deprecated = {};
Deprecated.deprecated = function(msg, fnc, args)
{
    return function deprecationWrapper()
    {
        if (!this.nagged)
        {
            // drop frame with deprecated()
            var caller = Components.stack.caller;
            var explain = "Deprecated function, " + msg;

            if (typeof(FBTrace) !== undefined)
            {
                FBTrace.sysout(explain, getStackDump());

                //if (exc.stack)
                //    exc.stack = exc.stack.split("\n");

                FBTrace.sysout(explain + " " + caller.toString());
            }

            if (consoleService)
                consoleService.logStringMessage(explain + " " + caller.toString());

            this.nagged = true;
        }

        return fnc.apply(this, args || arguments);
    }
};

// ********************************************************************************************* //
// Local helpers

function getStackDump()
{
    var lines = [];
    for (var frame = Components.stack; frame; frame = frame.caller)
        lines.push(frame.filename + " (" + frame.lineNumber + ")");

    return lines.join("\n");
};

// ********************************************************************************************* //
// Registration

return Deprecated;

// ********************************************************************************************* //
});

Allow to specify arguments for new function


import { version as nodeVersion } from 'process'

import readPkgUp from 'read-pkg-up'

// Caches it.
// TODO: use async instead
const {
  package: { version: autoserverVersion },
} = readPkgUp.sync()

// Retrieve environment-specific versions
export const getVersionsInfo = function() {
  const autoserver = `v${autoserverVersion}`

  return { node: nodeVersion, autoserver }
}

import { version as nodeVersion } from 'process'

import readPkgUp from 'read-pkg-up'

// Caches it.
// TODO: use async instead
const {
  packageJson: { version: autoserverVersion },
} = readPkgUp.sync()

// Retrieve environment-specific versions
export const getVersionsInfo = function() {
  const autoserver = `v${autoserverVersion}`

  return { node: nodeVersion, autoserver }
}

Fix new read-pkg-up major release


import isNumber from './isNumber';

const lengths = [
    'em',
    'ex',
    'ch',
    'rem',
    'vh',
    'vw',
    'vmin',
    'vmax',
    'px',
    'mm',
    'cm',
    'in',
    'pt',
    'pc',
];

export default num => {
    let int = isNumber(num);
    return int && (int.number === '0' || ~lengths.indexOf(int.unit));
};

import isNumber from './isNumber';

const lengths = [
    'em',
    'ex',
    'ch',
    'rem',
    'vh',
    'vw',
    'vmin',
    'vmax',
    'px',
    'q',
    'mm',
    'cm',
    'in',
    'pt',
    'pc',
];

export default num => {
    let int = isNumber(num);
    return int && (int.number === '0' || ~lengths.indexOf(int.unit));
};

Add 'q' unit to length validator.


(function (GoL) {
  var CT = {
    Dead:  {},
    Alive: {}
  };

  function cellSymbolToObject(symbol) {
    switch (symbol) {
      case '.':
        return CT.Dead;
      case '*':
        return CT.Alive;
      default:
        throw new Error('Invalid argument: unknown cell symbol in zero generation: ' + symbol);
    }
  }

  GoL.Support = {
      CellTypes: CT
    , parseCanvas: function (canvas) {
        if (!canvas || !canvas[0] || !canvas[0].getContext) {
          throw new Error("Invalid argument: not a canvas element");
        }
        return canvas[0];
      }
    , parseCellGrid: function (layout) {
        var rows = layout.trim().split("\n")
          , grid
          , gridWidth
          , gridIsSquare;

        if (rows.length < 1) {
          throw new Error("Invalid argument: cell grid is too small");
        }

        grid = _.map(rows, function (row) { return _.map(row.split(''), cellSymbolToObject) });
        gridWidth = grid.length;
        gridIsSquare = _.all(grid, function (row) { return row.length === gridWidth });

        if (!gridIsSquare) {
          throw new Error('Invalid argument: cell grid is not a square');
        }

        return grid;
      }
  };
})(GameOfLife);

(function (GoL) {
  var CT = { Dead: {}, Alive: {} };

  function InvalidArgument(message) {
    this.prototype  = Error.prototype;
    this.name       = 'InvalidArgument';
    this.message    = message;
    this.toString   = function () {
      return this.name + ': ' + this.message;
    };
  };

  function cellSymbolToObject(symbol) {
    switch (symbol) {
      case '.':
        return CT.Dead;
      case '*':
        return CT.Alive;
      default:
        throw new InvalidArgument('Unknown cell symbol in zero generation: ' + symbol);
    }
  }

  GoL.Support = {
      CellTypes: CT
    , parseCanvas: function (canvas) {
        if (!canvas || !canvas[0] || !canvas[0].getContext) {
          throw new InvalidArgument("Not a canvas element");
        }
        return canvas[0];
      }
    , parseCellGrid: function (layout) {
        var rows = layout.trim().split("\n")
          , grid
          , gridWidth
          , gridIsSquare;

        if (rows.length < 1) {
          throw new InvalidArgument('Cell grid is too small');
        }

        grid = _.map(rows, function (row) { return _.map(row.split(''), cellSymbolToObject) });
        gridWidth = grid.length;
        gridIsSquare = _.all(grid, function (row) { return row.length === gridWidth });

        if (!gridIsSquare) {
          throw new InvalidArgument('Cell grid is not a square');
        }

        return grid;
      }
  };
})(GameOfLife);

Add our own error class for invalid arguments


var path = require('path');
var batch = require('gulp-batch');

module.exports = init;

function init(options){
  options = defaultOptions(options);

  registerTask(options);
}

function defaultOptions(options){
  options = options || {};
  options.gulp = options.gulp || require('gulp');
  options.task = options.task || 'watch';
  options.dependencies = options.dependencies || ['default'];
  options.watch = options.watch || [];
  options.batch = options.batch || {};
  options.log = options.log || true;
  options.start = options.start || 'default';

  return options;
}

function registerTask(options){
  var gulp = options.gulp;

  gulp.task(options.task, options.dependencies, function(){
    gulp.watch(options.watch, batch(options.batch, function(events, done){
      events
        .on('data', function(data){
          if(options.log){
            console.log(data.type, path.basename(data.path));
          }
        })
        .on('end', function(){
          gulp.start(options.start, done);
        });
    }));
  });
}

var path = require('path');
var batch = require('gulp-batch');

module.exports = init;

function init(options){
  options = defaultOptions(options);

  registerTask(options);
}

function defaultOptions(options){
  options = options || {};
  options.gulp = options.gulp || require('gulp');
  options.task = options.task || 'watch';
  options.dependencies = options.dependencies || ['default'];
  options.watch = options.watch || [];
  options.batch = options.batch || {};
  options.log = (typeof options.log !== 'undefined') ? options.log : true;
  options.start = options.start || 'default';

  return options;
}

function registerTask(options){
  var gulp = options.gulp;

  gulp.task(options.task, options.dependencies, function(){
    gulp.watch(options.watch, batch(options.batch, function(events, done){
      events
        .on('data', function(data){
          if(options.log){
            console.log(data.type, path.basename(data.path));
          }
        })
        .on('end', function(){
          gulp.start(options.start, done);
        });
    }));
  });
}

Fix log option with ternary operator


module.exports = function(
  $stateProvider,
  $urlRouterProvider,
  $urlMatcherFactoryProvider
) {
  // Disable ui-router strict mode
  $urlMatcherFactoryProvider.strictMode(false);

  // Render 404 when no routes are matched
  $urlRouterProvider.otherwise('/404');

  $stateProvider
    .state('root', {
      abstract: true,
      templateUrl: 'app/templates/default.html',
      resolve: {
        loadEndpoints: function ($rootScope, API, $q) {
          $rootScope.apiLoaded = false;
          var deferred = $q.defer();
          var gapiInterval = window.setInterval(function() {
            if ($rootScope.apiLoaded) {
              window.clearInterval(gapiInterval);
              return;
            }

            gapi.client.load(API.NAME, API.VERSION, function (data) {
              $rootScope.apiLoaded = true;
              deferred.resolve();
            }, API.URL);
          }, 200);

          return deferred.promise;
        }
      }
    })
    .state('404', {
      url: '/404',
      templateUrl: 'app/templates/404.html'
    });
};

module.exports = function(
  $stateProvider,
  $urlRouterProvider,
  $urlMatcherFactoryProvider
) {
  // Disable ui-router strict mode
  $urlMatcherFactoryProvider.strictMode(false);

  // Render 404 when no routes are matched
  $urlRouterProvider.otherwise('/404');

  $stateProvider
    .state('root', {
      abstract: true,
      templateUrl: 'app/templates/default.html',
      resolve: {
        loadEndpoints: function ($rootScope, API, $q) {
          $rootScope.apiLoaded = false;
          var deferred = $q.defer();
          var gapiInterval = window.setInterval(function() {
            if ($rootScope.apiLoaded) {
              window.clearInterval(gapiInterval);
              return;
            }

            gapi.client.load(API.NAME, API.VERSION, function (data) {
              $rootScope.apiLoaded = true;
              deferred.resolve();
            }, API.URL);
          }, 200);

          return deferred.promise;
        }
      }
    })
    .state('404', {
      url: '/404',
      controller : function (AppService) {
        AppService.setPageTitle('Página não encontrada');
      },
      templateUrl: 'app/templates/404.html'
    });
};

Add page title to error page


/**
 * Collect all cloned nodes, including the original node.
 *
 * @method  collectInclClones
 * @author  Fritz Lekschas
 * @date    2015-12-30
 * @param   {Object}  node  Start node
 * @return  {Array}         Array of original and cloned nodes.
 */
export function collectInclClones (node) {
  let originalNode = node;

  if (node.clone) {
    originalNode = node.originalNode;
  }

  let clones = [originalNode];

  if (originalNode.clones.length) {
    clones = clones.concat(originalNode.clones);
  }

  return clones;
}

/**
 * Collect all cloned nodes, including the original node.
 *
 * @method  collectInclClones
 * @author  Fritz Lekschas
 * @date    2016-03-20
 * @param   {Object}   node                 Start node
 * @param   {Boolean}  onlyForOriginalNode  If `true` only collect clones when
 *   `node` is not a clone itself.
 * @return  {Array}                         Array of original and cloned nodes.
 */
export function collectInclClones (node, onlyForOriginalNode) {
  let originalNode = node;

  if (node.clone) {
    originalNode = node.originalNode;
    if (onlyForOriginalNode) {
      return [];
    }
  }

  let clones = [originalNode];

  if (originalNode.clones.length) {
    clones = clones.concat(originalNode.clones);
  }

  return clones;
}

Add an option to only include clones when the original node is hovered. This is useful when traversing down the graph because clones don't display children.


'use strict';

var <%= safeSlugname %> = require('../lib/<%= slugname %>.js');

/*
  ======== 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.<%= safeSlugname %> = {
  setUp: function(done) {
    // setup here
    done();
  },
  'no args': function(test) {
    test.expect(1);
    // tests here
    test.equal(<%= safeSlugname %>.awesome(), 'awesome', 'should be awesome.');
    test.done();
  }
};

'use strict';

var <%= safeSlugname %> = require('../index.js');

/*
  ======== 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.<%= safeSlugname %> = {
  setUp: function(done) {
    // setup here
    done();
  },
  'no args': function(test) {
    test.expect(1);
    // tests here
    test.equal(<%= safeSlugname %>.awesome(), 'awesome', 'should be awesome.');
    test.done();
  }
};

Change location of test file


(function (window) {
    "use strict";

    var JSON_ = {};

    function snakeToCamelCase(key) {
        // first_name -> firstName
        return key.replace(/(_+[a-z])/g, function (snip) {
            return snip.toUpperCase().replace("_", "");
        });
    }

    function camelToSnakeCase(key) {
        // firstName -> first_name
        return key.replace(/([A-Z])/g, function (snip) {
            return "_" + snip.toLowerCase();
        });
    }

    JSON_.parse = function parse(text, reviver) {
        text = text.replace(/"([^"]*)"\s*:/g, snakeToCamelCase);
        return JSON.parse(text, reviver);
    };

    JSON_.stringify = function stringify(value, replacer, space) {
        var str = JSON.stringify(value, replacer, space);
        return str.replace(/"([^"]*)"\s*:/g, camelToSnakeCase);
    };

    // Export to popular environments boilerplate.
    if (typeof define === "function" && define.amd) {
        define(JSON_);
    } else if (typeof module !== "undefined" && module.exports) {
        module.exports = JSON_;
    } else {
        window["JSON_"] = JSON_;
    }
}(window));

/* jshint unused:vars, sub:true */
/* global window, define, module */
(function () {
    "use strict";

    var JSON_ = {};

    function snakeToCamelCase(key) {
        // first_name -> firstName
        return key.replace(/(_+[a-z])/g, function (snip) {
            return snip.toUpperCase().replace("_", "");
        });
    }

    function camelToSnakeCase(key) {
        // firstName -> first_name
        return key.replace(/([A-Z])/g, function (snip) {
            return "_" + snip.toLowerCase();
        });
    }

    JSON_.parse = function parse(text, reviver) {
        text = text.replace(/"([^"]*)"\s*:/g, snakeToCamelCase);
        return JSON.parse(text, reviver);
    };

    JSON_.stringify = function stringify(value, replacer, space) {
        var str = JSON.stringify(value, replacer, space);
        return str.replace(/"([^"]*)"\s*:/g, camelToSnakeCase);
    };

    // Export to popular environments boilerplate.
    if (typeof define === "function" && define.amd) {
        define(JSON_);
    } else if (typeof module !== "undefined" && module.exports) {
        module.exports = JSON_;
    } else {
        window["JSON_"] = JSON_;
    }
}());

Clean up and better jshint support.


CKEDITOR.editorConfig = function( config )
{
    config.toolbar_Silki =
        [ [ "Bold", "Italic" ],
          [ "H2", "H3", "H4", "-", "Pre" ],
          [ "NumberedList", "BulletedList", "-", "Outdent", "Indent", "Blockquote" ],
          [ "Link", "Unlink", "Anchor" ],
          [ "Image", "Table", "HorizontalRule", "SpecialChar" ],
          [ "Undo", "Redo", "Maximize" ] ];

    config.toolbar = "Silki";

    config.skin = "Silki";

    config.linkShowTargetTab = false;
    config.linkShowAdvancedTab = false;
};

CKEDITOR.editorConfig = function( config )
{
    config.toolbar_Silki =
        [ [ "Bold", "Italic" ],
          [ "H2", "H3", "H4", "-", "Pre" ],
          [ "NumberedList", "BulletedList", "-", "Outdent", "Indent", "Blockquote" ],
          [ "Link", "Unlink" ],
          [ "Image", "Table", "HorizontalRule", "SpecialChar" ],
          [ "Undo", "Redo", "Maximize" ] ];

    config.toolbar = "Silki";

    config.skin = "Silki";

    config.linkShowTargetTab = false;
    config.linkShowAdvancedTab = false;
};

Remove Anchor from ckeditor tab for now


/* global window */
import ApolloClient from 'apollo-client';
import { withClientState } from 'apollo-link-state';
import { from } from 'apollo-link';
import getGraphqlFragments from './getGraphqlFragments';
import buildNetworkComponents from './buildNetworkComponents';
import buildCache from './buildCache';
import Config from 'lib/Config';

const buildClient = async (baseUrl) => {
    const graphQLConfig = Config.getSection('SilverStripe\\Admin\\LeftAndMain').graphql;
    const cachedTypenames = graphQLConfig && graphQLConfig.cachedTypenames;
    let fragmentData;
    try {
      fragmentData = await getGraphqlFragments(baseUrl, cachedTypenames);
    } catch (e) {
        fragmentData = null;
    }
    const cache = buildCache(fragmentData);
    const components = buildNetworkComponents(baseUrl);
    const stateLink = withClientState({
      cache,
      resolvers: {}
    });
    const link = from([stateLink, ...components]);
    return new ApolloClient({ cache, link });
};

export default buildClient;

/* global window */
import ApolloClient from 'apollo-client';
import { withClientState } from 'apollo-link-state';
import { from } from 'apollo-link';
import getGraphqlFragments from './getGraphqlFragments';
import buildNetworkComponents from './buildNetworkComponents';
import buildCache from './buildCache';
import Config from 'lib/Config';

const buildClient = async (baseUrl) => {
    const graphQLConfig = Config.getSection('SilverStripe\\Admin\\LeftAndMain').graphql;
    const cachedTypenames = graphQLConfig && graphQLConfig.cachedTypenames;
    let fragmentData;
    // GraphQL may not return what we want (e.g. if schema is empty, so fail gracefully)
    try {
      fragmentData = await getGraphqlFragments(baseUrl, cachedTypenames);
    } catch (e) {
        fragmentData = null;
    }
    const cache = buildCache(fragmentData);
    const components = buildNetworkComponents(baseUrl);
    const stateLink = withClientState({
      cache,
      resolvers: {}
    });
    const link = from([stateLink, ...components]);
    return new ApolloClient({ cache, link });
};

export default buildClient;

Add comment for graphql fragment


// this xhr patch may move to {N} core some day and can be removed
require("xhr");

var xhrAddEventListenerOrig = XMLHttpRequest.prototype.addEventListener;
XMLHttpRequest.prototype.addEventListener = function(eventName, callback) {
  if (eventName === "readystatechange") {
    this.onreadystatechange = callback;
  } else if (eventName === "progress") {
    this.onprogress = callback;
  } else if (eventName === "timeout") {
    this.ontimeout = callback;
  } else {
    xhrAddEventListenerOrig.call(this, eventName, callback);
  }
};
if (!XMLHttpRequest.prototype.upload) {
  XMLHttpRequest.prototype['upload'] = {
    addEventListener: function() {}
  };
}

// a few global properties node modules may rely on
global.process = require("process/browser");
global.Buffer = require("buffer").Buffer;

// this xhr patch may move to {N} core some day and can be removed
require("xhr");

var xhrAddEventListenerOrig = XMLHttpRequest.prototype.addEventListener;
XMLHttpRequest.prototype.addEventListener = function(eventName, callback) {
  if (eventName === "readystatechange") {
    this.onreadystatechange = callback;
  } else if (eventName === "progress") {
    this.onprogress = callback;
  } else if (eventName === "abort") {
    this.abort = callback;
  } else if (eventName === "timeout") {
    this.ontimeout = callback;
  } else {
    xhrAddEventListenerOrig.call(this, eventName, callback);
  }
};
if (!XMLHttpRequest.prototype.upload) {
  XMLHttpRequest.prototype['upload'] = {
    addEventListener: function() {}
  };
}

// a few global properties node modules may rely on
global.process = require("process/browser");
global.Buffer = require("buffer").Buffer;

Support the xhr abort event


/**
 * 24.05.2017
 * TCP Chat using NodeJS
 * https://github.com/PatrikValkovic/TCPChat
 * Created by patri
 */
'use strict'

let counter = 0

/**
 * Represent connected client
 * @type {Client}
 */
module.exports = class Client {
    constructor(socket) {
        this.socket = socket
        this.name = 'anonymous'
        this.connected = true
        this.id = counter++
        this.groups = {}
    }

    /**
     * Disconnect client from server
     */
    disconnect() {
        this.connected = false
        this.socket.destroy()
    }

    /**
     * Check, if is user in specific group
     * @param {string} name Name of group to check
     * @returns {boolean} True if is user in group, false otherwise
     */
    isInGroup(name) {
        return this.groups.hasOwnProperty(name)
    }
}

/**
 * 24.05.2017
 * TCP Chat using NodeJS
 * https://github.com/PatrikValkovic/TCPChat
 * Created by patri
 */
'use strict'

let counter = 0

/**
 * Represent connected client
 * @type {Client}
 */
module.exports = class Client {
    constructor(socket) {
        this.socket = socket
        this.name = 'anonymous'
        this.id = counter++
        this.groups = {}
    }

    /**
     * Disconnect client from server
     */
    disconnect() {
        this.socket.destroy()
    }

    /**
     * Check, if is user in specific group
     * @param {string} name Name of group to check
     * @returns {boolean} True if is user in group, false otherwise
     */
    isInGroup(name) {
        return this.groups.hasOwnProperty(name)
    }
}

Remove connected prooperty from client


var parser = require('./parser');
var Interpreter = require('./interpreter');

function TileAction(tile, tileX, tileY, key, data, renderer, callback) {
  this.tile = tile;
  this.key = key;
  this.data = data;
  this.tileX = tileX;
  this.tileY = tileY;
  this.renderer = renderer;
  this.callback = callback;
}

TileAction.prototype.exec = function() {
  this.before = this.tile[this.key];
  this.tile[this.key] = this.data;
  this.update();
}

TileAction.prototype.undo = function() {
  this.tile[this.key] = this.before;
  this.update();
}

TileAction.prototype.update = function() {
  // Fill the data with 0 if it's required and null.
  if(Interpreter.CommandMap[this.tile.command].argument &&
    this.tile.data == null) {
    this.tile.data = 0;
  }
  this.tile.original = parser.encodeSyllable(this.tile);
  this.renderer.map.set(this.tileX, this.tileY, this.tile);
  this.renderer.updateTile(this.tileX, this.tileY);
  if(this.callback) this.callback();
}

module.exports = TileAction;

var parser = require('./parser');
var Interpreter = require('./interpreter');

function TileAction(tile, tileX, tileY, key, data, renderer, callback) {
  this.tile = tile;
  this.key = key;
  this.data = data;
  this.tileX = tileX;
  this.tileY = tileY;
  this.renderer = renderer;
  this.callback = callback;
}

TileAction.prototype.exec = function() {
  this.before = this.tile[this.key];
  this.tile[this.key] = this.data;
  this.update();
}

TileAction.prototype.undo = function() {
  this.tile[this.key] = this.before;
  this.update();
}

TileAction.prototype.update = function() {
  // Fill the data with 0 if it's required and null.
  var command = Interpreter.CommandMap[this.tile.command];
  if(command != null && command.argument && this.tile.data == null) {
    this.tile.data = 0;
  }
  this.tile.original = parser.encodeSyllable(this.tile);
  this.renderer.map.set(this.tileX, this.tileY, this.tile);
  this.renderer.updateTile(this.tileX, this.tileY);
  if(this.callback) this.callback();
}

module.exports = TileAction;

Fix not being able to edit commandless tile


var assert = require('assert');
var fs = require('fs');
var should = require('should');

var ResultsPage = require('./../../lib/results-page');
var Plugin = require('./../../lib/plugin');

var allResultsPages = [],
    allPlugins = [];

before(function readPluginFile() {
    fs.readFile(__dirname + '/../data/results-page.html', 'utf8', function (err, data) {
        if (err) {
            return console.log(err);
        }
        var resultsPage = new ResultsPage(data);
        allResultsPages = resultsPage.getAllResultsPages();
        allPlugins = resultsPage.getAllPlugins();
    });
});

describe('ResultsPage', function() {
    describe('#getAllResultsPages()', function() {
        it('should return an array of ResultsPage\'s', function() {
            for (var i = 1; i <= 614; i++) {
               allResultsPages.should.containEql('https://wordpress.org/plugins/search/forms/page/' + i.toString());
            }
        });
    });
    describe('#getAllPlugins()', function() {
        it('should return an array of Plugins', function() {
            allPlugins.forEach(function(plugin) {
               plugin.should.be.an.instanceOf(Plugin);
            });
        });
    });
});

var assert = require('assert');
var fs = require('fs');
var should = require('should');

var ResultsPage = require('./../../lib/results-page');
var Plugin = require('./../../lib/plugin');

var allResultsPages = [],
    allPlugins = [];

before(function readPluginFile() {
    fs.readFile(__dirname + '/../data/results-page.html', 'utf8', function (err, data) {
        if (err) {
            return console.log(err);
        }
        var resultsPage = new ResultsPage(data);
        allResultsPages = resultsPage.getAllResultsPages();
        allPlugins = resultsPage.getAllPlugins();
    });
});

describe('ResultsPage', function() {
    describe('#getAllResultsPages()', function() {
        it('should return an array of ResultsPage\'s', function() {
            for (var i = 1; i <= 614; i++) {
               allResultsPages.should.containEql('https://wordpress.org/plugins/search/forms/page/' + i.toString() + '?');
            }
        });
    });
    describe('#getAllPlugins()', function() {
        it('should return an array of Plugins', function() {
            allPlugins.forEach(function(plugin) {
               plugin.should.be.an.instanceOf(Plugin);
            });
        });
    });
});

Add question mark to query path.


'use strict';

var isnan = require( './../lib' );

console.log( isnan( NaN ) );
// returns true

console.log( isnan( new Number( NaN ) ) );
// returns true

console.log( isnan( 5 ) );
// returns false

console.log( isnan( '5' ) );
// returns false

console.log( isnan( null ) );
// returns false

console.log( isnan( Symbol( 'NaN' ) ) );
// returns false

'use strict';

var hasSymbolSupport = require( '@stdlib/utils/detect-symbol-support' )();
var isnan = require( './../lib' );

console.log( isnan( NaN ) );
// returns true

console.log( isnan( new Number( NaN ) ) );
// returns true

console.log( isnan( 5 ) );
// returns false

console.log( isnan( '5' ) );
// returns false

console.log( isnan( null ) );
// returns false

if ( hasSymbolSupport ) {
	console.log( isnan( Symbol( 'NaN' ) ) );
	// returns false
}

Use utility to detect Symbol support


var keystone = require('keystone'),
	Types = keystone.Field.Types;

// Create model. Additional options allow menu name to be used what auto-generating URLs
var Disabilities = new keystone.List('Disabilities', {
	autokey: { path: 'key', from: 'disability', unique: true },
	map: { name: 'disability' }
});

// Create fields
Disabilities.add({
	disability: { type: String, label: 'Disability', required: true, index: true, initial: true }
});

// Define default columns in the admin interface and register the model
Disabilities.defaultColumns = 'disability';
Disabilities.register();

var keystone = require('keystone'),
	Types = keystone.Field.Types;

// Create model. Additional options allow menu name to be used what auto-generating URLs
var Disability = new keystone.List('Disability', {
	autokey: { path: 'key', from: 'disability', unique: true },
	map: { name: 'disability' }
});

// Create fields
Disability.add({
	disability: { type: String, label: 'Disability', required: true, index: true, initial: true }
});

// Define default columns in the admin interface and register the model
Disability.defaultColumns = 'disability';
Disability.register();

Add Reference list model for Disabilities.


module.exports = {
  entry: ['./app/main.jsx'],
  output: {
    path: './build',
    filename: 'bundle.js',
    pathinfo: true
  },
  module: {
    loaders: [
      {
        test: /\.jsx$/,
        exclude: /node_modules/,
        loader: 'babel'
      },
      {
        test: /\.scss$/,
        exclude: /node_modules/,
        loader: 'style!css!sass'
      },
      {
        test: /\.svg$/,
        loader: 'file-loader'
      }
    ]
  },
  devtool: 'source-map',
  devServer: {
    contentBase: './build',
    hot: true,
    progress: true,
    colors: true,
  }
};

module.exports = {
  entry: ['./app/main.jsx'],
  output: {
    path: './build',
    filename: 'bundle.js',
    pathinfo: true
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel'
      },
      {
        test: /\.scss$/,
        exclude: /node_modules/,
        loader: 'style!css!sass'
      },
      {
        test: /\.svg$/,
        loader: 'file-loader'
      }
    ]
  },
  devtool: 'source-map',
  devServer: {
    contentBase: './build',
    hot: true,
    progress: true,
    colors: true,
  }
};

Convert .js files with babel


/*
* Used to generate a list of roles that are both lower than the bot's role, and subscribed to feeds
* Returns the feed source and the role list
*/

module.exports = (guild, rssList) => {
  let finalList = []
  const botRole = guild.members.get(guild.client.user.id).highestRole
  for (var rssName in rssList) {
    let subscribersFound = []
    const keys = ['globalSubscriptions', 'filteredSubscriptions']
    const source = rssList[rssName]
    for (const key of keys) {
      const subscriptions = source[key]
      if (!Array.isArray(subscriptions) || subscriptions.length === 0) continue
      for (const subscriber of subscriptions) {
        if (subscriber.type === 'role') {
          const role = guild.roles.get(subscriber.id)
          if (role.comparePositionTo(botRole) < 0) subscribersFound.push(role.id)
        }
      }
    }

    if (subscribersFound.length !== 0) finalList.push({ source: rssList[rssName], roleList: subscribersFound })
  }

  if (finalList.length === 0) return null
  return finalList
}

/*
* Used to generate a list of roles that are both lower than the bot's role, and subscribed to feeds
* Returns the feed source and the role list
*/

module.exports = (guild, rssList) => {
  let finalList = []
  const botRole = guild.members.get(guild.client.user.id).highestRole
  for (var rssName in rssList) {
    let subscribersFound = []
    const source = rssList[rssName]
    const subscribers = source.subscribers
    if (!Array.isArray(subscribers) || subscribers.length === 0) continue
    for (const subscriber of subscribers) {
      if (subscriber.type === 'role') {
        const role = guild.roles.get(subscriber.id)
        if (role.comparePositionTo(botRole) < 0) subscribersFound.push(role.id)
      }
    }

    if (subscribersFound.length !== 0) finalList.push({ source: rssList[rssName], roleList: subscribersFound })
  }

  if (finalList.length === 0) return null
  return finalList
}

Fix subme/unsubme not seeing subscriptions