$(document).ready(function() {

  $('.rule-item').on('mouseenter', function() {
    $(this).addClass('highlighted');
    var controls = $('<span>').addClass('pull-right controls');
    controls.append($.editButton($(this).attr('id')));
    controls.append($.removeButton($(this).attr('id')));
    $(this).find('h2').append(controls);
    $('.edit-button').on('click', function(e) {
      var ruleID = $(e.currentTarget).parents('.rule-item').attr('id');
      window.location.href =
        document.URL + '/' + ruleID + '/input';
    });

  });

  $('.rule-item').on('mouseleave', function() {
    $(this).removeClass('highlighted');
    $(this).find('.controls').remove();
  });

});

var Rule = Backbone.Model.extend({

  initialize: function() {
    this.urlRoot = '/rules';
  },

});

$(document).ready(function() {

  $('.rule-item').on('mouseenter', function() {
    $(this).addClass('highlighted');
    var controls = $('<span>').addClass('pull-right controls');
    controls.append($.editButton($(this).attr('id')));
    controls.append($.removeButton($(this).attr('id')));
    $(this).find('h2').append(controls);
    $('.edit-button').on('click', function(e) {
      var ruleID = $(e.currentTarget).parents('.rule-item').attr('id');
      window.location.href =
        document.URL + '/' + ruleID + '/input';
    });
    $('.remove-button').on('click', function(e) {
      var ruleID = $(e.currentTarget).parents('.rule-item').attr('id')
        .substring(1);
      var rule = new Rule({ id: ruleID });
      rule.destroy();
    });
  });

  $('.rule-item').on('mouseleave', function() {
    $(this).removeClass('highlighted');
    $(this).find('.controls').remove();
  });

});

Delete feature when clicking its `.remove-button` in Rule Browser.


module.exports = function () {
    var outputPath = "./<%= outFolder %>/";
    var src = "./<%= srcFolder %>/";

    var config = {
        vendor: {
            destPath: outputPath + "js",
            src: []
        },
        templates: src + "**/*.tpl.html",
        scss: {
            entry: src + "styles/<%= appName %>.scss",
            src: [src + "**/*.scss"],
            destPath: outputPath + "css"
        },
        ts: {
            src: [src + "**/*.ts"],
            dest: outputPath + "js"
        },
        html: {
            src: [src + "**/**.html"],
            dest: outputPath + "js"
        }
    };

    return config;
};

module.exports = function () {
    var outputPath = "./<%= outFolder %>/";
    var src = "./<%= srcFolder %>/";

    var config = {
        vendor: {
            destPath: outputPath + "js",
            src: []
        },
        templates: src + "**/*.tpl.html",
        scss: {
            entry: src + "styles/<%= hAppName %>.scss",
            src: [src + "**/*.scss"],
            destPath: outputPath + "css"
        },
        ts: {
            src: [src + "**/*.ts"],
            dest: outputPath + "js"
        },
        html: {
            src: [src + "**/**.html"],
            dest: outputPath + "js"
        }
    };

    return config;
};

Fix an error causing the css not being generated


const React = require('react')

const Search = React.createClass({
  propTypes: {
    value: React.PropTypes.string.isRequired,
    handleQueryChange: React.PropTypes.func.isRequired,
  },

  getInitialState () {
    return {
      input: null,
    }
  },

  focus () {
    this.state.input && this.state.input.focus()
  },

  componentDidMount () {
    this.focus()
  },

  componentDidUpdate () {
    if (this.props.value === '') {
      this.focus()
    }
  },

  handleKeyPress (event) {
    if (event.keyCode === 13 && event.keyCode === 27) {
      return false
    }
  },

  handleQueryChange (event) {
    const query = event.target.value
    this.props.handleQueryChange(query)
  },

  setReference (input) {
    this.setState({
      input,
    })
  },

  render () {
    const { value } = this.props

    return (
      <input
        title='Search Zazu'
        className='mousetrap'
        ref={this.setReference}
        type='text'
        onKeyPress={this.handleKeyPress}
        onChange={this.handleQueryChange}
        value={value}/>
    )
  },
})

module.exports = Search

const React = require('react')

const Search = React.createClass({
  propTypes: {
    value: React.PropTypes.string.isRequired,
    handleQueryChange: React.PropTypes.func.isRequired,
  },

  getInitialState () {
    return {
      input: null,
    }
  },

  focus () {
    this.state.input && this.state.input.focus()
  },

  componentDidMount () {
    this.focus()
  },

  componentDidUpdate () {
    if (this.props.value === '') {
      this.focus()
    }
  },

  handleQueryChange (event) {
    const query = event.target.value
    this.props.handleQueryChange(query)
  },

  setReference (input) {
    this.setState({
      input,
    })
  },

  render () {
    const { value } = this.props

    return (
      <input
        title='Search Zazu'
        className='mousetrap'
        ref={this.setReference}
        type='text'
        onChange={this.handleQueryChange}
        value={value}/>
    )
  },
})

module.exports = Search

Revert "Fix alert beep on osx"


'use strict';

GLClient.controller('LoginCtrl', ['$scope', '$location',
                    '$routeParams', 'Authentication', 'Receivers',
  function($scope, $location, $routeParams, Authentication, Receivers) {
    var src = $routeParams['src'];

    $scope.loginUsername = "";
    $scope.loginPassword = "";
    $scope.loginRole = "receiver";

    Receivers.query(function (receivers) {
      $scope.receivers = receivers;
    });

    if (src && src.indexOf("/admin") != -1) {
      $scope.loginUsername = "admin";
      $scope.loginRole = "admin";
    };

    $scope.$watch("loginUsername", function(){
      if ($scope.loginUsername == "admin") {
        $scope.loginRole = "admin";
      } else if ($scope.loginUsername == "wb") {
        $scope.loginRole = "wb";
      } else {
        $scope.loginRole = "receiver";
      }
    });

}]);

'use strict';

GLClient.controller('LoginCtrl', ['$scope', '$location',
                    '$routeParams', 'Authentication', 'Receivers',
  function($scope, $location, $routeParams, Authentication) {
    var src = $routeParams['src'];

    $scope.loginUsername = "";
    $scope.loginPassword = "";
    $scope.loginRole = "receiver";

    if (src && src.indexOf("/admin") != -1) {
      $scope.loginUsername = "admin";
      $scope.loginRole = "admin";
    };

    $scope.$watch("loginUsername", function(){
      if ($scope.loginUsername == "admin") {
        $scope.loginRole = "admin";
      } else if ($scope.loginUsername == "wb") {
        $scope.loginRole = "wb";
      } else {
        $scope.loginRole = "receiver";
      }
    });

}]);

Remove unused resource fetching of receivers


Package.describe({
  summary: "The dynamic stylesheet language."
});

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

Package.register_extension(
  "less", function (bundle, source_path, serve_path, where) {
    serve_path = serve_path + '.css';

    var contents = fs.readFileSync(source_path);

    try {
      less.render(contents.toString('utf8'), function (err, css) {
        // XXX why is this a callback? it's not async.
        if (err) {
          bundle.error(source_path + ": Less compiler error: " + err.message);
          return;
        }

        bundle.add_resource({
          type: "css",
          path: serve_path,
          data: new Buffer(css),
          where: where
        });
      });
    } catch (e) {
      // less.render() is supposed to report any errors via its
      // callback. But sometimes, it throws them instead. This is
      // probably a bug in less. Be prepared for either behavior.
      bundle.error(source_path + ": Less compiler error: " + err.message);
    }
  }
);

Package.describe({
  summary: "The dynamic stylesheet language."
});

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

Package.register_extension(
  "less", function (bundle, source_path, serve_path, where) {
    serve_path = serve_path + '.css';

    var contents = fs.readFileSync(source_path);

    try {
      less.render(contents.toString('utf8'), function (err, css) {
        // XXX why is this a callback? it's not async.
        if (err) {
          bundle.error(source_path + ": Less compiler error: " + err.message);
          return;
        }

        bundle.add_resource({
          type: "css",
          path: serve_path,
          data: new Buffer(css),
          where: where
        });
      });
    } catch (e) {
      // less.render() is supposed to report any errors via its
      // callback. But sometimes, it throws them instead. This is
      // probably a bug in less. Be prepared for either behavior.
      bundle.error(source_path + ": Less compiler error: " + e.message);
    }
  }
);

Use correct variable name when logging a less error


import React from 'react';
import './QuickStart.scss';

const QuickStart = () => (

Documentation

New to Skygear?

      <form action="/guides/get-started/ios/">
        <button className="quick-start-button">Quick Start</button>
      </form>

);

export default QuickStart;

import React from 'react';
import './QuickStart.scss';

const QuickStart = () => (

Documentation

New to Skygear?

      <form action="/guides/quickstart/ios/">
        <button className="quick-start-button">Quick Start</button>
      </form>

);

export default QuickStart;

Update Quickstart button at index to new Quick start guide


import Ember from 'ember';
import preloadDataMixin from '../mixins/preload_data';

export default Ember.Route.extend(preloadDataMixin, {
  cordova: Ember.inject.service(),

  beforeModel() {
    Ember.run(() => this.controllerFor('application').send('logMeIn'));
    return this.preloadData().catch(error => {
      if (error.status === 0) {
        this.transitionTo("offline");
      } else {
        throw error;
      }
    }).finally(() => this.get("cordova").appLoad());
  },

  afterModel() {

    if (this.get("session.isAdminApp")) {
      this.loadStaticData().catch(error => {
        if (error.status === 0) {
          this.transitionTo("offline");
        } else {
          throw error;
        }
      });
    }

    // After everthying has been loaded, redirect user to requested url
    var attemptedTransition = this.controllerFor('login').get('attemptedTransition');
    if (attemptedTransition) {
      attemptedTransition.retry();
      this.set('attemptedTransition', null);
    } else {
      var currentUser = this.get('session.currentUser');
      if (this.get('session.isAdminApp')) {
        this.transitionTo('dashboard');
      } else {
        this.transitionTo('/offers');
      }
    }
  }

});

import Ember from 'ember';
import preloadDataMixin from '../mixins/preload_data';

export default Ember.Route.extend(preloadDataMixin, {
  cordova: Ember.inject.service(),

  beforeModel() {
    Ember.run(() => this.controllerFor('application').send('logMeIn'));
    return this.preloadData().catch(error => {
      if (error.status === 0) {
        this.transitionTo("offline");
      } else {
        throw error;
      }
    }).finally(() => this.get("cordova").appLoad());
  },

  afterModel() {

    if (this.get("session.isAdminApp")) {
      this.loadStaticData().catch(error => {
        if (error.status === 0) {
          this.transitionTo("offline");
        } else {
          throw error;
        }
      });
    }

    // After everthying has been loaded, redirect user to requested url
    var attemptedTransition = this.controllerFor('login').get('attemptedTransition');
    if (attemptedTransition) {
      attemptedTransition.retry();
      this.set('attemptedTransition', null);
    } else {
      var currentUser = this.get('session.currentUser');
      if (this.get('session.isAdminApp')) {
        var myOffers = this.store.peekAll('offer').filterBy('reviewedBy.id', currentUser.get('id'));
        if (myOffers.get('length') > 0) {
          this.transitionTo('my_list');
        } else {
          this.transitionTo('offers');
        }
      } else {
        this.transitionTo('/offers');
      }
    }
  }

});

Revert "GCW- 2473- Replace Admin Offers UI with Dashboard and Search Filters"


Prism.languages.python= {
	'comment': {
		pattern: /(^|[^\\])#.*?(\r?\n|$)/g,
		lookbehind: true
	},
	'string': /"""[\s\S]+?"""|("|')(\\?.)*?\1/g,
	'keyword' : /\b(as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/g,
	'boolean' : /\b(True|False)\b/g,
	'number' : /\b-?(0x)?\d*\.?[\da-f]+\b/g,
	'operator' : /[-+]{1,2}|=?<|=?>|!|={1,2}|(&){1,2}|(&){1,2}|\|?\||\?|\*|\/|~|\^|%|\b(or|and|not)\b/g,
	'ignore' : /&(lt|gt|amp);/gi,
	'punctuation' : /[{}[\];(),.:]/g
};

Prism.languages.python= {
	'comment': {
		pattern: /(^|[^\\])#.*?(\r?\n|$)/g,
		lookbehind: true
	},
	'string': /"""[\s\S]+?"""|'''[\s\S]+?'''|("|')(\\?.)*?\1/g,
	'keyword' : /\b(as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/g,
	'boolean' : /\b(True|False)\b/g,
	'number' : /\b-?(0x)?\d*\.?[\da-f]+\b/g,
	'operator' : /[-+]{1,2}|=?<|=?>|!|={1,2}|(&){1,2}|(&){1,2}|\|?\||\?|\*|\/|~|\^|%|\b(or|and|not)\b/g,
	'ignore' : /&(lt|gt|amp);/gi,
	'punctuation' : /[{}[\];(),.:]/g
};

Add support for single quoted multi-line strings in Python


'use strict';

angular.module('koastAdminApp.core.constants', [])
  .factory('constants', function() {
    return {
      adminPath: 'http://localhost:3000/admin',
      // TODO make this a server side configuration option and add endpoints to
      // facilitate selection
      awsBucket: 'rvaiya-development'
    };
  });

'use strict';

angular.module('koastAdminApp.core.constants', [])
  .factory('constants', function () {
    return {
      adminPath: 'http://localhost:3000/admin',
      // TODO make this a server side configuration option and add endpoints to
      // facilitate selection
      awsBucket: 'test-koast'
    };
  });

Update aws-bucket to use koast test


(function( angular ) {
  'use strict';

  angular.module('angular-humanize', []).
    filter('humanizeFilesize', function () {
      return function ( input, decimals, decPoint, thousandsSep ) {
        if ( isNaN(parseInt(input)) ) { return input; }
        return humanize.filesize(parseInt(input, decimals || 2, decPoint || '.', thousandsSep || ','));
      };
    }).
    filter('humanizeOrdinal', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.ordinal(input);
      };
    }).
    filter('humanizeNaturalDay', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.naturalDay(input);
      };
    }).
    filter('humanizeRelativeTime', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.relativeTime(input);
      };
    });

}( angular ));

(function( angular ) {
  'use strict';

  angular.module('angular-humanize', []).
    filter('humanizeFilesize', function () {
      return function ( input, kilo, decimals, decPoint, thousandsSep ) {
        if ( isNaN(parseInt(input)) ) { return input; }
        return humanize.filesize(parseInt(input, kilo || undefined, decimals || undefined, decPoint || undefined, thousandsSep || undefined));
      };
    }).
    filter('humanizeOrdinal', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.ordinal(input);
      };
    }).
    filter('humanizeNaturalDay', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.naturalDay(input);
      };
    }).
    filter('humanizeRelativeTime', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.relativeTime(input);
      };
    });

}( angular ));

Fix 'kilo' arg was missing'


var swig = require('swig');

swig.setDefaults({
  cache: false
});

module.exports = function(data, locals){
  return swig.render(data.text, {
    locals: locals,
    filename: data.path
  });
};

var swig = require('swig'),
  forTag = require('swig/lib/tags/for');

swig.setDefaults({
  cache: false
});

// Hack: Override for tag of Swig
swig.setTag('for', forTag.parse, function(compiler, args, content, parents, options, blockName){
  var compile = forTag.compile.apply(this, arguments).split('\n');

  compile.splice(3, 0, '  if (!Array.isArray(__l) && typeof __l.toArray === "function") { __l = __l.toArray(); }');

  return compile.join('\n');
}, forTag.ends, true);

module.exports = function(data, locals){
  return swig.render(data.text, {
    locals: locals,
    filename: data.path
  });
};

Make Swig capable for Warehouse query instance


// Obtain ALL anchors on the page.
var links = document.links;

// The previous/next urls if they exist.
var previous = findHref("prev");
var next = findHref("next");

/**
 * Find the href for a given name.
 * @param {String} The name of the anchor to search for.
 * @return {String} The href for a given tag, otherwise an empty string.
 */
function findHref(name) {
  for (var index = 0; index < links.length; ++index) {
    // The complete anchor HTML element (<a>).
    var anchor = links[index];
    // Not all anchors have text, rels or classes defined.
    var rel = (anchor.rel !== undefined) ? anchor.rel : '';
    var text = (anchor.text !== undefined) ? anchor.text.toLowerCase() : '';
    var class_name = (anchor.className !== undefined) ? anchor.className : '';
    if (rel.indexOf(name) > -1 || text.indexOf(name) > -1 || class_name.indexOf(name) > -1) {
      return anchor.href;
    }
  }
}

// Go to the next/previous pages using the arrow keys.
document.addEventListener('keydown', function(event) {
  if(event.keyCode == 37) {
    if (previous) chrome.extension.sendMessage({redirect: previous});
  }
  else if(event.keyCode == 39) {
    if (next) chrome.extension.sendMessage({redirect: next});
  }
});

// Obtain ALL anchors on the page.
var links = document.links;

// The previous/next urls if they exist.
var prev = findHref("prev");
var next = findHref("next");

/**
 * Find the href for a given name.
 * @param {String} The name of the anchor to search for.
 * @return {String} The href for a given tag, otherwise an empty string.
 */
function findHref(name) {
  for (var index = 0; index < links.length; ++index) {
    // The complete anchor HTML element (<a>).
    var anchor = links[index];
    // Not all anchors have text, rels or classes defined.
    var rel = (anchor.rel !== undefined) ? anchor.rel : '';
    var text = (anchor.text !== undefined) ? anchor.text.toLowerCase() : '';
    var class_name = (anchor.className !== undefined) ? anchor.className : '';
    if (rel.indexOf(name) > -1 || text.indexOf(name) > -1 || class_name.indexOf(name) > -1) {
      return anchor.href;
    }
  }
}

// Go to the next/previous pages using the arrow keys.
document.addEventListener('keydown', function(event) {
  if(event.keyCode == 37) {
    if (prev) chrome.extension.sendMessage({redirect: prev});
  }
  else if(event.keyCode == 39) {
    if (next) chrome.extension.sendMessage({redirect: next});
  }
});

Rename previous to prev for consistency.


// Loaded ready states
const loadedStates = ['interactive', 'complete'];

// Return Promise
module.exports = (cb, doc) => new Promise(resolve => {
	// Allow doc to be passed in as the lone first param
	if (cb && typeof cb !== 'function') {
		doc = cb;
		cb = null;
	}

	// Use global document if we don't have one
	doc = doc || window.document;

	// Handle DOM load
	const done = () => resolve(cb && cb());

	// Resolve now if DOM has already loaded
	// Otherwise wait for DOMContentLoaded
	if (loadedStates.includes(doc.readyState)) {
		done();
	} else {
		doc.addEventListener('DOMContentLoaded', done);
	}
});

// Loaded ready states
const loadedStates = ['interactive', 'complete'];

// Return Promise
const domLoaded = (cb, doc) => new Promise(resolve => {
	// Allow doc to be passed in as the lone first param
	if (cb && typeof cb !== 'function') {
		doc = cb;
		cb = null;
	}

	// Use global document if we don't have one
	doc = doc || window.document;

	// Handle DOM load
	const done = () => resolve(cb && cb());

	// Resolve now if DOM has already loaded
	// Otherwise wait for DOMContentLoaded
	if (loadedStates.includes(doc.readyState)) {
		done();
	} else {
		doc.addEventListener('DOMContentLoaded', done);
	}
});

// Promise chain helper
domLoaded.wait = doc => data => domLoaded(doc).then(() => data);

module.exports = domLoaded;

Add Promise chain helper method


module.exports = function mutableProxyFactory(defaultTarget) {
  let mutableHandler;
  let mutableTarget;

  function setTarget(target) {
    if (!(target instanceof Object)) {
      throw new Error(`Target "${target}" is not an object`);
    }
    mutableTarget = target;
  }

  function setHandler(handler) {
    Object.keys(handler).forEach(key => {
      const value = handler[key];

      if (typeof value !== 'function') {
        throw new Error(`Trap "${key}: ${value}" is not a function`);
      }

      if (!Reflect[key]) {
        throw new Error(`Trap "${key}: ${value}" is not a valid trap`);
      }
    });
    mutableHandler = handler;
  }

  if (defaultTarget) {
    setTarget(defaultTarget);
  }
  setHandler(Reflect);

  // Dynamically forward all the traps to the associated methods on the mutable handler
  const handler = new Proxy({}, {
    get(target, property) {
      return (...args) => mutableHandler[property].apply(null, [mutableTarget, ...args.slice(1)]);
    }
  });

  return {
    setTarget,
    setHandler,
    getTarget() {
      return mutableTarget;
    },
    getHandler() {
      return mutableHandler;
    },
    proxy: new Proxy(() => {}, handler)
  };
};

module.exports = function mutableProxyFactory(defaultTarget) {
  let mutableHandler;
  let mutableTarget;

  function setTarget(target) {
    if (!(target instanceof Object)) {
      throw new Error(`Target "${target}" is not an object`);
    }
    mutableTarget = target;
  }

  function setHandler(handler) {
    Object.keys(handler).forEach(key => {
      const value = handler[key];

      if (typeof value !== 'function') {
        throw new Error(`Trap "${key}: ${value}" is not a function`);
      }

      if (!Reflect[key]) {
        throw new Error(`Trap "${key}: ${value}" is not a valid trap`);
      }
    });
    mutableHandler = handler;
  }
  setTarget(() => {});

  if (defaultTarget) {
    setTarget(defaultTarget);
  }
  setHandler(Reflect);

  // Dynamically forward all the traps to the associated methods on the mutable handler
  const handler = new Proxy({}, {
    get(target, property) {
      return (...args) => mutableHandler[property].apply(null, [mutableTarget, ...args.slice(1)]);
    }
  });

  return {
    setTarget,
    setHandler,
    getTarget() {
      return mutableTarget;
    },
    getHandler() {
      return mutableHandler;
    },
    proxy: new Proxy(mutableTarget, handler)
  };
};

Revert to setting target with noOp


'use strict';

import assign from 'lodash.assign';
import ResultList from './result-list';

const requiredDefaults = {
  page: 1,
  per_page: 20,
};

const pixabayjs = {
  _auth: {},

  _makeConfig: function(url, opts) {
    const urlObj = { url };
    return assign({}, requiredDefaults, urlObj, this.defaults, this._auth,
      opts);
  },

  defaults: {},

  authenticate: function(key) {
    this._auth.key = key;
  },

  imageResultList: function(search, opts, onSuccess, onFailure) {
    const url = 'https://pixabay.com/api';
    const conf = this._makeConfig(url, opts);
    return new ResultList(search, conf, onSuccess, onFailure);
  },

  videoResultList: function(search, opts, onSuccess, onFailure) {
    const url = 'https://pixabay.com/api/videos';
    const conf = this._makeConfig(url, opts);
    return new ResultList(search, conf, onSuccess, onFailure);
  }
};

export default pixabayjs;
module.exports = pixabayjs;

'use strict';

import assign from 'lodash.assign';
import path from 'path';
import url from 'url';

import ResultList from './result-list';

const requiredDefaults = {
  page: 1,
  per_page: 20,
  url: 'https://pixabay.com/api'
};

const pixabayjs = {
  _auth: {},

  _makeConfig: function(endpoint, opts) {
    const conf = assign({}, requiredDefaults, this.defaults, this._auth, opts);
    const urlObj = url.parse(conf.url);

    urlObj.pathname = path.join(urlObj.pathname, endpoint, '/');
    conf.url = url.format(urlObj);

    return conf;
  },

  defaults: {},

  authenticate: function(key) {
    this._auth.key = key;
  },

  imageResultList: function(search, opts, onSuccess, onFailure) {
    const conf = this._makeConfig('', opts);
    return new ResultList(search, conf, onSuccess, onFailure);
  },

  videoResultList: function(search, opts, onSuccess, onFailure) {
    const conf = this._makeConfig('videos', opts);
    return new ResultList(search, conf, onSuccess, onFailure);
  }
};

export default pixabayjs;
module.exports = pixabayjs;

Enable overriding of the default url


import postcss            from 'postcss';
import Core               from 'css-modules-loader-core';
import Parser             from 'css-modules-loader-core/lib/parser';
import FileSystemLoader   from 'css-modules-loader-core/lib/file-system-loader';
import generateScopedName from './generateScopedName';
import saveJSON           from './saveJSON';

module.exports = postcss.plugin('postcss-modules', (opts = {}) => {
  Core.scope.generateScopedName = opts.generateScopedName || generateScopedName;
  const getJSON = opts.getJSON || saveJSON;

  return (css, result) => {
    const resultPlugins = result.processor.plugins
      .filter(plugin => plugin.postcssPlugin !== 'postcss-modules');

    const plugins = [
      Core.values,
      Core.localByDefault,
      Core.extractImports,
      Core.scope,
      ...resultPlugins,
    ];

    const loader  = new FileSystemLoader('/', plugins);
    const parser  = new Parser(loader.fetch.bind(loader));

    const promise = new Promise(resolve => {
      postcss([...plugins, parser.plugin])
        .process(css, { from: css.source.input.file })
        .then(() => {
          Object.keys(loader.sources).forEach(key => {
            css.prepend(loader.sources[key]);
          });

          getJSON(css.source.input.file, parser.exportTokens);

          resolve();
        });
    });

    return promise;
  };
});

import postcss            from 'postcss';
import Core               from 'css-modules-loader-core';
import Parser             from 'css-modules-loader-core/lib/parser';
import FileSystemLoader   from 'css-modules-loader-core/lib/file-system-loader';
import generateScopedName from './generateScopedName';
import saveJSON           from './saveJSON';

module.exports = postcss.plugin('postcss-modules', (opts = {}) => {
  Core.scope.generateScopedName = opts.generateScopedName || generateScopedName;
  const getJSON = opts.getJSON || saveJSON;

  return (css, result) => {
    const resultPlugins = result.processor.plugins
      .filter(plugin => plugin.postcssPlugin !== 'postcss-modules');

    const plugins = [
      Core.values,
      Core.localByDefault,
      Core.extractImports,
      Core.scope,
      ...resultPlugins,
    ];

    const loader  = typeof opts.Loader === 'function' ?
      new opts.Loader('/', plugins) :
      new FileSystemLoader('/', plugins);

    const parser  = new Parser(loader.fetch.bind(loader));

    const promise = new Promise(resolve => {
      postcss([...plugins, parser.plugin])
        .process(css, { from: css.source.input.file })
        .then(() => {
          Object.keys(loader.sources).forEach(key => {
            css.prepend(loader.sources[key]);
          });

          getJSON(css.source.input.file, parser.exportTokens);

          resolve();
        });
    });

    return promise;
  };
});

Add support for custom `Loader` via `opts`


import React from 'react';
import { map } from 'lodash';
import { displayUserInfo, displayCityState } from '../../helpers';

const UserInformation = (props) => (

    {props.user.length ?

        {props.linkSignup ?

<a href={`/signups/${props.linkSignup}`}>{displayUserInfo(props.user.first_name, props.user.last_name, props.user.birthdate)}

        :

{displayUserInfo(props.user.first_name, props.user.last_name, props.user.birthdate)}

        }

          {props.user.email ? {props.user.email}
: null}
          {props.user.mobile ? {props.user.mobile}
 : null }
          {displayCityState(props.user.addr_city, props.user.addr_state) ? {displayCityState(props.user.addr_city, props.user.addr_state) }
 : null }

    :

User Not Found

    }
    {props.children}

);

export default UserInformation;

import React from 'react';
import { map, isEmpty } from 'lodash';
import { displayUserInfo, displayCityState } from '../../helpers';

const UserInformation = (props) => (

    {!isEmpty(props.user) ?

        {props.linkSignup ?

<a href={`/signups/${props.linkSignup}`}>{displayUserInfo(props.user.first_name, props.user.last_name, props.user.birthdate)}

        :

{displayUserInfo(props.user.first_name, props.user.last_name, props.user.birthdate)}

        }

          {props.user.email ? {props.user.email}
: null}
          {props.user.mobile ? {props.user.mobile}
 : null }
          {displayCityState(props.user.addr_city, props.user.addr_state) ? {displayCityState(props.user.addr_city, props.user.addr_state) }
 : null }

    :

User Not Found

    }
    {props.children}

);

export default UserInformation;

Check for empty user properly


var saikuWidgetComponent = BaseComponent.extend({

	update : function() {
		var myself=this;
		var htmlId = "#" + myself.htmlObject;
		if (myself.saikuFilePath.substr(0,1) == "/") {
			myself.saikuFilePath = myself.saikuFilePath.substr(1,myself.saikuFilePath.length - 1 );
		}

		var parameters = {};
		if (myself.parameters) {
			_.each(myself.parameters, function(parameter) {
				var k = parameter[0];
				var v = parameter[1];

				if (window.hasOwnProperty(v)) {
					v = window[v];
				}
				parameters[k] = v;
			});
		}
		if (myself.width) {
			$(htmlId).width(myself.width);
		}
		if (myself.width) {
			$(htmlId).height(myself.height);
		}
		if ("table" == myself.renderMode) {
			$(htmlId).addClass('workspace_results');
			var t = $("

");
			$(htmlId).html(t);
			htmlId = t;
		}
		var myClient = new SaikuClient({
		    server: "../../../plugin/saiku/api",
		    path: "/cde-component"
		});

		myClient.execute({
		    file: myself.saikuFilePath,
		    htmlObject: htmlId,
		    render: myself.renderMode,
		    mode: myself.renderType,
		    zoom: true,
		    params: parameters
		});

	}
});

var saikuWidgetComponent = BaseComponent.extend({

	update : function() {
		var myself=this;
		var htmlId = "#" + myself.htmlObject;
		if (myself.saikuFilePath.substr(0,1) == "/") {
			myself.saikuFilePath = myself.saikuFilePath.substr(1,myself.saikuFilePath.length - 1 );
		}

		var parameters = {};
		if (myself.parameters) {
			_.each(myself.parameters, function(parameter) {
				var k = parameter[0];
				var v = parameter[1];

				if (window.hasOwnProperty(v)) {
					v = window[v];
				}
				parameters[k] = v;
			});
		}
		if (myself.width) {
			$(htmlId).width(myself.width);
		}
		if (myself.width) {
			$(htmlId).height(myself.height);
		}
		if ("table" == myself.renderMode) {
			$(htmlId).addClass('workspace_results');
			var t = $("

");
			$(htmlId).html(t);
			htmlId = t;
		}
		var myClient = new SaikuClient({
		    server: "/pentaho/plugin/saiku/api",
		    path: "/cde-component"
		});

		myClient.execute({
		    file: myself.saikuFilePath,
		    htmlObject: htmlId,
		    render: myself.renderMode,
		    mode: myself.renderType,
		    zoom: true,
		    params: parameters
		});

	}
});

Use full path to api in stead of relatieve path


"use strict";

exports.NOT_IMPLEMENTED = function (target, nameForErrorMessage) {
  return function () {
    var raise = target ? target.raise : this.raise;
    raise.call(this, "error", "NOT IMPLEMENTED" + (nameForErrorMessage ? ": " + nameForErrorMessage : ""));
  };
};

"use strict";

exports.NOT_IMPLEMENTED = function (target, nameForErrorMessage) {
  return function () {
    var raise;

    var message = "Called NOT_IMPLEMENTED without an element to raise on" +
      (nameForErrorMessage ? ": " + nameForErrorMessage : "");

    target = target || this;
    if (target) {
      raise = target.raise;
    } else {
      if (typeof console !== "undefined" && console.log) {
        console.log(new Error(message));
      }

      return;
    }

    raise.call(this, "error", message);
  };
};

Fix NOT_IMPLEMENTED to not crash user-code if no target is given


/* German translation for the jQuery Timepicker Addon */
/* Written by Michał Pena */
(function($) {
	$.timepicker.regional['pl'] = {
		timeOnlyTitle: 'Wybierz godzinę',
		timeText: 'Czas',
		hourText: 'Godzina',
		minuteText: 'Minuta',
		secondText: 'Sekunda',
		millisecText: 'Milisekunda',
		timezoneText: 'Strefa czasowa',
		currentText: 'Teraz',
		closeText: 'Gotowe',
		timeFormat: 'hh:mm tt',
		ampm: false
	};
	$.timepicker.setDefaults($.timepicker.regional['pl']);
})(jQuery);

/* Polish translation for the jQuery Timepicker Addon */
/* Written by Michał Pena */
(function($) {
	$.timepicker.regional['pl'] = {
		timeOnlyTitle: 'Wybierz godzinę',
		timeText: 'Czas',
		hourText: 'Godzina',
		minuteText: 'Minuta',
		secondText: 'Sekunda',
		millisecText: 'Milisekunda',
		timezoneText: 'Strefa czasowa',
		currentText: 'Teraz',
		closeText: 'Gotowe',
		timeFormat: 'hh:mm tt',
		amNames: ['AM', 'A'],
		pmNames: ['PM', 'P'],
		ampm: false
	};
	$.timepicker.setDefaults($.timepicker.regional['pl']);
})(jQuery);

Add `amNames`/`pmNames` for Polish translation.


require('babel/register')({
  ignore: false,
  only: /.+(?:(?:\.es6\.js)|(?:.jsx))$/,
  extensions: ['.js', '.es6.js', '.jsx' ],
  sourceMap: true,
});

// lib
require('./lib/titleCase');
require('./lib/formatDifference');

// Even with shallow rendering react currently looks for document when setState is used.
// see https://github.com/facebook/react/issues/4019
global.document = {};

// components
require('./views/components/Modal');

//Layouts
require('./views/layouts/BodyLayout');

// pages
require('./views/pages/Index');
require('./views/pages/userSaved');

require('babel/register')({
  ignore: false,
  only: /.+(?:(?:\.es6\.js)|(?:.jsx))$/,
  extensions: ['.js', '.es6.js', '.jsx' ],
  sourceMap: true,
  stage: 0
});

// lib
require('./lib/titleCase');
require('./lib/formatDifference');

// Even with shallow rendering react currently looks for document when setState is used.
// see https://github.com/facebook/react/issues/4019
global.document = {};

// components
require('./views/components/Modal');

//Layouts
require('./views/layouts/BodyLayout');

// pages
require('./views/pages/Index');
require('./views/pages/userSaved');

Use stage 0 for tests like everything else


import { join } from 'path'
import assert from 'yeoman-assert'
import helpers from 'yeoman-test'
import pify from 'pify'
import test from 'ava'

test('generates expected files', async t => {
  await pify(helpers.testDirectory)(join(__dirname, '..', 'temp'))

  const generator = helpers.createGenerator(
    'wyze-nm:app', [ '../app' ], null, { skipInstall: true }
  )

  helpers.mockPrompt(generator, {
    module: 'test',
    description: 'test',
    github: 'test',
    url: 'test.com',
  })

  await pify(generator.run.bind(generator))()

  assert.file([
    'src/index.js',
    'test/index.js',
    '.editorconfig',
    '.git',
    '.gitattributes',
    '.gitignore',
    '.travis.yml',
    'license',
    'package.json',
    'readme.md',
  ])

  t.pass()
})

import { join } from 'path'
import assert from 'yeoman-assert'
import helpers from 'yeoman-test'
import pify from 'pify'
import test from 'ava'

test('generates expected files', async t => {
  await pify(helpers.testDirectory)(join(__dirname, '..', 'temp'))

  const generator = helpers.createGenerator(
    'wyze-nm:app', [ '../app' ], null, { skipInstall: true }
  )

  helpers.mockPrompt(generator, {
    module: 'test',
    description: 'test',
    github: 'test',
    url: 'test.com',
    // Pass in git name/email for Travis
    name: 'travis',
    email: 'travis@travis-ci.org',
  })

  await pify(generator.run.bind(generator))()

  assert.file([
    'src/index.js',
    'test/index.js',
    '.editorconfig',
    '.git',
    '.gitattributes',
    '.gitignore',
    '.travis.yml',
    'license',
    'package.json',
    'readme.md',
  ])

  t.pass()
})

Update test to pass in git name/email for Travis


var PluginDependency = require('../../models/pluginDependency');
var resolveVersion = require('../resolveVersion');

describe('resolveVersion', function() {
    it('must skip resolving and return non-semver versions', function(done) {
        var plugin = PluginDependency.createFromString('plugin-ga@git+ssh://samy@github.com/GitbookIO/plugin-ga.git');

        resolveVersion(plugin)
        .then(function(version) {
            expect(version).toBe('git+ssh://samy@github.com/GitbookIO/plugin-ga.git');
            done();
        });
    });
});

var PluginDependency = require('../../models/pluginDependency');
var resolveVersion = require('../resolveVersion');

describe('resolveVersion', function() {
    it('must skip resolving and return non-semver versions', function() {
        var plugin = PluginDependency.createFromString('ga@git+ssh://samy@github.com/GitbookIO/plugin-ga.git');

        return resolveVersion(plugin)
        .then(function(version) {
            expect(version).toBe('git+ssh://samy@github.com/GitbookIO/plugin-ga.git');
        });
    });

    it('must resolve a normal plugin dependency', function() {
        var plugin = PluginDependency.createFromString('ga@>0.9.0 < 1.0.1');

        return resolveVersion(plugin)
        .then(function(version) {
            expect(version).toBe('1.0.0');
        });
    });
});

Add test for plugin version resolution


 var getRecipeEvent = function(apiRequest){
  $('.container').on('click', '.recipe-container', function(event) {
    var $target = $(event.target);
    var recipeId = $target.closest('.recipe-container')[0].dataset.recipeid;
    apiRequest(recipeId);
  });
};

var getSignUpFormEvent = function(){
  $('.container').on('click', '.signup-link', function(event) {
    event.preventDefault();
    var loginTemplate = Mustache.render($('#sign-up-template').html());
    $('.navbar-collapse').collapse('toggle')
    $('.content-container').html(loginTemplate);
  });
};

Add getSignUpFormEvent function to clickListeners.js


/*
 * Copyright (c) 2015-2017 Steven Soloff
 *
 * This is free software: you can redistribute it and/or modify it under the
 * terms of the MIT License (https://opensource.org/licenses/MIT).
 * This software comes with ABSOLUTELY NO WARRANTY.
 */

'use strict'

const correlationId = require('../../../src/server/middleware/correlation-id')

describe('correlationId', () => {
  describe('correlator', () => {
    let correlator
    let next
    let req
    let res

    beforeEach(() => {
      correlator = correlationId()
      next = jasmine.createSpy('next')
      req = {
        get: jasmine.createSpy('get')
      }
      res = {
        set: jasmine.createSpy('set')
      }
    })

    it('should invoke the next middleware in the chain', () => {
      correlator(req, res, next)

      expect(next).toHaveBeenCalled()
    })

    describe('when the request contains a request ID', () => {
      it('should echo the request ID as the correlation ID in the response', () => {
        const requestId = 'the-request-id'
        req.get.and.returnValue(requestId)

        correlator(req, res, next)

        expect(req.get).toHaveBeenCalledWith('X-Request-ID')
        expect(res.set).toHaveBeenCalledWith('X-Correlation-ID', requestId)
      })
    })

    describe('when the request does not contain a request ID', () => {
      it('should not modify the response', () => {
        correlator(req, res, next)

        expect(res.set).not.toHaveBeenCalled()
      })
    })
  })
})

/*
 * Copyright (c) 2015-2017 Steven Soloff
 *
 * This is free software: you can redistribute it and/or modify it under the
 * terms of the MIT License (https://opensource.org/licenses/MIT).
 * This software comes with ABSOLUTELY NO WARRANTY.
 */

'use strict'

const middleware = require('../../../src/server/middleware')

describe('correlationId', () => {
  describe('correlator', () => {
    let correlator
    let next
    let req
    let res

    beforeEach(() => {
      correlator = middleware.correlationId()
      next = jasmine.createSpy('next')
      req = {
        get: jasmine.createSpy('get')
      }
      res = {
        set: jasmine.createSpy('set')
      }
    })

    it('should invoke the next middleware in the chain', () => {
      correlator(req, res, next)

      expect(next).toHaveBeenCalled()
    })

    describe('when the request contains a request ID', () => {
      it('should echo the request ID as the correlation ID in the response', () => {
        const requestId = 'the-request-id'
        req.get.and.returnValue(requestId)

        correlator(req, res, next)

        expect(req.get).toHaveBeenCalledWith('X-Request-ID')
        expect(res.set).toHaveBeenCalledWith('X-Correlation-ID', requestId)
      })
    })

    describe('when the request does not contain a request ID', () => {
      it('should not modify the response', () => {
        correlator(req, res, next)

        expect(res.set).not.toHaveBeenCalled()
      })
    })
  })
})

Access individual middleware through aggregating module


var Gulp = require('gulp'),

    Linoleum = require('linoleum');

var $jsFiles = Linoleum.jsFiles;
Linoleum.jsFiles = function() {
  return $jsFiles().concat('tasks/*.js', 'index.js');
};

require('./index');

Gulp.task('build', ['clean', 'lint'], function(done) {
  Linoleum.runTask('babel', done);
});
Gulp.task('test', ['build'], function(done) {
  Linoleum.runTask('test:mocha', done);
});
Gulp.task('cover', ['build'], function(done) {
  Linoleum.runTask(['cover:mocha', 'cover:report'], done);
});

Linoleum.watch(Linoleum.jsFiles(), 'cover');

Gulp.task('travis', function(done) {
  // These need to be run in series to prevent issues with error tracking
  Linoleum.runTask(['cover', 'test'], done);
});
Gulp.task('default', ['cover']);

var Gulp = require('gulp'),

    Linoleum = require('linoleum');

require('./index');

Gulp.task('build', ['clean', 'lint'], function(done) {
  Linoleum.runTask('babel', done);
});
Gulp.task('test', ['build'], function(done) {
  Linoleum.runTask('test:mocha', done);
});
Gulp.task('cover', ['build'], function(done) {
  Linoleum.runTask(['cover:mocha', 'cover:report'], done);
});

Linoleum.watch(Linoleum.jsFiles(), 'cover');

Gulp.task('travis', function(done) {
  // These need to be run in series to prevent issues with error tracking
  Linoleum.runTask(['cover', 'test'], done);
});
Gulp.task('default', ['cover']);

require('linoleum/Gulpfile.local');

Use gulp local for self test


// FIXME: debugging only.
/* eslint-disable */
// import fetch from 'node-fetch'

const callRedis = async data => {
  try {
    console.log(
      '===== Calling Redis service =====',
      process.env.redisServiceEndpoint
    )
  } catch (e) {
    console.log('Error calling Redis service', e)
  }
}

export default callRedis

// FIXME: debugging only.
/* eslint-disable */
import fetch from 'node-fetch'

const callRedis = async data => {
  let responseData
  try {
    console.log(
      '===== Calling Redis service =====',
      process.env.redisServiceEndpoint
    )
    const response = await fetch(process.env.redisServiceEndpoint, {
      method: 'POST',
    })
    responseData = response.json()
  } catch (e) {
    console.log('Error calling Redis service', e)
  }
  console.log('===== Redis service response data =====', responseData)
}

export default callRedis

Add test request to Redis service


// Main Module for searchthedocs demo
define(function (require) {
  var _ = require('underscore'),
    $ = require('jquery'),
    SearchTheDocsView = require('searchthedocs/src/searchthedocs');

  var searchthedocs_main = function() {

    window.searchtd = new SearchTheDocsView({
      el: '#searchthedocs',
    });

  };

  return searchthedocs_main;

});

// Main Module for searchthedocs demo
define(function (require) {
  var _ = require('underscore'),
    $ = require('jquery'),
    SearchTheDocsView = require('searchthedocs/src/searchthedocs');

  var searchthedocs_main = function() {

    window.searchtd = new SearchTheDocsView({
      el: '#searchthedocs',
      brand: 'searchthedocs',
      brand_href: '#'
    });

  };

  return searchthedocs_main;

});

Send brand and brand_href into SearchTheDocsView


import OsfAdapter from './osf-adapter';
import Ember from 'ember';

export default OsfAdapter.extend({
    findHasMany(store, snapshot, url, relationship) {
        var id = snapshot.id;
        var type = snapshot.modelName;

        url = this.urlPrefix(url, this.buildURL(type, id, snapshot, 'findHasMany'));

        // If fetching user nodes, will embed root and parent. (@hmoco 12-27-17: why?)
        if (relationship.type === 'node') {
            url += '?embed=parent&embed=root';
            // TODO: revisit this, we shouldnt hard code any embeds
            if (snapshot.record.get('__' + relationship.key + 'QueryParams')) {
                url += '&' + Ember.$.param(snapshot.record.get('__' + relationship.key + 'QueryParams'));
            }
        } else if (snapshot.record.get('query-params')) {
            url += '?' + Ember.$.param(snapshot.record.get('query-params'));
        }
        return this.ajax(url, 'GET');
    }
});

import OsfAdapter from './osf-adapter';
import Ember from 'ember';

export default OsfAdapter.extend({
});

Remove unused findHasMany method on osfadapter


// Create `window.describe` etc. for our BDD-like tests.
mocha.setup({ui: 'bdd'});
mocha.reporter('html');

// Create another global variable for simpler syntax.
window.expect = chai.expect;

// Create `window.describe` etc. for our BDD-like tests.
mocha.setup({ui: 'bdd'})
mocha.reporter('html')

// initialize chai.should (@see http://chaijs.com/guide/styles/#should)
window.should = chai.should()

// Create another global variable for simpler syntax.
window.expect = chai.expect

Add chai.should to tests and remove semicolons


import SimpleSchema from 'simpl-schema';

/*

Look for type name in a few different places
Note: look into simplifying this

*/
export const isIntlField = fieldSchema => {
  const typeProperty = fieldSchema.type;
  let type;
  if (Array.isArray(typeProperty)) {
    type = typeProperty[0].type;
  } else {
    type = typeProperty.singleType ? typeProperty.singleType : typeProperty.definitions[0].type;
  }
  return type.name === 'IntlString';
}

/*

Generate custom IntlString SimpleSchema type
TODO: WIP (languages hardcoded)

*/
const schema = {};

['en', 'ja'].forEach(locale => {
  schema[locale] = {
    type: String,
    optional: true,
  };
});

export const IntlString = new SimpleSchema(schema);
IntlString.name = 'IntlString';

import SimpleSchema from 'simpl-schema';
import { Strings } from './strings';

/*

Look for type name in a few different places
Note: look into simplifying this

*/
export const isIntlField = fieldSchema => {
  const typeProperty = fieldSchema.type;
  let type;
  if (Array.isArray(typeProperty)) {
    type = typeProperty[0].type;
  } else {
    type = typeProperty.singleType ? typeProperty.singleType : typeProperty.definitions[0].type;
  }
  return type.name === 'IntlString';
}

/*

Generate custom IntlString SimpleSchema type

*/
export const getIntlString = () => {

  const schema = {};

  Object.keys(Strings).forEach(locale => {
    schema[locale] = {
      type: String,
      optional: true,
    };
  });

  const IntlString = new SimpleSchema(schema);
  IntlString.name = 'IntlString';
  return IntlString;
}

Use function to get IntlString type


$(document).ready(function() {
    $(".delete-comment").click(function(){
        var form = $(this).parent().find('form');
        form.submit();
    });

    $(".redirection-button").click(function(){
        var path = $(this).attr('path');
        location.href = path;
    });

    $('.comment-iframe').on('load', function () {
        var height = this.contentWindow.document.body.offsetHeight;
        $(this).height(height);
    });
});

$(document).ready(function() {
    $(".delete-comment").click(function(){
        var form = $(this).parent().find('form');
        form.submit();
    });

    $(".redirection-button").click(function(){
        var path = $(this).attr('path');
        location.href = path;
    });

    $('.comment-iframe').on('load', function () {
        var height = this.contentWindow.document.body.offsetHeight;
        $(this).height(height);
    });

    $('#id_content_iframe').on('load', function () {
        var height = this.contentWindow.document.body.offsetHeight;
        $(this).height(height);
        $(this).attr('scrolling', 'no');
    });
});

Set summernote iframe body height


const meetOrSliceTypes = {
    meet: 0,
    slice: 1,
    none: 2,
};

const alignEnum = [
    "xMinYMin",
    "xMidYMin",
    "xMaxYMin",
    "xMinYMid",
    "xMidYMid",
    "xMaxYMid",
    "xMinYMax",
    "xMidYMax",
    "xMaxYMax",
    "none",
].reduce((prev, name) => {
    prev[name] = name;
    return prev;
}, {});

const spacesRegExp = /\s+/;

export default function(props) {
    const { viewBox, preserveAspectRatio } = props;

    if (!viewBox) {
        return null;
    }

    const params = viewBox
        .trim()
        .split(spacesRegExp)
        .map(Number);

    if (params.length === 4 && params.some(isNaN)) {
        console.warn("Invalid `viewBox` prop:" + viewBox);
        return null;
    }

    const modes = preserveAspectRatio
        ? preserveAspectRatio.trim().split(spacesRegExp)
        : [];

    const meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
    const align = alignEnum[modes[0]] || "xMidYMid";
    const [minX, minY, vbWidth, vbHeight] = params;

    return {
        minX,
        minY,
        vbWidth,
        vbHeight,
        align,
        meetOrSlice,
    };
}

export { meetOrSliceTypes, alignEnum };

const meetOrSliceTypes = {
    meet: 0,
    slice: 1,
    none: 2,
};

const alignEnum = [
    "xMinYMin",
    "xMidYMin",
    "xMaxYMin",
    "xMinYMid",
    "xMidYMid",
    "xMaxYMid",
    "xMinYMax",
    "xMidYMax",
    "xMaxYMax",
    "none",
].reduce((prev, name) => {
    prev[name] = name;
    return prev;
}, {});

const spacesRegExp = /\s+/;

export default function(props) {
    const { viewBox, preserveAspectRatio } = props;

    if (!viewBox) {
        return null;
    }

    const params = viewBox
        .trim()
        .split(spacesRegExp)
        .map(Number);

    if (params.length !== 4 || params.some(isNaN)) {
        console.warn("Invalid `viewBox` prop:" + viewBox);
        return null;
    }

    const modes = preserveAspectRatio
        ? preserveAspectRatio.trim().split(spacesRegExp)
        : [];

    const meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
    const align = alignEnum[modes[0]] || "xMidYMid";
    const [minX, minY, vbWidth, vbHeight] = params;

    return {
        minX,
        minY,
        vbWidth,
        vbHeight,
        align,
        meetOrSlice,
    };
}

export { meetOrSliceTypes, alignEnum };

Fix viewBox pre condition warning


// This is a karma config file. For more details see
//   http://karma-runner.github.io/0.13/config/configuration-file.html
// we are also using it with karma-webpack
//   https://github.com/webpack/karma-webpack

var webpackConfig = require('../../build/webpack.test.conf');

module.exports = function (config) {
  config.set({
    // to run in additional browsers:
    // 1. install corresponding karma launcher
    //    http://karma-runner.github.io/0.13/config/browsers.html
    // 2. add it to the `browsers` array below.
    browsers: ['PhantomJS'],
    frameworks: ['mocha', 'sinon-chai'],
    reporters: ['spec', 'coverage'],
    files: ['./index.js'],
    preprocessors: {
      './index.js': ['webpack', 'sourcemap']
    },
    webpack: webpackConfig,
    webpackMiddleware: {
      noInfo: true,
    },
    coverageReporter: {
      dir: './coverage',
      reporters: [
        { type: 'lcov', subdir: '.' },
        { type: 'text-summary' },
      ]
    },
  });
};

// This is a karma config file. For more details see
//   http://karma-runner.github.io/0.13/config/configuration-file.html
// we are also using it with karma-webpack
//   https://github.com/webpack/karma-webpack

let webpackConfig = require('../../build/webpack.test.conf');

module.exports = function(config) {
  config.set({
    // to run in additional browsers:
    // 1. install corresponding karma launcher
    //    http://karma-runner.github.io/0.13/config/browsers.html
    // 2. add it to the `browsers` array below.
    browsers: ['PhantomJS'],
    browserNoActivityTimeout: 24000,
    frameworks: ['mocha', 'sinon-chai'],
    reporters: ['spec', 'coverage'],
    files: ['./index.js'],
    preprocessors: {
      './index.js': ['webpack', 'sourcemap']
    },
    webpack: webpackConfig,
    webpackMiddleware: {
      noInfo: true,
    },
    coverageReporter: {
      dir: './coverage',
      reporters: [
        { type: 'lcov', subdir: '.' },
        { type: 'text-summary' },
      ]
    },
  });
};

Add additional timeout for travis


var dbr = require('./build/Release/dbr');
var v4l2camera = require("v4l2camera");
var barcodeTypes = 0x3FF | 0x2000000 | 0x8000000 | 0x4000000; // 1D, QRCODE, PDF417, DataMatrix

var cam = new v4l2camera.Camera("/dev/video0");

// list all supported formats
console.log(cam.formats);

// set frame format as YUYV
var format = cam.formats[0];
cam.configSet(format);

if (cam.configGet().formatName !== "YUYV") {
    console.log("YUYV camera required");
    process.exit(1);
}

cam.start();

function capture() {
    cam.capture(function(success) {
        var frame = cam.frameRaw();

        dbr.decodeYUYVAsync(frame, format.width, format.height, barcodeTypes,
            function(msg) {
                var result = null;
                for (index in msg) {
                    result = msg[index]
                    console.log("Format: " + result['format']);
                    console.log("Value : " + result['value']);
                    console.log("##################");
                }
                setTimeout(capture, 0);
            });
    });
}

setTimeout(capture, 0);

var dbr = require('./build/Release/dbr');
var v4l2camera = require("v4l2camera");
var barcodeTypes = 0x3FF | 0x2000000 | 0x8000000 | 0x4000000; // 1D, QRCODE, PDF417, DataMatrix

var cam = new v4l2camera.Camera("/dev/video0");

// list all supported formats
console.log(cam.formats);

// set frame format as YUYV
var format = cam.formats[0];
cam.configSet(format);

if (cam.configGet().formatName !== "YUYV") {
    console.log("YUYV camera required");
    process.exit(1);
}

dbr.initLicense("BE3F70D6536894C4E7758E43934C92A6");    // This is trial license. To use full license, please contact support@dynamsoft.com

cam.start();

function capture() {
    cam.capture(function(success) {
        var frame = cam.frameRaw();

        dbr.decodeYUYVAsync(frame, format.width, format.height, barcodeTypes,
            function(msg) {
                var result = null;
                for (index in msg) {
                    result = msg[index]
                    console.log("Format: " + result['format']);
                    console.log("Value : " + result['value']);
                    console.log("##################");
                }
                setTimeout(capture, 0);
            });
    });
}

setTimeout(capture, 0);

Initialize DBR license before using camera preview


import moment from 'moment';

import { Posts } from '../../api/collections';

const seedPosts = () => {
  const post = Posts.findOne();

  if (!post) {
    for (let i = 0; i < 50; i++) {
      Posts.insert({
        userId: 'QBgyG7MsqswQmvm7J',
        username: 'evancorl',
        createdAt: moment().utc().toDate(),
        message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod ' +
                 'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, ' +
                 'quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.',
        media: {
          type: 'Video',
          source: 'YouTube',
          thumbnail: '/images/feeds.jpg',
          url: 'https://www.meteor.com/',
        },
        likeCount: 14,
        commentCount: 3,
      });

      Posts.insert({
        userId: 'QBgyG7MsqswQmvm7J',
        username: 'evancorl',
        createdAt: moment().utc().toDate(),
        message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod ' +
                 'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, ' +
                 'quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.',
        media: {
          type: 'Photo',
          thumbnail: '/images/feeds-2.jpg',
          url: 'https://www.meteor.com/',
        },
        likeCount: 14,
        commentCount: 3,
      });
    }
  }
};

export default seedPosts;

import moment from 'moment';

import { Posts } from '../../api/collections';

const seedPosts = () => {
  const post = Posts.findOne();

  if (!post) {
    for (let i = 0; i < 50; i++) {
      Posts.insert({
        userId: 'QBgyG7MsqswQmvm7J',
        username: 'evancorl',
        avatar: '/images/avatar.jpg',
        createdAt: moment().utc().toDate(),
        type: 'Video',
        title: 'This is a sample title',
        message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod ' +
                 'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, ' +
                 'quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.',
        media: {
          source: 'YouTube',
          thumbnail: '/images/feeds.jpg',
          url: 'https://www.meteor.com/',
        },
        likeCount: 14,
        commentCount: 3,
      });

      Posts.insert({
        userId: 'QBgyG7MsqswQmvm7J',
        username: 'evancorl',
        avatar: '/images/avatar.jpg',
        createdAt: moment().utc().toDate(),
        type: 'Photo',
        message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod ' +
                 'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, ' +
                 'quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.',
        media: {
          thumbnail: '/images/feeds-2.jpg',
          url: 'https://www.meteor.com/',
        },
        likeCount: 14,
        commentCount: 3,
      });
    }
  }
};

export default seedPosts;

Restructure fields in post seed data


const authHandler = require('./auth-handler'),
      sessionHandler = require('./session-handler');

function connectionHandler(client, clientInfo){
	let user = {};
	user.keys = [];

	client.on('authentication', (context) => {
		authHandler(context, clientInfo, user);
	});

	client.on('ready', () => {
		client.once('session', (accept, reject) => {
            sessionHandler(accept, reject, user);
        });
	});

	client.on('end', () => {
		console.log("Client disconnected");
	});

	client.on('error', () => {
		// what's an error?
	});

}

module.exports = connectionHandler;

const authHandler = require('./auth-handler'),
      sessionHandler = require('./session-handler');

function connectionHandler(client, clientInfo){
	let user = {};
	user.keys = [];

	client.on('authentication', (context) => {
		authHandler(context, clientInfo, user);
	});

	client.on('ready', () => {
		client.once('session', (accept, reject) => {
            sessionHandler(accept, reject, user);
        });
	});

	client.on('end', () => {
		console.log("Client disconnected");
	});

	client.on('error', (err) => {
		// what's an error?
	});

}

module.exports = connectionHandler;

Fix a reversion caused by cleanup


import React from 'react'
import { createStore, applyMiddleware } from 'redux'
import { Provider } from 'react-redux'
import createSagaMiddleware from 'redux-saga'
import 'tachyons/css/tachyons.min.css'

import { ShellContainer } from './containers'
import { rootReducer } from './reducers'
import { saga } from './sagas/saga'
import github from './assets/github.svg'

const sagaMiddleware = createSagaMiddleware()
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware))
sagaMiddleware.run(saga)

export class App extends React.PureComponent {
  render() {
    return (

          <Provider store={store}>
            <ShellContainer />
          </Provider>

    )
  }
}

import React from 'react'
import { createStore, applyMiddleware } from 'redux'
import { Provider } from 'react-redux'
import createSagaMiddleware from 'redux-saga'
import 'tachyons/css/tachyons.min.css'

import { ShellContainer } from './containers'
import { rootReducer } from './reducers'
import { saga } from './sagas'
import github from './assets/github.svg'

const sagaMiddleware = createSagaMiddleware()
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware))
sagaMiddleware.run(saga)

export class App extends React.PureComponent {
  render() {
    return (

          <Provider store={store}>
            <ShellContainer />
          </Provider>

    )
  }
}

Fix import of root saga


// Sentences should be preceded by a space

var tokenize = require("../tokenize");
var levels = require("../levels");
var english = require("tokenize-english")(tokenize);

module.exports = tokenize.check(
    // Tokenize as sentences
    english.sentences(),

    // Output
    tokenize.define(function(sentence, current, prev) {
        if (!prev || sentence[0] == ' ') return null;

        return {
            index: 0,
            offset: 1,
            message: "sentence should be preceded by a space"
        };
    })
);
module.exports.level = levels.ERROR;

// Sentences should be preceded by a space

var tokenize = require("../tokenize");
var levels = require("../levels");
var english = require("tokenize-english")(tokenize);

module.exports = tokenize.check(
    // Tokenize as sentences
    english.sentences(),

    // Output
    tokenize.define(function(sentence, current, prev) {
        if (!prev || (prev.index + prev.offset) < current.index || sentence[0] == ' ') return null;

        return {
            index: 0,
            offset: 1,
            message: "sentence should be preceded by a space"
        };
    })
);
module.exports.level = levels.ERROR;

Fix sentence:start warning when preceded by a line


'use strict';
const symbol = require('../utilities/symbol');

let experiments = {
  MODULE_UNIFICATION: symbol('module-unification'),
};

Object.freeze(experiments);

module.exports = experiments;

'use strict';

let experiments = {};

Object.freeze(experiments);

module.exports = experiments;

Disable in-progress experiments for beta.


/**
 * @fileoverview WebGL.js - Set up WebGL context
 * @author Ben Brooks (beb12@aber.ac.uk)
 * @version 1.0
 */

/**
 * Initialise the WebGL context and return it
 * @params canvas - HTML5 Canvas element
 */
function initWebGL(canvas) {

  glContext = canvas.getContext("webgl") ||
              canvas.getContext("experimental-webgl");

  if (!glContext) {
    alert("Unable to initialise WebGL. Your browser may not support it.");
  }

  return glContext;

}

/**
 * @fileoverview WebGL.js - Set up WebGL context
 * @author Ben Brooks (beb12@aber.ac.uk)
 * @version 1.0
 */

/**
 * Initialise the WebGL context and return it
 * @params canvas - HTML5 Canvas element
 */
function initWebGL(canvas) {

  var devicePixelRatio = window.devicePixelRatio || 1;
  var width = canvas.clientWidth;
  var height = canvas.clientHeight;

  // set the display size of the canvas.
  canvas.style.width  = width  + "px";
  canvas.style.height = height + "px";

  // set the size of the drawingBuffer
  canvas.width  = width  * devicePixelRatio;
  canvas.height = height * devicePixelRatio;

  glContext = canvas.getContext("webgl") ||
              canvas.getContext("experimental-webgl");

  if (!glContext) {
    alert("Unable to initialise WebGL. Your browser may not support it.");
  }

  return glContext;

}

Add retina support for canvas


import Ember from 'ember';

export default Ember.Component.extend({
  actions: {
    setKontaktinfoGruppeById: function (id) {
      var model = this.get('model');
      if (Ember.typeOf(model.setKontaktinfoGruppeById) === 'function') {
        model.setKontaktinfoGruppeById(id);
      }
    }
  }

});

import Ember from 'ember';

export default Ember.Component.extend({
  actions: {
    setKontaktinfoGruppeById: function (id) {
      var model = this.get('model');
      if (Ember.typeOf(model.setKontaktinfoGruppeById) === 'function') {
        model.setKontaktinfoGruppeById(id);
      }
    }
  },

  init: function (e) {
    this._super(...arguments);
    const kontaktinfoGruppeId = this.get('model.kontaktinfo_gruppe.gruppe_id');

    if (kontaktinfoGruppeId) {
      this.send('setKontaktinfoGruppeById', kontaktinfoGruppeId);
    }
  }

});

Call setKontaktinfoGruppeById on kontaktinfo component init, to get latest kontaktinfo from Turbasen


// @flow

import type { RelativeUserInfo } from '../types/user-types';
import type { RelativeMemberInfo } from '../types/thread-types';

import ashoat from '../facts/ashoat';
import friends from '../facts/friends';

function stringForUser(user: RelativeUserInfo | RelativeMemberInfo): string {
  if (user.isViewer) {
    return "you";
  } else if (user.username) {
    return user.username;
  } else {
    return "anonymous";
  }
}

function isStaff(userID: string) {
  return userID === ashoat.id;
}

function hasWebChat(userID: string) {
  return isStaff(userID) || userID === friends.larry;
}

export {
  stringForUser,
  isStaff,
  hasWebChat,
};

// @flow

import type { RelativeUserInfo } from '../types/user-types';
import type { RelativeMemberInfo } from '../types/thread-types';

import ashoat from '../facts/ashoat';
import friends from '../facts/friends';
import bots from '../facts/bots';

function stringForUser(user: RelativeUserInfo | RelativeMemberInfo): string {
  if (user.isViewer) {
    return "you";
  } else if (user.username) {
    return user.username;
  } else {
    return "anonymous";
  }
}

function isStaff(userID: string) {
  if (userID === ashoat.id) {
    return true;
  }
  for (let key in bots) {
    const bot = bots[key];
    if (userID === bot.userID) {
      return true;
    }
  }
  return false;
}

function hasWebChat(userID: string) {
  return isStaff(userID) || userID === friends.larry;
}

export {
  stringForUser,
  isStaff,
  hasWebChat,
};

Include all bots in isStaff


var build = require('./build/build.js'),
    version = require('./src/polarmap.js').version;

desc('Combine and compress PolarMap source files');
task('build', {async: true}, function (compsBase32, buildName) {
  var v;

  jake.exec('git log -1 --pretty=format:"%h"', {breakOnError: false}, function () {
    build.build(complete, v, compsBase32, buildName);

  }).on('stdout', function (data) {
    v = version + ' (' + data.toString() + ')';
  }).on('error', function () {
    v = version;
  });
});

task('default', ['build']);

jake.addListener('complete', function () {
  process.exit();
});

var build = require('./build/build.js'),
    version = require('./src/polarmap.js').version;

desc('Combine and compress PolarMap source files');
task('build', {async: true}, function (compsBase32, buildName) {
  var v;

  jake.exec('git log -1 --pretty=format:"%h"', {breakOnError: false}, function () {
    build.build(complete, v, compsBase32, buildName);

  }).on('stdout', function (data) {
    v = version + ' (' + data.toString() + ')';
  }).on('error', function () {
    v = version;
  });
});

watchTask(['build'], function () {
  this.watchFiles.include([
    './src/**/*.js'
  ]);
});

task('default', ['build']);

Add support for auto-build on file change


import {
  getDashboards as getDashboardsAJAX,
  updateDashboard as updateDashboardAJAX,
} from 'src/dashboards/apis'

export function loadDashboards(dashboards, dashboardID) {
  return {
    type: 'LOAD_DASHBOARDS',
    payload: {
      dashboards,
      dashboardID,
    },
  }
}

export function setDashboard(dashboardID) {
  return {
    type: 'SET_DASHBOARD',
    payload: {
      dashboardID,
    },
  }
}

export function setTimeRange(timeRange) {
  return {
    type: 'SET_DASHBOARD_TIME_RANGE',
    payload: {
      timeRange,
    },
  }
}

export function setEditMode(isEditMode) {
  return {
    type: 'SET_EDIT_MODE',
    payload: {
      isEditMode,
    },
  }
}

export function getDashboards(dashboardID) {
  return (dispatch) => {
    getDashboardsAJAX().then(({data: {dashboards}}) => {
      dispatch(loadDashboards(dashboards, dashboardID))
    });
  }
}

export function putDashboard(dashboard) {
  return (dispatch) => {
    updateDashboardAJAX(dashboard).then(({data}) => {
      dispatch(updateDashboard(data))
    })
  }
}

export function updateDashboard(dashboard) {
  return {
    type: 'UPDATE_DASHBOARD',
    payload: {
      dashboard,
    },
  }
}

import {
  getDashboards as getDashboardsAJAX,
  updateDashboard as updateDashboardAJAX,
} from 'src/dashboards/apis'

export const loadDashboards = (dashboards, dashboardID) => ({
  type: 'LOAD_DASHBOARDS',
  payload: {
    dashboards,
    dashboardID,
  },
})

export const setDashboard = (dashboardID) => ({
  type: 'SET_DASHBOARD',
  payload: {
    dashboardID,
  },
})

export const setTimeRange = (timeRange) => ({
  type: 'SET_DASHBOARD_TIME_RANGE',
  payload: {
    timeRange,
  },
})

export const setEditMode = (isEditMode) => ({
  type: 'SET_EDIT_MODE',
  payload: {
    isEditMode,
  },
})

export const updateDashboard = (dashboard) => ({
  type: 'UPDATE_DASHBOARD',
  payload: {
    dashboard,
  },
})

// Async Action Creators

export const getDashboards = (dashboardID) => (dispatch) => {
  getDashboardsAJAX().then(({data: {dashboards}}) => {
    dispatch(loadDashboards(dashboards, dashboardID))
  })
}

export const putDashboard = (dashboard) => (dispatch) => {
  updateDashboardAJAX(dashboard).then(({data}) => {
    dispatch(updateDashboard(data))
  })
}

Use implicit returns for dashboard action creators


jQuery(document).ready( function($) {

	function resizeTree() {
	    $('#fileTree').height($(window).height());
	    // window.top.console.debug('resize', $(window).width(), $(window).height());
	}

    function onFileClick(path) {
        bespin.get("editor").openFile(bespin.get('editSession').project, path, {});
        // bespin.publish("ui:escape", {});
    }

	$('#fileTree').fileTree({ root: '.', script: 'cmd/php/ls/' }, onFileClick);
	$(window).bind('resize', resizeTree);

	resizeTree();
});

jQuery(document).ready( function($) {

	function resizeTree() {
	    $('#fileTree').height($(window).height());
	}

    function onFileClick(path) {
        bespin.get("editor").openFile(bespin.get('editSession').project, path, {});
    }

	$('#fileTree').fileTree({ root: '.', script: 'cmd/php/ls/' }, onFileClick);
	$(window).bind('resize', resizeTree);

	resizeTree();
});

Remove commented lines of code


/*
var args = ['jar', 'username', 'password']

raw function login (jar, username, password)

exported function login ()
  check number of arguments if necessary
    options object: login(arguments[0])
    individual arguments:
      for each argument add to an options array corresponding with argument order
      login(options)
*/
// Includes
var options = require('../options.js');

// Define
var defaults = {
  'jar': options.jar
};

function appendDefaults (opt, argumentList) {
  for (var index in defaults) {
    if (!opt[index] && argumentList.indexOf(index) > -1) {
      opt[index] = defaults[index];
    }
  }
  return opt;
}

exports.wrapExport = function (wrapFunction, argumentList) {
  if (argumentList.length > 0) {
    return function () {
      var options = {};
      if (arguments.length > 0) {
        if (typeof arguments[0] === 'object') {
          options = arguments[0];
        } else {
          for (var i = 0; i <= arguments.length; i++) {
            options[argumentList[i]] = arguments[i];
          }
        }
      }
      return wrapFunction(options);
    };
  } else {
    return wrapFunction;
  }
};

/*
var args = ['jar', 'username', 'password']

raw function login (jar, username, password)

exported function login ()
  check number of arguments if necessary
    options object: login(arguments[0])
    individual arguments:
      for each argument add to an options array corresponding with argument order
      login(options)
*/
// Includes
var options = require('../options.js');

// Define
var defaults = {
  'jar': options.jar
};

function appendDefaults (opt, argumentList) {
  for (var index in defaults) {
    if (!opt[index] && argumentList.indexOf(index) > -1) {
      opt[index] = defaults[index];
    }
  }
  return opt;
}

exports.wrapExport = function (wrapFunction, argumentList) {
  if (argumentList.length > 0) {
    return function () {
      var options = {};
      if (arguments.length > 0) {
        var first = arguments[0];
        if (arguments.length === 1 && (argumentList.length !== 1 || (first instanceof Object && first[argumentList[0]]))) {
          options = first;
        } else {
          for (var i = 0; i <= arguments.length; i++) {
            options[argumentList[i]] = arguments[i];
          }
        }
      }
      return wrapFunction(options);
    };
  } else {
    return wrapFunction;
  }
};

Fix for multiple usage types


$(document).ready(function () {
    //var route = Routing.generate('seen_userCardication', { id: {{ userCard.id }} });

    var $content = $('.userCardContent');
    var array = {};

    $('.userCardBlock').hide();

    $('.userCardButton').click(function(){
        $('.userCardBlock').toggle("ease-in");
    });

});

$(document).ready(function () {
    //var route = Routing.generate('seen_userCardication', { id: {{ userCard.id }} });

    var $content = $('.userCardContent');
    var array = {};

    $('.userCardBlock').hide();

    $('.userCardButton').click(function(e){
        e.preventDefault();
        $('.userCardBlock').toggle("ease-in");
    });

});

Fix bug from previous merge conflict


// import Vue from 'vue'
// import Hello from '@/components/Hello'

describe('this test runner', () => {
  it('needs at least one test', () => {
    expect(true).to.equal(true)
  })
})

// describe('Hello.vue', () => {
  // it('should render correct contents', () => {
    // const Constructor = Vue.extend(Hello)
    // const vm = new Constructor().$mount()
    // expect(vm.$el.querySelector('.hello h1').textContent)
      // .to.equal('Welcome to Your Vue.js App')
  // })
// })

Remove comments in test file


export default {
  name: 'webpack-images',
  configure () {
    return {
      module: {
        loaders: [
          {
            test: /\.(png|jpg|gif)$/,
            loader: 'url-loader?limit=8192&name=[name]-[hash].[ext]'
          }
        ]
      }
    }
  }
}

export default {
  name: 'webpack-images',
  configure () {
    return {
      module: {
        loaders: [
          {
            test: /\.(png|jpg|jpeg|gif)$/,
            loader: 'url-loader?limit=8192&name=[name]-[hash].[ext]'
          }
        ]
      }
    }
  }
}

Add jpeg file extension loading support


/*
 * Run the code contained in the file manager, by compiling everything and
 * executing the main class, then display the result.
 */
/* global FileManager */

function runCodeCheerp() {
    // Get the main class's actual name..
    // drop the .java extension
    var mainFile = FileManager.getMainFile().name;
    var mainName = mainFile.replace(/\.[^/.]+$/, "");

    // Get the file's package name
    var pkgReg = /package\s+([\w\.]+)\s*;/;
    var packageName = pkgReg.exec(FileManager.getMainFile().contents);
    // Add the package name to the class's name
    if (packageName === null || packageName.length < 2) {
        packageName = ["package", "default"];
    }

    // Prepare the request to run the code
    // Set up the request body for a compile-run request
    var body = {
        version: 1,
        compile: {
            version: 1,
            mainClass: packageName[1] + "." + mainName,
            mainFile: mainFile,
            sourceFiles: []
        },
        data: {
            version: 1,
            dataFiles: []
        },
        "test-type": "run"
    };

    var root = FileManager.getRootFolder();
    // Add the files in the global file manager to the request body.
    addAllSourceFiles(root, body.compile.sourceFiles, true);

    // Add data files to the request
    addAllDataFiles(root, body.data.dataFiles);

    let newWindow = window.open('./cheerpjConsole.html');
    newWindow.compileData = body;
}

/*
 * Run the code contained in the file manager, by compiling everything and
 * executing the main class, then display the result.
 */
/* global FileManager */

function runCodeCheerp() {
    // Get the main class's actual name..
    // drop the .java extension
    var mainName = FileManager.getMainFile().name.replace(/\.[^/.]+$/, "");
    // Get the file's package name
    var pkgReg = /package\s+([\w\.]+)\s*;/;
    var packageName = pkgReg.exec(FileManager.getMainFile().contents);
    // Add the package name to the class's name
    if (packageName === null || packageName.length < 2) {
        packageName = ["package", "default"];
    }

    // Prepare the request to run the code
    // Set up the request body for a compile-run request
    var body = {
        version: 1,
        compile: {
            version: 1,
            mainClass: packageName[1] + "." + mainName,
            mainFile: mainName,
            sourceFiles: []
        },
        data: {
            version: 1,
            dataFiles: []
        },
        "test-type": "run"
    };

    var root = FileManager.getRootFolder();
    // Add the files in the global file manager to the request body.
    addAllSourceFiles(root, body.compile.sourceFiles, true);

    // Add data files to the request
    addAllDataFiles(root, body.data.dataFiles);

    let newWindow = window.open('./cheerpjConsole.html');
    newWindow.compileData = body;
}

Revert "keep .java on mainFile"


function generateResults
(
  recognitionResults,
  q,
  context
)
{
  var resultList = recognitionResults['com.solveforall.recognition.lang.chinese.Chinese'];

  if (!resultList)
  {
    return null;
  }

  return [{
    label: 'MDBG',
    uri: 'http://www.mdbg.net/chindict/mobile.php?mwddw=' + resultList[0].traditional + '&handler=DecomposeWord',
    iconUrl: 'http://www.mdbg.net/favicon.ico'
  }];
}

/*jslint continue: true, devel: true, evil: true, indent: 2, plusplus: true, rhino: true, unparam: true, vars: true, white: true */
function generateResults(recognitionResults, q, context) {
  'use strict';

  var resultList = recognitionResults['com.solveforall.recognition.lang.chinese.Chinese'];

  if (!resultList) {
    return null;
  }

  var word = resultList[0].traditional;
  return [{
    label: 'MDBG',
    iconUrl: 'http://www.mdbg.net/favicon.ico',
    uri: 'http://www.mdbg.net/chindict/mobile.php?mwddw=' + encodeURIComponent(word) + '&handler=DecomposeWord',
    embeddable: true,
    summaryHtml: 'Lookup ' + _(word).escapeHTML() + ' on MDBG'
  }];
}

Add summaryHtml and embeddable: true flag to MDBG Answer Generator


var dbm = global.dbm || require('db-migrate');
var type = dbm.dataType;

exports.up = function(db, callback) {
  db.createTable('users', {
    id: {
      type: 'int',
      primaryKey: true,
      unsigned: true,
      notNull: true,
      autoIncrement: true,
      length: 10
    },
    username: {
      type: 'string',
      unique: true,
      notNull: true
    },
    password: {
      type: 'string',
      notNull: true
    }
  }, callback);
};

exports.down = function(db, callback) {
  db.dropTable('users', callback);
};

var dbm = global.dbm || require('db-migrate');
var type = dbm.dataType;

exports.up = function(db, callback) {
  db.createTable('users', {
    id: {
      type: 'int',
      primaryKey: true,
      unsigned: true,
      notNull: true,
      autoIncrement: true
    },
    username: {
      type: 'string',
      unique: true,
      notNull: true
    },
    password: {
      type: 'string',
      notNull: true
    }
  }, callback);
};

exports.down = function(db, callback) {
  db.dropTable('users', callback);
};

Fix to the users migration.


// Copyright (c) 2015-2016 Yuya Ochiai
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

/**
 * Default user preferences. End-users can change these parameters by editing config.json
 * @param {number} version - Scheme version. (Not application version)
 */
const defaultPreferences = {
  version: 1,
  teams: [],
  showTrayIcon: false,
  trayIconTheme: 'light',
  minimizeToTray: false,
  notifications: {
    flashWindow: 0,
    bounceIcon: false,
    bounceIconType: 'informational',
  },
  showUnreadBadge: true,
  useSpellChecker: true,
  enableHardwareAcceleration: true,
  autostart: false,
};

export default defaultPreferences;

// Copyright (c) 2015-2016 Yuya Ochiai
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

/**
 * Default user preferences. End-users can change these parameters by editing config.json
 * @param {number} version - Scheme version. (Not application version)
 */
const defaultPreferences = {
  version: 1,
  teams: [],
  showTrayIcon: false,
  trayIconTheme: 'light',
  minimizeToTray: false,
  notifications: {
    flashWindow: 0,
    bounceIcon: false,
    bounceIconType: 'informational',
  },
  showUnreadBadge: true,
  useSpellChecker: true,
  enableHardwareAcceleration: true,
  autostart: true,
};

export default defaultPreferences;

Set "app start on login" preference to default on


import classNames from 'classnames/dedupe';
import {Link} from 'react-router';
import React from 'react';

class PageHeaderTabs extends React.Component {
  render() {
    let {props: {tabs}} = this;

    let tabElements = tabs.map(function (tab, index) {
      let {isActive} = tab;
      let classes = classNames('tab-item', {active: isActive});
      let linkClasses = classNames('tab-item-label', {active: isActive});

      return (

          <Link className={linkClasses} to={tab.routePath}>

              {tab.label}

          </Link>

      );
    });

    return (

        {tabElements}

    );
  }
}

PageHeaderTabs.defaultProps = {
  tabs: []
};

PageHeaderTabs.propTypes = {
  tabs: React.PropTypes.arrayOf(
    React.PropTypes.shape({
      isActive: React.PropTypes.bool,
      label: React.PropTypes.node.isRequired,
      routePath: React.PropTypes.string.isRequired
    })
  )
};

module.exports = PageHeaderTabs;

import classNames from 'classnames/dedupe';
import {Link} from 'react-router';
import React from 'react';

class PageHeaderTabs extends React.Component {
  render() {
    let {props: {tabs}} = this;

    let tabElements = tabs.map(function (tab, index) {
      let {isActive, callback} = tab;
      let classes = classNames('menu-tabbed-item', {active: isActive});
      let linkClasses = classNames('menu-tabbed-item-label', {active: isActive});

      let innerLinkSpan = {tab.label};
      return (

          <Link className={linkClasses} to={tab.routePath}>

              {tab.label}

          </Link>

      );
    });

    return (

          {tabElements}

    );
  }
}

PageHeaderTabs.defaultProps = {
  tabs: []
};

PageHeaderTabs.propTypes = {
  tabs: React.PropTypes.arrayOf(
    React.PropTypes.shape({
      isActive: React.PropTypes.bool,
      label: React.PropTypes.node.isRequired,
      routePath: React.PropTypes.string.isRequired
    })
  )
};

module.exports = PageHeaderTabs;

Update styles in page header tabs to match latest canvas


var Qux = (function () {
  'use strict';

  function Qux () {
    this.events = {};
  }

  var uid = -1;

  Qux.prototype.publish = function (ev, data) {
    if (typeof this.events[ev] === 'undefined') {
      return false;
    }

    var q = this.events[ev];
    var len = q.length;

    for (var i = 0; i < len; i++) {
      q[i].fn(ev, data);
    }
    return true;
  };

  Qux.prototype.subscribe = function (ev, fn) {
    // if event not already registered, add it
    if (typeof this.events[ev] === 'undefined') {
      this.events[ev] = [];
    }

    var token = ++uid;

    this.events[ev].push({
      token: token,
      fn: fn
    });
  };

  Qux.prototype.unsubscribe = function (token) {
    for (var e in this.events) {
      var q = this.events[e];
      for (var i = 0; i < q.length; i++) {
        if (q[i].token === token) {
          q.splice(i, 1);
        }
      }
    }
  };

  return Qux;
})();

/* jshint node: true */

(function () {
  'use strict';

  var root = this;
  var uid = -1;

  function Qux () {
    this.topics = {};
  }

  Qux.prototype.publish = function (topic, data) {
    if (typeof this.topics[topic] === 'undefined') {
      return false;
    }

    var queue = this.topics[topic];
    var len = queue.length;

    for (var i = 0; i < len; i++) {
      queue[i].cb(data);
    }
    return true;
  };

  Qux.prototype.subscribe = function (topic, cb) {
    var token = ++uid;

    // if event not already registered, add it
    if (typeof this.topics[topic] === 'undefined') {
      this.topics[topic] = [];
    }

    this.topics[topic].push({
      token: token,
      cb: cb
    });

    return token;
  };

  Qux.prototype.unsubscribe = function (token) {
    for (var topic in this.topics) {
      var queue = this.topics[topic];
      for (var i = 0; i < queue.length; i++) {
        if (queue[i].token === token) {
          queue.splice(i, 1);
          return true;
        }
      }
    }
    return false;
  };

  if (typeof module !== 'undefined' &&
      typeof module.exports !== 'undefined') {
    module.exports = Qux;
  }
  else {
   root.Qux = Qux;
  }
}).call(this);

Create a module or a global object depending on context


var CONTEXT_URI = process.env.CONTEXT_URI;

var _ = require('underscore');

var IntentManager = function () {
};

IntentManager.prototype.process = function (intent, req, res) {

    var redirect = function (url) {
        console.log("And CONTEXT URI IS ->", CONTEXT_URI);
        res.redirect(CONTEXT_URI + url + "?username=" + req.session.oneselfUsername);
    };

    if (_.isEmpty(intent)) {
        res.redirect("/dashboard");
    } else {
        var intentName = intent.name;
        var intentData = intent.data;

        console.log("intentName -#-#->", intentName);
        if (intentName === "website_signup") {
            res.redirect("http://1self.co/confirmation.html");
        } else if (intentName === "chart.comment") {
            res.redirect(intentData.url);
        } else {
            redirect("/dashboard");
        }
    }

};

module.exports = new IntentManager();

var CONTEXT_URI = process.env.CONTEXT_URI;

var _ = require('underscore');

var IntentManager = function () {
};

IntentManager.prototype.process = function (intent, req, res) {

    var redirect = function (url) {
        console.log("And CONTEXT URI IS ->", CONTEXT_URI);
        res.redirect(CONTEXT_URI + url + "?username=" + req.session.oneselfUsername);
    };

    if (_.isEmpty(intent)) {
        res.redirect("/dashboard");
    } else {
        var intentName = intent.name;
        var intentData = intent.data;

        console.log("intentName -#-#->", intentName);
        if (intentName === "website_signup") {
            res.redirect("http://www-staging.1self.co/confirmation.html");
        } else if (intentName === "chart.comment") {
            res.redirect(intentData.url);
        } else {
            redirect("/dashboard");
        }
    }

};

module.exports = new IntentManager();

Use staging for confirmation while testing


var DisplayLeaderboard = require('./display-leaderboard');
const $ = require('jquery');

function DisplayMessage(){
  this.element = $('#post-game');
}

DisplayMessage.prototype.showWinMessage = function(){
  var div = this.element;
  div.empty()
     .show()
     .append(`
You Win!

Click to play the next level.
`
            );
  div.on('click', function(){
    div.hide();
  });
};

DisplayMessage.prototype.showHighScoreMessage = function(game, leaderboard){
  var div = this.element;
  div.empty()
     .show()
     .append(`
High Score!

Name:

              <input class='input'></input>
              <button id="high-submit-button">Submit</button>`
            );
  div.unbind('click').on('click', 'button', function() {
    var input = $('.input').val();
    game.getName(input, leaderboard);
    if(leaderboard.name === 'Level Random'){
      new DisplayLeaderboard(leaderboard);
    }
    div.hide();
  });
};

DisplayMessage.prototype.showScore = function(score){
  $('#score').empty().append(this.scoreElement(score));
};

DisplayMessage.prototype.scoreElement = function(score){
  return '
Score: ' + score + '
';
};

module.exports = DisplayMessage;

var DisplayLeaderboard = require('./display-leaderboard');
const templates = require('./message-templates');
const $ = require('jquery');

function DisplayMessage(){
  this.element = $('#post-game');
}

DisplayMessage.prototype.showBoardMessage = function(template) {
  var div = this.element;
  div.empty()
     .show()
     .append(template);
};

DisplayMessage.prototype.showWinMessage = function(){
  var div = this.element;
  div.empty()
     .show()
     .append(`
You Win!

Click to play the next level.
`
            );
  div.on('click', function(){
    div.hide();
  });
};

DisplayMessage.prototype.showHighScoreMessage = function(game, leaderboard){
  this.showBoardMessage(templates.highScoreWin);
  div.unbind('click').on('click', 'button', function() {
    var input = $('.input').val();
    game.getName(input, leaderboard);
    if(leaderboard.name === 'Level Random'){
      new DisplayLeaderboard(leaderboard);
    }
    div.hide();
  });
};

DisplayMessage.prototype.showScore = function(score){
  $('#score').empty().append(this.scoreElement(score));
};

DisplayMessage.prototype.scoreElement = function(score){
  return '
Score: ' + score + '
';
};

module.exports = DisplayMessage;

Add generic full board display message method


module.exports = function (stackName, id) {
	if (typeof id === 'string') {
		id = this.idByFront(stackName, id)
	}
	this.stacks[stackName][id].wrong += 1
}

var copy = require('../copy.js')
module.exports = function (stack, id) {
	var newStack = copy(stack)
	if (typeof id === 'undefined') {
		// stack is not a stack - it's just a card, so update the card's wrong key
		newStack.wrong += 1
	}
	else {
		newStack[id].wrong += 1
	}
	return newStack
}

Make f.gotWrong() work with actual arrays


/* eslint-env jest */
import 'react-native';
import React from 'react';
import App from '../App';

// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';

it('renders correctly', () => {
  const tree = renderer.create(
    <App />
  );
});

Fix lint for react-native example


const LifeforcePlugin = require("../utils/LifeforcePlugin.js");

class SlackBot extends LifeforcePlugin {
    constructor(restifyserver, logger, name) {
        super(restifyserver, logger, name);
        this.apiMap = [
            {
                path: "/api/slack/log",
                type: "post",
                handler: handleSlackPush
            }
        ];

        const SlackBot = require('slackbots');
        this.bot = new SlackBot({
            token: this.config.slack.token,
            name: 'kabuildbot'
        });
    }
}

function handleSlackPush(req, res, next) {
    if (req.body) {
        var payload = req.body + "";

        this.bot.postMessageToChannel('general', payload, {
            icon_emoji: ':robot_face:'
        });

        // send a message to the chat acknowledging receipt of their message
        res.send(200, { error: false });
    } else {
        res.send(400, { error: true, msg: "No request body" });
    }
}

module.exports = SlackBot;

const LifeforcePlugin = require("../utils/LifeforcePlugin.js");

class SlackBot extends LifeforcePlugin {
    constructor(restifyserver, logger, name) {
        super(restifyserver, logger, name);
        this.apiMap = [
            {
                path: "/api/slack/log",
                type: "post",
                handler: handleSlackPush
            },
            {
                path: "/api/slack/deploy",
                type: "post",
                handler: handleSlackPushDeploy
            }
        ];

        const SlackBot = require('slackbots');
        this.bot = new SlackBot({
            token: this.config.slack.token,
            name: 'kabuildbot'
        });
    }
}

function handleSlackPush(req, res, next) {
    if (req.body) {
        var payload = req.body + "";

        this.bot.postMessageToChannel('general', payload, {
            icon_emoji: ':robot_face:'
        });

        // send a message to the chat acknowledging receipt of their message
        res.send(200, { error: false });
    } else {
        res.send(400, { error: true, msg: "No request body" });
    }
}

function handleSlackPushDeploy(req, res, next) {
    if (req.body) {
        var payload = req.body + "";

        this.bot.postMessageToChannel('deployment', payload, {
            icon_emoji: ':robot_face:'
        });

        // send a message to the chat acknowledging receipt of their message
        res.send(200, { error: false });
    } else {
        res.send(400, { error: true, msg: "No request body" });
    }
}

module.exports = SlackBot;

Add a new channel for deployment logging


var cobs = require('../..'),
    fs = require('fs');

var runtime = {
    display: function() {
        var result = '';
        if (arguments && arguments.length)
            for (var k = 0; k < arguments.length; k++)
                if (arguments[k])
                    result += arguments[k].toString();

        console.log(result);
    }
}

function runFile(filename) {
    var text = fs.readFileSync(filename).toString();
    var parser = new cobs.Parser(text);
    var program = parser.parseProgram();
    cobs.run(program.command.compile(program), runtime, program);
};

process.argv.forEach(function(val) {
    if (val.slice(-5) == ".cobs" || val.slice(-4) == ".cob")
        runFile(val);
});

var cobs = require('../..'),
    fs = require('fs');

var runtime = {
    display: function() {
        var result = '';
        if (arguments && arguments.length)
            for (var k = 0; k < arguments.length; k++)
                if (arguments[k])
                    result += arguments[k].toString();

        console.log(result);
    }
}

function runFile(filename) {
    cobs.compileProgramFile(filename).run(runtime);
};

process.argv.forEach(function(val) {
    if (val.slice(-4) == ".cob")
        runFile(val);
});

Refactor factorial sample to use compileProgramFile


'use strict'

var expect = require('expect.js')
var fs = require('fs')
var path = require('path')
var sshConfig = require('..')

describe('ssh-config', function() {
  var fixture = fs.readFileSync(path.join(__dirname, 'fixture/config'), 'utf-8')
  var config = sshConfig.parse(fixture)

  it('.parse ssh config text into object', function() {
    expect(config.ControlMaster).to.equal('auto')
    expect(config.length).to.equal(4)

    expect(config[0]).to.eql({
      Host: 'tahoe1',
      HostName: 'tahoe1.com',
      Compression: 'yes'
    })
  })

  it('.query ssh config by host', function() {
    var opts = config.query('tahoe2')

    expect(opts.User).to.equal('nil')
    expect(opts.IdentityFile).to.equal('~/.ssh/id_rsa')

    // the first obtained parameter value will be used. So there's no way to
    // override parameter values.
    expect(opts.ServerAliveInterval).to.eql(80)

    opts = config.query('tahoe1')
    expect(opts.User).to.equal('nil')
    expect(opts.ForwardAgent).to.equal('true')
    expect(opts.Compression).to.equal('yes')
  })

  it('.stringify the parsed object back to string', function() {
    expect(fixture).to.contain(sshConfig.stringify(config))
  })
})

'use strict'

var expect = require('expect.js')
var fs = require('fs')
var path = require('path')
var sshConfig = require('..')

describe('ssh-config', function() {
  var fixture = fs.readFileSync(path.join(__dirname, 'fixture/config'), 'utf-8')
    .replace(/\r\n/g, '\n')
  var config = sshConfig.parse(fixture)

  it('.parse ssh config text into object', function() {
    expect(config.ControlMaster).to.equal('auto')
    expect(config.length).to.equal(4)

    expect(config[0]).to.eql({
      Host: 'tahoe1',
      HostName: 'tahoe1.com',
      Compression: 'yes'
    })
  })

  it('.query ssh config by host', function() {
    var opts = config.query('tahoe2')

    expect(opts.User).to.equal('nil')
    expect(opts.IdentityFile).to.equal('~/.ssh/id_rsa')

    // the first obtained parameter value will be used. So there's no way to
    // override parameter values.
    expect(opts.ServerAliveInterval).to.eql(80)

    opts = config.query('tahoe1')
    expect(opts.User).to.equal('nil')
    expect(opts.ForwardAgent).to.equal('true')
    expect(opts.Compression).to.equal('yes')
  })

  it('.stringify the parsed object back to string', function() {
    expect(fixture).to.contain(sshConfig.stringify(config))
  })
})

Make sure the line endings are consistent


import React from 'react';

import Colours from '../../modules/colours';

const Colour = (props) => {
  var colour = props.colour;

  if (props.format === 'rgb') {
    var rgb = Colours.hexToRgb(colour.substring(1, 7));

    colour = `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;
  }

  return (

{colour}

  );
};

export default Colour;

Make only the colour code the copy region instead of entire row