module.exports = function (grunt) {
  grunt.initConfig({
    uglify: {
      main: {
        options: {
          preserveComments: 'some'
        },
        files: {
          'dist/ng-stomp.min.js': ['src/ng-stomp.js'],
          'dist/ng-stomp.standalone.min.js': [
            'bower_components/sockjs/sockjs.min.js',
            'bower_components/stomp-websocket/lib/stomp.min.js',
            'src/ng-stomp.js'
          ]
        }
      }
    },
    standard: {
      options: {
        format: true
      },
      app: {
        src: ['ng-stomp.js']
      }
    }
  })

  grunt.loadNpmTasks('grunt-contrib-uglify')
  grunt.loadNpmTasks('grunt-standard')
  grunt.registerTask('default', ['standard', 'uglify'])
}

module.exports = function (grunt) {
  grunt.initConfig({
    uglify: {
      main: {
        options: {
          preserveComments: 'some'
        },
        files: {
          'dist/ng-stomp.min.js': ['src/ng-stomp.js'],
          'dist/ng-stomp.standalone.min.js': [
            'bower_components/sockjs-client/dist/sockjs.min.js',
            'bower_components/stomp-websocket/lib/stomp.min.js',
            'src/ng-stomp.js'
          ]
        }
      }
    },
    standard: {
      options: {
        format: true
      },
      app: {
        src: ['ng-stomp.js']
      }
    }
  })

  grunt.loadNpmTasks('grunt-contrib-uglify')
  grunt.loadNpmTasks('grunt-standard')
  grunt.registerTask('default', ['standard', 'uglify'])
}

Update sockjs-client path for 1.X


/*!
 * Bootstrap's Gruntfile
 * https://getbootstrap.com
 * Copyright 2013-2017 The Bootstrap Authors
 * Copyright 2013-2017 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 */

module.exports = function (grunt) {
  'use strict'

  // Project configuration.
  grunt.initConfig({
    'saucelabs-qunit': {
      all: {
        options: {
          build: process.env.TRAVIS_JOB_ID,
          concurrency: 10,
          maxRetries: 3,
          maxPollRetries: 4,
          urls: ['http://127.0.0.1:3000/js/tests/index.html?hidepassed'],
          browsers: grunt.file.readYAML('build/sauce_browsers.yml')
        }
      }
    }
  })

  grunt.loadNpmTasks('grunt-saucelabs')
}

/*!
 * Bootstrap's Gruntfile
 * https://getbootstrap.com
 * Copyright 2013-2017 The Bootstrap Authors
 * Copyright 2013-2017 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 */

module.exports = function (grunt) {
  'use strict'

  // Project configuration.
  grunt.initConfig({
    'saucelabs-qunit': {
      all: {
        options: {
          build: process.env.TRAVIS_JOB_ID,
          concurrency: 10,
          maxRetries: 3,
          maxPollRetries: 4,
          urls: ['http://localhost:3000/js/tests/index.html?hidepassed'],
          browsers: grunt.file.readYAML('build/sauce_browsers.yml')
        }
      }
    }
  })

  grunt.loadNpmTasks('grunt-saucelabs')
}

Use localhost because Win Edge block loopback access


module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    copy: {
      main: {
        src: 'src/index.js',
        dest: 'dist/<%= pkg.name %>.js',
      },
    },
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n',
        report: 'gzip'
      },
      dist: {
        files: {
          'dist/<%= pkg.name %>.min.js': ['dist/<%= pkg.name %>.js'],
        }
      }
    },
    mochaTest: {
      test: {
        options: {
          reporter: 'spec'
        },
        src: ['test/**/*.js']
      }
    },
    jshint: {
      files: ['src/**/*.js', 'test/**/*.js']
    },
    watch: {
      files: ['<%= jshint.files %>'],
      tasks: ['jshint', 'mochaTest']
    }
  });

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

  grunt.registerTask('test', ['jshint', 'mochaTest']);

  grunt.registerTask('default', ['jshint', 'mochaTest', 'copy', 'uglify']);

};

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    copy: {
      main: {
        src: 'src/index.js',
        dest: 'dist/<%= pkg.name %>.js',
      },
    },
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= pkg.version %> */\n',
        report: 'gzip'
      },
      dist: {
        files: {
          'dist/<%= pkg.name %>.min.js': ['dist/<%= pkg.name %>.js'],
        }
      }
    },
    mochaTest: {
      test: {
        options: {
          reporter: 'spec'
        },
        src: ['test/**/*.js']
      }
    },
    jshint: {
      files: ['src/**/*.js', 'test/**/*.js']
    },
    watch: {
      files: ['<%= jshint.files %>'],
      tasks: ['jshint', 'mochaTest']
    }
  });

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

  grunt.registerTask('test', ['jshint', 'mochaTest']);

  grunt.registerTask('default', ['jshint', 'mochaTest', 'copy', 'uglify']);

};

Use pkg.version instead of build date


require('js-yaml');
var path = require('path');

module.exports = function (grunt) {
  grunt.loadNpmTasks('grunt-contrib-jst');
  grunt.loadNpmTasks('grunt-mocha-test');
  grunt.loadNpmTasks('grunt-karma');

  grunt.initConfig({
    paths: require('js_paths.yml'),
    mochaTest: {
      jsbox_apps: {
        src: ['<%= paths.tests.jsbox_apps.spec %>'],
      }
    },
    jst: {
      options: {
        processName: function(filename) {
          var dir = path.dirname(filename);
          dir = path.relative('go/base/static/templates', dir);

          var parts = dir.split('/');
          parts.push(path.basename(filename, '.jst'));

          // process the template names the arb Django Pipelines way
          return parts.join('_');
        }
      },
      templates: {
        files: {
          "<%= paths.client.templates.dest %>": [
            "<%= paths.client.templates.src %>"
          ]
        }
      },
    },
    karma: {
      dev: {
        singleRun: true,
        reporters: ['dots'],
        configFile: 'karma.conf.js'
      }
    }
  });

  grunt.registerTask('test:jsbox_apps', [
    'mochaTest:jsbox_apps'
  ]);

  grunt.registerTask('test:client', [
    'jst:templates',
    'karma:dev'
  ]);

  grunt.registerTask('test', [
    'test:jsbox_apps',
    'test:client'
  ]);

  grunt.registerTask('default', [
    'test'
  ]);
};

require('js-yaml');
var path = require('path');

module.exports = function (grunt) {
  grunt.loadNpmTasks('grunt-contrib-jst');
  grunt.loadNpmTasks('grunt-mocha-test');
  grunt.loadNpmTasks('grunt-karma');

  grunt.initConfig({
    paths: require('js_paths.yml'),
    mochaTest: {
      jsbox_apps: {
        src: ['<%= paths.tests.jsbox_apps.spec %>'],
      }
    },
    jst: {
      options: {
        processName: function(filename) {
          var dir = path.dirname(filename);
          dir = path.relative('go/base/static/templates', dir);

          var parts = dir.split('/');
          parts.push(path.basename(filename, '.jst'));

          return parts.join('_');
        }
      },
      templates: {
        files: {
          "<%= paths.client.templates.dest %>": [
            "<%= paths.client.templates.src %>"
          ]
        }
      },
    },
    karma: {
      dev: {
        singleRun: true,
        reporters: ['dots'],
        configFile: 'karma.conf.js'
      }
    }
  });

  grunt.registerTask('test:jsbox_apps', [
    'mochaTest:jsbox_apps'
  ]);

  grunt.registerTask('test:client', [
    'jst:templates',
    'karma:dev'
  ]);

  grunt.registerTask('test', [
    'test:jsbox_apps',
    'test:client'
  ]);

  grunt.registerTask('default', [
    'test'
  ]);
};

Remove a not-too-useful comment hating on Django Pipelines


module.exports = function(grunt) {
	var pkg = grunt.file.readJSON("package.json");

	grunt.initConfig({
		uglify : {
			options : {
				banner : '//! Tokchi ' + pkg.version + ' - ' + pkg.copyright + ', https://github.com/tiguchi/tokchi - MIT license\n',
			},
			my_target : {
				files : {
					'build/jquery.tokchi.min.js' : [ 'src/jquery.tokchi.js' ]
				}
			}
		}
	});

	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.registerTask('default', [ 'uglify' ]);
};

module.exports = function(grunt) {
	var pkg = grunt.file.readJSON("package.json");

	grunt.initConfig({
		uglify : {
			options : {
				banner : '/*! Tokchi ' + pkg.version + ' - ' + pkg.copyright + ', https://github.com/tiguchi/tokchi - MIT license */\n',
			},
			my_target : {
				files : {
					'build/jquery.tokchi.min.js' : [ 'src/jquery.tokchi.js' ]
				}
			}
		}
	});

	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.registerTask('default', [ 'uglify' ]);
};

Make sure that version / license header is preserved


Template.register.helpers({
  errorList: function() {
    return Session.get('errors');
  },

  formValid: function(user) {
    return !($.isEmptyObject(user.userName) &&
          $.isEmptyObject(user.firstName) &&
          $.isEmptyObject(user.lastName) &&
          $.isEmptyObject(user.email) &&
          $.isEmptyObject(user.password));
  }
});

Template.register.events({
  'submit .form-signin': function(e) {
    Session.set('errors', null);
    e.preventDefault();
    var user = {
        email: $('#inputEmail').val(),
        password: $('#inputPassword').val(),
        profile: {
          userName: $('#inputUsername').val(),
          firstName: $('#inputFirstName').val(),
          lastName: $('#inputLastName').val()
        }
    };

    Accounts.createUser(user, function(err) {
      var errors = [];
      if (err) {
        console.log(err);
        errors.push({message: err.reason});
        Session.set('errors', errors);
      } else {
        Router.go('/projects');
        console.log('User with id: ' + Meteor.userId() + ' added successfully');
      }
    });
  },
});

errors = new ReactiveArray([]);

Template.register.helpers({
  errorList: function() {
    return errors.list();
  },

  formValid: function(user) {
    return !($.isEmptyObject(user.userName) &&
          $.isEmptyObject(user.firstName) &&
          $.isEmptyObject(user.lastName) &&
          $.isEmptyObject(user.email) &&
          $.isEmptyObject(user.password));
  }
});

Template.register.events({
  'submit .form-signin': function(e) {
    Session.set('errors', null);
    e.preventDefault();
    var user = {
        email: $('#inputEmail').val(),
        password: $('#inputPassword').val(),
        profile: {
          userName: $('#inputUsername').val(),
          firstName: $('#inputFirstName').val(),
          lastName: $('#inputLastName').val()
        }
    };

    Accounts.createUser(user, function(err) {
      if (err) {
        console.log(err);
        errors.push({message: err.reason});
      } else {
        console.log('User with id: ' + Meteor.userId() + ' added successfully');
        Router.go('projects', {
          _id: Meteor.userId()
        });

      }
    });
  },
});

Switch to ReactiveArray instead of Session and navigate to projects home page after successfull login


/* global Games */
angular
  .module('PLeague')
  .controller('GamesCtrl', GamesCtrl);

function GamesCtrl ($scope, $reactive, NewGame, NewTeam) {
  $reactive(this).attach($scope);
  console.log('in games controller');
  this.remove = remove;
  this.showNewGameModal = showNewGameModal;

  function showNewGameModal() {
    NewGame.showModal();
  }

  this.helpers({
    data() {
      return Games.find();
    }
  });

  function remove(game) {
      Games.remove(game._id);
  }
}

/* global Games */
angular
  .module('PLeague')
  .controller('GamesCtrl', GamesCtrl);

function GamesCtrl ($scope, $reactive, NewGame, NewTeam) {
  $reactive(this).attach($scope);
  console.log('in games controller');
  this.remove = remove;
  this.showNewGameModal = showNewGameModal;

  function showNewGameModal() {
    NewGame.showModal();
  }

  this.helpers({
    data() {
      return Games.find();
    },
    inprogress() {
      return Games.findOne(
        { endDate: { $exists: false } }
      );
    }
  });

  function remove(game) {
      Games.remove(game._id);
  }
}

Add in progress game to helper data


import React from 'react';
import { shallow } from 'enzyme';
import { expect } from 'chai';
import R from 'ramda';
import { Link } from 'react-router';
import EntityListItem from '../../../src/components/EntityListItem';

describe('EntityListItem', function () {
    function createDefaultProps() {
        return {
            name: 'any name'
        };
    }

    function createComponent(props = {}) {
        const mergedProps = R.merge(createDefaultProps(), props);

        return <EntityListItem {...mergedProps} />;
    }

    const testCases = [
        { name: 'a', expected: 'a' },
        { name: 'A', expected: 'a' },
        { name: 'a b', expected: 'ab' },
        { name: 'äb', expected: 'b' },
        { name: '#a', expected: 'a' },
        { name: 'a3', expected: 'a3' }
    ];

    testCases.forEach((testCase) => {
        it('should remove non-word characters and lower-case the result', function () {
            const { name, expected } = testCase;
            const expectedUri = `/entities/${expected}`;
            const entityListItem = shallow(createComponent({ name }));
            const link = entityListItem.find(Link);

            expect(link.prop('to')).to.equal(expectedUri);
            expect(link.children().text()).to.equal(expected);
        });
    });
});

import React from 'react';
import { shallow } from 'enzyme';
import { expect } from 'chai';
import R from 'ramda';
import { Link } from 'react-router';
import EntityListItem from '../../../src/components/EntityListItem';

describe('EntityListItem', function () {
    function createDefaultProps() {
        return {
            name: 'any name'
        };
    }

    function createComponent(props = {}) {
        const mergedProps = R.merge(createDefaultProps(), props);

        return <EntityListItem {...mergedProps} />;
    }

    const testCases = [
        { name: 'a', expected: 'a' },
        { name: 'A', expected: 'a' },
        { name: 'a b', expected: 'ab' },
        { name: 'äb', expected: 'b' },
        { name: '#a', expected: 'a' },
        { name: 'a3', expected: 'a3' }
    ];

    testCases.forEach((testCase) => {
        it(`should remove non-word characters and lower-case the result for ${testCase.name}`, function () {
            const { name, expected } = testCase;
            const expectedUri = `/entities/${expected}`;
            const entityListItem = shallow(createComponent({ name }));
            const link = entityListItem.find(Link);

            expect(link.prop('to')).to.equal(expectedUri);
            expect(link.children().text()).to.equal(expected);
        });
    });
});

Add test names for parametrized tests


"use strict";
module.exports = function (grunt) {
	// Start w/ a clean slate
	grunt.initConfig({});

	// JSHint
	grunt.loadNpmTasks("grunt-contrib-jshint");
	grunt.config("jshint", {
		"options": {"jshintrc": true},
		"all": ["*.js"]
	});

	// Default task
	grunt.registerTask("default", "Does nothing", function () { /* Does nothing */ });
	// Aliases
	grunt.registerTask("hint", ["jshint"]);
	grunt.registerTask("lint", ["jshint"]);
};

"use strict";
module.exports = function (grunt) {
	// Start w/ a clean slate
	grunt.initConfig({});

	// JSHint
	grunt.loadNpmTasks("grunt-contrib-jshint");
	grunt.config("jshint", {
		"options": { "jshintrc": true },
		"all": ["*.js", "tests/*.js"]
	});

	grunt.loadNpmTasks("grunt-contrib-nodeunit");
	grunt.config("nodeunit", {
		all: ["tests/*.js"]
	});

	// Default task
	grunt.registerTask("default", "Does nothing", function () { /* Does nothing */ });
	// Aliases
	grunt.registerTask("hint", ["jshint"]);
	grunt.registerTask("lint", ["jshint"]);
};

Add nodeunit to Grunt file


import pify from 'pify'
import gradient from '@sanity/gradient-client'

class SanityClient {
  constructor(config = {}) {
    const client = gradient(config)

    this.gradient = pify({
      fetch: client.fetch.bind(client),
      update: client.update.bind(client)
    })
  }

  fetch(query, params) {
    return this.gradient.fetch(query, params).then(res => res.result)
  }

  update(documentId, patch, opts) {
    return this.gradient.update(documentId, patch, opts)
  }

  observe(query, opts) {

  }
}

function createClient(config) {
  return new SanityClient(config)
}

export default createClient

import pify from 'pify'
import gradient from '@sanity/gradient-client'

class SanityClient {
  constructor(config = {}) {
    const client = gradient(config)

    this.gradient = pify({
      fetch: client.fetch.bind(client),
      update: client.update.bind(client),
      create: client.create.bind(client),
      delete: client.delete.bind(client)
    })
  }

  fetch(query, params) {
    return this.gradient.fetch(query, params).then(res => res.result)
  }

  update(documentId, patch, opts) {
    return this.gradient.update(documentId, patch, opts)
  }

  create(doc, opts) {
    return this.gradient.create(doc, opts).then(res => res.result)
  }

  delete(documentId, opts) {
    return this.gradient.delete(documentId, opts).then(res => res.result)
  }

  observe(query, opts) {

  }
}

function createClient(config) {
  return new SanityClient(config)
}

export default createClient

Add delete and create methods


import React from 'react';

import Style from '../config/GlobalStyle';
import { Layout, EventList, Header, Footer } from '../components';
import { fixtureApi } from '../services';

export default class Index extends React.Component {
  static async getInitialProps () {
    const events = await fixtureApi.getAllEvents();
    return { events };
  }

  render () {
    return (
      <Layout>
        <Style />
        <Header />
        <EventList events={this.props.events} />
        <Footer />
      </Layout>
    );
  }
}

import React from 'react';

import Global from '../css/Global';
import { Layout, EventList, Header, Footer } from '../components';
import { fixtureApi } from '../services';

export default class Index extends React.Component {
  static async getInitialProps () {
    const events = await fixtureApi.getAllEvents();
    return { events };
  }

  render () {
    return (
      <Layout>
        <Global />
        <Header />
        <EventList events={this.props.events} />
        <Footer />
      </Layout>
    );
  }
}

Update for new Global location


// TODO: This should be replaced with a styled-components theme

import { createGlobalStyle } from 'styled-components'
import Cookies from 'cookies-js'

export const toggle = mode => {
  const { theme } = document.documentElement.dataset
  const nextTheme = { dark: 'default', default: 'dark' }[theme]
  document.documentElement.dataset.theme = mode || nextTheme
  const cookieFlag = { dark: '1', default: '0' }[nextTheme]
  Cookies.set('is-inverted', cookieFlag)
}

export default createGlobalStyle`
  html[data-theme='dark'] {
    &,
    img,
    canvas,
    [style*='background-image'] {
      filter: invert(100%) hue-rotate(180deg);

      iframe {
        filter: invert(100%) hue-rotate(180deg);
      }
    }

    // Chrome
    @media all and (-webkit-min-device-pixel-ratio: 0) and (min-resolution: 0.001dpcm) {
      body {
        background-color: black;
      }
    }

    // Safari 8+
    _::-webkit-full-page-media,
    _:future,
    :root {
      body {
        background-color: white;
      }
    }
  }
`

// TODO: This should be replaced with a styled-components theme

import { createGlobalStyle } from 'styled-components'
import Cookies from 'cookies-js'

export const toggle = mode => {
  const { theme } = document.documentElement.dataset
  const nextTheme = { dark: 'default', default: 'dark' }[theme]
  document.documentElement.dataset.theme = mode || nextTheme
  const cookieFlag = { dark: '1', default: '0' }[nextTheme]
  Cookies.set('is-inverted', cookieFlag)
}

export default createGlobalStyle`
  html[data-theme='dark'] {
    &,
    img,
    canvas,
    [style*='background-image'] {
      filter: invert(100%) hue-rotate(180deg);

      iframe {
        filter: invert(100%) hue-rotate(180deg);
      }
    }

    // Chrome
    @media all and (-webkit-min-device-pixel-ratio: 0) and (min-resolution: 0.001dpcm) {
      body {
        background-color: white;
      }
    }

    // Safari 8+
    _::-webkit-full-page-media,
    _:future,
    :root {
      body {
        background-color: white;
      }
    }
  }
`

Fix background for chrome dark mode


const path = require('path');
const webpack = require('webpack');

// Load base config
const baseConfig = require('./webpack.config.base');

// Create the config
const config = Object.create(baseConfig);

config.devtool = 'cheap-source-map';

config.devServer = {
    contentBase: path.resolve(__dirname, '../src'),
    watchContentBase: true
};

module.exports = config;

const path = require('path');
const webpack = require('webpack');

// Listen port
const PORT = process.env.PORT || 8080;

// Load base config
const baseConfig = require('./webpack.config.base');

// Create the config
const config = Object.create(baseConfig);

config.devtool = 'cheap-source-map';

config.devServer = {
    hot: true,
    host: "0.0.0.0",
    port: PORT,
    contentBase: path.resolve(__dirname, '../src'),
    watchContentBase: true
};

module.exports = config;

Allow ENV "PORT" to override listen port


import { moduleForComponent, test } from 'ember-qunit';<% if (testType === 'integration') { %>
import hbs from 'htmlbars-inline-precompile';<% } %>

moduleForComponent('<%= componentPathName %>', '<%= friendlyTestDescription %>', {
  <% if (testType === 'integration' ) { %>integration: true<% } else if(testType === 'unit') { %>// Specify the other units that are required for this test
  // needs: ['component:foo', 'helper:bar'],
  unit: true<% } %>
});

test('it renders', function(assert) {
  <% if (testType === 'integration' ) { %>// Set any properties with this.set('myProperty', 'value');
  // Handle any actions with this.on('myAction', function(val) { ... });

  this.render(hbs`{{<%= componentPathName %>}}`);

  assert.equal(this.$().text().trim(), '');

  // Template block usage:
  this.render(hbs`
    {{#<%= componentPathName %>}}
      template block text
    {{/<%= componentPathName %>}}
  `);

  assert.equal(this.$().text().trim(), 'template block text');<% } else if(testType === 'unit') { %>
  // Creates the component instance
  /*let component =*/ this.subject();
  // Renders the component to the page
  this.render();
  assert.equal(this.$().text().trim(), '');<% } %>
});

Remove space from blank line for unit-tests


var nodeHelper = require('node_helper'),
    request = require('request'),
    console = require('console'),
    TemplateHandler = require('../shared/template_handler.js');

module.exports = nodeHelper.create({
  start: function() {
    var th = new TemplateHandler(this.expressApp, this.name, this.path);
    th.installTemplateHandler();
  },

  socketNotificationReceived: function(notification, payload) {
    if (notification == 'download') {
      var self = this;
      request({url: payload, timeout: 30 * 1000}, (error, response, body) => {
        if (error) {
          console.log(error);
          self.sendSocketNotification('error', error);
          return;
        }
        if (response.statusCode != 200) {
          console.log('weather response status code ' + response.statusCode);
          self.sendSocketNotification('error500', response);
          return;
        }
        self.sendSocketNotification('download', body);
      });
    }
  }
});

var nodeHelper = require('node_helper'),
    request = require('request'),
    console = require('console'),
    TemplateHandler = require('../shared/template_handler.js');

module.exports = nodeHelper.create({
  start: function() {
    var th = new TemplateHandler(this.expressApp, this.name, this.path);
    th.installTemplateHandler();
  },

  socketNotificationReceived: function(notification, payload) {
    if (notification == 'download') {
      var self = this;
      request({url: payload, timeout: 300 * 1000}, (error, response, body) => {
        if (error) {
          console.log(error);
          self.sendSocketNotification('error', error);
          return;
        }
        if (response.statusCode != 200) {
          console.log('weather response status code ' + response.statusCode);
          self.sendSocketNotification('error500', response);
          return;
        }
        self.sendSocketNotification('download', body);
      });
    }
  }
});

Increase timeout for weather net fetch.


import req from '../req.js';
import Event from '../Event';

const RETRY_INTERVAL = 1000; // ms

export default function Ticker() {
  this.event = new Event();

  this.ready = false;
  this.data = {};

  this.load();
}

Ticker.prototype.load = function() {
  req.getJson('https://api.stellarterm.com/v1/ticker.json')
  .then(tickerData => {
    this.ready = true;
    this.data = tickerData;
    this.event.trigger();
  })
  .catch(e => {
    console.log('Unable to load ticker');
    setTimeout(() => {
      this.load();
    }, RETRY_INTERVAL)
  })
}

import req from '../req.js';
import Event from '../Event';

export default function Ticker() {
  this.event = new Event();

  this.ready = false;
  this.data = {};

  this.load();
}

const MAX_ATTEMPTS = 5;

Ticker.prototype.load = function(attempt) {
  if (attempt >= MAX_ATTEMPTS) {
    return;
  }
  req.getJson('https://api.stellarterm.com/v1/ticker.json')
  .then(tickerData => {
    this.ready = true;
    this.data = tickerData;
    this.event.trigger();
  })
  .catch(e => {
    console.log('Unable to load ticker');
    if (!attempt) {
      attempt = 0;
    }
    setTimeout(() => {
      this.load(attempt + 1);
    }, 100)
  })
}

Add faster ticker fetch retry with limited attempts


const Router = require('express').Router;
const router = new Router();

router.get('/', (req, res) => {
  res.json({
    message: 'Welcome to Clash Royale API!',
    endpoints: {
      arenas: 'api/arenas',
      cards: 'api/cards',
      chests: 'api/chests',
      players: 'api/players',
    },
    version: '1.0.0',
    lastUpdate: 'June 06 2016',
  });
});

module.exports = router;

const Router = require('express').Router;
const router = new Router();

router.get('/', (req, res) => {
  res.json({
    message: 'Welcome to Clash Royale API!',
    endpoints: {
      arenas: 'api/arenas',
      cards: 'api/cards',
      chests: 'api/chests',
      players: 'api/players',
    },
    version: '1.0.0',
    lastUpdate: 'June 23 2016',
  });
});

module.exports = router;

Update cards to match june update. Change last update date


import express from 'express';
import cors from 'cors';

export const router = express.Router();

const {APP_WEB_BASE_PATH} = process.env;

router.get('/nav', cors(), (req, res) => {
    res.send([
        {
            "href": `${APP_WEB_BASE_PATH}`,
            "text": "Home",
            "rel": "home"
        },
        {
            "href": `${APP_WEB_BASE_PATH}/not-found`,
            "text": "404"
        }
    ]);
});

export default router;

import express from 'express';
import cors from 'cors';

export const router = express.Router();

const {APP_WEB_BASE_PATH} = process.env;

router.get('/nav', cors(), (req, res) => {
    res.send([
        {
            "href": `${APP_WEB_BASE_PATH}/`,
            "text": "Home",
            "rel": "home"
        },
        {
            "href": `${APP_WEB_BASE_PATH}/not-found`,
            "text": "404"
        }
    ]);
});

export default router;

Fix invalid mock nav data


const {Schema, DOMParser} = require("prosemirror-model")
const {EditorView} = require("prosemirror-view")
const {EditorState} = require("prosemirror-state")
const {schema} = require("prosemirror-schema-basic")
const {addListNodes} = require("prosemirror-schema-list")
const {addTableNodes} = require("prosemirror-schema-table")
const {exampleSetup} = require("prosemirror-example-setup")

const demoSchema = new Schema({
  nodes: addListNodes(addTableNodes(schema.nodeSpec, "block+", "block"), "paragraph block*", "block"),
  marks: schema.markSpec
})

let state = EditorState.create({doc: DOMParser.fromSchema(demoSchema).parse(document.querySelector("#content")),
                                plugins: exampleSetup({schema: demoSchema})})

let view = window.view = new EditorView(document.querySelector(".full"), {state})

const {Schema, DOMParser} = require("prosemirror-model")
const {EditorView} = require("prosemirror-view")
const {EditorState} = require("prosemirror-state")
const {schema} = require("prosemirror-schema-basic")
const {addListNodes} = require("prosemirror-schema-list")
const {addTableNodes} = require("prosemirror-schema-table")
const {exampleSetup} = require("prosemirror-example-setup")

const demoSchema = new Schema({
  nodes: addListNodes(addTableNodes(schema.spec.nodes, "block+", "block"), "paragraph block*", "block"),
  marks: schema.spec.marks
})

let state = EditorState.create({doc: DOMParser.fromSchema(demoSchema).parse(document.querySelector("#content")),
                                plugins: exampleSetup({schema: demoSchema})})

let view = window.view = new EditorView(document.querySelector(".full"), {state})

Use 0.18-style schema spec access


/**
 * Created by cos-caner on 2/19/16.
 */

/**
 * Code for interaction in the support page
 */

'use strict';

var Raven = require('raven-js');
var $ = require('jquery');
var $osf = require('js/osfHelpers');

$(document).ready(function(){
    /**
     * Toggle individual item with jQuery
     * @param item {Object} jQuery object for the .support-item element
     * @param turnOff {Boolean} true if we are closing and open item
     * @private
     */
    function _toggleItem (item, turnOff) {
        var body = item.children('.support-body');
        var head = item.children('.support-head');
        var icon = head.children('.fa');
        if (turnOff){
            body.slideUp();
            icon.removeClass('fa-angle-down').addClass('fa-angle-right');
            item.removeClass('open').addClass('collapsed');
        } else {
            body.slideDown();
            icon.removeClass('fa-angle-right').addClass('fa-angle-down');
            item.removeClass('collapsed').addClass('open');
        }

    }

    function resetFilter () {
        $('.support-item').each(function() {
            var el = $(this);
            _toggleItem(el, true);
            el.removeClass('support-nomatch');
        });
    }
    // Toggle individual view when clicked on header
    $('.support-head').click(function(){
        var item = $(this).parent();
        _toggleItem(item, item.hasClass('open'));
    });

    $('.expand-all').click(function(){
        $('.support-item').each(function(){
            _toggleItem($(this));
        });
    });

    $('.collapse-all').click(function(){
        $('.support-item').each(function(){
            _toggleItem($(this), true);
        });
    });

    $('.support-filter').keyup(function(){
        var text = $(this).val().toLowerCase();
        if (text.length < 2) {
            resetFilter();
            return;
        }
        var el;
        var content;
        $('.support-item').each(function(){
            el = $(this);
            content = el.text().toLowerCase();
            if (content.indexOf(text) !== -1) {
                _toggleItem(el);
                el.removeClass('support-nomatch');
            } else {
                _toggleItem(el, true);
                el.addClass('support-nomatch');
            }
        });
    });

});

Add jquery functions for interaction


// The lean build does not include any of the third-party runtime dependencies, rather
// it assumes they are in the global namespace at runtime.
var config = require('./webpack.base.config');
var merge = require('webpack-merge');

module.exports = merge(config, {
  entry: {
    'geo.lean': './index.js',
    'geo.lean.min': './index.js'
  },
  externals: {
    d3: 'd3',
    hammerjs: {
      root: 'Hammer',
      commonjs: 'hammerjs',
      commonjs2: 'hammerjs',
      amd: 'hammerjs',
      // Since GeoJS's libraryTarget is "umd", defining this (undocumented) external library type
      // will allow Webpack to create a better error message if a "hammerjs" import fails
      umd: 'hammerjs'
    },
    'vtk.js': 'vtkjs'
  }
});

// The lean build does not include any of the third-party runtime dependencies, rather
// it assumes they are in the global namespace at runtime.
var config = require('./webpack.base.config');
var merge = require('webpack-merge');

module.exports = merge(config, {
  entry: {
    'geo.lean': './index.js',
    'geo.lean.min': './index.js'
  },
  externals: {
    d3: 'd3',
    hammerjs: {
      root: 'Hammer',
      commonjs: 'hammerjs',
      commonjs2: 'hammerjs',
      amd: 'hammerjs',
      // Since GeoJS's libraryTarget is "umd", defining this (undocumented) external library type
      // will allow Webpack to create a better error message if a "hammerjs" import fails
      umd: 'hammerjs'
    },
    'vtk.js': 'vtk'
  }
});

Fix global name of vtk module


var webpack = require('webpack');

module.exports = {
  entry: [
    './src/index'
  ],
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel'
    }, {
      test: /\.css$/,
      loader: 'style!css'
    }]
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': '"production"',
      'process.env.API_URL': '"https://api.expensetracker.rjbernaldo.com"',
    })
  ]
}

var webpack = require('webpack');

module.exports = {
  entry: [
    './src/index'
  ],
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel'
    }, {
      test: /\.css$/,
      loader: 'style!css'
    }]
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': '"production"',
      'process.env.API_URL': '"https://api.expensetracker.rjbernaldo.com"',
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
}

Add uglify to prod build.


import { VisibilityFilters, SET_VISIBILITY_FILTER } from '../actions';
const {SHOW_ALL} = VisibilityFilters;

// reducer in charge of dealing with the visibility filter.
function visibilityFilter(state = SHOW_ALL, action = {}) {
    const {type, filter} = action;
    switch (type) {
        case SET_VISIBILITY_FILTER:
            return filter;
        default:
            return state;
    }
}

export default visibilityFilter;

Fix missing export of reducer visibilityFilter


const db = require('../db.js');
const Rooms = require('../models/roomModel.js');
const UsersRooms = require('../models/userRoomModel.js');

module.exports = (user1Id, user2Id) => {
  const queryStr = `
                    SELECT ur_1.ur1_id FROM (
                      (
                        SELECT user_id AS user1_id, room_id AS ur1_id FROM users_rooms
                          WHERE user_id = '${user1Id}'
                      ) AS ur_1
                      INNER JOIN
                      (
                        SELECT user_id AS user2_id, room_id AS ur2_id FROM users_rooms
                          WHERE user_id = '${user2Id}'
                      ) AS ur_2
                      ON ur_1.ur1_id = ur_2.ur2_id
                    )
                    `;

  return db.query(queryStr).spread((results) => {
    if (results.length > 0) {
      return db.query(
        `UPDATE users_rooms
          SET \`show\` = true
          WHERE room_id = '${results[0].id}'
        `
      )
      .spread(data => data);
    }
    return Rooms.create({
      number_active_participants: 2,
    })
    .then(room => (
      UsersRooms.bulkCreate([
        {
          user_id: user1Id,
          room_id: room.id,
          show: true,
        },
        {
          user_id: user2Id,
          room_id: room.id,
          show: true,
        },
      ])
      .then(() => (
        [room]
      ))
    ));
  });
};

const db = require('../db.js');
const Rooms = require('../models/roomModel.js');
const UsersRooms = require('../models/userRoomModel.js');

module.exports = (user1Id, user2Id) => { //user1 is the one trying to start a conversation
  const queryStr = `
                    SELECT ur_1.ur1_id FROM (
                      (
                        SELECT user_id AS user1_id, room_id AS ur1_id FROM users_rooms
                          WHERE user_id = '${user1Id}'
                      ) AS ur_1
                      INNER JOIN
                      (
                        SELECT user_id AS user2_id, room_id AS ur2_id FROM users_rooms
                          WHERE user_id = '${user2Id}'
                      ) AS ur_2
                      ON ur_1.ur1_id = ur_2.ur2_id
                    )
                    `; //checks whether or not they already have a room in common

  return db.query(queryStr).spread((results) => {
    if (results.length > 0) {
      return db.query(
        `UPDATE users_rooms
          SET \`show\` = true
          WHERE room_id = '${results[0].id}' AND user_id = '${user1Id}'
        `
      )
      .spread(data => data);
    }
    return Rooms.create({
      number_active_participants: 2,
    })
    .then(room => (
      UsersRooms.bulkCreate([
        {
          user_id: user1Id,
          room_id: room.id,
          show: true,
        },
        {
          user_id: user2Id,
          room_id: room.id,
          show: true,
        },
      ])
      .then(() => (
        [room]
      ))
    ));
  });
};

Improve logic in showing userRoom


module.exports = function (grunt) {
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-mocha-cli');
    grunt.loadNpmTasks('grunt-release');

    grunt.initConfig({
        jshint: {
            all: ["lib/*.js", "test/*.js", "Gruntfile.js"],
            options: {
                jshintrc: ".jshintrc"
            }
        },
        watch: {
            all: {
                files: ['lib/**.js', 'test/**'],
                tasks: ['test']
            }
        },
        mochacli: {
            options: {
                files: ['test/*_test.js'],
            },
            spec: {
                options: {
                    reporter: 'spec',
                    slow: 2000,
                    timeout: 10000
                }
            }
        }
    });

    grunt.registerTask('default', ['test']);
    grunt.registerTask('build', ['jshint']);
    grunt.registerTask('package', ['build', 'release']);
    grunt.registerTask('test', ['build', 'mochacli']);
};

module.exports = function (grunt) {
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-mocha-cli');
    grunt.loadNpmTasks('grunt-release');

    grunt.initConfig({
        jshint: {
            all: ["lib/*.js", "test/*.js", "Gruntfile.js"],
            options: {
                jshintrc: ".jshintrc"
            }
        },
        watch: {
            all: {
                files: ['lib/**.js', 'test/**'],
                tasks: ['test']
            }
        },
        mochacli: {
            options: {
                files: ['test/*_test.js'],
            },
            spec: {
                options: {
                    reporter: 'spec',
                    slow: 2000,
                    timeout: 10000
                }
            }
        },
        release: {
            options: {
                npm: false
            }
        }
    });

    grunt.registerTask('default', ['test']);
    grunt.registerTask('build', ['jshint']);
    grunt.registerTask('package', ['build', 'release']);
    grunt.registerTask('test', ['build', 'mochacli']);
};

Disable NPM publish, do it manually to cope with failures.


module.exports = function( grunt ) {
  // Add the library tasks
  grunt.loadNpmTasks( "grunt-contrib-jshint" );

  grunt.initConfig({
    pkg: grunt.file.readJSON( "package.json" ),
    jshint: {
      files: [
        "Gruntfile.js",
        "main.js",
        "package.json"
      ]
    }
  });

  // Register custom tasks
  grunt.registerTask( "default", [ "jshint" ]);
  grunt.registerTask( "travis", [ "jshint" ]);
};

module.exports = function( grunt ) {
  // Add the library tasks
  grunt.loadNpmTasks( "grunt-contrib-jshint" );

  grunt.initConfig({
    pkg: grunt.file.readJSON( "package.json" ),
    jshint: {
      files: [
        "Gruntfile.js",
        "main.js",
        "package.json",
        "playlist.json"
      ]
    }
  });

  // Register custom tasks
  grunt.registerTask( "default", [ "jshint" ]);
  grunt.registerTask( "travis", [ "jshint" ]);
};

Add playlist.json to grunt linting


'use strict';

module.exports = function (grunt) {
    grunt.initConfig({
        grid_units: {
            dest : 'build/css/responsive-grid.css',
            options: {
                mediaQueries: {
                    med : 'screen and (min-width: 40em)', //approx 767px at 16px base font
                    lrg : 'screen and (min-width: 75em)' //approx 1200px at 16px base font
                }
            }
        },

        stripmq: {
            all: {
                files: {
                    'build/css/responsive-grid-old-ie.css': ['build/css/responsive-grid.css'],
                    'build/css/main-old-ie.css': ['public/css/main.css'],

                    // Layout Files
                    'build/css/layouts/blog-old-ie.css': ['public/css/layouts/blog.css']
                }
            }
        }
    });

    // Local tasks.
    grunt.loadTasks('lib/tasks/');
    grunt.loadNpmTasks('grunt-stripmq');

    grunt.registerTask('default', ['grid_units', 'stripmq']);
};

'use strict';

module.exports = function (grunt) {
    grunt.initConfig({
        grid_units: {
            dest : 'build/css/responsive-grid.css',
            options: {
                mediaQueries: {
                    med : 'screen and (min-width: 48em)', // 768px
                    lrg : 'screen and (min-width: 75em)'  // 1200px
                }
            }
        },

        stripmq: {
            all: {
                files: {
                    'build/css/responsive-grid-old-ie.css': ['build/css/responsive-grid.css'],
                    'build/css/main-old-ie.css': ['public/css/main.css'],

                    // Layout Files
                    'build/css/layouts/blog-old-ie.css': ['public/css/layouts/blog.css']
                }
            }
        }
    });

    // Local tasks.
    grunt.loadTasks('lib/tasks/');
    grunt.loadNpmTasks('grunt-stripmq');

    grunt.registerTask('default', ['grid_units', 'stripmq']);
};

Fix custom `med` grid media query to be: 48em === 768px


import Player from './player';

// A human player that requires user interaction; every human player inherits
// from the base Player model
function HumanPlayer(args) {
  Player.call(this, args);
}
HumanPlayer.prototype = Object.create(Player.prototype);
HumanPlayer.prototype.type = 'human';

export default HumanPlayer;

import Player from './player';

// A human player that requires user interaction; every human player inherits
// from the base Player model
class HumanPlayer extends Player {
  // Nothing to do here!
}
HumanPlayer.prototype.type = 'human';

export default HumanPlayer;

Convert human player model to ES6 class


import { ens } from '/imports/lib/ethereum';

Template['components_address'].onCreated(function() {
  const template = Template.instance();
  template.autorun(() => {
    const addr = Template.currentData().addr;
    TemplateVar.set(template, 'name', null);
    if (!addr) {
      return;
    }
    ens.reverse(addr, (err, resolver) =>{
      if (!err && resolver.name) {
        resolver.name((err, name) => {
          if (!err) {
            TemplateVar.set(template, 'name', name);
          }
        });
      }
    })
  })

})

Template['components_address'].helpers({
  mine() {
    return web3.eth.accounts.filter(
      (acc) => acc === Template.instance().data.addr
    ).length > 0;
  },
  name() {
    return TemplateVar.get('name');
  }
})

import { ens } from '/imports/lib/ethereum';

function validateName(claimedAddr, name, cb) {
  ens.resolver(name, (err, res) => {
    if (err) {
      return cb(err);
    }
    res.addr((err, actualAddr) => {
      if (err) {
        return cb(err);
      }
      cb(null, claimedAddr == actualAddr);
    });
  });
}

Template['components_address'].onCreated(function() {
  const template = Template.instance();
  template.autorun(() => {
    const addr = Template.currentData().addr;
    TemplateVar.set(template, 'name', null);
    if (!addr) {
      return;
    }
    ens.reverse(addr, (err, resolver) =>{
      if (!err && resolver.name) {
        resolver.name((err, name) => {
          validateName(addr, name, (err, isValid) => {
            if (!err && isValid) {
              TemplateVar.set(template, 'name', name);
            }
          });
        });
      }
    })
  })

})

Template['components_address'].helpers({
  mine() {
    return web3.eth.accounts.filter(
      (acc) => acc === Template.instance().data.addr
    ).length > 0;
  },
  name() {
    return TemplateVar.get('name');
  }
})

Validate reverse resolution before displaying the name


Template.newEkloreQuestion.helpers({});

Template.newEkloreQuestion.events({
	'click #addEkloreQuestion': function(event) {
		event.preventDefault();
		var ekloreQuestion = {
			title: $('#ekloreQuestionTitle').val(),
			level: Number($('#ekloreQuestionLevel').val())
		};
		if ($('input[name="displayType"]:checked').val() === 'text') {
			ekloreQuestion.displayType = 'text';
		} else if ($('input[name="displayType"]:checked').val() === 'picture') {
			ekloreQuestion.displayType = 'picture';
		}
		if (!ekloreQuestion.title) {
			return throwError('Title must be filled');
		}
		if (!ekloreQuestion.displayType) {
			return throwError('Display type must be defined');
		}
		if (ekloreQuestion.level < 2) {
			return throwError('The level must be superior to 1');
		}
		Meteor.call('addAnEkloreQuestion', ekloreQuestion, (error, result) => {
			if (error) {
				return throwError(error.message);
			} else {
				Router.go('editEkloreQuestion', { _id: result });
			}
		});
	}
});

Template.newEkloreQuestion.events({
	'click #addEkloreQuestion': function(event) {
		event.preventDefault();
		const ekloreQuestion = {
			title: $('#ekloreQuestionTitle').val(),
			level: Number($('#ekloreQuestionLevel').val())
		};
		if ($('input[name="displayType"]:checked').val() === 'text') {
			ekloreQuestion.displayType = 'text';
		} else if ($('input[name="displayType"]:checked').val() === 'picture') {
			ekloreQuestion.displayType = 'picture';
		}
		if (!ekloreQuestion.title) {
			return throwError('Title must be filled');
		}
		if (!ekloreQuestion.displayType) {
			return throwError('Display type must be defined');
		}
		if (ekloreQuestion.level < 2) {
			return throwError('The level must be superior to 1');
		}
		Meteor.call('addAnEkloreQuestion', ekloreQuestion, (error, result) => {
			if (error) {
				return throwError(error.message);
			} else {
				Router.go('editEkloreQuestion', { _id: result });
			}
		});
	}
});

Remove helper and change var to const


import React, { Component } from 'react';
import Fetch from 'react-fetch-component';
import buildQuery from 'odata-query';

function buildUrl(baseUrl, query) {
  return query !== false && baseUrl + buildQuery(query);
}

class OData extends Component {
  render() {
    const { baseUrl, query = {}, ...rest } = this.props;

    return (
      <Fetch
        url={query}
        fetchFunction={(query, options, updateOptions) => {
          const url = buildUrl(baseUrl, query);
          return fetch(url, options, updateOptions);
        }}
        {...rest}
      />
    );
  }
}

export { buildQuery };
export default OData;

import React, { Component } from 'react';
import Fetch from 'react-fetch-component';
import buildQuery from 'odata-query';

function buildUrl(baseUrl, query) {
  return query !== false && baseUrl + buildQuery(query);
}

class OData extends Component {
  render() {
    const { baseUrl, query = {}, ...rest } = this.props;

    return (
      <Fetch
        url={buildUrl(baseUrl, query)}
        fetchFunction={(url, options, updateOptions) => {
          url = typeof url === 'string' ? url : buildUrl(baseUrl, url);
          return fetch(url, options, updateOptions);
        }}
        {...rest}
      />
    );
  }
}

export { buildQuery };
export default OData;

Fix re-refetching on re-render due to url as objects not being equal (check within react-fetch-component)


'use strict';

var ap = require('ap');
var d = require('../decorators');
var fs = require('fs');
var merge = require('merge');
var q = require('q');
var cons = require('consolidate');

var writeFile;

Object.keys(cons).forEach(function (engine) {
  var renderFile;

  exports[engine] = d.push(d.srcDest(function (src, dest, options) {
    // Lazy
    renderFile = renderFile || q.denodeify(cons[engine]);
    writeFile = writeFile || q.denodeify(fs.writeFile);

    // Merge options
    var ctx = merge({}, this.ctx, options);

    // Write destination callback
    var writeDest = ap([dest], writeFile);

    // Ensure base path is set
    this.base(dest);

    // Render, then write
    return renderFile(src, ctx).then(writeDest);
  }));
});

'use strict';

var ap = require('ap');
var d = require('../decorators');
var fs = require('fs');
var merge = require('merge');
var q = require('q');
var cons = require('consolidate');

var writeFile;

Object.keys(cons).forEach(function (engine) {
  var renderFile;

  exports[engine] = d.push(d.srcDest(function (src, dest, options) {
    // Lazy
    renderFile = renderFile || q.denodeify(cons[engine]);
    writeFile = writeFile || q.denodeify(fs.writeFile);

    // Ensure base path is set
    this.base(dest);

    // Merge options
    var ctx = merge({}, this.ctx, options);

    // Write destination callback
    var writeDest = ap([dest], writeFile);

    // Render, then write
    return renderFile(src, ctx).then(writeDest);
  }));
});

Set base path before capturing context


'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace nlp
*/
var nlp = {};

/**
* @name lda
* @memberof nlp
* @readonly
* @type {Function}
* @see {@link module:@stdlib/nlp/lda}
*/
setReadOnly( nlp, 'lda', require( '@stdlib/nlp/lda' ) );

/**
* @name tokenize
* @memberof nlp
* @readonly
* @type {Function}
* @see {@link module:@stdlib/nlp/tokenize}
*/
setReadOnly( nlp, 'tokenize', require( '@stdlib/nlp/tokenize' ) );

// EXPORTS //

module.exports = nlp;

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace nlp
*/
var nlp = {};

/**
* @name expandContractions
* @memberof nlp
* @readonly
* @type {Function}
* @see {@link module:@stdlib/nlp/expand-contractions}
*/
setReadOnly( nlp, 'expandContractions', require( '@stdlib/nlp/expand-contractions' ) );

/**
* @name lda
* @memberof nlp
* @readonly
* @type {Function}
* @see {@link module:@stdlib/nlp/lda}
*/
setReadOnly( nlp, 'lda', require( '@stdlib/nlp/lda' ) );

/**
* @name tokenize
* @memberof nlp
* @readonly
* @type {Function}
* @see {@link module:@stdlib/nlp/tokenize}
*/
setReadOnly( nlp, 'tokenize', require( '@stdlib/nlp/tokenize' ) );

// EXPORTS //

module.exports = nlp;

Add function to NLP namespace


'use strict';

//
// --- Aggregator
//

function Aggregator(defaultTags) {
    this.buffer = {};
    this.defaultTags = defaultTags || [];
}

Aggregator.prototype.makeBufferKey = function(key, tags) {
    tags = tags || [''];
    return key + '#' + tags.concat().sort().join('.');
};

Aggregator.prototype.addPoint = function(Type, key, value, tags, host, timestampInMillis, options) {
    const bufferKey = this.makeBufferKey(key, tags);
    if (!this.buffer.hasOwnProperty(bufferKey)) {
        this.buffer[bufferKey] = new Type(key, tags, host, options);
    }

    this.buffer[bufferKey].addPoint(value, timestampInMillis);
};

Aggregator.prototype.flush = function() {
    let series = [];
    for (let key in this.buffer) {
        if (this.buffer.hasOwnProperty(key)) {
            series = series.concat(this.buffer[key].flush());
        }
    }

    // Concat default tags
    if (this.defaultTags) {
        for (let i = 0; i < series.length; i++) {
            series[i].tags = this.defaultTags.concat(series[i].tags);
        }
    }

    this.buffer = {};

    return series;
};

module.exports = {
    Aggregator: Aggregator
};

'use strict';

//
// --- Aggregator
//

function Aggregator(defaultTags) {
    this.buffer = {};
    this.defaultTags = defaultTags || [];
}

Aggregator.prototype.makeBufferKey = function(key, tags) {
    tags = tags || [''];
    return key + '#' + tags.concat().sort().join('.');
};

Aggregator.prototype.addPoint = function(Type, key, value, tags, host, timestampInMillis, options) {
    const bufferKey = this.makeBufferKey(key, tags);
    if (!this.buffer.hasOwnProperty(bufferKey)) {
        this.buffer[bufferKey] = new Type(key, tags, host, options);
    }

    this.buffer[bufferKey].addPoint(value, timestampInMillis);
};

Aggregator.prototype.flush = function() {
    let series = [];
    for (const item of Object.values(this.buffer)) {
        series = series.concat(item.flush());
    }

    // Concat default tags
    if (this.defaultTags) {
        for (const metric of series) {
            metric.tags = this.defaultTags.concat(metric.tags);
        }
    }

    this.buffer = {};

    return series;
};

module.exports = {
    Aggregator: Aggregator
};

Use for...of loops where appropriate


var vscode = require('vscode');
var loremIpsum = require('lorem-ipsum');

function activate(context) {
  var commands = [
    vscode.commands.registerCommand('lorem-ipsum.line', generateLine),
    vscode.commands.registerCommand('lorem-ipsum.paragraph', generateParagraph),
    vscode.commands.registerCommand('lorem-ipsum.multipleParagraphs', generateMultipleParagraphs)
  ];

  commands.forEach(function (command) {
    context.subscriptions.push(command);
  });
}

function insertText(lorem) {
  var editor = vscode.window.activeTextEditor;
  editor.edit(edit => editor.selections.forEach(v => edit.replace(v, loremIpsum(lorem))));
}

function generateLine() {
  insertText({
    count: 1,
    units: 'sentences'
  });
}

function generateParagraph() {
  insertText({
    count: 1,
    units: 'paragraphs'
  });
}

async function generateMultipleParagraphs() {
  const items = [];
  for (let i = 2; i <= 10; i++) {
    items.push(i.toString());
  }

  const count = await vscode.window.showQuickPick(items, { placeHolder: 'How many paragraphs?' });
  if (!count) {
    return;
  }

  insertText({
    count: Number.parseInt(count),
    units: 'paragraphs'
  });
}

exports.activate = activate;

var vscode = require('vscode');
var loremIpsum = require('lorem-ipsum');

function activate(context) {
  var commands = [
    vscode.commands.registerCommand('lorem-ipsum.line', generateLine),
    vscode.commands.registerCommand('lorem-ipsum.paragraph', generateParagraph),
    vscode.commands.registerCommand('lorem-ipsum.multipleParagraphs', generateMultipleParagraphs)
  ];

  commands.forEach(function (command) {
    context.subscriptions.push(command);
  });
}

function insertText(lorem) {
  var editor = vscode.window.activeTextEditor;
  editor.edit(
    edit => editor.selections.forEach(
      selection => {
        edit.delete(selection);
        edit.insert(selection.start, loremIpsum(lorem));
      }
    )
  );
}

function generateLine() {
  insertText({
    count: 1,
    units: 'sentences'
  });
}

function generateParagraph() {
  insertText({
    count: 1,
    units: 'paragraphs'
  });
}

async function generateMultipleParagraphs() {
  const items = [];
  for (let i = 2; i <= 10; i++) {
    items.push(i.toString());
  }

  const count = await vscode.window.showQuickPick(items, { placeHolder: 'How many paragraphs?' });
  if (!count) {
    return;
  }

  insertText({
    count: Number.parseInt(count),
    units: 'paragraphs'
  });
}

exports.activate = activate;

Revert back to putting cursor at the end of selection after insertion


/**
 * Event subscription for Microcosm
 */

var Diode = function (app) {
  var callbacks = []

  if (this instanceof Diode) {
    app = this
  } else if (arguments.length == 0){
    return new Diode()
  }

  /**
   * Given a CALLBACK function, add it to the Set of all callbacks.
   */
  app.listen = app.subscribe = function (callback, scope) {
    callbacks.push({ callback: callback, scope: scope || app })
    return app
  }

  /**
   * Given a CALLBACK function, remove it from the set of callbacks.
   * Throws an error if the callback is not included in the set.
   */
  app.ignore = app.unsubscribe = function (unwanted) {
    callbacks = callbacks.filter(function(entry) {
      return entry.callback !== unwanted
    })

    return app
  }

  /**
   * Immediately trigger every callback
   */
  app.emit = app.publish = function () {
    for (var i = 0; i < callbacks.length; i++) {
      callbacks[i].callback.apply(callbacks[i].scope, arguments)
    }

    return app
  }

  return app
}

export default Diode(Diode)

/**
 * Event subscription for Microcosm
 */

function Diode (app) {
  var callbacks = []

  if (this instanceof Diode) {
    app = this
  } else if (arguments.length == 0){
    return new Diode()
  }

  /**
   * Given a CALLBACK function, add it to the Set of all callbacks.
   */
  app.listen = app.subscribe = function (callback, scope) {
    callbacks.push({ callback: callback, scope: scope || app })
    return app
  }

  /**
   * Given a CALLBACK function, remove it from the set of callbacks.
   * Throws an error if the callback is not included in the set.
   */
  app.ignore = app.unsubscribe = function (unwanted) {
    callbacks = callbacks.filter(function(entry) {
      return entry.callback !== unwanted
    })

    return app
  }

  /**
   * Immediately trigger every callback
   */
  app.emit = app.publish = function () {
    for (var i = 0; i < callbacks.length; i++) {
      callbacks[i].callback.apply(callbacks[i].scope, arguments)
    }

    return app
  }

  return app
}

export default Diode(Diode)

Tweak the way namespaces are defined to fix strange instanceof error


"use strict"

module.exports = function (opts) {
  var inlinePlugin = require('./md_items_inline')
    , hrefPlugin = require('./md_items_href')

  opts = opts || {};

  if (!opts.projectBaseURL) {
    throw Error("Must pass projectBaseURL");
  }

  if (!opts.resolveItemText) {
    throw Error("Must pass resolveItemText");
  }

  return require('markdown-it')()
    .use(inlinePlugin, {
      projectBaseURL: opts.projectBaseURL,
      resolveItemText: opts.resolveItemText
    })
    .use(hrefPlugin, {
      projectBaseURL: opts.projectBaseURL
    })
}

"use strict"

module.exports = function (opts) {
  var inlinePlugin = require('./md_items_inline')
    , hrefPlugin = require('./md_items_href')
    , citationPlugin = require('./md_citations')
    , documentBlockPlugin = require('./md_document_block')

  opts = opts || {};

  if (!opts.projectBaseURL) throw Error("Must pass projectBaseURL");
  if (!opts.resolveItemText) throw Error("Must pass resolveItemText");
  if (!opts.makeCitationText) throw Error("Must pass makeCitationText");

  return require('markdown-it')()
    .use(inlinePlugin, {
      projectBaseURL: opts.projectBaseURL,
      resolveItemText: opts.resolveItemText
    })
    .use(hrefPlugin, {
      projectBaseURL: opts.projectBaseURL
    })
    .use(citationPlugin, {
      projectBaseURL: opts.projectBaseURL,
      makeCitationText: opts.makeCitationText
    })
    .use(documentBlockPlugin, {
      projectBaseURL: opts.projectBaseURL,
      makeCitationText: opts.makeCitationText
    })
}

Add citation and document block extensions to parser


/**
 * Hand-written Promisified wrapper around generated ESI code.
 * This module returns a factory function that takes an optional datasource
 * string and base URL. If any parameter is not provided, the defaults are used.
 *
 * The factory function returns an object with properties that expose
 * instantiations of each sub-module for the ESI groups.
 *
 * @param {String} datasource The datasource string, defaults to `'tranquility'`
 * @param {String} baseURL The base URL of the ESI Swagger endpoint, which
 *   defaults to `'https://esi.tech.ccp.is/latest'`
 * @module eve_swagger_interface
 */
module.exports = function(datasource, baseURL) {
    var exports = {};
    var internal = require('./internal')(datasource, baseURL);

    /**
     * This is an instance of `alliance` module configured to use the
     * datasource and baseURL provided to the factory. This instance
     * uses a cache shared by the other exposed APIs members.
     *
     * @constant {module:alliance}
     */
    exports.alliance = require('./alliance')(internal);

    /**
     * This is an instance of `corporation` module configured to use the
     * datasource and baseURL provided to the factory. This instance
     * uses a cache shared by the other exposed APIs members.
     *
     * @constant {module:corporation}
     */
    exports.corporation = require('./corporation')(internal);

    return exports;
};

/**
 * Hand-written Promisified wrapper around generated ESI code.
 * This module returns a factory function that takes an optional datasource
 * string and base URL. If any parameter is not provided, the defaults are used.
 *
 * The factory function returns an object with properties that expose
 * instantiations of each sub-module for the ESI groups.
 *
 * @param {String} datasource The datasource string, defaults to `'tranquility'`
 * @param {String} baseURL The base URL of the ESI Swagger endpoint, which
 *   defaults to `'https://esi.tech.ccp.is/latest'`
 * @module eve_swagger_interface
 */
module.exports = function(datasource, baseURL) {
    var exports = {};
    var internal = require('./internal')(datasource, baseURL);

    /**
     * This is an instance of `alliance` module configured to use the
     * datasource and baseURL provided to the factory. This instance
     * uses a cache shared by the other exposed APIs members.
     *
     * @constant {module:alliance}
     */
    exports.alliance = require('./alliance')(internal);

    /**
     * This is an instance of `corporation` module configured to use the
     * datasource and baseURL provided to the factory. This instance
     * uses a cache shared by the other exposed APIs members.
     *
     * @constant {module:corporation}
     */
    exports.corporation = require('./corporation')(internal);

    /**
     * This is an instance of `incursions` module configured to use the
     * datasource and baseURL provided to the factory. This instance
     * uses a cache shared by the other exposed APIs members.
     *
     * @constant {module:incursions}
     */
    exports.incursions = require('./incursions')(internal);

    return exports;
};

Include incursions module in main exports


var postRequest = new XMLHttpRequest();
postRequest.onreadystatechange = function () {
    if (postRequest.readyState == 4) {
        if (postRequest.status == 200) {
            document.getElementById("result").innerText = postRequest.responseText;
        } else {
            document.getElementById("result").innerTest = "An error has occurred";
        }
    }
};
postRequest.open("POST", "api/greeter", true);
postRequest.setRequestHeader("Content-type", "application/json");
postRequest.send('["Sally","Harry","Fred"]');

var postRequest = new XMLHttpRequest();
postRequest.onreadystatechange = function () {
    if (postRequest.readyState == 4) {
        if (postRequest.status == 200) {
            document.getElementById("result").textContent = postRequest.responseText;
        } else {
            document.getElementById("result").textContent = "An error has occurred";
        }
    }
};
postRequest.open("POST", "api/greeter", true);
postRequest.setRequestHeader("Content-type", "application/json");
postRequest.send('["Sally","Harry","Fred"]');

Fix JavaScript to use correct property


Template.allActivities.created = function () {
  // Get reference to template instance
  var instance = this;

  // Subscribe to all activities and related collections
  instance.subscribe("activitiesComposite");
};

Template.allActivities.helpers({
  "activities": function () {
    // Query Activities collection for all activities
    var activities = Activities.find().fetch();

    // Create a placeholder array for resident objects
    var activitiesArray = [];

    // Iterate through activities
    activities.forEach(function (activity) {
      // set resident names, type, duration, and date values
      var activityObject = {
        residents: activity.residentNames(),
        type: activity.activityType(),
        duration: activity.duration,
        date: activity.activityDate
      };

      // Add activity object to residents list
      activitiesArray.push(activityObject);
    });

    return activitiesArray;
  },
  'tableSettings': function () {
    var tableSettings = {
      showFilter: false
    };

    return tableSettings;
  }
});

Add activities and tableSettings helpers


export { createChainCreator } from './factories';

import { createChainCreator } from './factories';
import { createChain } from './chain';

import { toGroovy, toBoundGroovy } from './groovy';

export const groovy = createChainCreator(createChain, toGroovy);
export const gremlin = createChainCreator(createChain, toBoundGroovy);

export default {
  groovy,
  gremlin,
};

export { createChainCreator } from './factories';

import { createChainCreator } from './factories';
import { createChain } from './chain';

import { toGroovy } from './groovy';
import { toBoundGroovy } from './gremlin-groovy';

export const groovy = createChainCreator(createChain, toGroovy);
export const gremlin = createChainCreator(createChain, toBoundGroovy);

export default {
  groovy,
  gremlin,
};

Fix erroneous import of gremlin-groovy chain


/**
 * External imports
 */
import libdebug from 'debug';

// create debug logger
const debug = libdebug('lgho:root');

export default function create(options = {}) {
  debug('options %j', options);
}

/**
 * External imports
 */
import koa from 'koa';
import libdebug from 'debug';

// create debug logger
const debug = libdebug('lgho:root');

export default function create(options = {}) {
  debug('options %j', options);

  return koa();
}

Update app factory to return a Koa application.


// These are the primary log levels.
// Your logger object has a method for each of these.
var LOG_LEVELS = {
	emergency : 7,
	alert     : 6,
	critical  : 5,
	error     : 4,
	warning   : 3,
	notice    : 2,
	info      : 1,
	debug     : 0,
}

// Need these to be shared across triton and corvair (can actually be modified
// by the logging modules).
var config = (global._TRITON_CONFIG || (global._TRITON_CONFIG = {
	main: {
		baseLevel: 'error',
		levels: LOG_LEVELS,
		colors: {
			emergency : 'red',
			alert     : 'red',
			critical  : 'red',
			error     : 'red',
			warning   : 'yellow',
			notice    : 'yellow',
			info      : 'green',
			debug     : 'blue',
		},
	},

	// This config is for an internal logger used by the `time` method.
	stats: {
		baseLevel: 'slow',
		levels: {
			slow: 2,
			fine: 1,
			fast: 0,
		},
		colors: {
			slow: 'red',
			fine: 'yellow',
			fast: 'green',
		},
	},
}));

module.exports = { config };

// These are the primary log levels.
// Your logger object has a method for each of these.
var LOG_LEVELS = {
	emergency : 7,
	alert     : 6,
	critical  : 5,
	error     : 4,
	warning   : 3,
	notice    : 2,
	info      : 1,
	debug     : 0,
}

// Need these to be shared across triton and corvair (can actually be modified
// by the logging modules).
var config = (global._TRITON_CONFIG || (global._TRITON_CONFIG = {
	main: {
		baseLevel: 'error',
		levels: LOG_LEVELS,
		colors: {
			emergency : 'red',
			alert     : 'red',
			critical  : 'red',
			error     : 'red',
			warning   : 'yellow',
			notice    : 'yellow',
			info      : 'green',
			debug     : 'blue',
		},
	},

	// This config is for an internal logger used by the `time` method.
	stats: {
		// TODO: Some day, when slow times are rare, we should set
		// this to 'slow' in production to surface performance issues.
		baseLevel: 'none',
		levels: {
			none: 3, // Not used.  Disables in production.
			slow: 2,
			fine: 1,
			fast: 0,
		},
		colors: {
			slow: 'red',
			fine: 'yellow',
			fast: 'green',
		},
	},
}));

module.exports = { config };

Disable all timing output in production for now


var passport = require('passport');

exports.setRoutes = function(app, config) {
    app.get('/login', function(req, res) {
        res.render('login.html', { errors: req.flash('error') });
    });

    app.post('/login',
        passport.authenticate('local', {
            failureRedirect : config.app.namespace + '/login',
            failureFlash    : true
        }),
        function(req, res) {
            res.redirect(req.session.returnTo || config.app.namespace);
        }
    );

    app.get('/logout', function(req, res) {
        req.logout();
        res.redirect(req.header('Referrer') || config.app.namespace);
    });
};

var passport = require('passport');

exports.setRoutes = function(app, config) {
    app.get('/login', function(req, res) {
        res.render('login.html', { errors: req.flash('error') });
    });

    app.post('/login',
        passport.authenticate('local', {
            failureRedirect : res.locals.namespace + '/login',
            failureFlash    : true
        }),
        function(req, res) {
            res.redirect(req.session.returnTo || res.locals.namespace);
        }
    );

    app.get('/logout', function(req, res) {
        req.logout();
        res.redirect(req.header('Referrer') || res.locals.namespace);
    });
};

Use res.locals.namespace instead of config.app.namespace


define([
    "src/tree"
], function(Tree) {
    var hr = codebox.require("hr/hr");
    var menu = codebox.require("utils/menu");
    var dialogs = codebox.require("utils/dialogs");
    var File = codebox.require("models/file");

    var Panel = hr.View.extend({
        className: "component-files-panel",

        initialize: function(options) {
            Panel.__super__.initialize.apply(this, arguments);

            // Add files tree
            this.tree = new Tree({
                model: codebox.root
            });
            this.tree.appendTo(this);

            // Context menu
            menu.add(this.$el, this.getContextMenu.bind(this));
        },

        render: function() {
            this.tree.refresh();

            return this.ready();
        },

        // Generate the context menu items
        getContextMenu: function() {
            var items = [
                {
                    label: "New File",
                    click: function() {
                        return dialogs.prompt("Create a new file", "untitled")
                        .then(function(n) {
                            return File.create("./", n);
                        });
                    }
                },
                {
                    label: "New Folder",
                    click: function() {

                    }
                }
            ];

            return items;
        },
    });

    return Panel;
});

define([
    "src/tree"
], function(Tree) {
    var hr = codebox.require("hr/hr");
    var menu = codebox.require("utils/menu");
    var dialogs = codebox.require("utils/dialogs");
    var File = codebox.require("models/file");

    var Panel = hr.View.extend({
        className: "component-files-panel",

        initialize: function(options) {
            Panel.__super__.initialize.apply(this, arguments);

            // Add files tree
            this.tree = new Tree({
                model: codebox.root
            });
            this.tree.appendTo(this);

            // Context menu
            menu.add(this.$el, this.getContextMenu.bind(this));
        },

        render: function() {
            this.tree.refresh();

            return this.ready();
        },

        // Generate the context menu items
        getContextMenu: function() {
            var that = this;

            var items = [
                {
                    label: "New File",
                    click: function() {
                        return dialogs.prompt("Create a new file", "untitled")
                        .then(function(n) {
                            return File.create("./", n);
                        })
                        .then(that.update.bind(that));
                    }
                },
                {
                    label: "New Folder",
                    click: function() {
                        return dialogs.prompt("Create a new folder", "untitled")
                        .then(function(n) {
                            return File.mkdir("./", n);
                        })
                        .then(that.update.bind(that));
                    }
                }
            ];

            return items;
        },
    });

    return Panel;
});

Add action to create folder in root


app.service('Domains', ['$rootScope', '$q', '$resource', '$log',
    function($rootScope, $q, $resource, $log) {
        var service = {};

        return service;
    }
]);

app.factory('Domain', ['$resource', function($resource) {
    return $resource('/domain/:id'{ id: '@_id' }, {
        update: {
            method: 'PUT'
        }
    });
}]);

app.factory('Domains', ['$resource', function($resource) {
    return $resource('/domain/:id', { id: '@id' }, {
        update: {
            method: 'PUT'
        }
    });
}]);

Use a factory instead of a service


import { STATUS } from './cache';

/**
 * Given a list of models, preload them and set them in the cache.
 * TODO: Add support for dependencies. E.g. to know if we can fetch
 * subscription model or organization model, we have fetch the user model first.
 * @param {Array} models
 * @param {Function} api
 * @param {Map} cache
 * @return {Promise<Array>}
 */
export const loadModels = async (models = [], { api, cache }) => {
    const result = await Promise.all(
        models.map((model) => {
            // Special case to not re-fetch the model if it exists. This can happen for
            // the user model which is set at login.
            if (cache.has(model.key)) {
                return cache.get(model.key).value;
            }
            return model.get(api);
        })
    );

    models.forEach((model, i) => {
        cache.set(model.key, {
            value: result[i],
            status: STATUS.RESOLVED
        });
    });

    return result;
};

import { STATUS } from './cache';

export const loadModels = async (models = [], { api, cache, useCache = true }) => {
    const result = await Promise.all(
        models.map((model) => {
            // Special case to not re-fetch the model if it exists. This can happen for
            // the user model which is set at login.
            if (useCache && cache.has(model.key)) {
                return cache.get(model.key).value;
            }
            return model.get(api);
        })
    );

    models.forEach((model, i) => {
        cache.set(model.key, {
            value: result[i],
            status: STATUS.RESOLVED
        });
    });

    return result;
};

Add useCache option to loadModels


import React, { PropTypes, Component } from 'react';
import MarketPickerContainer from '../_common/MarketPickerContainer';
import InputGroup from '../_common/InputGroup';

export default class AssetPickerFilter extends Component {

	static propTypes = {
		actions: PropTypes.object.isRequired,
		filter: PropTypes.object.isRequired,
	};

	render() {
		const { actions, filter } = this.props;

		const onSearchQueryChange = e => actions.updateAssetPickerSearchQuery(e.target.value);
		const onSubmarketChange = e => actions.updateAssetPickerSubmarket(e);

		const showOnlyTickTradable = false;

		return (
			<fieldset>
				<MarketPickerContainer
					onChange={onSubmarketChange}
					allOptionShown
					showMarkets={showOnlyTickTradable ? ['Forex', 'Randoms'] : null}
					value={filter.submarket}
				/>
				<InputGroup
					className="asset-search"
					type="search"
					placeholder="Search for assets"
					onChange={onSearchQueryChange}
					autoFocus
				/>
			</fieldset>
		);
	}
}

import React, { PropTypes, Component } from 'react';
import MarketPickerContainer from '../_common/MarketPickerContainer';
import InputGroup from '../_common/InputGroup';

export default class AssetPickerFilter extends Component {

	static propTypes = {
		actions: PropTypes.object.isRequired,
		filter: PropTypes.object.isRequired,
	};

	render() {
		const { actions, filter } = this.props;

		const onSearchQueryChange = e => actions.updateAssetPickerSearchQuery(e.target.value);
		const onSubmarketChange = e => actions.updateAssetPickerSubmarket(e);

		const showOnlyTickTradable = false;

		return (
			<fieldset>
				<MarketPickerContainer
					onChange={onSubmarketChange}
					allOptionShown
					showMarkets={showOnlyTickTradable ? ['Forex', 'Randoms'] : null}
					value={filter.submarket}
				/>
				<InputGroup
					className="asset-search"
					defaultValue={filter.query}
					type="search"
					placeholder="Search for assets"
					onChange={onSearchQueryChange}
					autoFocus
				/>
			</fieldset>
		);
	}
}

Fix one more bug with asset picker


import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import Box from '../box';
import cx from 'classnames';
import theme from './theme.css';

class Container extends PureComponent {
  render() {
    const { children, className, fixed, ...others } = this.props;

    const classNames = cx(
      theme['container'],
      {
        [theme['is-fixed']]: fixed,
      },
      className,
    );

    return (
      <Box {...others} boxSizing="content-box" className={classNames}>
        {children}
      </Box>
    );
  }
}

Container.propTypes = {
  fixed: PropTypes.bool,
};

export default Container;

import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import Box from '../box';
import cx from 'classnames';
import theme from './theme.css';

class Container extends PureComponent {
  render() {
    const { children, className, fixed, ...others } = this.props;

    const classNames = cx(
      theme['container'],
      {
        [theme['is-fixed']]: fixed,
      },
      className,
    );

    return (
      <Box {...others} boxSizing="content-box" className={classNames}>
        {children}
      </Box>
    );
  }
}

Container.propTypes = {
  children: PropTypes.node,
  fixed: PropTypes.bool,
};

export default Container;

Add `children` to the prop types


import { nextCoord } from './utils';

export function tile() {
  return pixelToTile({
    x: this.x,
    y: this.y,
  });
}

export function nextTile(tile, faceDirection) {
  tile = tile || this.tile;
  faceDirection = faceDirection || this.faceDirection;

  return nextCoord(tile, faceDirection, 1);
}

export function pixelToTile(pixelCoord) {
  return {
    x: Math.floor(pixelCoord.x / 32),
    y: Math.floor(pixelCoord.y / 32),
  };
}

export function tileToPixel(tileCoord) {
  return {
    x: (tileCoord.x * 32) + 16,
    y: (tileCoord.y * 32) + 16,
  };
}

export function alignToGrid(pixelCoord) {
  if (pixelCoord.x % 16 === 0 && pixelCoord.y % 16 === 0) return pixelCoord;

  // perhaps not the most efficient way to do this
  return tileToPixel(pixelToTile(pixelCoord));
}

import { nextCoord } from './utils';

export function tile(coord) {
  coord = coord || { x: this.x, y: this.y };

  return pixelToTile({
    x: coord.x,
    y: coord.y,
  });
}

export function nextTile(tile, faceDirection) {
  tile = tile || this.tile;
  faceDirection = faceDirection || this.faceDirection;

  return nextCoord(tile, faceDirection, 1);
}

export function pixelToTile(pixelCoord) {
  return {
    x: Math.floor(pixelCoord.x / 32),
    y: Math.floor(pixelCoord.y / 32),
  };
}

export function tileToPixel(tileCoord) {
  return {
    x: (tileCoord.x * 32) + 16,
    y: (tileCoord.y * 32) + 16,
  };
}

export function alignToGrid(pixelCoord) {
  if (pixelCoord.x % 16 === 0 && pixelCoord.y % 16 === 0) return pixelCoord;

  // perhaps not the most efficient way to do this
  return tileToPixel(pixelToTile(pixelCoord));
}

Allow function to be provided args


requirejs(["vendor/mithril"], function(mIgnore) {
    const root = document.body

    const Hello = {
        count: 0,
        increment: function() { Hello.count++ },
        view: function() {
            return m("main", [
                m("h1", {class: "title bw24 b--solid b--blue"}, "Click count " + Hello.count),
                m("button", { onclick: Hello.increment }, "Increment"),
            ])
        }
    }

    m.mount(root, Hello)
})

requirejs(["vendor/mithril"], function(mIgnore) {
    const root = document.body

    const Archive = {
        items: [],
        add: function() { Archive.items.push(Archive.editorContents); Archive.editorContents = "" },
        editorContents: "",
        view: function() {
            return m("main", [
                m("h1", {class: "title bw24 b--solid b--blue"}, "Item count " + Archive.items.length),
                m("textarea", { value: Archive.editorContents,  onchange: function (event) { Archive.editorContents = event.target.value } }),
                m("br"),
                m("button", { onclick: Archive.add }, "Add"),
                m("button", { onclick: function () { console.log("items", Archive.items) }}, "Log"),
            ])
        }
    }

    m.mount(root, Archive)
})

Save textarea to local archive


var http = require('http');
var urlparse = require('url').parse;

// simple page that acts as the OAuth endpoint
http.createServer(function(request, response) {
    var url = urlparse(request.url, true);
    if (url.query.code) {
        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write('<title>Authentication successful | cabdriver</title>');
        response.write('
Successfully authenticated
');
        response.write('
Copy the following code back to the terminal for cabdriver: ');
        response.write('' + url.query.code + '
');
        response.end('');
    } else {
        response.writeHead(401, {'Content-Type': 'text/html'});
        response.write('<title>Authentication failed | cabdriver</title>');
        response.end('
401 Not Authorized
');
    }
}).listen(process.env.PORT || 5000);

var http = require('http');
var urlparse = require('url').parse;

// simple page that acts as the OAuth endpoint
http.createServer(function(request, response) {
    var url = urlparse(request.url, true);
    if (url.path == '/jira') {
        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write('<title>Jira | cabdriver</title>');
        response.write('
Welcome Jira
');
        response.end('');
        return;
    }
    if (url.query.code) {
        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write('<title>Authentication successful | cabdriver</title>');
        response.write('
Successfully authenticated
');
        response.write('
Copy the following code back to the terminal for cabdriver: ');
        response.write('' + url.query.code + '
');
        response.end('');
    } else {
        response.writeHead(401, {'Content-Type': 'text/html'});
        response.write('<title>Authentication failed | cabdriver</title>');
        response.end('
401 Not Authorized
');
    }
}).listen(process.env.PORT || 5000);

Add 200 response for jira


function parseQueryString(query) {
	var vars = {};
	query = query.substring(1);  // remove leading '?'
	var pairs = query.replace(/\+/g,'%20').split('&');
	for(var i=0; i<pairs.length; ++i) {
		var name, value='';
		var n = pairs[i].indexOf('=');
		if(n === -1) name = decodeURIComponent(pairs[i]);
		else {
			name = decodeURIComponent(pairs[i].substring(0, n));
			value = decodeURIComponent(pairs[i].substring(n+1));
		}
		if(vars.hasOwnProperty(name)) {
			if(!Array.isArray(vars[name])) vars[name] = [vars[name]];
			vars[name].push(value);
		} else vars[name] = value;
	}
	return vars;
}

function setExercise(name, exercise, hints) {
	var h = document.getElementById('lesson-name');
	h.appendChild(document.createTextNode(name));
	document.title = name + ' - ' + document.title;

	var back = document.getElementById('back');
	back.href = document.location.href.split('?')[0];
	var again = document.getElementById('again');
	again.href = document.location.href;

	return jig = new TypeJig(exercise, 'exercise', 'answer', 'clock', hints);
}

function parseQueryString(query) {
	var vars = {};
	query = query.substring(1);  // remove leading '?'
	var pairs = query.replace(/\+/g,'%20').split('&');
	for(var i=0; i<pairs.length; ++i) {
		var name, value='';
		var n = pairs[i].indexOf('=');
		if(n === -1) name = decodeURIComponent(pairs[i]);
		else {
			name = decodeURIComponent(pairs[i].substring(0, n));
			value = decodeURIComponent(pairs[i].substring(n+1));
		}
		if(vars.hasOwnProperty(name)) {
			if(!Array.isArray(vars[name])) vars[name] = [vars[name]];
			vars[name].push(value);
		} else vars[name] = value;
	}
	return vars;
}

function setExercise(name, exercise, hints) {
	var h = document.getElementById('lesson-name');
	h.appendChild(document.createTextNode(name));
	document.title = name + ' - ' + document.title;

	var back = document.getElementById('back');
	back.href = 'form.html';
	var again = document.getElementById('again');
	again.href = document.location.href;

	return jig = new TypeJig(exercise, 'exercise', 'answer', 'clock', hints);
}

Fix "Back to Menu" link for Gutenberg drills


// Module dependencies
var debug = require('debug')('ruche:test:cli:atlernatives');
var expect = require('chai').expect;
var cli = require('../../lib/cli');
var fake = require('./util/fake');

/**
 * Test suite for cli:alternatives
 *
 * Compare the results of `cli.argv(command)` against expected scenarios.
 */
describe('cli:alternatives', function () {

  it('alternatives package should produce `alternatives` context', function () {
    var argv = fake.argv('ruche alternatives package');
    var result = cli.argv(argv);
    expect(result.context).to.equal('alternatives');
  });

  it('With no package should produce `alternatives` help', function () {
    var argv = fake.argv('ruche alternatives');
    var result = cli.argv(argv);
    expect(result.context).to.equal('help');
    expect(result.help).to.equal('alternatives');
  });

  it('should be called with only one package', function () {
    var argv = fake.argv('ruche alternatives pack1 pack2');
    var result = cli.argv(argv);
    expect(result.context).to.equal('help');
    expect(result.help).to.equal('alternatives');
  });

});

// Module dependencies
var debug = require('debug')('ruche:test:cli:atlernatives');
var expect = require('chai').expect;
var cli = require('../../lib/cli');
var fake = require('./util/fake');

/**
 * Test suite for cli:alternatives
 *
 * Compare the results of `cli.argv(command)` against expected scenarios.
 */
describe('cli:alternatives', function () {

  it('alternatives package should produce `alternatives` context', function () {
    var argv = fake.argv('ruche alternatives package');
    var result = cli.argv(argv);
    expect(result.context).to.equal('alternatives');
  });

  it('With no package should produce `alternatives` help', function () {
    var argv = fake.argv('ruche alternatives');
    var result = cli.argv(argv);
    expect(result.context).to.equal('help');
    expect(result.help).to.equal('alternatives');
  });

  it('should be called with only one package', function () {
    var argv = fake.argv('ruche alternatives pack1 pack2');
    var result = cli.argv(argv);
    expect(result.context).to.equal('help');
    expect(result.help).to.equal('alternatives');
  });

  it('could be called with --choice option', function () {
    var argv = fake.argv('ruche alternatives package --choice package-1-win32');
    var result = cli.argv(argv);
    expect(result.context).to.equal('alternatives');
    expect(result.package).to.equal('package');
    expect(result.choice).to.equal('package-1-win32');
  });

});

Add test for the alternative --choice options


'use strict';

// This is a client that produces load on hodor-net-server.

process.title = 'nodejs hodor client';

var net = require('net');

var BACKOFF = 1000;

function next() {
    var connected = false;
    var finished = false;
    var data = "";

    var client = net.connect(+process.env.HODOR_PORT, 'localhost', function () {
        connected = true;
    });

    client.setEncoding('utf-8');

    client.on('error', function (error) {
        console.log('unexpected error', error.message);
        setTimeout(next, BACKOFF);
    });
    client.on('data', function (_data) {
        data += _data;
    });
    client.on('finish', function () {
        finished = true;
    });
    client.on('end', function () {
        if (!connected) {
            console.log('unexpected end before connection');
            setTimeout(next, BACKOFF);
        } else if (data !== 'HODOR') {
            console.log('unexpected response', data);
            setTimeout(next, BACKOFF);
        } else if (!finished) {
            console.log('expected finish before end');
            setTimeout(next, BACKOFF);
        } else {
            next();
        }
    });

}

// Five concurrent requests
next();
next();
next();
next();
next();

'use strict';

// This is a client that produces load on hodor-net-server.

process.title = 'nodejs hodor client';

var net = require('net');
var debuglog = require('debuglog');
var log = debuglog('hodor-net-client');

var BACKOFF = 1000;

function next() {
    var connected = false;
    var finished = false;
    var data = "";

    var client = net.connect(+process.env.HODOR_PORT, 'localhost', function () {
        connected = true;
    });

    client.setEncoding('utf-8');

    client.on('error', function (error) {
        log('unexpected error', error.message);
        setTimeout(next, BACKOFF);
    });
    client.on('data', function (_data) {
        data += _data;
    });
    client.on('finish', function () {
        finished = true;
    });
    client.on('end', function () {
        if (!connected) {
            log('unexpected end before connection');
            setTimeout(next, BACKOFF);
        } else if (data !== 'HODOR') {
            log('unexpected response', JSON.stringify(data));
            setTimeout(next, BACKOFF);
        } else if (!finished) {
            log('expected finish before end');
            setTimeout(next, BACKOFF);
        } else {
            next();
        }
    });

}

// Five concurrent requests
next();
next();
next();
next();
next();

Use debuglog for test client


windmill.jsTest.require('shared.js');

// Namespace obj to contain our tests
windmillMain.test_waitForXHR = new function () {
  // Make the async XHR call
  this.test_xhrCall = function () {
    // Callback function -- sets temp flag to 'returned'
    var success = function () {
      windmillMain.tempData = 'returned';
    };
    fleegix.xhr.get(success, '/test.txt');
  };
  this.test_wait = windmillMain.shared.util.waitForTempData;
  this.test_afterWait = function () {
    jum.assertEquals('returned', windmillMain.tempData);
  };
  // Remove the node so we can run the test again
  this.teardown = function () {
    windmillMain.tempData = null;
  }
};

windmill.jsTest.require('shared.js');

// Namespace obj to contain our tests
windmillMain.test_waitForXHR = new function () {
  // Make the async XHR call
  this.test_xhrCall = function () {
    // Callback function -- sets temp flag to 'returned'
    var success = function () {
      windmillMain.tempData = 'returned';
    };
    fleegix.xhr.get(success, '/windmill-serv/jstest/data.json');
  };
  this.test_wait = windmillMain.shared.util.waitForTempData;
  this.test_afterWait = function () {
    jum.assertEquals('returned', windmillMain.tempData);
  };
  // Remove the node so we can run the test again
  this.teardown = function () {
    windmillMain.tempData = null;
  }
};

Load a file that actually exists on the filesystem.


'use strict';

module.exports = {
    app: {
        name: "OpenIt - Control your Raspberry Pi"
    },
    facebook: {
        clientID: "APP_ID",
        clientSecret: "APP_SECRET",
        callbackURL: "http://localhost:3000/auth/facebook/callback"
    },
    twitter: {
        clientID: "CONSUMER_KEY",
        clientSecret: "CONSUMER_SECRET",
        callbackURL: "http://localhost:3000/auth/twitter/callback"
    },
    github: {
        clientID: "APP_ID",
        clientSecret: "APP_SECRET",
        callbackURL: "http://localhost:3000/auth/github/callback"
    },
    google: {
        clientID: process.env.GOOGLE_APP_ID,
        clientSecret: process.env.GOOGLE_APP_SECRET,
        callbackURL: process.env.GOOGLE_CALLBACK
    }
}

'use strict';

module.exports = {
    app: {
        name: "OpenIt - Control your Raspberry Pi"
    },
    facebook: {
        clientID: "APP_ID",
        clientSecret: "APP_SECRET",
        callbackURL: "http://localhost:3000/auth/facebook/callback"
    },
    twitter: {
        clientID: "CONSUMER_KEY",
        clientSecret: "CONSUMER_SECRET",
        callbackURL: "http://localhost:3000/auth/twitter/callback"
    },
    github: {
        clientID: "APP_ID",
        clientSecret: "APP_SECRET",
        callbackURL: "http://localhost:3000/auth/github/callback"
    },
    google: {
        clientID: process.env.GOOGLE_APP_ID || "APP_ID" ,
        clientSecret: process.env.GOOGLE_APP_SECRET || "APP_SECRET",
        callbackURL: process.env.GOOGLE_CALLBACK || "http://localhost:3000/auth/google/callback"
    }
}

Add default values for google strategy


import compression from 'compression';
import express from 'express';
import proxy from 'http-proxy-middleware';

import serverRenderer from './renderer';

const app = express();
app.use(compression());

app.get('/', serverRenderer);
app.use(express.static('public'));

app.use('/api', proxy({
  target: 'http://api.douban.com',
  pathRewrite: { '^/api': '' },
  changeOrigin: true,
}));

console.log('\n[WARNING] movie-board is now running in PRODUCTION mode.'); // eslint-disable-line
app.listen(8080, () => {
  console.log('[INFO] movie-board is now listening at 8080...'); // eslint-disable-line
});

import compression from 'compression';
import express from 'express';
import path from 'path';
import proxy from 'http-proxy-middleware';

import serverRenderer from './renderer';

const app = express();
app.use(compression());

app.get('/', serverRenderer);
app.use(express.static('public'));

app.get('/movie/*', (req, res) => {
  res.sendFile(path.resolve(__dirname, '../public/index.html'));
});

app.get('/topic/*', (req, res) => {
  res.sendFile(path.resolve(__dirname, '../public/index.html'));
});

app.use('/api', proxy({
  target: 'http://api.douban.com',
  pathRewrite: { '^/api': '' },
  changeOrigin: true,
}));

console.log('\n[WARNING] movie-board is now running in PRODUCTION mode.'); // eslint-disable-line
app.listen(8080, () => {
  console.log('[INFO] movie-board is now listening at 8080...'); // eslint-disable-line
});

Set default value of movies


import GithubPackage from './github-package';

let pack;
const entry = {
  initialize() {
    pack = new GithubPackage({
      workspace: atom.workspace,
      project: atom.project,
      commandRegistry: atom.commands,
      notificationManager: atom.notificationManager,
      tooltips: atom.tooltips,
      styles: atom.styles,
      grammars: atom.grammars,
      config: atom.config,
      deserializers: atom.deserializers,

      confirm: atom.confirm.bind(atom),
      getLoadSettings: atom.getLoadSettings.bind(atom),

      configDirPath: atom.getConfigDirPath(),
    });
  },
};

module.exports = new Proxy(entry, {
  get(target, name) {
    if (pack && Reflect.has(pack, name)) {
      let item = pack[name];
      if (typeof item === 'function') {
        item = item.bind(pack);
      }
      return item;
    } else {
      return target[name];
    }
  },
});

import GithubPackage from './github-package';

let pack;
const entry = {
  initialize() {
    pack = new GithubPackage({
      workspace: atom.workspace,
      project: atom.project,
      commandRegistry: atom.commands,
      notificationManager: atom.notifications,
      tooltips: atom.tooltips,
      styles: atom.styles,
      grammars: atom.grammars,
      config: atom.config,
      deserializers: atom.deserializers,

      confirm: atom.confirm.bind(atom),
      getLoadSettings: atom.getLoadSettings.bind(atom),

      configDirPath: atom.getConfigDirPath(),
    });
  },
};

module.exports = new Proxy(entry, {
  get(target, name) {
    if (pack && Reflect.has(pack, name)) {
      let item = pack[name];
      if (typeof item === 'function') {
        item = item.bind(pack);
      }
      return item;
    } else {
      return target[name];
    }
  },
});

Fix that damn proptype error