function DeferredChain() {
  var self = this;
  this.chain = new Promise(function(accept, reject) {
    self._accept = accept;
    self._reject = reject;
  });

  this.await = new Promise(function() {
    self._done = arguments[0];
  });
  this.started = false;
};

DeferredChain.prototype.then = function(fn) {
  var self = this;
  this.chain = this.chain.then(function() {
    var args = Array.prototype.slice.call(arguments);

    return fn.apply(null, args);
  });

  return this;
};

DeferredChain.prototype.catch = function(fn) {
  var self = this;
  this.chain = this.chain.catch(function() {
    var args = Array.prototype.slice.call(arguments);

    return fn.apply(null, args);
  });

  return this;
};

DeferredChain.prototype.start = function() {
  this.started = true;
  this.chain = this.chain.then(this._done);
  this._accept();
  return this.await;
};

module.exports = DeferredChain;

function DeferredChain() {
  var self = this;
  this.chain = new Promise(function(accept, reject) {
    self._accept = accept;
    self._reject = reject;
  });

  this.await = new Promise(function() {
    self._done = arguments[0];
    self._error = arguments[1];
  });
  this.started = false;
};

DeferredChain.prototype.then = function(fn) {
  var self = this;
  this.chain = this.chain.then(function() {
    var args = Array.prototype.slice.call(arguments);

    return fn.apply(null, args);
  });
  this.chain = this.chain.catch(function(e) {
    self._error(e);
  });

  return this;
};

DeferredChain.prototype.catch = function(fn) {
  var self = this;
  this.chain = this.chain.catch(function() {
    var args = Array.prototype.slice.call(arguments);

    return fn.apply(null, args);
  });

  return this;
};

DeferredChain.prototype.start = function() {
  this.started = true;
  this.chain = this.chain.then(this._done);
  this._accept();
  return this.await;
};

module.exports = DeferredChain;

Fix issue where errors aren't being propagated.


#! /usr/bin/env node

var path = require("path");
var codebox = require("../lib");

codebox.start({
    port: 3000,
    root: path.resolve(__dirname, "../")
})
.fail(function(err) {
    console.log(err.stack || err.message || err);
});

#! /usr/bin/env node

var path = require("path");
var codebox = require("../lib");

codebox.start({
    port: 3000,
    root: path.resolve(__dirname, "../test/workspace")
})
.fail(function(err) {
    console.log(err.stack || err.message || err);
});

Use test workspace when testing the ide


// Karma configuration

// base path, that will be used to resolve files and exclude
basePath = '';

// list of files / patterns to load in the browser
files = [
  MOCHA,
  MOCHA_ADAPTER,
  'node_modules/chai/chai.js',
  'node_modules/sinon/pkg/sinon.js',
  'dist/sinon-doublist.js',
  'lib/jquery.js',
  'test/lib/sinon-doublist-fs/index.js',
  'test/mocha.js'
];

// test results reporter to use
// possible values: 'dots', 'progress', 'junit'
reporters = ['progress'];

// web server port
port = 9876;

// cli runner port
runnerPort = 9100;

// enable / disable colors in the output (reporters and logs)
colors = true;

// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_WARN;

// enable / disable watching file and executing tests whenever any file changes
autoWatch = false;

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

// If browser does not capture in given timeout [ms], kill it
captureTimeout = 60000;

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

// Karma configuration

// base path, that will be used to resolve files and exclude
basePath = '';

// list of files / patterns to load in the browser
files = [
  'node_modules/chai/chai.js',
  'node_modules/sinon/pkg/sinon.js',
  'dist/sinon-doublist.js',
  'lib/jquery.js',
  'test/lib/sinon-doublist-fs/index.js',
  'test/mocha.js'
];

frameworks = ['mocha'];

// test results reporter to use
// possible values: 'dots', 'progress', 'junit'
reporters = ['progress'];

// web server port
port = 9876;

// cli runner port
runnerPort = 9100;

// enable / disable colors in the output (reporters and logs)
colors = true;

// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_WARN;

// enable / disable watching file and executing tests whenever any file changes
autoWatch = false;

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

// If browser does not capture in given timeout [ms], kill it
captureTimeout = 60000;

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

Update adapter selection to 0.9.x


/** @babel */
/** @jsx etch.dom */

import etch from 'etch'

const style = {
  position: 'fixed',
  zIndex: 100000000,
  backgroundColor: 'white',
  minWidth: '100px',
  minHeight: '100px',
  top: '200px',
  left: '200px',
  maxWidth: '800px',
  maxHeight: '400px',
  overflow: 'auto',
  whiteSpace: 'pre',
  fontFamily: 'monospace',
  border: '3px solid black'
}

export default class DebuggerComponent {
  constructor ({data}) {
    this.data = data
    etch.initialize(this)
  }

  update ({data}) {
    this.data = data
    etch.update(this)
  }

  render () {
    return (
      <div style={style}> {JSON.stringify(this.data, null, '  ')}
      </div>)
  }
}

/** @babel */
/** @jsx etch.dom */

import etch from 'etch'

const defaultStyle = {
  position: 'fixed',
  zIndex: 100000000,
  backgroundColor: 'white',
  minWidth: '100px',
  minHeight: '100px',
  top: '200px',
  left: '200px',
  maxWidth: '800px',
  maxHeight: '400px',
  overflow: 'auto',
  whiteSpace: 'pre',
  fontFamily: 'monospace',
  border: '3px solid black'
}

export default class DebuggerComponent {
  constructor (props) {
    this.props = props
    etch.initialize(this)
  }

  update (props) {
    this.props = props
    etch.update(this)
  }

  render () {
    const {data, style, ...others} = this.props
    const finalStyle = {
      ...defaultStyle,
      ...style
    }

    return
{JSON.stringify(data, null, '  ')}

  }
}

Allow DebuggerComponent to take external props


/* globals I18n LocalTime */

if (I18n.translations.nl) {
  LocalTime.config.i18n['nl'] = {
    date: {
      dayNames: I18n.translations.nl.date.day_names,
      abbrDayNames: I18n.translations.nl.date.abbr_day_names,
      monthNames: I18n.translations.nl.date.month_names,
      abbrMonthNames: I18n.translations.nl.date.abbr_month_names
    }
  };
}

/* globals I18n LocalTime */

if (I18n.translations.nl) {
  LocalTime.config.i18n['nl'] = {
    date: {
      dayNames: I18n.translations.nl.date.day_names,
      abbrDayNames: I18n.translations.nl.date.abbr_day_names,
      monthNames: I18n.translations.nl.date.month_names.slice(1),
      abbrMonthNames: I18n.translations.nl.date.abbr_month_names.slice(1)
    }
  };
}

Fix NL local-time months names being off-by-one


module.exports = function(sails) {
    return {
        initialize: function(cb) {
            sails.on('app:bootstrap', function() {
                LogService.create('System started', LogService.TYPES.EVENT);
            });

            sails.config.beforeShutdown = function(cb) {
                LogService.create('System stopped', LogService.TYPES.EVENT);
            };

            cb();
        }
    };
};

module.exports = function(sails) {
    return {
        initialize: function(cb) {
            sails.on('app:bootstrap', function() {
                LogService.create('System started', LogService.TYPES.EVENT);
            });

            sails.config.beforeShutdown = function(cb) {
                LogService.create('System stopped', LogService.TYPES.EVENT).then(function() {
                    cb();
                });
            };

            cb();
        }
    };
};

Fix not shutting down after last change.


var path = require("path")

module.exports = {
  url : "http://registry.npmjs.org/npm/",
  pkg : require(path.join(__dirname, "../package.json")),
  dirname : {
    current : path.join(__dirname, "../current"),
    src : path.join(__dirname, "../src"),
    npm : path.join(__dirname, "../npm")
  }
}

var path = require("path")
var home = process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME']
var npmbrew = path.join(home, ".npmbrew")

module.exports = {
  url : "http://registry.npmjs.org/npm/",
  pkg : require(path.join(__dirname, "../package.json")),
  dirname : {
    current : path.join(npmbrew, "../current"),
    src : path.join(npmbrew, "../src"),
    npm : path.join(npmbrew, "../npm")
  }
}

Move npmbrew to home path


Clean up, Clean up, Clean up!


chrome.runtime.onMessage.addListener( function(request, sender, sendResponse){
    var click_event = new MouseEvent('click', {
        'view': window,
        'bubbles': true,
        'cancelable': true
    });
    switch(request.action){
        case 'NEXT-MK':
            document.getElementsByClassName('control-next')[0].dispatchEvent(click_event);
            break;
        case 'PREV-MK':
            document.getElementsByClassName('control-prev')[0].dispatchEvent(click_event);
            break;
        case 'PLAY-PAUSE-MK':
        case 'STOP-MK':
            if ( document.getElementsByClassName('control-play').length > 0 )
                document.getElementsByClassName('control-play')[0].dispatchEvent(click_event);
            else
                document.getElementsByClassName('control-pause')[0].dispatchEvent(click_event);
            break;
    }
});

chrome.runtime.onMessage.addListener( function(request, sender, sendResponse){
    var click_event = new MouseEvent('click', {
        'view': window,
        'bubbles': true,
        'cancelable': true
    });
    switch(request.action){
        case 'NEXT-MK':
            document.getElementsByClassName('control-next')[0].dispatchEvent(click_event);
            break;
        case 'PREV-MK':
            document.getElementsByClassName('control-prev')[0].dispatchEvent(click_event);
            break;
        case 'STOP-MK':
            if ( document.getElementsByClassName('control-pause').length > 0 )
                document.getElementsByClassName('control-pause')[0].dispatchEvent(click_event);
        case 'PLAY-PAUSE-MK':
            if ( document.getElementsByClassName('control-play').length > 0 )
                document.getElementsByClassName('control-play')[0].dispatchEvent(click_event);
            else
                document.getElementsByClassName('control-pause')[0].dispatchEvent(click_event);
            break;
    }
});

Stop button should only stop.


var Topic = require('../core/Topic');
var DuplexStream = require('stream').Duplex;

/**
 * Publish a connected ROS topic to a duplex
 * stream. This stream can be piped to, which will
 * publish to the topic
 */
Topic.prototype.toStream = function(transform) {
    var topic = this;
    var hasTransform = typeof transform === 'function';

    var stream = new DuplexStream({
        objectMode: true
    });
    stream._read = function() {};

    // Publish to the topic if someone pipes to stream
    stream._write = function(chunk, encoding, callback) {
        if (hasTransform) {
            chunk = transform(chunk);
        }
        if (chunk) {
            topic.publish(chunk);
        }
        callback();
    };

    this.subscribe(function(message) {
        stream.push(message);
    });
    this.on('unsubscribe', stream.push.bind(stream, null));

    return stream;
};

module.exports = Topic;

var Topic = require('../core/Topic');
var DuplexStream = require('stream').Duplex;

/**
 * Publish a connected ROS topic to a duplex
 * stream. This stream can be piped to, which will
 * publish to the topic
 *
 * @options
 *   * subscribe: whether to subscribe to the topic and start emitting
 *              Data
 *   * publish: whether to register the stream as a publisher to the topic
 *   * transform: a function to change the data to be published
 *              or filter it if false is returned
 */
Topic.prototype.toStream = function(options) {
    options = options || {subscribe: true, publish: true};

    var topic = this;
    var hasTransform = typeof options.transform === 'function';

    var stream = new DuplexStream({
        objectMode: true
    });
    stream._read = function() {};

    // Publish to the topic if someone pipes to stream
    stream._write = function(chunk, encoding, callback) {
        if (hasTransform) {
            chunk = options.transform(chunk);
        }
        if (chunk === false) {
            topic.publish(chunk);
        }
        callback();
    };

    if (options.subscribe) {
        this.subscribe(function(message) {
            stream.push(message);
        });
        this.on('unsubscribe', stream.push.bind(stream, null));
    }

    if (options.publish) {
        this.advertise();
    }

    return stream;
};

module.exports = Topic;

Make registering as a subscriber or publisher an option for the streaming API


var lint = require('./lint');
var clean = require('./clean');
var compile = require('./compile');
var copy = require('./copy');

var runSequence = require('run-sequence');

exports.config = function(gulp, packageName, source, libraries, assets, debugTarget, releaseTarget, useLint) {
	lint.config(gulp, source);
	clean.config(gulp, debugTarget, releaseTarget);
	compile.config(gulp, packageName, source, debugTarget, releaseTarget);
	copy.config(gulp, source, libraries, assets, debugTarget, releaseTarget);

	gulp.task('build', ['build.debug']);

	gulp.task('build.debug', function(done) {
		if (useLint) {
			runSequence('lint',
						'clean.debug',
						'compile.debug',
						'copy.debug',
						done);
		} else {
			runSequence('clean.debug',
						'compile.debug',
						'copy.debug',
						done);
		}
	});

	gulp.task('build.release', function(done) {
		if (useLint) {
			runSequence('lint',
						'clean.release',
						'compile.release',
						'copy.release',
						done);
		} else {
			runSequence('clean.release',
						'compile.release',
						'copy.release',
						done);
		}
	});
};

var _ = require('lodash');

var lint = require('./lint');
var clean = require('./clean');
var compile = require('./compile');
var copy = require('./copy');

var runSequence = require('run-sequence');

exports.config = function(gulp, packageName, source, libraries, assets, debugTarget, releaseTarget, useLint) {
	if (_.isUndefined(useLint)) {
		useLint = true;
	}

	lint.config(gulp, source);
	clean.config(gulp, debugTarget, releaseTarget);
	compile.config(gulp, packageName, source, debugTarget, releaseTarget);
	copy.config(gulp, source, libraries, assets, debugTarget, releaseTarget);

	gulp.task('build', ['build.debug']);

	gulp.task('build.debug', function(done) {
		if (useLint) {
			runSequence('lint',
						'clean.debug',
						'compile.debug',
						'copy.debug',
						done);
		} else {
			runSequence('clean.debug',
						'compile.debug',
						'copy.debug',
						done);
		}
	});

	gulp.task('build.release', function(done) {
		if (useLint) {
			runSequence('lint',
						'clean.release',
						'compile.release',
						'copy.release',
						done);
		} else {
			runSequence('clean.release',
						'compile.release',
						'copy.release',
						done);
		}
	});
};

Set useLint to true by default.


/*
  Returns letters with currencies to shorten them.
  Taken from: http://stackoverflow.com/questions/36734201/how-to-convert-numbers-to-million-in-javascript
 */
export default function currencyRounder(rawValue) {

  // Nine Zeroes for Billions
  return Math.abs(Number(rawValue)) >= 1.0e+9

    ? Math.round(Math.abs(Number(rawValue)) / 1.0e+9) + "B"
    // Six Zeroes for Millions
    : Math.abs(Number(rawValue)) >= 1.0e+6

      ? Math.round(Math.abs(Number(rawValue)) / 1.0e+6) + "M"
      // Three Zeroes for Thousands
      : Math.abs(Number(rawValue)) >= 1.0e+3

        ? Math.round(Math.abs(Number(rawValue)) / 1.0e+3) + "K"

        // Otherwise return the number
        : Math.abs(Number(rawValue));
}

/*
  Returns letters with currencies to shorten them.
  Taken from: http://stackoverflow.com/questions/36734201/how-to-convert-numbers-to-million-in-javascript
 */
export default function currencyRounder(rawValue) {
    if (Math.abs(Number(rawValue)) >= 1.0e+9) {
        return Math.round(Math.abs(Number(rawValue)) / 1.0e+9) + "B";
    }
    if (Math.abs(Number(rawValue)) >= 1.0e+6){
        return Math.round(Math.abs(Number(rawValue)) / 1.0e+6) + "M";
    }
    if (Math.abs(Number(rawValue)) >= 1.0e+3) {
        return Math.round(Math.abs(Number(rawValue)) / 1.0e+3) + "K";
    }
    return Math.abs(Number(rawValue));
}

Refactor function for rounding currency


'use strict';

var enabled = require('enabled');

/**
 * Bare minimum browser version of diagnostics. It doesn't need fancy pancy
 * detection algorithms. The code is only enabled when *you* enable it for
 * debugging purposes.
 *
 * @param {String} name Namespace of the diagnostics instance.
 * @returns {Function} The logger.
 * @api public
 */
module.exports = function factory(name) {
  if (!enabled(name)) return function diagnopes() {};

  return function diagnostics() {
    var args = Array.prototype.slice.call(arguments, 0);
    args.unshift(name);

    //
    // So yea. IE8 doesn't have an apply so we need a work around to puke the
    // arguments in place.
    //
    try { Function.prototype.apply.call(console.log, console, args); }
    catch (e) {}
  };
};

'use strict';

var enabled = require('enabled');

/**
 * Bare minimum browser version of diagnostics. It doesn't need fancy pancy
 * detection algorithms. The code is only enabled when *you* enable it for
 * debugging purposes.
 *
 * @param {String} name Namespace of the diagnostics instance.
 * @returns {Function} The logger.
 * @api public
 */
module.exports = function factory(name) {
  if (!enabled(name)) return function diagnopes() {};

  return function diagnostics() {
    var args = Array.prototype.slice.call(arguments, 0);

    //
    // We cannot push a value as first argument of the argument array as
    // console's formatting %s, %d only works on the first argument it receives.
    // So in order to prepend our namespace we need to override and prefix the
    // first argument.
    //
    args[0] = name +': '+ args[0];

    //
    // So yea. IE8 doesn't have an apply so we need a work around to puke the
    // arguments in place.
    //
    try { Function.prototype.apply.call(console.log, console, args); }
    catch (e) {}
  };
};

Make sure that formatting of %s still works as intended


/**
 * this is TestGuessReturn.
 */
export default class TestGuessReturn {
  method1(){
    return 123;
  }

  method2(){
    return [123, 456];
  }

  method3(){
    return {x1: 123, x2: 'text'};
  }

  method4(){
    return `text`;
  }
}

/**
 * this is TestGuessReturn.
 */
export default class TestGuessReturn {
  method1(){
    return 123;
  }

  method2(){
    return [123, 456];
  }

  method3(){
    return {x1: 123, x2: 'text'};
  }

  method4(){
    return `text`;
  }

  method5(){
    const obj = {}
    return {...obj}
  }
}

Add test to show parser crash.


/*
 * Copyright 2016 Studentmediene i Trondheim AS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

angular.module('momusApp.resources')
    .factory('Person', $resource => {
        return $resource('/api/person/:id/:resource',
            {
                id: '@id'
            },
            {
                me: { method: 'GET' , params: {id: 'me'}, cache: true },
                updateFavouritesection: {method: 'PATCH', params: {id: 'me', resource: 'favouritesection'} },
                myPhoto: { method: 'GET', params: {id: 'me', resource: 'photo'} },
                photo: { method: 'GET', params: {resource: 'photo'}, bypassInterceptor: true}
            })
    });

/*
 * Copyright 2016 Studentmediene i Trondheim AS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

angular.module('momusApp.resources')
    .factory('Person', $resource => {
        return $resource('/api/person/:id/:resource',
            {
                id: '@id'
            },
            {
                me: { method: 'GET' , params: {id: 'me'}, cache: true },
                updateFavouritesection: {method: 'PATCH', params: {id: 'me', resource: 'favouritesection'} }
            })
    });

Remove person resource methods for photo


angular.module( 'sample.home', [
'auth0'
])
.controller( 'HomeCtrl', function HomeController( $scope, auth, $http, $location, store ) {

  $scope.auth = auth;

  $scope.callApi = function() {
    // Just call the API as you'd do using $http
    $http({
      url: 'http://localhost:3001/secured/ping',
      method: 'GET'
    }).then(function() {
      alert("We got the secured data successfully");
    }, function(response) {
      if (response.status == -1) {
        alert("Please download the API seed so that you can call it.");
      }
      else {
        alert(response.data);
      }
    });
  }

  $scope.logout = function() {
    auth.signout();
    store.remove('profile');
    store.remove('token');
    $location.path('/login');
  }

});

angular.module('sample.home', [
    'auth0'
  ])
  .controller('HomeCtrl', function HomeController($scope, auth, $http,
    $location, store) {

    $scope.auth = auth;

    $scope.callApi = function() {
      // Just call the API as you'd do using $http
      $http({
        url: '/secured/ping',
        method: 'GET'
      }).then(function() {
        alert("We got the secured data successfully");
      }, function(response) {
        if (response.status == -1) {
          alert("Please download the API seed so that you can call it.");
        } else {
          alert(response.data);
        }
      });
    }

    $scope.logout = function() {
      auth.signout();
      store.remove('profile');
      store.remove('token');
      $location.path('/login');
    }

  });

Format and update the secure ping url


"use strict"

const QueryHandler = require('./queryHandler');
const AdminHandler = require('../../router/handler/adminHandler');

class AdminQueryHandler extends QueryHandler {}

AdminQueryHandler.allowAccess = AdminHandler.allowAccess;

module.exports = AdminQueryHandler;

"use strict"

const QueryHandler = require('./queryHandler');
const AdminHandler = require('../../router/handler/adminHandler');

class AdminQueryHandler extends QueryHandler {}

// Use the AdminHandler function to control Access.
AdminQueryHandler.prototype.allowAccess = AdminHandler.prototype.allowAccess;

module.exports = AdminQueryHandler;

Correct AdminQueryHandler allowAccess function to be set on prototype


const ua = typeof navigator === 'undefined'? '' : navigator.userAgent;

export const isTrident = ua.indexOf('Trident') > -1;
export const isEdge = ua.indexOf('Edge') > -1;
export const isIos = /iPad|iPhone|iPod/.test(ua) && typeof MSStream === 'undefined';

const ua = typeof navigator === 'undefined'? '' : navigator.userAgent,
    platform = typeof navigator === 'undefined'? '' : navigator.platform;

export const isTrident = ua.indexOf('Trident') > -1;
export const isEdge = ua.indexOf('Edge') > -1;
export const isIos = /iPad|iPhone|iPod/.test(platform);

Use navigator.platform to detect ios in desktop mode


import { sourceNode } from './sourceNode';
import { notNull } from '../utils';

export default {
  Document: ({node, figure, compile, options}) => {
    figure.children = node.body.map((child) => compile(child)).filter(notNull);

    if (options.asModule) {
      return sourceNode(node.loc, [
        `var Monkberry = require('monkberry');\n`,
        figure.generate(), `\n`,
        `module.exports = ${figure.name};\n`
      ]);
    } else {
      return sourceNode(node.loc, [
        figure.generate(), `\n`,
        `window.${figure.name} = ${figure.name};\n`
      ]);
    }
  }
};

import { sourceNode } from './sourceNode';
import { notNull } from '../utils';

export default {
  Document: ({node, figure, compile, options}) => {
    figure.children = node.body.map((child) => compile(child)).filter(notNull);

    if (options.asModule) {
      return sourceNode(node.loc, [
        `var Monkberry = require('monkberry');\n`,
        figure.generate(), `\n`,
        `exports.default = ${figure.name};\n`
      ]);
    } else {
      return sourceNode(node.loc, [
        figure.generate(), `\n`,
        `window.${figure.name} = ${figure.name};\n`
      ]);
    }
  }
};

Fix bug with custom tag importing.


c = Object(Symbol());
var y = { [e = c]:(class {}) };
print('Pass');

Add copyright to test file


if (window == top) {
  chrome.extension.onRequest.addListener(function(req, sender, sendResponse) {
    if (req.supported) {
      sendResponse(true);
    } else if (req.tickets) {
      sendResponse(findOpenTickets());
    }
  });
}

var findOpenTickets = function() {
  var title = $(".js-issue-title").text();
  var id = $(".gh-header-number").text().substr(1);
  var type = "feature";
  if ($(".sidebar-labels .label[title='bug']").length > 0) {
    type = "bug"
  }

  return [{type: type, title: title, id: id}];
}

if (window == top) {
  chrome.extension.onRequest.addListener(function(req, sender, sendResponse) {
    if (req.supported) {
      sendResponse(true);
    } else if (req.tickets) {
      sendResponse(findOpenTickets());
    }
  });
}

var findOpenTickets = function() {
  if ($(".gh-header-number").length > 0) {
    var title = $(".js-issue-title").text();
    var id = $(".gh-header-number").text().substr(1);
    var type = "feature";
    if ($(".sidebar-labels .label[title='bug']").length > 0) {
      type = "bug"
    }
    return [{type: type, title: title, id: id}];
  } else {
    return [];
  }
}

Return empty list if it can't find a ticket


/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var d3 = require('d3');

var Drawing = require('../../components/drawing');
var ErrorBars = require('../../components/errorbars');

module.exports = function style(gd) {
    var s = d3.select(gd).selectAll('g.trace.scatter');

    s.style('opacity', function(d) {
        return d[0].trace.opacity;
    });

    s.selectAll('g.points')
        .each(function(d) {
            var el = d3.select(this);
            var pt = el.selectAll('path.point');
            var trace = d.trace || d[0].trace;

            pt.call(Drawing.pointStyle, trace);

            if(trace.customdata) {
                pt.each(function(cd) {
                    d3.select(this).classed('plotly-customdata', cd.data !== null && cd.data !== undefined);
                });
            }

            el.selectAll('text')
                .call(Drawing.textPointStyle, trace);
        });

    s.selectAll('g.trace path.js-line')
        .call(Drawing.lineGroupStyle);

    s.selectAll('g.trace path.js-fill')
        .call(Drawing.fillGroupStyle);

    s.call(ErrorBars.style);
};

/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var d3 = require('d3');

var Drawing = require('../../components/drawing');
var ErrorBars = require('../../components/errorbars');

module.exports = function style(gd) {
    var s = d3.select(gd).selectAll('g.trace.scatter');

    s.style('opacity', function(d) {
        return d[0].trace.opacity;
    });

    s.selectAll('g.points')
        .each(function(d) {
            var el = d3.select(this);
            var pts = el.selectAll('path.point');
            var trace = d.trace || d[0].trace;

            pts.call(Drawing.pointStyle, trace);

            if(trace.customdata) {
                pts.each(function(cd) {
                    d3.select(this).classed('plotly-customdata', cd.data !== null && cd.data !== undefined);
                });
            }

            el.selectAll('text')
                .call(Drawing.textPointStyle, trace);
        });

    s.selectAll('g.trace path.js-line')
        .call(Drawing.lineGroupStyle);

    s.selectAll('g.trace path.js-fill')
        .call(Drawing.fillGroupStyle);

    s.call(ErrorBars.style);
};

Change variable name for clarity


// General search
//

'use strict';

const querystring = require('querystring');

module.exports = function (N, apiPath) {
  N.validate(apiPath, {
    $query: { type: 'string', required: false }
  });

  N.wire.on(apiPath, function search_general(env) {
    env.res.head.title = env.t('title');

    if (env.params.$query) {
      let query = querystring.parse(env.params.$query);

      env.res.search_query = query.query;
    }
  });
};

// General search
//

'use strict';

const querystring = require('querystring');

module.exports = function (N, apiPath) {
  N.validate(apiPath, {
    $query: { type: 'string', required: false }
  });

  N.wire.on(apiPath, function search_general(env) {
    env.res.head.title = env.t('title');
    env.res.head.robots = 'noindex,nofollow';

    if (env.params.$query) {
      let query = querystring.parse(env.params.$query);

      env.res.search_query = query.query;
    }
  });
};

Add robots=noindex,nofollow to search page


define([
       'jquery',
       'app',
       'views/event/creation'
], function ($, Stratus, EventCreationView) {
    var create = Stratus.module('Events.Create', { startWithParent: false });
    create.on('start', function (options) {
        // Form to create new downtime events
        var event_creation_view = new EventCreationView({
            collection: options.event_collection
        });

        $(document).find('div#event-list').append(event_creation_view.render().$el);
    });
});

define([
       'jquery',
       'app',
       'views/event/creation'
], function ($, Stratus, EventCreationView) {
    var create = Stratus.module('Events.Create', { startWithParent: false });
    create.on('start', function (options) {
        // Form to create new downtime events
        var event_creation_view = new EventCreationView({
            collection: options.event_collection
        });

        $(document).find('ul.event-list').before(event_creation_view.render().$el);
    });
});

Prepend creation form at the appropriate place


/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name PlacedItem
 *
 * @class The PlacedItem class is the base for any items that have a matrix
 * associated with them, describing their placement in the project, such as
 * {@link Raster} and {@link PlacedSymbol}.
 *
 * @extends Item
 */
var PlacedItem = this.PlacedItem = Item.extend(/** @lends PlacedItem# */{
	// PlacedItem uses strokeBounds for bounds
	_boundsGetter: { getBounds: 'getStrokeBounds' },

	_hitTest: function(point, options, matrix) {
		var hitResult = this._symbol._definition._hitTest(point, options, matrix);
		// TODO: When the symbol's definition is a path, should hitResult contain
		// information like HitResult#curve?
		if (hitResult)
			hitResult.item = this;
		return hitResult;
	}
});

/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name PlacedItem
 *
 * @class The PlacedItem class is the base for any items that have a matrix
 * associated with them, describing their placement in the project, such as
 * {@link Raster} and {@link PlacedSymbol}.
 *
 * @extends Item
 */
var PlacedItem = this.PlacedItem = Item.extend(/** @lends PlacedItem# */{
	// PlacedItem uses strokeBounds for bounds
	_boundsGetter: { getBounds: 'getStrokeBounds' },

	_hitTest: function(point, options, matrix) {
		var result = this._symbol._definition._hitTest(point, options, matrix);
		// TODO: When the symbol's definition is a path, should hitResult
		// contain information like HitResult#curve?
		if (result)
			result.item = this;
		return result;
	}
});

Clean up code a bit.


module.exports = {
  'Filtering on search page': function (browser) {
    browser
      .url('http://localhost:8000/search?q=rocket')
      .waitForElementVisible('body', 1000)
      .waitForElementVisible('.resultcard__figure', 1000)
      .assert.attributeEquals('.resultcard__figure img', 'src', 'http://smgco-images.s3.amazonaws.com/media/W/P/A/large_thumbnail_1909_0003.jpg')
      .url('http://localhost:8000/search?q=calculating-machine')
      .click('.searchtab:nth-of-type(4)')
      .pause(2000)
      .waitForElementVisible('.resultcard__figure', 1000)
      .assert.attributeEquals('.resultcard__figure img', 'src', 'http://smgco-images.s3.amazonaws.com/media/I/A/A/large_thumbnail_BAB_K_62_Calculating_Machine.jpg')
      .end();
  }
};

module.exports = {
  'Filtering on search page': function (browser) {
    browser
      .url('http://localhost:8000/search?q=rocket')
      .waitForElementVisible('body', 1000)
      .waitForElementVisible('.resultcard__figure', 1000)
      .assert.attributeEquals('.resultcard__figure img', 'src', 'http://smgco-images.s3.amazonaws.com/media/I/A/A/large_thumbnail_1949_0049_0003__0001_.jpg')
      .url('http://localhost:8000/search?q=calculating-machine')
      .click('.searchtab:nth-of-type(4)')
      .pause(2000)
      .waitForElementVisible('.resultcard__figure', 1000)
      .assert.attributeEquals('.resultcard__figure img', 'src', 'http://smgco-images.s3.amazonaws.com/media/I/A/A/large_thumbnail_BAB_K_62_Calculating_Machine.jpg')
      .end();
  }
};

Update test to match changes in index


module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    watch: {
      react: {
        files: ['components/*.jsx', 'dashboards/*.jsx'],
        tasks: ['browserify']
      }
    },

    browserify: {
      options: {
        transform: [ require('grunt-react').browserify ]
      },
      dashboards: {
        files: [
          {
            expand: true,
            cwd: 'dashboards/',
            src: ['*.jsx'],
            dest: 'src/main/resources/static/scripts/dashboards/',
            ext: '.built.js',
            extDot: 'first'
          }
        ]
      }
    },

    cssmin: {
      dashboards: {
        files: {
          'src/main/resources/static/styles/dashboard.built.css': ['node_modules/normalize.css/normalize.css']
        }
      }
    },

    copy: {
      fonts: {
        files: [
          {
            expand: true,
            cwd: 'node_modules/font-awesome/fonts/',
            src: ['*'],
            dest: 'src/main/resources/static/fonts/',
            filter: 'isFile'
          }
        ]
      }
    }
  });

  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('build', ['browserify', 'cssmin', 'copy']);
  grunt.registerTask('default', ['build', 'watch']);
};

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    watch: {
      react: {
        files: ['components/**/*.jsx', 'dashboards/**/*.jsx'],
        tasks: ['browserify']
      }
    },

    browserify: {
      options: {
        transform: [ require('grunt-react').browserify ]
      },
      dashboards: {
        files: [
          {
            expand: true,
            cwd: 'dashboards/',
            src: ['*.jsx'],
            dest: 'src/main/resources/static/scripts/dashboards/',
            ext: '.built.js',
            extDot: 'first'
          }
        ]
      }
    },

    cssmin: {
      dashboards: {
        files: {
          'src/main/resources/static/styles/dashboard.built.css': ['node_modules/normalize.css/normalize.css']
        }
      }
    },

    copy: {
      fonts: {
        files: [
          {
            expand: true,
            cwd: 'node_modules/font-awesome/fonts/',
            src: ['*'],
            dest: 'src/main/resources/static/fonts/',
            filter: 'isFile'
          }
        ]
      }
    }
  });

  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('build', ['browserify', 'cssmin', 'copy']);
  grunt.registerTask('default', ['build', 'watch']);
};

Fix the wildcards in watch task


module.exports = function(grunt) {
    grunt.initConfig({
        jshint: {
            options: {
                "sub": true
            },
            all: ['src/**/*.js']
        },
        connect: {
            server: {
                options: {
                    port: 8000,
                    hostname: '127.0.0.1',
                    base: '../../'
                }
            }
        },
        jasmine: {
            src: ['src/**/*.js'],
            options: {
                specs: 'tests/**/*.spec.js',
                host: 'http://127.0.0.1:8000/products/argos-saleslogix/',
                template: 'GruntRunner.tmpl'
            }
        },
        cssmin: {
            combine: {
                files: {
                    'min/css/app.min.css': ['content/css/toggle.css', 'content/css/app.css']
                }
            }
        },
        csslint: {
            options: {
                csslintrc: '.csslintrc',
                formatters: [
                    { id: 'junit-xml', dest: 'report/junit.xml' }
                ]
            },
            lax: {
                src: ['content/**/*.css']
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-contrib-jasmine');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-csslint');

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

module.exports = function(grunt) {
    grunt.initConfig({
        jshint: {
            options: {
                "sub": true
            },
            all: ['src/**/*.js']
        },
        connect: {
            server: {
                options: {
                    port: 8000,
                    hostname: '127.0.0.1',
                    base: '../../'
                }
            }
        },
        jasmine: {
            src: ['src/**/*.js'],
            options: {
                specs: 'tests/**/*.spec.js',
                host: 'http://127.0.0.1:8000/products/argos-saleslogix/',
                template: 'GruntRunner.tmpl'
            }
        },
        cssmin: {
            combine: {
                files: {
                    'min/css/app.min.css': ['content/css/toggle.css', 'content/css/app.css']
                }
            }
        },
        csslint: {
            options: {
                csslintrc: '.csslintrc',
                formatters: [
                    { id: 'junit-xml', dest: 'report/junit.xml' }
                ]
            },
            lax: {
                src: ['content/**/*.css']
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-contrib-jasmine');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-csslint');

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

Update default grunt task to run unit tests and cssmin


import * as deps from '../deps';
import { closeMobileMenu } from '../actions';

export const initialHeaderItems = [];

const closeMobileMenuAction = () => deps.store.dispatch(closeMobileMenu());

export const loggedInItems = [
  {
    name: 'Sites',
    type: 'button',
    url: 'sites',
    link: '/sites',
    icon: 'th',
    action: closeMobileMenuAction,
  },
  {
    name: 'Licenses',
    type: 'button',
    url: 'licenses',
    link: '/licenses',
    icon: 'list-ul',
    action: closeMobileMenuAction,
  },
  {
    name: 'Profile',
    type: 'button',
    url: 'profile',
    link: '/profile',
    icon: 'user',
    action: closeMobileMenuAction,
  },
  {
    name: 'Logout',
    type: 'button',
    icon: 'power-off',
    action: () => deps.store.dispatch(deps.actions.logoutRequested()),
  },
];

import * as deps from '../deps';
import { closeMobileMenu } from '../actions';

export const initialHeaderItems = [];

const closeMobileMenuAction = () => deps.store.dispatch(closeMobileMenu());

export const loggedInItems = [
  {
    name: 'Sites',
    type: 'button',
    url: 'sites',
    link: '/sites',
    icon: 'th',
    action: closeMobileMenuAction,
  },
  /*
  {
    name: 'Licenses',
    type: 'button',
    url: 'licenses',
    link: '/licenses',
    icon: 'list-ul',
    action: closeMobileMenuAction,
  },
  {
    name: 'Profile',
    type: 'button',
    url: 'profile',
    link: '/profile',
    icon: 'user',
    action: closeMobileMenuAction,
  },
  */
  {
    name: 'Logout',
    type: 'button',
    icon: 'power-off',
    action: () => deps.store.dispatch(deps.actions.logoutRequested()),
  },
];

Comment Licenses and Profile top-menu buttons for interface RFL.


/**
 * Created by Fabian on 12.07.2015.
 */

// Copyright 2015 Fabian Dietenberger

var should = require('chai').should(),
    hypemResolver = require('../hypem-resolver');

describe('Use the hypem link to get the songs url', function () {
    describe('if the song is hosted on soundcloud', function () {
        it('should return a soundcloud url', function (done) {
            var soundcloudUrl = hypemResolver.getUrl('adad');
            soundcloudUrl.should.be.a('string');
            done();
        })
    });
});

Add test for the result function


var Ni = require('ni');

var userController = module.exports = {
  __init: function (cb, req, res, next) {
    res.Ni.action = 'login';
    res.Ni.controller = 'User';
    Ni.controllers.User.login(req, res, next);
  },

  login: function (req, res, next) {
    if (req.body) {
      if (req.body.name === Ni.config('user') && req.body.password === Ni.config('password')) {
        req.session.logged_in = true;
        res.redirect('/');
      }
    }
    next();
  }
}

var Ni = require('ni');

var userController = module.exports = {
  __init: function (cb, req, res, next) {
    res.Ni.action = 'login';
    res.Ni.controller = 'User';
    Ni.controllers.User.login(req, res, next);
  },

  login: function (req, res, next) {
    if (req.body) {
      if (req.body.name === Ni.config('user') && req.body.password === Ni.config('password')) {
        req.session.logged_in = true;
        return res.redirect('/');
      }
    }
    next();
  }
}

Fix bug where the login did not properly handle the redirect and thus was trying to send headers twice (and content).


/*
 * use-test.js: Basic tests for the carapace module
 *
 * (C) 2011 Nodejitsu Inc
 * MIT LICENCE
 *
 */

var assert = require('assert'),
    vows = require('vows'),
    helper = require('../helper/macros.js'),
    carapace = require('../../lib/carapace');

var PORT = 5050;

vows.describe('carapace/simple/use-plugins').addBatch({
  "When using haibu-carapace":  helper.assertListen(PORT, {
    "load up chdir, chroot, heartbeat plugins" : helper.assertUse(['chdir', 'chroot', 'heartbeat'], {
      "and running the heartbeat plugin" : {
        topic : function () {
          carapace.on('carapace::heartbeat', this.callback.bind(carapace, null));
          carapace.heartbeat();
        },
        "should see a carapace::heartbeat event" : function (_, event, data) {
          assert.isString(carapace.event);
          assert.equal(carapace.event, 'carapace::heartbeat');
        }
      }
    })
  })
}).export(module);

/*
 * use-test.js: Basic tests for the carapace module
 *
 * (C) 2011 Nodejitsu Inc
 * MIT LICENCE
 *
 */

var assert = require('assert'),
    vows = require('vows'),
    helper = require('../helper/macros.js'),
    carapace = require('../../lib/carapace');

vows.describe('carapace/simple/use-plugins').addBatch({
  "When using haibu-carapace":  {
    "load up chdir, chroot, heartbeat plugins" : helper.assertUse(['chdir', 'chroot', 'heartbeat'], {
      "and running the heartbeat plugin" : {
        topic : function () {
          carapace.on('heartbeat', this.callback.bind(carapace, null));
          carapace.heartbeat();
        },
        "should see a heartbeat event" : function (_, event, data) {
          assert.isString(carapace.event);
          assert.equal(carapace.event, 'heartbeat');
        }
      }
    })
  }
}).export(module);

Use new API in `simple/use-load` test


var gulp = require("gulp");
var browserify = require("browserify");
var source = require("vinyl-source-stream");

var alias = function(name) {
  return {cwd: "src/coffee/" + name, base: name};
};

gulp.task("scripts", function() {
  var opts = {
    entries: ["./src/coffee/main.coffee"],
    extensions: [".coffee", ".eco"]
  }

  browserify(opts)
    .transform("browserify-eco")
    .transform("coffeeify")
    .bundle()
    .pipe(source("bokeh.js"))
    .pipe(gulp.dest("./build/js/"))
});

gulp.task('eco', function(){
  gulp.src('./src/templates/**/*.eco')
    .pipe(template({author: "Continuum Analytics"}))
    .pipe(gulp.dest('./build'));
});

gulp.task("default", ["scripts"], function() {
  gulp.watch("./src/coffee/**/*.coffee", ["scripts"]);
})

Add a default command that watches


var packager = require('electron-packager');
var path = require('path');
var os = require('os');

options = {
	"dir": ".",
	"out": path.resolve(os.homedir(), "firmware_flasher"),
	"platform": "win32,darwin",
	"arch": "ia32",
	"overwrite": true,
	"asar": {
		"unpackDir": "dfu"
	}
}

packager(options, function done_callback (err, appPaths) {
	if(err) {
		console.log(err);
	}
});

var packager = require('electron-packager');
var path = require('path');
var os = require('os');

options = {
	"dir": ".",
	"out": path.resolve(os.homedir(), "firmware_flasher"),
	"platform": "win32,darwin",
	"arch": "ia32",
	"overwrite": true,
	"asar": {
		"unpackDir": "dfu"
	},
	"ignore": ["wix", ".*md", ".idea"]
}

packager(options, function done_callback (err, appPaths) {
	if(err) {
		console.log(err);
	}
});

Remove unecessary stuff from asar archive


import React from 'react'

export default class MenuItem extends React.Component {
  componentDidMount () {
    this.props.getMenu().menuItems.push(this)
  }

  render () {
    return (

 { this.props.getMenu().hide(); this.props.onClick() }}>

          {this.props.children}

    )
  }
}

MenuItem.defaultProps = {
  show: true
}

import React from 'react'

export default class MenuItem extends React.Component {
  componentDidMount () {
    this.props.getMenu().menuItems.push(this)
  }

  render () {
    function onClick () {
      this.props.getMenu().hide()
      if (typeof this.props.onClick === 'function') {
        this.props.onClick()
      }
    }

    return (

          {this.props.children}

    )
  }
}

MenuItem.defaultProps = {
  show: true
}

Fix errors with onClick in MenuItem


Ext.define('MusicSearch.App', {
	extend: 'Deft.mvc.Application',

	init: function() {
		Ext.fly('followingBallsG').destroy();

		Ext.tip.QuickTipManager.init();

		Deft.Injector.configure({
			searchResultStore: 'MusicSearch.SongsStore',
			playlistStore: 'MusicSearch.PlaylistStore'
		});

		Ext.create('MusicSearch.Viewport');
	}
});

Ext.namespace('MusicSearch.Utils');
MusicSearch.Utils.secondsToHms = function(d) {
	var no = Number(d);
	var h = Math.floor(no / 3600);
	var m = Math.floor(no % 3600 / 60);
	var s = Math.floor(no % 3600 % 60);
	return ((h > 0 ? h + ":" : "")
			+ (m > 0 ? (h > 0 && m < 10 ? "0" : "") + m + ":" : "0:")
			+ (s < 10 ? "0" : "") + s);
};

soundManager.setup({
	url: app_context_path + '/resources/swf/',
	flashVersion: 9,
	preferFlash: true,
	debugMode: true,
	onready: function() {
		Ext.create('MusicSearch.App');
	}
});

Ext.define('MusicSearch.App', {
	extend: 'Deft.mvc.Application',

	init: function() {
		Ext.fly('followingBallsG').destroy();

		Ext.tip.QuickTipManager.init();

		Deft.Injector.configure({
			searchResultStore: 'MusicSearch.SongsStore',
			playlistStore: 'MusicSearch.PlaylistStore'
		});

		Ext.create('MusicSearch.Viewport');
	}
});

Ext.namespace('MusicSearch.Utils');
MusicSearch.Utils.secondsToHms = function(d) {
	var no = Number(d);
	var h = Math.floor(no / 3600);
	var m = Math.floor(no % 3600 / 60);
	var s = Math.floor(no % 3600 % 60);
	return ((h > 0 ? h + ":" : "")
			+ (m > 0 ? (h > 0 && m < 10 ? "0" : "") + m + ":" : "00:")
			+ (s < 10 ? "0" : "") + s);
};

soundManager.setup({
	url: app_context_path + '/resources/swf/',
	flashVersion: 9,
	preferFlash: true,
	onready: function() {
		Ext.create('MusicSearch.App');
	}
});

Write two zeros when 0 minutes. Looks nicer


/**
 *  Name: Figlet
 *  Description: Replies with a figlet of a message.
 *  Usage: /figlet String in
 *  Author: j <jay@jayhankins.me>
 */

var figlet = require('figlet');

function trigger(message, api, messageObj) {
  threadID = messageObj.threadID;
  var figged = '```\n' + makeFig(message) + '```';
  api.sendMessage(figged, threadID);
}

function makeFig(message) {
	return figlet.textSync(message, {
	    font: 'small'
	}, function(err, data) {
	    if (err) {
	        console.log('Something went wrong...');
	        console.dir(err);
	        return;
	    }
	});
}

module.exports = {
  trigger: trigger
}

/**
 *  Name: Figlet
 *  Description: Replies with a figlet of a message.
 *  Usage: /figlet String in
 *  Author: j <jay@jayhankins.me>
 */

var figlet = require('figlet');

function trigger(message, api, messageObj) {
  threadID = messageObj.threadID;
  var figged = '```\n' + makeFig(message) + '```';
  api.sendMessage(figged, threadID);
}

function makeFig(message) {
	return figlet.textSync(message, {
	    font: 'Small'
	}, function(err, data) {
	    if (err) {
	        console.log('Something went wrong...');
	        console.dir(err);
	        return;
	    }
	});
}

module.exports = {
  trigger: trigger
}

Change for case sensitive loading on Linux


/* vim:set ts=2 sw=2 sts=2 expandtab */
/*jshint asi: true undef: true es5: true node: true browser: true devel: true
         forin: true latedef: false globalstrict: true */

'use strict';

var reduce = require('./accumulator').reduce;
var when = require('eventual/eventual').when;

function print(source) {
  var open = false
  var promise = reduce(source, function(_, value) {
    if (!open) process.stdout.write('<stream ')
    open = true
    process.stdout.write(JSON.stringify(value, 2, 2) + ' ')
  }, false)
  when(promise, function() {
    if (!open) process.stdout.write('<stream ')
    process.stdout.write('/>\n')
  }, function(error) {
    if (!open) process.stdout.write('<stream ')
    process.stdout.write('/Error: ')
    process.stdout.write(error + ' ' + JSON.stringify(error, 2, 2))
    process.stdout.write('>\n')
  })
}
exports.print = print

/* vim:set ts=2 sw=2 sts=2 expandtab */
/*jshint asi: true undef: true es5: true node: true browser: true devel: true
         forin: true latedef: false globalstrict: true */

'use strict';

var reduce = require('./accumulator').reduce;
var when = require('eventual/eventual').when;

function print(source) {
  var open = false
  var promise = reduce(source, function(_, value) {
    if (!open) process.stdout.write('<stream ')
    open = true
    process.stdout.write(JSON.stringify(value, 2, 2) + ' ')
  }, false)
  when(promise, function() {
    if (!open) process.stdout.write('<stream ')
    process.stdout.write('/>\n> ')
  }, function(error) {
    if (!open) process.stdout.write('<stream ')
    process.stdout.write('/Error: ')
    process.stdout.write(error + ' ' + JSON.stringify(error, 2, 2))
    process.stdout.write('>\n> ')
  })
}
exports.print = print

Change `print` utility function to print repl prompt on end.


// Polyfill needed by ie 11
import 'string.prototype.startswith';

import React from 'react';
import ReactDOM from 'react-dom';
import Router from 'react-router/BrowserRouter';
import App from './App';
import './index.css';
import 'bootstrap/dist/css/bootstrap.css';
import 'font-awesome/css/font-awesome.css';
import 'react-bootstrap-table/dist/react-bootstrap-table-all.min.css';

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

// Polyfill needed by ie 11
import 'string.prototype.startswith';

import React from 'react';
import ReactDOM from 'react-dom';
import Router from 'react-router/BrowserRouter';
import App from './App';

// use default bootstrap theme unless a custom one is provided by the user
if (!process.env.REACT_APP_BOOTSTRAP_CSS_PATH) {
  require('bootstrap/dist/css/bootstrap.css');
} else {
  require(process.env.REACT_APP_BOOTSTRAP_CSS_PATH);
}

if (!process.env.REACT_APP_APPLICATION_STYLES_PATH) {
  require('./index.css');
} else {
  require(process.env.REACT_APP_APPLICATION_STYLES_PATH);
}

import 'font-awesome/css/font-awesome.css';
import 'react-bootstrap-table/dist/react-bootstrap-table-all.min.css';

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

Allow styles to be overwritten on each deployment


/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*/
window.addEventListener("load", function(e) {
  startup();
}, false);

function startup() {
  var myPanel = document.getElementById("my-panel");
  myPanel.label = "Tor enabled";
}

/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*/
window.addEventListener("load", function(e) {
  startup();
}, false);

function startup() {
  var myPanel = document.getElementById("my-panel");
  myPanel.label = "Tor Enabled";
  myPanel.style.color = "red";
}

Change color of 'Tor Enabled' label


module.exports = function (campaign) {

  // Should Add Some Validation Methods

  campaign.beforeRemote('prototype.__create__subcampaigns', function (ctx, modelInstance, next) {
    if (!ctx.args.options.accessToken)
      return next()
    ctx.args.data.clientId = ctx.args.options.accessToken.userId
    next()
  })

  campaign.beforeRemote('prototype.__updateById__subcampaigns', function (ctx, modelInstance, next) {
    if (!ctx.args.options.accessToken)
      return next()
    ctx.args.data.clientId = ctx.args.options.accessToken.userId
    next()
  })
}

var startStyleList = require('../../config/startStyle.json')
var mediaStyleList = require('../../config/mediaStyle.json')

module.exports = function (campaign) {

  campaign.validatesInclusionOf('startStyle', { in: startStyleList })
  campaign.validatesInclusionOf('mediaStyle', { in: mediaStyleList })

  campaign.beforeRemote('prototype.__create__subcampaigns', function (ctx, modelInstance, next) {
    if (!ctx.args.options.accessToken)
      return next()
    ctx.args.data.clientId = ctx.args.options.accessToken.userId
    next()
  })

  campaign.beforeRemote('prototype.__updateById__subcampaigns', function (ctx, modelInstance, next) {
    if (!ctx.args.options.accessToken)
      return next()
    ctx.args.data.clientId = ctx.args.options.accessToken.userId
    next()
  })
}

Add Input Validation Methods to Campaign


export const __DEV__ = process.env.NODE_ENV !== 'production';

export const API_BASE_URL = process.env.SPLASH_API_BASE_URL || 'https://online.ntnu.no';

export const API_APPLICATION_PERIODS_URL = `${API_BASE_URL}/api/v1/committee-application-periods/`;
export const API_EVENTS_URL = `${API_BASE_URL}/api/v1/splash-events/?start_time__gte=2019-08-01`;
export const API_SLACK_URL = `${API_BASE_URL}/api/v1/slack/`;

export const __DEV__ = process.env.NODE_ENV !== 'production';

export const API_BASE_URL = process.env.SPLASH_API_BASE_URL || 'https://online.ntnu.no';

export const API_APPLICATION_PERIODS_URL = `${API_BASE_URL}/api/v1/committee-application-periods/`;
export const API_EVENTS_URL = `${API_BASE_URL}/api/v1/splash-events/?start_time__gte=2020-08-01`;
export const API_SLACK_URL = `${API_BASE_URL}/api/v1/slack/`;

Update API_EVENT_URL for new year


const Config = require("truffle-config");
const expect = require("truffle-expect");
const Resolver = require("truffle-resolver");
const Artifactor = require("truffle-artifactor");

function prepareConfig(options) {
  expect.options(options, ["contracts_build_directory"]);

  expect.one(options, ["contracts_directory", "files"]);

  // Use a config object to ensure we get the default sources.
  const config = Config.default().merge(options);

  config.compilersInfo = {};

  if (!config.resolver) config.resolver = new Resolver(config);

  if (!config.artifactor) {
    config.artifactor = new Artifactor(config.contracts_build_directory);
  }

  return config;
}

function multiPromisify(func) {
  return (...args) =>
    new Promise((accept, reject) => {
      const callback = (err, ...results) => {
        if (err) reject(err);

        accept(results);
      };

      func(...args, callback);
    });
}

function byContractName(contracts) {
  return contracts
    .map(contract => ({ [contract.contractName]: contract }))
    .reduce((a, b) => Object.assign({}, a, b), {});
}

module.exports = {
  prepareConfig,
  multiPromisify,
  byContractName
};

const Config = require("truffle-config");
const expect = require("truffle-expect");
const Resolver = require("truffle-resolver");
const Artifactor = require("truffle-artifactor");

function prepareConfig(options) {
  expect.options(options, ["contracts_build_directory"]);

  expect.one(options, ["contracts_directory", "files"]);

  // Use a config object to ensure we get the default sources.
  const config = Config.default().merge(options);

  config.compilersInfo = {};

  if (!config.resolver) config.resolver = new Resolver(config);

  if (!config.artifactor) {
    config.artifactor = new Artifactor(config.contracts_build_directory);
  }

  return config;
}

function multiPromisify(func) {
  return (...args) =>
    new Promise((accept, reject) => {
      const callback = (err, ...results) => {
        if (err) reject(err);

        accept(results);
      };

      func(...args, callback);
    });
}

function byContractName(contracts) {
  return contracts
    .map(contract => ({
      [contract.contractName || contract.contract_name]: contract
    }))
    .reduce((a, b) => Object.assign({}, a, b), {});
}

module.exports = {
  prepareConfig,
  multiPromisify,
  byContractName
};

Fix byContractName to support either name name


import {Strategy} from 'passport-saml'

// ===================================================================

function extract (obj, prop, defaultValue = undefined) {
  if (prop in obj) {
    const value = obj[prop]
    delete obj[prop]

    return value
  }

  return defaultValue
}

// ===================================================================

export const configurationSchema = {
  type: 'object',
  properties: {
    cert: {
      type: 'string'
    },
    entryPoint: {
      type: 'string'
    },
    issuer: {
      type: 'string'
    },
    usernameField: {
      type: 'string'
    }
  },
  required: ['cert', 'entryPoint', 'issuer']
}

// ===================================================================

class AuthSamlXoPlugin {
  constructor (xo) {
    this._xo = xo
  }

  configure (conf) {
    this._usernameField = extract(conf, 'usernameField', 'uid')
    this._conf = conf
  }

  load () {
    const {_xo: xo} = this

    xo.registerPassportStrategy(new Strategy(this._conf, async (profile, done) => {
      const name = profile[this._usernameField]
      if (!name) {
        done('no name found for this user')
        return
      }

      try {
        done(null, await xo.registerUser('saml', name))
      } catch (error) {
        done(error.message)
      }
    }))
  }
}

// ===================================================================

export default ({xo}) => new AuthSamlXoPlugin(xo)

import {Strategy} from 'passport-saml'

// ===================================================================

function extract (obj, prop, defaultValue = undefined) {
  if (prop in obj) {
    const value = obj[prop]
    delete obj[prop]

    return value
  }

  return defaultValue
}

// ===================================================================

export const configurationSchema = {
  type: 'object',
  properties: {
    cert: {
      type: 'string'
    },
    entryPoint: {
      type: 'string'
    },
    issuer: {
      type: 'string'
    },
    usernameField: {
      type: 'string'
    }
  },
  required: ['cert', 'entryPoint', 'issuer']
}

// ===================================================================

class AuthSamlXoPlugin {
  constructor (xo) {
    this._xo = xo
  }

  configure ({ usernameField, ...conf }) {
    this._usernameField = usernameField
    this._conf = conf
  }

  load () {
    const {_xo: xo} = this

    xo.registerPassportStrategy(new Strategy(this._conf, async (profile, done) => {
      const name = profile[this._usernameField]
      if (!name) {
        done('no name found for this user')
        return
      }

      try {
        done(null, await xo.registerUser('saml', name))
      } catch (error) {
        done(error.message)
      }
    }))
  }
}

// ===================================================================

export default ({xo}) => new AuthSamlXoPlugin(xo)

Use object spread instead of altering passed object.


"use strict";
let db    = require('./db.js'),
  express = require('express'),
  router  = express.Router();

function convertBase62ToId(base62) {
  let chars = base62.split('');
  return chars.reduce(function(sum, char) {
    if (/[0-9]/.test(char))
      return sum += parseInt(char);
    else if (/[a-z]/.test(char))
      return sum += char.charCodeAt(0) - 87;
    else
      return sum += char.charCodeAt(0) - 29;
  }, 0);
}

router.get('/:stub', function(req, res) {
  db.one('select * from urls where id = $1;', convertBase62ToId(req.params.stub))
  .then(function(data) {
    res.redirect(301, data.url);
  })
  .catch(function(error) {
    console.log('Error: ' + error);
    res.sendStatus(404);
  });
});

router.get('/', function(req, res) {
  res.render('index');
});

module.exports = router;

Add use strict to stub controller


class ComponentViewModel {
  constructor (root, params, attrs, MDCFoundation, MDCComponent) {
    this.root = root;
    this.foundation = MDCFoundation;
    this.attachTo = MDCComponent.attachTo;
    this.instance = ko.observable({});

    ko.utils.objectForEach(this.defaultParams(), (name, defaultValue) => {
      if (params.hasOwnProperty(name)) {
        this[name] = params[name];
        delete params[name];
      }
      else {
        this[name] = defaultValue;
      }
    });

    ko.utils.arrayForEach(this.unwrapParams(),
                          name => this[name] = ko.toJS(this[name]));

    delete params.$raw;

    if (params.hasOwnProperty('')) {
      delete params[''];
    }

    this.bindings = params;

    this.attrs = attrs;
  }

  defaultParams () {
    return {}
  }

  unwrapParams () {
    return []
  }

  initialize (parent) {

  }
}

export default ComponentViewModel;

class ComponentViewModel {
  constructor (root, params, attrs, MDCFoundation, MDCComponent) {
    this.root = root;
    this.foundation = MDCFoundation;
    this.attachTo = MDCComponent.attachTo;
    this.instance = ko.observable({});

    ko.utils.objectForEach(this.defaultParams(), (name, defaultValue) => {
      if (params.hasOwnProperty(name)) {
        this[name] = params[name];
        delete params[name];
      }
      else {
        this[name] = defaultValue;
      }
    });

    ko.utils.arrayForEach(this.unwrapParams(),
                          name => this[name] = ko.toJS(this[name]));

    delete params.$raw;

    if (params.hasOwnProperty('')) {
      delete params[''];
    }

    this.bindings = params;

    this.attrs = attrs;
  }

  defaultParams () {
    return {}
  }

  unwrapParams () {
    return []
  }

  initialize (parent) {

  }

  static template () {
    return '';
  }
}

export default ComponentViewModel;

Add static template() method to base


function analyze_textfield() {
    var text = document.getElementById("TEXTAREA").value;

    var analyzer = new Analyzer(text);
    setOutputText(analyzer.toString());
}

function setOutputText(unescaped) {
    var div = document.createElement('div');
    div.appendChild(document.createTextNode(unescaped));
    var escaped = div.innerHTML;

    var outputDiv = document.getElementById("OUTPUT");
    outputDiv.innerHTML = escaped;
}

// Create an analyzer object
function Analyzer(text) {
    this.text = text;

    this.toString = function() {
        return this.text;
    };
}

function analyze_textfield() {
    var text = document.getElementById("TEXTAREA").value;

    var analyzer = new Analyzer(text);
    setOutputText(analyzer.toString());
}

function setOutputText(unescaped) {
    var div = document.createElement('div');
    div.appendChild(document.createTextNode(unescaped));
    var escaped = div.innerHTML;

    var outputDiv = document.getElementById("OUTPUT");
    outputDiv.innerHTML = escaped;
}

// Create an analyzer object
function Analyzer(text) {
    this._analyze = function(text) {
        var lines = text.split('\n');
        for (var i = 0; i < lines.length; i++) {
            var line = lines[i];

            this.asString += line + '\n';
        }
    };

    this.toString = function() {
        return this.asString;
    };

    this.asString = "";
    this._analyze(text);
}

Read thread dump line by line


#!/usr/bin/env node
'use strict';

var packageJson = require('./package.json'),
    adventure = require('adventure');

var shop = adventure(packageJson.name),
    lesson;

[
  'traditional-looping',
  'introduction-to-iterators',
  'built-in-iterators',
  'advanced-iterables',
  'introduction-to-generators'
].forEach(function(lesson, index) {

  lesson = require('./' + lesson);

  shop.add((index + 1) + '. ' + lesson.title, function() {
    return lesson.problem
  });
})

shop.execute(process.argv.slice(2));

#!/bin/sh
":" //# why? http://sambal.org/?p=1014 ; exec /usr/bin/env node --harmony "$0" "$@"

'use strict';

var packageJson = require('./package.json'),
    adventure = require('adventure');

var shop = adventure(packageJson.name),
    lesson;

[
  'traditional-looping',
  'introduction-to-iterators',
  'built-in-iterators',
  'advanced-iterables',
  'introduction-to-generators'
].forEach(function(lesson, index) {

  lesson = require('./' + lesson);

  shop.add((index + 1) + '. ' + lesson.title, function() {
    return lesson.problem
  });
})

shop.execute(process.argv.slice(2));

Add bash hack to ensure node is run with --harmony


var util = require('util');
var extend = require('extend');
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var BaseMailer = require('./BaseMailer');

util.inherits(SMTPMailer, BaseMailer);

/**
 * Create new mailer instance for sending via SMTP servers
 * @constructor
 */
function SMTPMailer() {
  BaseMailer.apply(this, arguments);

  this._setTransporter(nodemailer.createTransport(smtpTransport(this.getConfig().transporter)));
}

/**
 * Returns instantiated instance of nodemailer transporter
 * @returns {*}
 * @private
 */
SMTPMailer.prototype._getTransporter = function () {
  return this._transporter;
};

/**
 * Set new instance of the nodemailer transporter
 * @param {Object} transporter New transporter instantiated with nodemailer.createTransport()
 * @returns {SMTPMailer}
 * @private
 */
SMTPMailer.prototype._setTransporter = function (transporter) {
  this._transporter = transporter;
  return this;
};

/**
 * Send message
 * @param {Object} _config Configuration object for overriding default config
 * @returns {SMTPMailer}
 */
SMTPMailer.prototype.send = function (_config) {
  var config = extend({}, this.getConfig(), _config);

  this._getTransporter().sendMail(config);

  return this;
};

module.exports = SMTPMailer;

var util = require('util');
var extend = require('extend');
var Promise = require('bluebird');
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var BaseMailer = require('./BaseMailer');

util.inherits(SMTPMailer, BaseMailer);

/**
 * Create new mailer instance for sending via SMTP servers
 * @constructor
 */
function SMTPMailer() {
  BaseMailer.apply(this, arguments);

  this._setTransporter(nodemailer.createTransport(smtpTransport(this.getConfig().transporter)));
}

/**
 * Returns instantiated instance of nodemailer transporter
 * @returns {*}
 * @private
 */
SMTPMailer.prototype._getTransporter = function () {
  return this._transporter;
};

/**
 * Set new instance of the nodemailer transporter
 * @param {Object} transporter New transporter instantiated with nodemailer.createTransport()
 * @returns {SMTPMailer}
 * @private
 */
SMTPMailer.prototype._setTransporter = function (transporter) {
  this._transporter = transporter;
  return this;
};

/**
 * Send message
 * @param {Object} _config Configuration object for overriding default config
 * @returns {Promise}
 */
SMTPMailer.prototype.send = function (_config) {
  var config = extend({}, this.getConfig(), _config);

  return new Promise(function (resolve, reject) {
    this._getTransporter().sendMail(config, function (error, result) {
      return error ? reject(error) : resolve(result);
    });
  }.bind(this));
};

module.exports = SMTPMailer;

Add promise returning on sending


import { PropTypes } from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';

// PropTypes
export const paperPropType = ImmutablePropTypes.contains({
  id: PropTypes.number,
  title: ImmutablePropTypes.string,
  summary: ImmutablePropTypes.string,
});

export const userPropType = ImmutablePropTypes.contains({
  id: PropTypes.string,
  name: PropTypes.string,
  bookmarks: ImmutablePropTypes.listOf(PropTypes.number),
});

export const paginationPropType = ImmutablePropTypes.contains({
  limit: PropTypes.number,
  offset: PropTypes.number,
  total: PropTypes.number,
});

// URLs
export const papernetURL = `${process.env.PAPERNET_HOST}/api`;

import { PropTypes } from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';

// PropTypes
export const paperPropType = ImmutablePropTypes.contains({
  id: PropTypes.number,
  title: ImmutablePropTypes.string,
  summary: ImmutablePropTypes.string,
});

export const userPropType = ImmutablePropTypes.contains({
  id: PropTypes.string,
  name: PropTypes.string,
  bookmarks: ImmutablePropTypes.listOf(PropTypes.number),
});

export const paginationPropType = ImmutablePropTypes.contains({
  limit: PropTypes.number,
  offset: PropTypes.number,
  total: PropTypes.number,
});

// URLs
let baseHost = 'https://bobi.space';
if (
  window.location.hostname.indexOf('localhost') === 0 ||
  window.location.hostname.indexOf('127.0.0.1') === 0) {
  baseHost = 'http://127.0.0.1:1705';
} else if (window.location.hostname.indexOf('local-bobi') === 0) {
  baseHost = 'http://local-bobi.space';
}
export const papernetURL = `${baseHost}/api`;

Choose api host depending on url


const crypto = require('crypto');

/**
 * memHandler - In memory upload handler
 * @param {object} options
 * @param {string} fieldname
 * @param {string} filename
 */
module.exports = function(options, fieldname, filename) {
  let buffers = [];
  let fileSize = 0; // eslint-disable-line
  let hash = crypto.createHash('md5');

  return {
    dataHandler: function(data) {
      buffers.push(data);
      hash.update(data);
      fileSize += data.length;
      if (options.debug) {
        return console.log('Uploading %s -> %s, bytes: %d', fieldname, filename, fileSize); // eslint-disable-line
      }
    },
    getBuffer: function(){
      return Buffer.concat(buffers);
    },
    getFilePath: function(){
      return '';
    },
    getFileSize: function(){
      return fileSize;
    },
    getHash: function(){
      return hash.digest('hex');
    },
    complete: function(){
      return Buffer.concat(buffers);
    },
    cleanup: function(){
    }
  };
};

const crypto = require('crypto');

/**
 * memHandler - In memory upload handler
 * @param {object} options
 * @param {string} fieldname
 * @param {string} filename
 */
module.exports = function(options, fieldname, filename) {
  let buffers = [];
  let fileSize = 0; // eslint-disable-line
  let hash = crypto.createHash('md5');

  const getBuffer = () => Buffer.concat(buffers);
  const emptyFunc = () => '';

  return {
    dataHandler: function(data) {
      buffers.push(data);
      hash.update(data);
      fileSize += data.length;
      if (options.debug) {
        return console.log('Uploading %s -> %s, bytes: %d', fieldname, filename, fileSize); // eslint-disable-line
      }
    },
    getBuffer: getBuffer,
    getFilePath: emptyFunc,
    getFileSize: function(){
      return fileSize;
    },
    getHash: function(){
      return hash.digest('hex');
    },
    complete: getBuffer,
    cleanup: emptyFunc
  };
};

Make it a bit lighter


const electron = require('electron')
const Client = require('@bugsnag/core/client')
const makeDelivery = require('@bugsnag/delivery-electron')
const { FileStore } = require('@bugsnag/electron-filestore')
const { schema } = require('../config/main')

// noop native client for now
const NativeClient = {
  setApp () {},
  setDevice () {}
}

module.exports = (opts) => {
  const filestore = new FileStore(
    opts.apiKey,
    electron.app.getPath('cache'),
    electron.app.getPath('crashDumps')
  )

  const internalPlugins = [
    // main internal plugins go here
    require('@bugsnag/plugin-electron-state-sync'),
    require('@bugsnag/plugin-electron-ipc'),
    require('@bugsnag/plugin-electron-app')(NativeClient, process, electron.app, electron.BrowserWindow),
    require('@bugsnag/plugin-electron-app-breadcrumbs')(electron.app, electron.BrowserWindow),
    require('@bugsnag/plugin-electron-device')(electron.app, electron.screen, process, filestore, NativeClient, electron.powerMonitor)
  ]

  const bugsnag = new Client(opts, schema, internalPlugins, require('../id'))

  bugsnag._setDelivery(makeDelivery(filestore, electron.net))

  // noop session delegate for now
  bugsnag._sessionDelegate = { startSession: () => bugsnag, resumeSession: () => {}, pauseSession: () => {} }

  bugsnag._logger.debug('Loaded! In main process.')

  return bugsnag
}

const electron = require('electron')
const Client = require('@bugsnag/core/client')
const makeDelivery = require('@bugsnag/delivery-electron')
const { FileStore } = require('@bugsnag/electron-filestore')
const { schema } = require('../config/main')

// noop native client for now
const NativeClient = {
  setApp () {},
  setDevice () {}
}

module.exports = (opts) => {
  const filestore = new FileStore(
    opts.apiKey,
    electron.app.getPath('userCache'),
    electron.app.getPath('crashDumps')
  )

  const internalPlugins = [
    // main internal plugins go here
    require('@bugsnag/plugin-electron-state-sync'),
    require('@bugsnag/plugin-electron-ipc'),
    require('@bugsnag/plugin-electron-app')(NativeClient, process, electron.app, electron.BrowserWindow),
    require('@bugsnag/plugin-electron-app-breadcrumbs')(electron.app, electron.BrowserWindow),
    require('@bugsnag/plugin-electron-device')(electron.app, electron.screen, process, filestore, NativeClient, electron.powerMonitor)
  ]

  const bugsnag = new Client(opts, schema, internalPlugins, require('../id'))

  bugsnag._setDelivery(makeDelivery(filestore, electron.net))

  // noop session delegate for now
  bugsnag._sessionDelegate = { startSession: () => bugsnag, resumeSession: () => {}, pauseSession: () => {} }

  bugsnag._logger.debug('Loaded! In main process.')

  return bugsnag
}

Use userCache as filestore's storage


define([
    'flight/lib/component',
    'tpl!./form'
], function(
    defineComponent,
    formTemplate) {
    'use strict';

    return defineComponent(VisibilityEditor);

    function VisibilityEditor() {

        this.defaultAttrs({
            fieldSelector: 'input'
        })

        this.after('initialize', function() {
            this.$node.html(formTemplate({
                value: $.trim(_.isUndefined(this.attr.value) ? '' : this.attr.value)
            }));

            this.onChange = _.debounce(this.onChange.bind(this), 250);

            this.on('visibilityclear', this.onClear);
            this.on('change keyup paste', {
                fieldSelector: this.onChange
            });

            this.onChange();
        });

        this.onClear = function(event, data) {
            this.select('fieldSelector').val('');
        };

        this.onChange = function(event, data) {
            var value = $.trim(this.select('fieldSelector').val());
            this.trigger('visibilitychange', {
                value: value,
                valid: true
            });
        };
    }
});

define([
    'flight/lib/component',
    'tpl!./form'
], function(
    defineComponent,
    formTemplate) {
    'use strict';

    return defineComponent(VisibilityEditor);

    function VisibilityEditor() {

        this.defaultAttrs({
            fieldSelector: 'input'
        })

        this.after('initialize', function() {
            this.$node.html(formTemplate({
                value: $.trim(_.isUndefined(this.attr.value) ? '' : this.attr.value)
            }));

            this.on('visibilityclear', this.onClear);
            this.on('change keyup paste', {
                fieldSelector: this.onChange
            });

            this.onChange();
        });

        this.onClear = function(event, data) {
            this.select('fieldSelector').val('');
        };

        this.onChange = function(event, data) {
            var value = $.trim(this.select('fieldSelector').val());
            this.trigger('visibilitychange', {
                value: value,
                valid: true
            });
        };
    }
});

Fix fast visibility change not registering change


/* Nano Templates (Tomasz Mazur, Jacek Becela) */

(function($){
  $.nano = function(template, data){
    return template.replace(/\{([\w\.]*)}/g, function(str, key){
      var keys = key.split("."), value = data[keys.shift()]
      $.each(keys, function(){ value = value[this] })
      return value
    })
  }
})(jQuery)

/* Nano Templates (Tomasz Mazur, Jacek Becela) */

(function($){
  $.nano = function(template, data){
    return template.replace(/\{([\w\.]*)}/g, function(str, key){
      var keys = key.split("."), value = data[keys.shift()];
      $.each(keys, function(){ value = value[this]; });
      return value;
    });
  };
})(jQuery);

Add a missing semi-colon in JS (bug with closure compiler)


var $ = document.getElementById.bind(document);
var exampleTests = require('./example-tests');
var Main = require('../src/main/main-controller');

var providedByAceEditor = function() {/* noop() */};
var isMac = navigator.platform.indexOf('Mac') === 0;
var metaKey = isMac ? 'Meta' : 'Control';
var shortcuts = [
  [[metaKey, 'S'], executeTestCode, 'Save+Run'],
  [[metaKey, 'D'], providedByAceEditor(), 'Delete line'],
  [[metaKey, 'Shift', 'D'], providedByAceEditor(), 'Duplicate line'],
  [['Shift', 'F6'], refactoringRename, 'Rename (refactoring)']
];

var main = new Main($('tddbin'), {
  initialContent: exampleTests.simplePassingTestCode,
  iframeSrcUrl: '../src/test-runner/mocha/spec-runner.html',
  shortcuts: shortcuts
});

function executeTestCode() {
  main.runEditorContent();
}
function refactoringRename() {
  main.placeCursorsForRenaming();
}

var $ = document.getElementById.bind(document);
var exampleTests = require('./example-tests');
var Main = require('../src/main/main-controller');

var providedByAceEditor = function() {/* noop() */};
var isMac = navigator.platform.indexOf('Mac') === 0;
var metaKey = isMac ? 'Meta' : 'Control';
var shortcuts = [
  [[metaKey, 'S'], executeTestCode, 'Save+Run'],
  [[metaKey, 'D'], providedByAceEditor(), 'Delete line'],
  [[metaKey, 'Shift', 'D'], providedByAceEditor(), 'Duplicate line'],
  [[metaKey, '/'], providedByAceEditor(), 'Comment in/out line'],
  [['Shift', 'F6'], refactoringRename, 'Rename (refactoring)']
];

var main = new Main($('tddbin'), {
  initialContent: exampleTests.simplePassingTestCode,
  iframeSrcUrl: '../src/test-runner/mocha/spec-runner.html',
  shortcuts: shortcuts
});

function executeTestCode() {
  main.runEditorContent();
}
function refactoringRename() {
  main.placeCursorsForRenaming();
}

Add a useful standard ACE shortcut.


/*

Examples
Author: Addy Osmani

See: http://wiki.ecmascript.org/doku.php?id=harmony:module_loaders
for more information on the module loader proposal
*/

//Module: Define a new module
var module = new Module({test:'hello'});
console.log(module);

//System (pre-configured Loader)
System.import('js/test1.js', function(test1){
	console.log('test1.js loaded', test1);
	test1.tester();
});

// Loader: Define a new module loader instance
var baseURL = document.URL.substring(0, document.URL.lastIndexOf('\/') + 1);
var loader = new Loader({global: window,
    strict: false,
    resolve: function (name, options) {
      return  baseURL + name;
    }
  });

console.log(loader);

//Usage:

loader.import('js/test2.js',
    function(test) {
        console.log('test2.js loaded', test);
        test.foobar();
    }, function(err){
    	console.log(err);
	});

loader.import('js/libs/jquery-1.7.1.js',
    function() {
        console.log('jQuery loaded', loader.global.jQuery);
        loader.global.$('body').css({'background':'blue'});
    }, function(err){
    	console.log(err);
	});

/*

Examples
Author: Addy Osmani

See: http://wiki.ecmascript.org/doku.php?id=harmony:module_loaders
for more information on the module loader proposal
*/

//Module: Define a new module
var module = new Module({test:'hello'});
console.log(module);

//System (pre-configured Loader)
System.import('js/test1', function(test1){
	console.log('test1.js loaded', test1);
	test1.tester();
});

// Loader: Define a new module loader instance
var baseURL = document.URL.substring(0, document.URL.lastIndexOf('\/') + 1);
var loader = new Loader({global: window,
    strict: false,
    resolve: function (name, options) {
      return  baseURL + name;
    }
  });

console.log(loader);

//Usage:

loader.import('js/test2.js',
    function(test) {
        console.log('test2.js loaded', test);
        test.foobar();
    }, function(err){
    	console.log(err);
	});

loader.import('js/libs/jquery-1.7.1.js',
    function() {
        console.log('jQuery loaded', loader.global.jQuery);
        loader.global.$('body').css({'background':'blue'});
    }, function(err){
    	console.log(err);
	});

Correct demo so it actually works


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

var start = new Date()

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

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

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

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

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

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

var start    = new Date()
  , hostname = os.hostname()

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

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

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

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

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

Update request handler; make hostname a constant


var bodyParser = require('body-parser');
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var statusController = require('./controllers/statuses');
var pushInterval = 10000;

app.use(bodyParser());
require('./config/routes')(app);
app.set('port', 3000);
app.use(require('./controllers/static'));

io.on('connection', function(socket){
    setInterval(function(){ statusController.postDetailsToClient(socket) }, pushInterval);
});

http.listen(app.get('port'), function () {
      console.log('Server listening on', app.get('port'));
});

var bodyParser = require('body-parser');
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var statusController = require('./controllers/statuses');
var pushInterval = 10000;

app.use(bodyParser());
require('./config/routes')(app);
app.set('port', 3000);
app.use(require('./controllers/static'));

io.on('connection', function(socket){
    setInterval(function(){ statusController.postDetailsToClient(socket) }, pushInterval);
});

http.listen(app.get('port'), '0.0.0.0',  function () {
      console.log('Server listening on', app.get('port'));
});

Make run on public IP


import path from 'path';
import { getInterpretedFile } from './interpret-files';

function loadConfigFiles({ configDir }) {
  const storybookConfigPath = getInterpretedFile(path.resolve(configDir, 'config'));

  if (storybookConfigPath) {
    return [storybookConfigPath];
  }

  return [];
}

export default loadConfigFiles;

import path from 'path';
import { getInterpretedFile } from './interpret-files';

function loadConfigFiles({ configDir }) {
  const storybookConfigPath = getInterpretedFile(path.resolve(configDir, 'config'));
  const storybookPreviewPath = getInterpretedFile(path.resolve(configDir, 'preview'));

  return [].concat(storybookPreviewPath || storybookConfigPath || []);
}

export default loadConfigFiles;

ADD support for preview.js as a replacement for config.js


document.addEventListener("DOMContentLoaded", (event) => {
  const images = ["hello1.jpeg", "hello2.jpeg", "hello3.jpeg", "hello4.jpeg", "hello5.jpeg", "hello6.jpeg"];
  const todaysImage = images[(new Date().getDate() % images.length)];
  const image = document.getElementById("profile");
  image.setAttribute("src", "assets/" + todaysImage);
});

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-64774283-2', 'auto');
ga('send', 'pageview');

document.addEventListener("DOMContentLoaded", (event) => {
  const images = ["hello1.jpeg", "hello2.jpeg", "hello3.jpeg", "hello4.jpeg", "hello5.jpeg", "hello6.jpeg"];
  const todaysImage = images[(new Date().getDate() % images.length)];
  const image = document.getElementById("profile");
  image.setAttribute("src", "assets/" + todaysImage);
});

if (["0", "unspecified"].includes(navigator.doNotTrack)) {
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
  ga('create', 'UA-64774283-2', 'auto');
  ga('send', 'pageview');
}

Exclude GA if Do Not Track is set


/* eslint-disable import/no-extraneous-dependencies */

import ExtractTextPlugin from 'extract-text-webpack-plugin';
import nodeExternals from 'webpack-node-externals';
import path from 'path';
import webpack from 'webpack';

import { loaders, globalOptions, serverEntry, frontendPlugins, optimizePlugins } from './common';

export default {
  ...globalOptions,
  entry: serverEntry,
  externals: [nodeExternals()],
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: 'server.js',
  },
  target: 'node',
  module: {
    loaders: [
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract('style-loader', 'css-loader!postcss-loader'),
      },
      ...loaders,
    ],
  },
  plugins: [
    ...frontendPlugins,
    new webpack.IgnorePlugin(/webpack-assets\.json$/),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"',
      },
    }),
    new ExtractTextPlugin('[name].css'),
    ...optimizePlugins,
  ],
};

/* eslint-disable import/no-extraneous-dependencies */

import ExtractTextPlugin from 'extract-text-webpack-plugin';
import nodeExternals from 'webpack-node-externals';
import path from 'path';
import webpack from 'webpack';

import { loaders, globalOptions, serverEntry, frontendPlugins, optimizePlugins } from './common';

export default {
  ...globalOptions,
  entry: serverEntry,
  externals: [nodeExternals()],
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: 'server.js',
  },
  target: 'node',
  module: {
    loaders: [
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract('style-loader', 'css-loader!postcss-loader'),
      },
      ...loaders,
    ],
  },
  plugins: [
    ...frontendPlugins,
    new webpack.IgnorePlugin(/webpack-assets\.json$/),
    new ExtractTextPlugin('[name].css'),
    ...optimizePlugins,
  ],
};

Exclude env definition from server bundle


define(['jquery', 'backbone', 'underscore', 'favourites/models/Favourite', 'favourites/collections/Favourites'],
    function($, Backbone, _, Favourite, Favourites) {
        var FavouriteButtonView = Backbone.View.extend({
            initialize: function() {
                _.bindAll(this);
                this.favourites = new Favourites();
                this.favourites.fetch();
                this.updateButton();
                this.favourites.on("remove add", this.updateButton, this);
                window.addEventListener("hashchange", this.updateButton, false);
            },

            events: {'click': 'toggleFavourite'},

            toggleFavourite: function(e) {
                e.preventDefault();
                var fav = this.favourites.getCurrentPage();
                if (fav) {
                    this.removeFavourite(fav);
                } else {
                    this.addFavourite();
                }
                console.log(this.favourites.toJSON());
            },
            addFavourite: function() {
                var fragment = Backbone.history.fragment;
                this.favourites.create({fragment: fragment});
            },
            removeFavourite: function(favourite) {
                favourite.destroy();
            },
            updateButton: function(favourite) {
                if (this.favourites.getCurrentPage()) {
                    this.$el.addClass('favourited');
                } else {
                    this.$el.removeClass('favourited');
                }
            }
        });
        return FavouriteButtonView;
    }
);

define(['jquery', 'backbone', 'underscore', 'moxie.conf', 'favourites/collections/Favourites'],
    function($, Backbone, _, conf, Favourites) {
        var FavouriteButtonView = Backbone.View.extend({
            initialize: function() {
                _.bindAll(this);
                this.favourites = new Favourites();
                this.favourites.fetch();
                this.updateButton();
                this.favourites.on("remove add", this.updateButton, this);
                window.addEventListener("hashchange", this.updateButton, false);
            },

            attributes: {
                'class': 'generic free-text'
            },

            events: {'click': 'toggleFavourite'},

            toggleFavourite: function(e) {
                e.preventDefault();
                var fav = this.favourites.getCurrentPage();
                if (fav) {
                    this.removeFavourite(fav);
                } else {
                    this.addFavourite();
                }
                console.log(this.favourites.toJSON());
            },
            addFavourite: function() {
                var fragment = Backbone.history.fragment;
                var title = document.title.split(conf.titlePrefix, 2)[1];
                this.favourites.create({fragment: fragment, title: title});
            },
            removeFavourite: function(favourite) {
                favourite.destroy();
            },
            updateButton: function(favourite) {
                if (this.favourites.getCurrentPage()) {
                    this.$el.addClass('favourited');
                } else {
                    this.$el.removeClass('favourited');
                }
            }
        });
        return FavouriteButtonView;
    }
);

Save favourites with the page title


var _ = require('underscore'),
    db = require('../lib/db');

// Builds an object representation of a row in the DB `pulls` table
// from the data returned by GitHub's API.
function DBPull(pullData) {
   this.data = {
      number: pullData.number,
      state: pullData.state,
      title: pullData.title,
      body: pullData.body,
      created_at: pullData.created_at,
      updated_at: pullData.updated_at,
      closed_at: pullData.closed_at,
      merged_at: pullData.merged_at,
      head_branch: pullData.head.ref,
      head_sha: pullData.head.sha,
      repo_owner: pullData.head.repo.owner.login,
      repo_name: pullData.head.repo.name,
      base_branch: pullData.base.ref,
      user: pullData.user.login
   };
}

DBPull.prototype.save = function() {
   var q_update = 'REPLACE INTO pulls SET ?';

   db.query(q_update, this.data, function(err, rows) {
      if (err) { console.log(err); }
   });
};

DBPull.prototype.toObject = function() {
   var data = this.data;
   var obj = _.extend({}, data);
   return obj;
};

module.exports = DBPull;

var _ = require('underscore'),
    db = require('../lib/db');

// Builds an object representation of a row in the DB `pulls` table
// from the data returned by GitHub's API.
function DBPull(pullData) {
   this.data = {
      number: pullData.number,
      state: pullData.state,
      title: pullData.title,
      body: pullData.body,
      created_at: pullData.created_at,
      updated_at: pullData.updated_at,
      closed_at: pullData.closed_at,
      merged_at: pullData.merged_at,
      head_branch: pullData.head.ref,
      head_sha: pullData.head.sha,
      repo_owner: pullData.head.repo.owner.login,
      repo_name: pullData.head.repo.name,
      base_branch: pullData.base.ref,
      owner: pullData.user.login
   };
}

DBPull.prototype.save = function() {
   var q_update = 'REPLACE INTO pulls SET ?';

   db.query(q_update, this.data, function(err, rows) {
      if (err) { console.log(err); }
   });
};

DBPull.prototype.toObject = function() {
   var data = this.data;
   var obj = _.extend({}, data);
   return obj;
};

module.exports = DBPull;

Change name of column to reflect db change


function getXp(cr) {
  return parseInt(/\([,\d]*/g.exec(cr)[0].slice(1).replace(',', ''), 10);
}

function partialApply(func) {
  var args = [].slice.call(arguments, 1);
  return function part() {
    func.apply(null, args.concat( [].slice.call(arguments) ));
  };
}

export default {
  getXp,
  partialApply
};

export function getXp(cr) {
  return parseInt(/\([,\d]*/g.exec(cr)[0].slice(1).replace(',', ''), 10);
}

export function partialApply(func) {
  var args = [].slice.call(arguments, 1);
  return function part() {
    func.apply(null, args.concat( [].slice.call(arguments) ));
  };
}

export function loadState() {
  try {
    const savedState = localstorage.getItem('summoner');
    if (savedState === null) {
      return undefined;
    }
    return JSON.parse(savedState);
  } catch (err) {
    console.error('Error retrieving saved state: ' + err);
    return undefined;
  }
}

export function saveState(state) {
  try {
    const saveState = JSON.stringify(state);
    localstorage.saveState('summoner', saveState);
  } catch (err) {
    console.error('Error saving state: ' + err);
  }
}

Add loadState and saveState methods


var engine = require("./node-core-audio").createNewAudioEngine();

engine.addAudioCallback( function(numSamples, inputBuffer) {
	//console.log( inputBuffer[0] );
	var outputThing = new Array();

	outputThing = inputBuffer;

	console.log( outputThing.length + " channels" );
	console.log( outputThing[0].length + " samples" );
	console.log( outputThing[1].length + " samples" );

	for( var iChannel=0; iChannel<outputThing.length; ++iChannel ) {

		for( var iSample=0; iSample<outputThing[iChannel].length; ++iSample ) {

			if( iSample % 2 )
				outputThing[iChannel][iSample] = 1.0;
			else
				outputThing[iChannel][iSample] = -1.0;
		}
	}

	return outputThing;
});

var engine = require("./node-core-audio").createNewAudioEngine();
var outputBuffer = [];

engine.addAudioCallback( function(inputBuffer) {
	outputBuffer = inputBuffer[0];

	for( var iSample=0; iSample<outputBuffer[0].length; ++iSample ) {
		outputBuffer[0][iSample] = iSample / outputBuffer[0].length;
	}

	return outputBuffer;
});

Update second test, actually outputs audio