'use strict';

// To make id smaller we get microgseconds count from more recent date
var start = Date.UTC(2011, 8, 21) * 1000

// Prefix with number, it reduces chances of collision with variable names
// (helpful if used as property names on objects)
  , prefix = String(Math.floor(Math.random() * 10))

// Make it more unique
  , postfix = Math.floor(Math.random() * 36).toString(36);

module.exports = function (time) {
	return prefix + (time - start).toString(36) + postfix;
};

'use strict';

// To make id smaller we get microseconds count from more recent date
var start = Date.UTC(2012, 12, 21, 12, 0, 0, 0) * 1000

// Prefix with number, it reduces chances of collision with variable names
// (helpful if used as property names on objects)
  , prefix = String(Math.floor(Math.random() * 10))

// Make it more unique
  , postfix = Math.floor(Math.random() * 36).toString(36);

module.exports = function (time) {
	return prefix + (time - start).toString(36) + postfix;
};

Make recent date even more recent


var mongoose = require('mongoose');
var log = require('lib/logger')(module);
var config = require('../config');

// Установим соединение с базой
log.info('Connecting to MongoDB uri: ' + config.get('mongoose:uri'));

mongoose.connect(config.get('mongoose:uri'), config.get('mongoose:options'));

mongoose.connection.on('connected', function() {
  log.info('connected');
});

// TODO: die on error
mongoose.connection.on('error', function(err)  {
  console.error("Mongoose error", err);
});

log.info("DB initialized");

module.exports = mongoose;

var mongoose = require('mongoose');
var log = require('lib/logger')(module);
var config = require('../config');

log.info('Connecting to MongoDB uri: ' + config.get('mongoose:uri'));

mongoose.connect(config.get('mongoose:uri'), config.get('mongoose:options'));

mongoose.connection.on('connected', function() {
  log.info('Mongoose connected');
});

mongoose.connection.on('disconnected', function() {
  log.info('Mongoose disconnected');
});

// TODO: die on error
mongoose.connection.on('error', function(err)  {
  console.error("Mongoose error", err);
});

module.exports = mongoose;

Add logging on Mongoose 'disconnected' event


/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.foamlink',
  name: 'FoamlinkNodeModelFileFetcher',
  properties: [
    'root',
    'foamlinkData_'
  ],
  methods: [
    function init() {
      // TODO: error handling in this method
      var dataFile = foam.foamlink.dataFile;
      var dataText = require('fs').readFileSync(dataFile, 'utf8');
      this.foamlinkData_ = JSON.parse(dataText);
    },
    function getFile(id) {
      var self = this;
      return new Promise(function(ret, err) {
        var path = self.foamlinkData_.classesToFiles[id];
        if ( path === undefined ) {
          ret(null);
          return;
        }
        try {
          var js = require('fs').readFileSync(path, 'utf8');
          // TODO: anything but this terrible array thing
          ret(['withsource', {
            text: js,
            source: path
          }]);
        } catch(e) {
          console.error(e);
          ret(null);
        }
      });
    }
  ]
});

/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.foamlink',
  name: 'FoamlinkNodeModelFileFetcher',
  properties: [
    'root',
    'foamlinkData_'
  ],
  methods: [
    function init() {
      // TODO: error handling in this method
      var dataFile = foam.foamlink.dataFile;
      var dataText = require('fs').readFileSync(dataFile, 'utf8');
      this.foamlinkData_ = JSON.parse(dataText);
    },
    function getFile(id) {
      var self = this;
      return new Promise(function(ret, err) {
        var path = self.foamlinkData_.classesToFiles[id];
        if ( path === undefined ) {
          ret(null);
          return;
        }
        try {
          var js = require('fs').readFileSync(path, 'utf8');
          // TODO: anything but this terrible array thing
          ret(['withsource', {
            text: js,
            source: require('path').relative(process.cwd(), path)
          }]);
        } catch(e) {
          console.error(e);
          ret(null);
        }
      });
    }
  ]
});

Fix foamlink ModelFileFetcher path resolution


import DS from 'ember-data';
const { <%= importedModules %> } = DS;

export default Model.extend({
<%= attrs.length ? '  ' + attrs : '' %>
});

import DS from 'ember-data';
const { <%= importedModules %> } = DS;

export default Model.extend({
<%= attrs.length ? attrs : '' %>
});

Fix wrong indentation on Model Blueprint for Classic apps


import { Meteor } from 'meteor/meteor';

Meteor.startup(() => {
    // code to run on server at startup

    // Creating comment schema
    CommentSchema = new SimpleSchema({
        email: {
            type: String,
            unique: true
        },
        text: {
            type: String
        }
    });

    // Creating comments collection
    Comments = new Mongo.Collection('Comments');

    // Attaching CommentSchema to Comments collection
    Comments.attachSchema(CommentSchema);

    var obj = {
        "email": "a@a.com",
        "text": "test"
    }

    // Validating sample object
    var isValid = Comments.simpleSchema().namedContext().validate(obj, { modifier: false });
    console.log(isValid);

});

import { Meteor } from 'meteor/meteor';

Meteor.startup(() => {
    // code to run on server at startup

    // Creating comment schema
    CommentSchema = new SimpleSchema({
        email: {
            type: String,
            unique: true
        },
        text: {
            type: String
        }
    });

    // Creating comments collection
    Comments = new Mongo.Collection('Comments');

    // Attaching CommentSchema to Comments collection
    Comments.attachSchema(CommentSchema);

    var commentObj = {
        "email": "a@a.com",
        "text": "test"
    }

    // Validating sample object
    var isValid = Comments.simpleSchema().namedContext().validate(commentObj, { modifier: false });
    console.log(isValid);

    if(isValid) {
    	Comments.insert(commentObj);
    }

    console.log(Comments.find().fetch());

});

Insert to collection - sample comment object


$(document).ready(function() {
    %('#led_on').click(function() {
        console.log('LED on!');
    });
    %('#led_off').click(function() {
        console.log('LED off!');
    });
});

$(document).ready(function() {
    $('#led_on').click(function() {
        console.log('LED on!');
    });
    $('#led_off').click(function() {
        console.log('LED off!');
    });
});

Fix syntax error change % to $


module.exports = function(model) {
    'use strict';

    let validateProjectAccess = require('./project-access')(model.access);
    let schema = require('.././schema')(model);
    let router = require('koa-router')();
    let projects = require('./projects')(model.projects);
    let samples = require('./samples')(model.samples, schema);
    let processes = require('./processes')(model.processes, schema);

    router.get('/projects2', projects.all);
    router.post('/projects2/:project_id/processes', validateProjectAccess, processes.create);
    router.post('/projects2/:project_id/samples', validateProjectAccess, samples.create);
    router.put('/projects2/:project_id/samples/:sample_id', validateProjectAccess, samples.update);
    router.get('/projects2/:project_id/dir/:directory_id', validateProjectAccess, projects.dirTree);

    return router;
};

module.exports = function(model) {
    'use strict';

    let validateProjectAccess = require('./project-access')(model.access);
    let schema = require('.././schema')(model);
    let router = require('koa-router')();
    let projects = require('./projects')(model.projects);
    let samples = require('./samples')(model.samples, schema);
    let files = require('./files')(model.files);
    let processes = require('./processes')(model.processes, schema);

    router.get('/projects2', projects.all);
    router.get('/projects2/:project_id/dir/:directory_id', validateProjectAccess, projects.dirTree);

    router.post('/projects2/:project_id/processes', validateProjectAccess, processes.create);

    router.post('/projects2/:project_id/samples', validateProjectAccess, samples.create);
    router.put('/projects2/:project_id/samples/:sample_id', validateProjectAccess, samples.update);

    router.get('/projects2/:project_id/files/:file_id', validateProjectAccess, files.get);

    return router;
};

Add REST call for files.


$("#search-field").ghostHunter({
    results : "#search-results",
    onKeyUp : true,
    info_template   : "
Found {{amount}} posts
",
    result_template : "

{{title}}

{{pubDate}}
{{description}}
"
});

$("#search-field").ghostHunter({
    results : "#search-results",
    onKeyUp : true,
    info_template   : "
Results: {{amount}}
",
    result_template : "

{{title}}

{{pubDate}}
{{description}}
"
});

Change search result count text


/*!
  Copyright (C) 2016 Google Inc., authors, and contributors <see AUTHORS file>
  Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
  Created By: ivan@reciprocitylabs.com
  Maintained By: ivan@reciprocitylabs.com
*/

(function (can, $) {
  'use strict';

  can.Component.extend({
    tag: 'lazy-openclose',
    scope: {
      show: false
    },
    content: '<content/>',
    init: function () {
      this._control.element.closest('.tree-item').find('.openclose')
      .bind('click', function () {
        this.scope.attr('show', true);
      }.bind(this));
    }
  });
})(window.can, window.can.$);

/*!
  Copyright (C) 2016 Google Inc., authors, and contributors <see AUTHORS file>
  Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
  Created By: ivan@reciprocitylabs.com
  Maintained By: ivan@reciprocitylabs.com
*/

(function (can, $) {
  'use strict';

  GGRC.Components('lazyOpenClose', {
    tag: 'lazy-openclose',
    scope: {
      show: false
    },
    content: '<content/>',
    init: function () {
      this._control.element.closest('.tree-item').find('.openclose')
      .bind('click', function () {
        this.scope.attr('show', true);
      }.bind(this));
    }
  });
})(window.can, window.can.$);

Move lazy-openclose component to GGRC.Component


function confirmReboot () {
	if (confirm('Are you sure you want to reboot the system?')) {
		window.location.href = 'shellscripts/reboot.php?system=y';
	}
	else {
		// Do nothing
	}
}

function checkUpdate () {
	document.getElementById('update_display').style.display = "block";
	document.getElementById('check_update_button').onclick = hideUpdate;
	document.getElementById('check_update_button').innerHTML = "Hide Updates";
}

function hideUpdate () {
	document.getElementById('update_display').src = "";
	document.getElementById('update_display').style.display = "none";
}

function confirmReboot () {
	if (confirm('Are you sure you want to reboot the system?')) {
		window.location.href = 'shellscripts/reboot.php?system=y';
	}
	else {
		// Do nothing
	}
}

function checkUpdate () {
	document.getElementById('update_display').style.display = "block";
	document.getElementById('check_update_button').onclick = hideUpdate;
	document.getElementById('check_update_button').innerHTML = "Hide Updates";
}

function hideUpdate () {
	document.getElementById('update_display').src = "";
	document.getElementById('update_display').style.display = "none";
	document.getElementById('check_update_button').onclick = checkUpdate;
	document.getElementById('check_update_button').innerHTML = "Check for updates";
}

Check updates button trial II


module.exports = {
  HOST: process.env.HOST || null,
  PORT: process.env.PORT || 5000,
  DEFAULT_SHOT_WIDTH: process.env.DEFAULT_SHOT_WIDTH || 768,
  DEFAULT_SHOT_MIN_HEIGHT: process.env.DEFAULT_SHOT_MIN_HEIGHT || 700,
  WEBSHOTS_QUALITY: process.env.WEBSHOTS_QUALITY || 75,
};

module.exports = {
  HOST: process.env.HOST || null,
  PORT: process.env.PORT || 5000,
  DEFAULT_SHOT_WIDTH: process.env.DEFAULT_SHOT_WIDTH || 768,
  DEFAULT_SHOT_MIN_HEIGHT: process.env.DEFAULT_SHOT_MIN_HEIGHT || 1,
  WEBSHOTS_QUALITY: process.env.WEBSHOTS_QUALITY || 75,
};

Use min height of 1px.


var p5 = require('p5');

var sketch = function (p) {

  var Receiver = require('./Receiver.js');
  var receiver = new Receiver();

  var Processor = require('./Processor.js');
  var processor = new Processor();

  var DrawingManager = require('./DrawingManager.js');
  var dM = new DrawingManager(p);

  p.setup = function() {
    receiver.connect();

    receiver.on('received', function(data) {
      console.log("Pulsar: received: " + data);

      var drawing = processor.createDrawing(data);

      dM.add(drawing);
      // give to drawing manager
    })

    p.createCanvas(p.windowWidth, p.windowHeight);
  }

  p.draw = function() {
    dM.drawAll();

    p.background(0);

    p.textSize(15);
    p.fill(150);
    p.textStyle(p.BOLD);
    var verWidth = p.textWidth("PULSAR - v0.0.1");
    p.text("PULSAR - v0.0.1", p.windowWidth - verWidth - 10, p.windowHeight - 10);
  }

  p.windowResized = function() {
    p.resizeCanvas(p.windowWidth, p.windowHeight);
  }
}

var myp5 = new p5(sketch);

var p5 = require('p5');

var sketch = function (p) {

  var Receiver = require('./Receiver.js');
  var receiver = new Receiver();

  var Processor = require('./Processor.js');
  var processor = new Processor();

  var DrawingManager = require('./DrawingManager.js');
  var dM = new DrawingManager(p);

  p.setup = function() {
    receiver.connect();

    receiver.on('received', function(data) {
      console.log("Pulsar: received: " + data);

      var drawing = processor.createDrawing(data);

      dM.add(drawing);
      // give to drawing manager
    })

    p.createCanvas(p.windowWidth, p.windowHeight);
  }

  p.draw = function() {

    p.background(0);

    p.textSize(15);
    p.fill(175);
    p.textStyle(p.BOLD);
    var verWidth = p.textWidth("PULSAR - v0.0.1");
    p.text("PULSAR - v0.0.1", p.windowWidth - verWidth - 10, p.windowHeight - 10);

    dM.drawAll();
  }

  p.windowResized = function() {
    p.resizeCanvas(p.windowWidth, p.windowHeight);
  }
}

var myp5 = new p5(sketch);

Move drawing manager call to be in front of the background


const EventEmitter = require('events');

// wrapper around the Node.js ws module
// for use in browsers
class WebSocketWrapper extends EventEmitter {
    constructor(url) {
        super();
        this._ws = new WebSocket(url);
        this._ws.onopen = () => {
            this.emit('open');
        };
        this._ws.onclose = () => {
            this.emit('close');
        };
        this._ws.onmessage = (event) => {
            this.emit('message', event.data);
        };
        this._ws.onerror = () => {
            this.emit('error', new Error('WebSocket error'));
        };
    }

    close() {
        this._ws.close();
    }

    send(data) {
        this._ws.send(data);
    }
}

module.exports = WebSocketWrapper;

const EventEmitter = require('events');

// wrapper around the Node.js ws module
// for use in browsers
class WebSocketWrapper extends EventEmitter {
    constructor(url) {
        super();
        this._ws = new WebSocket(url);
        this._ws.onopen = () => {
            this.emit('open');
        };
        this._ws.onclose = () => {
            this.emit('close');
        };
        this._ws.onmessage = (event) => {
            this.emit('message', event.data);
        };
        this._ws.onerror = () => {
            this.emit('error', new Error('WebSocket error'));
        };
    }

    close() {
        this._ws.close();
    }

    send(data, callback) {
        try {
            this._ws.send(data);
            callback();
        } catch (err) {
            callback(err);
        }
    }
}

module.exports = WebSocketWrapper;

Add missing callback to WebSocket 'send' wrapper


L.Control.Attribution.prototype.options.prefix = '';
var map = L.map('map', {minZoom: 14}).setView([38.9, -76.99], 13);
var attr = '© OpenStreetMap contributors (this is gpstile, and it is open source)';
map.addHash();
(new mapbox.geocoderControl('tmcw.map-nlcg49tr')).addTo(map);

if (L.Browser.retina) {
    L.tileLayer('http://a.tiles.mapbox.com/v3/tmcw.map-8py9u67o/{z}/{x}/{y}.png', {
        attribution: attr
    }).addTo(map);
} else {
    L.tileLayer('http://a.tiles.mapbox.com/v3/tmcw.map-nlcg49tr/{z}/{x}/{y}.png', {
        attribution: attr
    }).addTo(map);
}

LgpsTile.addTo(map);

Change github like to point to osmlab org


var _ = require('underscore');
var PayInPaymentDetails = require('./PayInPaymentDetails');

var PayInPaymentDetailsCard = PayInPaymentDetails.extend({
    defaults: {
        /**
         *  CardType { CB_VISA_MASTERCARD, AMEX }
         */
        CardType: null,
        CardId: null
    }
});

module.exports = PayInPaymentDetailsCard;

var _ = require('underscore');
var PayInPaymentDetails = require('./PayInPaymentDetails');

var PayInPaymentDetailsCard = PayInPaymentDetails.extend({
    defaults: {
        /**
         *  CardType { CB_VISA_MASTERCARD, AMEX }
         */
        CardType: null,
        CardId: null,
        StatementDescriptor: null
    }
});

module.exports = PayInPaymentDetailsCard;

Add StatementDescriptor for card payins


$(function () {
    $('#btn-add-gadget').click(function () {
        var elem = $(this);
        asset.process(elem.data('type'), elem.data('aid'), location.href, elem);
    });

    $('#btn-remove-subscribe').click(function () {
        var elem = $(this);
        asset.unsubscribeBookmark(elem.data('type'), elem.data('aid'), location.href, elem);
    });

    $("a[data-toggle='tooltip']").tooltip();

    $('.embed-snippet').hide();

    $('.btn-embed').click(function () {
        $('.embed-snippet').toggle(400);
        return false;
    });

    var el = $('.user-rating'),
        rating = el.data('rating');
    $($('input', el)[rating - 1]).attr('checked', 'checked');

    $('.auto-submit-star').rating({
        callback: function (value, link) {
            if (value == undefined) {
                value = 0;
            }
            $('.rate-num-assert').html('(' + value + ')');
            caramel.post('/apis/rate', {
                asset: $('#assetp-tabs').data('aid'),
                value: value || 0
            }, function (data) {

            });
        }
    });

});

$(function () {
    $('#btn-add-gadget').click(function () {
        var elem = $(this);
        asset.process(elem.data('type'), elem.data('aid'), location.href, elem);
    });

    $('#btn-remove-subscribe').click(function () {
        var elem = $(this);
        asset.unsubscribeBookmark(elem.data('type'), elem.data('aid'), location.href, elem);
    });

    $('#btn-remove-subscribe').hover(
        function () {
            $(this).find("i").removeClass().addClass("fa fa-remove");
        },
        function () {
            $(this).find("i").removeClass().addClass("fw fw-bookmark");
        });

    $("a[data-toggle='tooltip']").tooltip();

    $('.embed-snippet').hide();

    $('.btn-embed').click(function () {
        $('.embed-snippet').toggle(400);
        return false;
    });

    var el = $('.user-rating'),
        rating = el.data('rating');
    $($('input', el)[rating - 1]).attr('checked', 'checked');

    $('.auto-submit-star').rating({
        callback: function (value, link) {
            if (value == undefined) {
                value = 0;
            }
            $('.rate-num-assert').html('(' + value + ')');
            caramel.post('/apis/rate', {
                asset: $('#assetp-tabs').data('aid'),
                value: value || 0
            }, function (data) {

            });
        }
    });

});

Fix for STORE-1330: Add hover method to impiles that bookmark is removable


var canvas = document.getElementById('game');
var context = canvas.getContext('2d');

var Ball = function(x, y, radius, context) {
  this.x = x;
  this.y = y;
  this.radius = radius || 10;
  this.startAngle = 0;
  this.endAngle = (Math.PI / 180) * 360;
  this.context = context
}

Ball.prototype.draw = function () {
  context.arc(this.x, this.y, this.radius, this.startAngle, this.endAngle);
  context.fillStyle = "white"
  context.fill();
  return this;
};

Ball.prototype.move = function () {
  if (this.x < canvas.width - this.radius){
    this.x++;
  }
  return this;
};

var golfBall = new Ball(350, 550, 5, 0);

requestAnimationFrame(function gameLoop() {
  context.beginPath();
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.closePath();
  golfBall.draw().move();
  requestAnimationFrame(gameLoop);
});

module.exports = Ball;

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');

var Ball = function(x, y, radius, context) {
  this.x = x;
  this.y = y;
  this.radius = radius || 10;
  this.startAngle = 0;
  this.endAngle = (Math.PI / 180) * 360;
  this.context = context
  this.speed = 0
}

Ball.prototype.draw = function () {
  context.arc(this.x, this.y, this.radius, this.startAngle, this.endAngle);
  context.fillStyle = "white"
  context.fill();
  return this;
};

Ball.prototype.move = function () {
  if (this.x < canvas.width - this.radius && this.y < canvas.height - this.radius ){
    this.x += this.speed;
    // this.y += this.speed;
  }
  return this;
};

var golfBall = new Ball(350, 450, 5, 0);

requestAnimationFrame(function gameLoop() {
  context.beginPath();
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.closePath();
  golfBall.draw().move();
  requestAnimationFrame(gameLoop);
});

module.exports = Ball;

Add ball speed and change move function


'use strict'

const Controller = require('trails-controller')

/**
 * @module <%= name %>Controller
 * @description Generated Trails.js Controller.
 */
module.exports = class <%= name %>Controller extends Controller {

}

'use strict'

/**
 * @module <%= name %>Controller
 * @description Generated Trails.js Controller.
 */
module.exports = class <%= name %>Controller {

}

Remove controller extends on template file


import React from 'react';
import { map } from 'lodash';

class DropdownFilter extends React.Component {
  constructor() {
    super();

    this.change = this.change.bind(this);
  }

  componentDidMount() {
    const type = this.props.options.type;
    const defaultValue = this.props.options.default;

    this.props.updateFilters({ [type]: defaultValue });
  }

  change(event) {
    const type = this.props.options.type;

    this.props.updateFilters({ [type]: event.target.value });
  }

  render() {
    return (

{this.props.header}

            <select onChange={(event) => this.change(event)}>
              {map(this.props.options.values, (option, key) => (
                 <option value={key} key={key}>{option}</option>
              ))}
            </select>

    )
  }
}

export default DropdownFilter;

import React from 'react';
import { map } from 'lodash';
import PropTypes from 'prop-types';

class DropdownFilter extends React.Component {
  constructor() {
    super();

    this.change = this.change.bind(this);
  }

  componentDidMount() {
    const type = this.props.options.type;
    const defaultValue = this.props.options.default;

    this.props.updateFilters({ [type]: defaultValue });
  }

  change(event) {
    const type = this.props.options.type;

    this.props.updateFilters({ [type]: event.target.value });
  }

  render() {
    return (

{this.props.header}

          <select onChange={event => this.change(event)}>
            {map(this.props.options.values, (option, key) => (
              <option value={key} key={key}>{option}</option>
            ))}
          </select>

    );
  }
}

DropdownFilter.propTypes = {
  options: PropTypes.shape({
    default: PropTypes.string,
    type: PropTypes.string,
    values: PropTypes.object,
  }).isRequired,
  updateFilters: PropTypes.func,
  header: PropTypes.string.isRequired,
};

DropdownFilter.defaultProps = {
  updateFilters: null,
};

export default DropdownFilter;

Add proptype validation to DropDownFilter component


"use strict";

function resolveHttpError(response, message) {
    if (response.statusCode < 400) {
        return;
    }

    message = message
        ? message + " "
        : "";

    message += "Status code " + response.statusCode + " (" + response.statusMessage + ").";

    if (response.body) {
        message += " " + response.body;
    }

    var error = new Error(message);
    error.response = response;

    return error;
}

function createCallback(action, cb) {
    return function (err, response) {
        err = err || resolveHttpError(response, "Error " + action + ".");

        if (err) {
            return cb(err);
        }

        cb(null, response);
    };
}

function createBodyCallback(action, cb) {
    return createCallback(action, function (err, response) {
        if (err) {
            return cb(err);
        }

        cb(null, response.body, response);
    });
}

function createJsonCallback(action, cb) {
    return createCallback(action, function (err, response) {
        if (err) {
            return cb(err);
        }

        try {
            var data = JSON.parse(response.body);
        } catch (e) {
            return cb(e);
        }

        cb(null, data, response);
    });
}

module.exports = {
    resolveHttpError: resolveHttpError,
    createCallback: createCallback,
    createBodyCallback: createBodyCallback,
    createJsonCallback: createJsonCallback
};

"use strict";

function resolveHttpError(response, message) {
    if (response.statusCode < 400) {
        return;
    }

    message = message
        ? message + " "
        : "";

    message += "Status code " + response.statusCode + " (" + response.statusMessage + "). See the response property for details.";

    var error = new Error(message);
    error.response = response;

    return error;
}

function createCallback(action, cb) {
    return function (err, response) {
        err = err || resolveHttpError(response, "Error " + action + ".");

        if (err) {
            return cb(err);
        }

        cb(null, response);
    };
}

function createBodyCallback(action, cb) {
    return createCallback(action, function (err, response) {
        if (err) {
            return cb(err);
        }

        cb(null, response.body, response);
    });
}

function createJsonCallback(action, cb) {
    return createCallback(action, function (err, response) {
        if (err) {
            return cb(err);
        }

        try {
            var data = JSON.parse(response.body);
        } catch (e) {
            return cb(e);
        }

        cb(null, data, response);
    });
}

module.exports = {
    createCallback: createCallback,
    createBodyCallback: createBodyCallback,
    createJsonCallback: createJsonCallback
};

Remove response body from error message. Hide HTTP error resolver.


/*
 * grunt-browser-extension
 * https://github.com/addmitriev/grunt-browser-extension
 *
 * Copyright (c) 2015 Aleksey Dmitriev
 * Licensed under the MIT license.
 */
'use strict';

var util = require('util');
var path = require('path');
var fs = require('fs-extra');

module.exports = function (grunt) {
    var BrowserExtension = require('./lib/browser-extension')(grunt);

    grunt.registerMultiTask('browser_extension', 'Grunt plugin to create any browser website extension', function () {
        if(this.target){
            var options = this.options();
            var required_options = [];
            for(var required_options_id in required_options){
                if(required_options_id){
                    var required_option = required_options[required_options_id];
                    if(!options[required_option]){
                        grunt.fail.fatal("Please set up all required options. All options must be string value! You have not setted " + required_option);
                    }
                }
            }
            var pluginRoot = path.join(path.dirname(fs.realpathSync(__filename)), '../');
            var bExt = new BrowserExtension(pluginRoot, options, this.target, grunt);

            bExt.copyUserFiles();
            grunt.verbose.ok('User files copied');
            bExt.copyBrowserFiles();
            grunt.verbose.ok('Extension files copied');
            bExt.buildNsisIE();
            grunt.verbose.ok('NSIS installer for IE builded');
            bExt.build();
            grunt.verbose.ok('Extensions builded');
        }
    });
};

/*
 * grunt-browser-extension
 * https://github.com/addmitriev/grunt-browser-extension
 *
 * Copyright (c) 2015 Aleksey Dmitriev
 * Licensed under the MIT license.
 */
'use strict';

var util = require('util');
var path = require('path');
var fs = require('fs-extra');

module.exports = function (grunt) {
    var BrowserExtension = require('./lib/browser-extension')(grunt);

    grunt.registerMultiTask('browser_extension', 'Grunt plugin to create any browser website extension', function () {
        if(this.target){
            var options = this.options();
            var required_options = [];
            for(var required_options_id in required_options){
                if(required_options_id){
                    var required_option = required_options[required_options_id];
                    if(!util.isString(options[required_option])){
                        grunt.fail.fatal("Please set up all required options. All options must be string value! You have not setted " + required_option);
                    }
                }
            }
            var pluginRoot = path.join(path.dirname(fs.realpathSync(__filename)), '../');
            var bExt = new BrowserExtension(pluginRoot, options, this.target, grunt);

            bExt.copyUserFiles();
            grunt.verbose.ok('User files copied');
            bExt.copyBrowserFiles();
            grunt.verbose.ok('Extension files copied');
            bExt.buildNsisIE();
            grunt.verbose.ok('NSIS installer for IE builded');
            bExt.build();
            grunt.verbose.ok('Extensions builded');
        }
    });
};

Check config and show what required options not exists


import Ember from 'ember';

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

  model(params) {
    let projectId = this.modelFor('project').id;
    let queryParams = {
      projectId: projectId,
      number: params.number
    };

    let userId = this.get('session.session.authenticated.user_id');

    return Ember.RSVP.hash({
      post: this.store.queryRecord('post', queryParams),
      user: Ember.isPresent(userId) ? this.store.find('user', userId) : null
    }).then((result) => {
      return Ember.RSVP.hash({
        post: result.post,
        comment: this.store.createRecord('comment', { post: result.post, user: result.user }),
        comments: this.store.query('comment', { postId: result.post.id })
      });
    });
  },

  setupController(controller, models) {
    controller.set('post', models.post);
    controller.set('newComment', models.comment);
    controller.set('comments', models.comments);
  },

  actions: {
    saveComment(comment) {
      let route = this;
      comment.save().then(() => {
        // TODO: Not sure if we want to reload all comments here, or just push the new one
        // reloading for now
        route.send('reloadComments', comment);
      }).catch((error) => {
        if (error.errors.length === 1) {
          this.controllerFor('project.posts.post').set('error', error);
        }
      });

    },

    reloadComments() {
      let controller = this.controllerFor('project.posts.post');
      let postId = controller.get('post.id');
      return this.store.query('comment', { postId: postId }).then((comments) => {
        controller.set('comments', comments);
      });
    }
  }
});

import Ember from 'ember';

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

  model(params) {
    let projectId = this.modelFor('project').id;
    let queryParams = {
      projectId: projectId,
      number: params.number
    };

    let userId = this.get('session.session.authenticated.user_id');

    return Ember.RSVP.hash({
      post: this.store.queryRecord('post', queryParams),
      user: Ember.isPresent(userId) ? this.store.find('user', userId) : null
    }).then((result) => {
      return Ember.RSVP.hash({
        post: result.post,
        comment: this.store.createRecord('comment', { post: result.post, user: result.user }),
        comments: this.store.query('comment', { postId: result.post.id })
      });
    });
  },

  setupController(controller, models) {
    controller.set('post', models.post);
    controller.set('newComment', models.comment);
    controller.set('comments', models.comments);
  },

  actions: {
    saveComment(comment) {
      let route = this;
      comment.save().then(() => {
        route.refresh();
      }).catch((error) => {
        if (error.errors.length === 1) {
          this.controllerFor('project.posts.post').set('error', error);
        }
      });
    }
  }
});

Simplify behavior for comment reload


/* global require, module */

var EmberApp = require('ember-cli/lib/broccoli/ember-app');

var app = new EmberApp({
  dotEnv: {
    clientAllowedKeys: ['CDN_HOST']
  },
  fingerprint: {
    prepend: 'drwikejswixhx.cloudfront.net/'
  }
});

// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.

module.exports = app.toTree();

/* global require, module */

var EmberApp = require('ember-cli/lib/broccoli/ember-app');

var app = new EmberApp({
  dotEnv: {
    clientAllowedKeys: ['CDN_HOST']
  },
  fingerprint: {
    prepend: 'http://drwikejswixhx.cloudfront.net/'
  }
});

// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.

module.exports = app.toTree();

Add full path for CDN


'use strict';

(() => {
  const electron = require('electron');
  const app = electron.app;
  const BrowserWindow = electron.BrowserWindow;
  let win = null;

  app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
      app.quit();
    }
  });

  // Avoid the slow performance issue when renderer window is hidden
  app.commandLine.appendSwitch('disable-renderer-backgrounding');

  app.on('ready', () => {
    win = new BrowserWindow({
      width: 600,
      height: 600
    });

    win.loadURL(`file://${__dirname}/index.html`);

    win.on('closed', () => {
      win = null;
    });
  });
})();

'use strict';

(() => {
  const electron = require('electron');
  const app = electron.app;
  const BrowserWindow = electron.BrowserWindow;
  let win = null;

  app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
      app.quit();
    }
  });

  // Avoid the slow performance issue when renderer window is hidden
  app.commandLine.appendSwitch('disable-renderer-backgrounding');

  app.on('ready', () => {
    win = new BrowserWindow({
      width: 850,
      height: 600
    });

    win.loadURL(`file://${__dirname}/index.html`);

    win.on('closed', () => {
      win = null;
    });
  });
})();

Change default window width 600px to 850px


import documentFormatter from 'src/logic/documentPackager/documentFormatter';
import base64OfSimplePdf from './reference/base64OfSimplePdf';

describe('DocumentFormatter', () => {
  it('should returns the same data for \'html viewMode\'', () => {
    const viewMode = 'html';
    const inputData = '
This is a HTML content
';
    const outputData = documentFormatter.format(inputData, viewMode);

    expect(outputData).to.equal('
This is a HTML content
');
  });

  it('should returns a pdfBlob for \'pages viewMode\'', (done) => {
    const expectedOutput = base64OfSimplePdf;
    const inputData = '
This is a HTML content
';

    const thatPromise = documentFormatter.getPdfBlob(inputData);

    thatPromise.then((outputData) => {
      // pdfJS does not give deterministic outputData
      // around 5 characters will always be different in the output
      // therefore, an approximation method to use content length for
      // testing is used.

      expect(outputData.length).to.equal(expectedOutput.length);
      done();
    }).catch((error) => {
      done(error);
    });
  });
});

import documentFormatter from 'src/logic/documentPackager/documentFormatter';
import base64OfSimplePdf from './reference/base64OfSimplePdf';

describe('DocumentFormatter', () => {
  it('should returns the same data for \'html viewMode\'', () => {
    const viewMode = 'html';
    const inputData = '
This is a HTML content
';
    const outputData = documentFormatter.format(inputData, viewMode);

    expect(outputData).to.equal('
This is a HTML content
');
  });

  it('should returns a pdfBlob for \'pages viewMode\'', (done) => {
    const expectedOutput = base64OfSimplePdf;
    const inputData = '
This is a HTML content
';

    const thatPromise = documentFormatter.getPdfBlob(inputData);

    thatPromise.then((outputData) => {
      // jsPDF does not give deterministic outputData
      // around 5 characters will always be different in the output
      // therefore, an approximation method to use content length for
      // testing is used.

      expect(outputData.length).to.equal(expectedOutput.length);
      done();
    }).catch((error) => {
      done(error);
    });
  });
});

Fix documentFormatter comment about jsPDF


/**
 * cbpAnimatedHeader.js v1.0.0
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2013, Codrops
 * http://www.codrops.com
 */
var cbpAnimatedHeader = (function() {

	var docElem = document.documentElement,
		header = document.querySelector( '.navbar-default' ),
		didScroll = false,
		changeHeaderOn = 300;

	function init() {
		window.addEventListener( 'scroll', function( event ) {
			if( !didScroll ) {
				didScroll = true;
				setTimeout( scrollPage, 250 );
			}
		}, false );
	}

	function scrollPage() {
		var sy = scrollY();
		if ( sy >= changeHeaderOn ) {
			classie.add( header, 'navbar-shrink' );
		}
		else {
			classie.remove( header, 'navbar-shrink' );
		}
		didScroll = false;
	}

	function scrollY() {
		return window.pageYOffset || docElem.scrollTop;
	}

	init();

})();

/**
 * cbpAnimatedHeader.js v1.0.0
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2013, Codrops
 * http://www.codrops.com
 */
var cbpAnimatedHeader = (function() {

	var docElem = document.documentElement,
		header = document.querySelector( '.navbar-default' ),
		didScroll = false,
		changeHeaderOn = 200;

	function init() {
		window.addEventListener( 'scroll', function( event ) {
			if( !didScroll ) {
				didScroll = true;
				setTimeout( scrollPage, 250 );
			}
		}, false );
	}

	function scrollPage() {
		var sy = scrollY();
		if ( sy >= changeHeaderOn ) {
			classie.add( header, 'navbar-shrink' );
		}
		else {
			classie.remove( header, 'navbar-shrink' );
		}
		didScroll = false;
	}

	function scrollY() {
		return window.pageYOffset || docElem.scrollTop;
	}

	init();

})();

Fix bug with animation on index page


var
  fs         = require('fs'),
  mkdirp     = require('mkdirp'),
  Builder    = require('component-builder'),
  config     = require('../config'),
  installDir = config.componentInstallDir,
  utils      = require('./utils'),
  options    = {
    dest : installDir
  },
  component;

component = !config.useMocks ?
  require('component') :
  require('../mocks/component');

exports.install = function (data, callback) {
  var pkg = component.install(data.repo, '*', options);
  pkg.on('end', callback);
  pkg.install();
};

exports.build = function (data, callback) {
  var builder = new Builder(utils.getInstallDir(data.repo));
  builder.build(function (err, res) {
    var
      dirPath = utils.getBuildDir(data.repo),
      scriptPath = utils.getBuildScriptPath(data.repo);
    if (err || (res && !res.js)) {
      return callback(err);
    }
    mkdirp(dirPath, function (err) {
      if (err) {
        return callback(err);
      }
      fs.writeFile(scriptPath, res.js, callback);
    });
  });
};

var
  fs         = require('fs'),
  mkdirp     = require('mkdirp'),
  rimraf     = require('rimraf'),
  Builder    = require('component-builder'),
  config     = require('../config'),
  installDir = config.componentInstallDir,
  utils      = require('./utils'),
  options    = {
    dest : installDir
  },
  component;

component = !config.useMocks ?
  require('component') :
  require('../mocks/component');

exports.install = function (data, callback) {
  var pkg = component.install(data.repo, '*', options);
  pkg.on('end', callback);

  // Clear out install directory to get latest
  rimraf(utils.getInstallDir(data.repo), function () {
    pkg.install();
  });
};

exports.build = function (data, callback) {
  var builder = new Builder(utils.getInstallDir(data.repo));
  builder.build(function (err, res) {
    var
      dirPath = utils.getBuildDir(data.repo),
      scriptPath = utils.getBuildScriptPath(data.repo);
    if (err || (res && !res.js)) {
      return callback(err);
    }
    mkdirp(dirPath, function (err) {
      if (err) {
        return callback(err);
      }
      fs.writeFile(scriptPath, res.js, callback);
    });
  });
};

Remove component installation dir when getting new


import fs from 'fs';
import path from 'path';

function findRecursive(directory) {
  if (directory === '/') {
    throw new Error('No project root found, looking for a directory with a package.json file.');
  }

  const pathToPackageJson = path.join(directory, 'package.json');

  if (fs.existsSync(pathToPackageJson)) {
    return directory;
  }

  return findRecursive(path.dirname(directory));
}

function makeAbsolute(pathToFile) {
  if (pathToFile.startsWith('/')) {
    return pathToFile;
  }

  return path.join(process.cwd(), pathToFile);
}

export default function findProjectRoot(pathToFile) {
  return findRecursive(path.dirname(makeAbsolute(pathToFile)));
}

import fs from 'fs';
import path from 'path';

function findRecursive(directory) {
  if (directory === '/') {
    throw new Error('No project root found, looking for a directory with a package.json file.');
  }

  const pathToPackageJson = path.join(directory, 'package.json');

  if (fs.existsSync(pathToPackageJson)) {
    return directory;
  }

  return findRecursive(path.dirname(directory));
}

function makeAbsolute(pathToFile) {
  if (path.isAbsolute(pathToFile)) {
    return pathToFile;
  }

  return path.join(process.cwd(), pathToFile);
}

export default function findProjectRoot(pathToFile) {
  return findRecursive(path.dirname(makeAbsolute(pathToFile)));
}

Use path.isAbsolute for Windows compatibility


"use strict";

const timestampMixin = require('loopback-ds-timestamp-mixin/time-stamp');
const shortid = require('shortid');

module.exports = function (SecMembership) {
	timestampMixin(SecMembership);

	SecMembership.definition.rawProperties.id.default =
		SecMembership.definition.properties.id.default = function () {
			return shortid();
		};

	SecMembership.validatesUniquenessOf('userId', {scopedTo: ['roleId']});
	SecMembership.validatesUniquenessOf('userId', {scopedTo: ['scope', 'scopeId']});

	return SecMembership;
};

"use strict";

const timestampMixin = require('loopback-ds-timestamp-mixin/time-stamp');
const shortid = require('shortid');

module.exports = function (SecMembership) {
	timestampMixin(SecMembership);

	SecMembership.definition.rawProperties.id.default =
		SecMembership.definition.properties.id.default = function () {
			return shortid();
		};

	SecMembership.validatesUniquenessOf('userId', {scopedTo: ['scope', 'scopeId']});

	return SecMembership;
};

Remove unnecessary uniqueness of userId scoped to roleId for membership model


Package.describe({
  summary: "Google's Material Design based Bootstrap 3 theme.",
  version: "0.1.0",
  // git: "https://github.com/FezVrasta/bootstrap-material-design.git"
});

Package.onUse(function(api) {
  api.versionsFrom('METEOR@0.9.3');
  api.use(['mizzao:bootstrap-3@3.2.0', 'jquery'], 'client');

  api.addFiles([
    // 'bootstrap-material-design/css-compiled/material-wfont.css',
    'bootstrap-material-design/css-compiled/material.css',
    'bootstrap-material-design/css-compiled/ripples.css',
    'bootstrap-material-design/scripts/ripples.js',
    'bootstrap-material-design/scripts/material.js',
    'bootstrap-material-design/icons/icons-material-design.css',
    'bootstrap-material-design/icons/fonts/Material-Design.eot',
    'bootstrap-material-design/icons/fonts/Material-Design.svg',
    'bootstrap-material-design/icons/fonts/Material-Design.ttf',
    'bootstrap-material-design/icons/fonts/Material-Design.woff'
    ], 'client', {bare: true});
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.use('html5cat:bootstrap-material-design');
  // api.addFiles('html5cat:bootstrap-material-design-tests.js');
});

Package.describe({
  summary: "Google's Material Design based Bootstrap 3 theme.",
  version: "0.1.2",
  name: 'html5cat:bootstrap-material-design',
  git: 'https://github.com/html5cat/bootstrap-material-design.git'
  // git: "https://github.com/FezVrasta/bootstrap-material-design.git"
});

Package.onUse(function(api) {
  api.versionsFrom('METEOR@0.9.3');
  api.use(['mizzao:bootstrap-3@3.2.0', 'jquery'], 'client');

  api.addFiles([
    // 'bootstrap-material-design/css-compiled/material-wfont.css',
    'bootstrap-material-design/css-compiled/material.css',
    'bootstrap-material-design/css-compiled/ripples.css',
    'bootstrap-material-design/scripts/ripples.js',
    'bootstrap-material-design/scripts/material.js',
    'bootstrap-material-design/icons/icons-material-design.css',
    'bootstrap-material-design/icons/fonts/Material-Design.eot',
    'bootstrap-material-design/icons/fonts/Material-Design.svg',
    'bootstrap-material-design/icons/fonts/Material-Design.ttf',
    'bootstrap-material-design/icons/fonts/Material-Design.woff'
    ], 'client', {bare: true});
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.use('html5cat:bootstrap-material-design');
  // api.addFiles('html5cat:bootstrap-material-design-tests.js');
});

Add name and git url


Package.describe({
  name: 'klaussner:svelte',
  version: '0.0.1',
  summary: 'Use the magical disappearing UI framework in Meteor',
  git: 'https://github.com/klaussner/svelte'
});

Package.registerBuildPlugin({
  name: 'svelte-compiler',
  use: ['caching-compiler@1.1.9', 'babel-compiler@6.13.0'],
  sources: [
    'plugin.js'
  ],
  npmDependencies: {
    htmlparser2: '3.9.2',
    'source-map': '0.5.6',
    'svelte-es5-meteor': '0.0.3'
  }
});

Package.onUse(function (api) {
  api.use('isobuild:compiler-plugin@1.0.0');

  api.imply('modules@0.7.7');
  api.imply('ecmascript-runtime@0.3.15');
  api.imply('babel-runtime@1.0.1');
  api.imply('promise@0.8.8');
});

Package.describe({
  name: 'klaussner:svelte',
  version: '0.0.1',
  summary: 'Use the magical disappearing UI framework in Meteor',
  git: 'https://github.com/klaussner/meteor-svelte.git'
});

Package.registerBuildPlugin({
  name: 'svelte-compiler',
  use: ['caching-compiler@1.1.9', 'babel-compiler@6.13.0'],
  sources: [
    'plugin.js'
  ],
  npmDependencies: {
    htmlparser2: '3.9.2',
    'source-map': '0.5.6',
    'svelte-es5-meteor': '0.0.3'
  }
});

Package.onUse(function (api) {
  api.use('isobuild:compiler-plugin@1.0.0');

  api.imply('modules@0.7.7');
  api.imply('ecmascript-runtime@0.3.15');
  api.imply('babel-runtime@1.0.1');
  api.imply('promise@0.8.8');
});

Fix link to Git repository


const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const {
  checkAndMakeDir,
  getTempFilename
} = require('./utilities');

module.exports = function(options, fieldname, filename) {
  const dir = path.normalize(options.tempFileDir || process.cwd() + '/tmp/');
  const tempFilePath = path.join(dir, getTempFilename());

  checkAndMakeDir({createParentPath: true}, tempFilePath);

  let hash = crypto.createHash('md5');
  let writeStream = fs.createWriteStream(tempFilePath);
  let fileSize = 0; // eslint-disable-line

  return {
    dataHandler: function(data) {
      writeStream.write(data);
      hash.update(data);
      fileSize += data.length;
      if (options.debug) {
        return console.log( // eslint-disable-line
          `Uploaded ${data.length} bytes for `,
          fieldname,
          filename
        );
      }
    },
    getFilePath: function(){
      return tempFilePath;
    },
    getFileSize: function(){
      return fileSize;
    },
    getHash: function(){
      return hash.digest('hex');
    },
    complete: function(){
      writeStream.end();
      //return empty buffer since data has been uploaded to the temporary file.
      return Buffer.concat([]);
    },
    cleanup: function(){
      writeStream.end();

      fs.unlink(tempFilePath, function(err) {
        if (err) throw err;
      });
    }
  };
};

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const {
  checkAndMakeDir,
  getTempFilename
} = require('./utilities');

module.exports = function(options, fieldname, filename) {
  const dir = path.normalize(options.tempFileDir || process.cwd() + '/tmp/');
  const tempFilePath = path.join(dir, getTempFilename());

  checkAndMakeDir({createParentPath: true}, tempFilePath);

  let hash = crypto.createHash('md5');
  let writeStream = fs.createWriteStream(tempFilePath);
  let fileSize = 0; // eslint-disable-line

  return {
    dataHandler: function(data) {
      writeStream.write(data);
      hash.update(data);
      fileSize += data.length;
      debugLog(options, `Uploading ${fieldname} -> ${filename}, bytes: ${fileSize}`);
    },
    getFilePath: function(){
      return tempFilePath;
    },
    getFileSize: function(){
      return fileSize;
    },
    getHash: function(){
      return hash.digest('hex');
    },
    complete: function(){
      writeStream.end();
      //return empty buffer since data has been uploaded to the temporary file.
      return Buffer.concat([]);
    },
    cleanup: function(){
      writeStream.end();

      fs.unlink(tempFilePath, function(err) {
        if (err) throw err;
      });
    }
  };
};

Use debug log for logging.


var _ = require('lodash')
var fs = require('fs')
var gzip = require('gzip-size')
var filesize = require('filesize')
var cssstats = require('cssstats')

var module = require('tachyons-text-decoration/package.json')
var moduleCss = fs.readFileSync('node_modules/tachyons-text-decoration/tachyons-text-decoration.min.css', 'utf8')
var moduleObj = cssstats(moduleCss)
var moduleSize = filesize(moduleObj.gzipSize)

var srcCSS = fs.readFileSync('./src/_text-decoration.css', 'utf8')

var template = fs.readFileSync('./templates/docs/text-decoration/index.html', 'utf8')
var tpl = _.template(template)
var html = tpl({
  moduleVersion: module.version,
  moduleSize: moduleSize,
  moduleObj: moduleObj,
  srcCSS: srcCSS
})

fs.writeFileSync('./docs/typography/text-decoration/index.html', html)

var _ = require('lodash')
var fs = require('fs')
var gzip = require('gzip-size')
var filesize = require('filesize')
var cssstats = require('cssstats')

var module = require('tachyons-text-decoration/package.json')
var moduleCss = fs.readFileSync('node_modules/tachyons-text-decoration/tachyons-text-decoration.min.css', 'utf8')
var moduleObj = cssstats(moduleCss)
var moduleSize = filesize(moduleObj.gzipSize)

var srcCSS = fs.readFileSync('./src/_text-decoration.css', 'utf8')
var navDocs = fs.readFileSync('./templates/nav_docs.html', 'utf8')

var template = fs.readFileSync('./templates/docs/text-decoration/index.html', 'utf8')
var tpl = _.template(template)
var html = tpl({
  moduleVersion: module.version,
  moduleSize: moduleSize,
  moduleObj: moduleObj,
  srcCSS: srcCSS,
  navDocs: navDocs
})

fs.writeFileSync('./docs/typography/text-decoration/index.html', html)

Update with reference to global nav partial


import Em from 'ember';
import { ArrayController } from 'ember-legacy-controllers';
const get = Em.get;
const copy = Em.copy;

const ArrayPauser = ArrayController.extend({
	isPaused: false,

	buffer: Em.computed(function () {
		return Em.A();
	}),

	addToBuffer: function (idx, removedCount, added) {
		const buffer = get(this, 'buffer');
		buffer.pushObject([idx, removedCount, added]);
	},

	clearBuffer: Em.observer('isPaused', function () {
		const buffer = get(this, 'buffer');
		const arrangedContent = get(this, 'arrangedContent');
		buffer.forEach((args) => {
			arrangedContent.replace(...args);
		});
		buffer.clear();
	}),

	arrangedContent: Em.computed('content', function () {
		const content = get(this, 'content');
		const clone = copy(content);
		return clone;
	}),

	contentArrayDidChange: function (arr, idx, removedCount, addedCount) {
		const added = arr.slice(idx, idx + addedCount);
		const isPaused = get(this, 'isPaused');
		let arrangedContent;
		if (isPaused) {
			this.addToBuffer(idx, removedCount, added);
		}
		else {
			arrangedContent = get(this, 'arrangedContent');
			arrangedContent.replace(idx, removedCount, added);
		}
	},
});

export default ArrayPauser;

import Em from 'ember';
import { ArrayController } from 'ember-legacy-controllers';

const ArrayPauser = ArrayController.extend({
	isPaused: false,

	buffer: Em.computed(function () {
		return Em.A();
	}),

	addToBuffer: function (idx, removedCount, added) {
		const buffer = this.get('buffer');
		buffer.pushObject([idx, removedCount, added]);
	},

	clearBuffer: Em.observer('isPaused', function () {
		const buffer = this.get('buffer');
		const arrangedContent = this.get('arrangedContent');
		buffer.forEach((args) => {
			arrangedContent.replace(...args);
		});
		buffer.clear();
	}),

	arrangedContent: Em.computed('content', function () {
		const content = this.get('content');
		const clone = Em.copy(content);
		return clone;
	}),

	contentArrayDidChange: function (arr, idx, removedCount, addedCount) {
		const added = arr.slice(idx, idx + addedCount);
		const isPaused = this.get('isPaused');
		let arrangedContent;
		if (isPaused) {
			this.addToBuffer(idx, removedCount, added);
		}
		else {
			arrangedContent = this.get('arrangedContent');
			arrangedContent.replace(idx, removedCount, added);
		}
	},
});

export default ArrayPauser;

Remove unnecessary aliases for Ember utils


/* global jQuery */
jQuery(function ($){
  'use strict';

  var $limitedTextAreas = $('textarea[data-limit]');
  if( $limitedTextAreas.length > 0 ){
    $limitedTextAreas.each(function (i, o){
      var updateCounter = function (){
        var charsLeft = limit - $textarea.val().length;

        if( charsLeft > 0 ){
          $counterBox.removeClass('error');
          $counter.html( '(' + charsLeft + ' remaining)');
        }else {
          $counterBox.addClass('error');
          $counter.html('(' + (charsLeft * -1) + ' extra)');
        }
      };

      var $textarea = $(o);
      var limit = $textarea.data('limit');
      var $counterBox = $(
        '
' +
        'Maximum ' + limit + ' characters, including spaces. ' +
        '(' + limit + ' remaining)' +
        '
'
      );

      var $counter = $counterBox.find('.chars-remaining');
      $textarea.after($counterBox);

      updateCounter();
      $textarea.keyup(updateCounter);
    });
  }
});

/* global jQuery */
jQuery(function ($){
  'use strict';

  var $limitedTextAreas = $('textarea[data-limit]');
  if( $limitedTextAreas.length > 0 ){
    $limitedTextAreas.each(function (i, o){
      var updateCounter = function (){
        var charsLeft = limit - $textarea.val().length;

        if( charsLeft > 0 ){
          $counterBox.removeClass('error');
          $counter.html( '(' + charsLeft + ' remaining)');
        }else {
          $counterBox.addClass('error');
          $counter.html('(' + (charsLeft * -1) + ' extra)');
        }
      };

      var $textarea = $(o);
      var limit = $textarea.data('limit');
      var $counterBox = $(
        '
' +
        'Maximum ' + limit + ' characters, including spaces and new lines. ' +
        '(' + limit + ' remaining)' +
        '
'
      );

      var $counter = $counterBox.find('.chars-remaining');
      $textarea.after($counterBox);

      updateCounter();
      $textarea.keyup(updateCounter);
    });
  }
});

Add copy to word count that it includes new lines


//= require solidus_admin/Sortable

Spree.ready(function() {
  var sortable_tables = document.querySelectorAll('table.sortable');

  _.each(sortable_tables, function(table) {
    var url = table.getAttribute('data-sortable-link');
    var tbody = table.querySelector('tbody');
    var sortable = Sortable.create(tbody,{
      handle: ".handle",
      onEnd: function(e) {
        var positions = {};
        _.each(e.to.querySelectorAll('tr'), function(el, index) {
          var idAttr = el.id;
          if (idAttr) {
            var objId = idAttr.split('_').slice(-1);
            positions['positions['+objId+']'] = index + 1;
          }
        });
        Spree.ajax({
          type: 'POST',
          dataType: 'script',
          url: url,
          data: positions,
        });
      }
    });
  });
});

//= require solidus_admin/Sortable

Spree.ready(function() {
  var sortable_tables = document.querySelectorAll('table.sortable');

  _.each(sortable_tables, function(table) {
    var url = table.getAttribute('data-sortable-link');
    var tbody = table.querySelector('tbody');
    var sortable = Sortable.create(tbody,{
      handle: ".handle",
      onEnd: function(e) {
        var positions = {};
        _.each(e.to.querySelectorAll('tr'), function(el, index) {
          var idAttr = el.id;
          if (idAttr) {
            var objId = idAttr.split('_').slice(-1);
            positions['positions['+objId+']'] = index + 1;
          }
        });
        Spree.ajax({
          type: 'POST',
          dataType: 'json',
          url: url,
          data: positions,
        });
      }
    });
  });
});

Use dataType: json for sortable tables


//= require jquery
//= require jquery_ujs
//= require twitter/bootstrap
//= require jquery-ui-bootstrap
//= require jquery.tokeninput
//= require_tree .

//= require jquery
//= require jquery_ujs
//= require jquery-ui-bootstrap
//= require twitter/bootstrap
//= require jquery.tokeninput
//= require_tree .

Load jquery before twitter bootstrap.


import SPECS from 'common/SPECS';

import CombatLogParser from './CombatLogParser';
import TALENT_DESCRIPTIONS from './TALENT_DESCRIPTIONS';

export default {
  spec: SPECS.VENGEANCE_DEMON_HUNTER,
  maintainer: '@mamtooth',
  parser: CombatLogParser,
  talentDescriptions: TALENT_DESCRIPTIONS,
};

import SPECS from 'common/SPECS';

import CombatLogParser from './CombatLogParser';
import TALENT_DESCRIPTIONS from './TALENT_DESCRIPTIONS';

export default {
  spec: SPECS.VENGEANCE_DEMON_HUNTER,
  maintainer: '@Mamtooth',
  parser: CombatLogParser,
  talentDescriptions: TALENT_DESCRIPTIONS,
};

Update contributor discord name (last time)


/**
 PSPDFKit

 Copyright (c) 2015-2016 PSPDFKit GmbH. All rights reserved.

 THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
 AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT.
 UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
 This notice may not be removed from this file.
 */
exports.defineAutoTests = function () {
    describe('PSPSDFKit (window.PSPDFKit)', function () {
        it("should exist", function () {
            expect(window.PSPDFKit).toBeDefined();
        });

        describe('showDocument', function() {
            it('should exist', function () {
                expect(window.PSPDFKit.showDocument).toBeDefined();
            });

        });

        describe('showDocumentFromAssets', function() {
            it('should exist', function () {
                expect(window.PSPDFKit.showDocumentFromAssets).toBeDefined();
            });

            it('should open a document from assets', function(done) {
                window.PSPDFKit.showDocumentFromAssets("www/Guide.pdf", function() {
                    done();
                }, function(error) {
                    done(error);
                });
            })
        });

    });
};

/**
 PSPDFKit

 Copyright (c) 2015-2016 PSPDFKit GmbH. All rights reserved.

 THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
 AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT.
 UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
 This notice may not be removed from this file.
 */
exports.defineAutoTests = function () {
    describe('PSPSDFKit (window.PSPDFKit)', function () {
        it("should exist", function () {
            expect(window.PSPDFKit).toBeDefined();
        });

        describe('showDocument', function() {
            it('should exist', function () {
                expect(window.PSPDFKit.showDocument).toBeDefined();
            });

        });

        describe('showDocumentFromAssets', function() {
            it('should exist', function () {
                expect(window.PSPDFKit.showDocumentFromAssets).toBeDefined();
            });
        });
    });
};

exports.defineManualTests = function(contentEl, createActionButton) {

    createActionButton('Open Document', function() {
        var asset = 'www/Guide.pdf';

        console.log('Opening document ' + asset);
        window.PSPDFKit.showDocumentFromAssets(asset, {}, function() {
            console.log("Document was successfully loaded.");
        }, function(error) {
            console.log('Error while loading the document:' + error)
        });
    });
};

Add manual document launch test


'use strict';

angular.module('mean.icu.ui.profile', [])
.controller('ProfileController', function($scope, $state, me, UsersService) {
    $scope.me = me;
    $scope.avatar = $scope.me.profile.avatar || 'http://placehold.it/250x250';
    $scope.hash = new Date().getTime();

    $scope.uploadAvatar = function(files) {
        if (files) {
            var file = files[0];
            UsersService.updateAvatar(file).success(function(data) {
                $scope.me.profile.avatar = data.avatar;

                $state.reload();
            });
        }
    };

    $scope.editProfile = function(form) {
        if ($scope.confirm !== $scope.me.password) {
            return;
        }

        UsersService.update($scope.me).then(function() {
            $state.reload();
        });
    };
});

'use strict';

angular.module('mean.icu.ui.profile', [])
.controller('ProfileController', function($scope, $state, me, UsersService) {
    $scope.me = me;

    if (!$scope.me.profile) {
        $scope.me.profile = {};
    }

    $scope.avatar = $scope.me.profile.avatar || 'http://placehold.it/250x250';
    $scope.hash = new Date().getTime();

    $scope.uploadAvatar = function(files) {
        if (files) {
            var file = files[0];
            UsersService.updateAvatar(file).success(function(data) {
                $scope.me.profile.avatar = data.avatar;

                $state.reload();
            });
        }
    };

    $scope.editProfile = function(form) {
        if ($scope.confirm !== $scope.me.password) {
            return;
        }

        UsersService.update($scope.me).then(function() {
            $state.reload();
        });
    };
});

Fix error when profile is not present


'use strict';

const express = require('express'),
      sassMiddleware = require('node-sass-middleware'),
      webpack = require('webpack'),
      webpackMiddleware = require('webpack-dev-middleware'),
      path = require('path'),
      app = express(),
      default_port = (process.env.PORT || 3000);

app.use(sassMiddleware({
    src: path.join(__dirname, 'sass'),
    dest: path.join(__dirname, 'dist'),
    debug: true,
    outputStyle: 'nested'
}));

app.use(webpackMiddleware(webpack(require('./webpack.config')), {
    noInfo: false,
    quiet: false,
    lazy: true,
    publicPath: "/",
    stats: {
        colors: true
    }
}));

app.use(express.static(path.join(__dirname, 'dist')));
app.use(require('connect-livereload')());  // runs livereload server and serves livereload.js
require('express-livereload')(app, { watchDir: path.join(__dirname) });  // inserts <script> reference to livereload.js
app.use('/', express.static(path.join(__dirname, 'views')));

let server = app.listen(default_port, function () {
  let port = server.address().port;
  console.log('Listening on port ' + port);
});

'use strict';

const express = require('express'),
      sassMiddleware = require('node-sass-middleware'),
      webpack = require('webpack'),
      webpackMiddleware = require('webpack-dev-middleware'),
      path = require('path'),
      app = express(),
      default_port = (process.env.PORT || 3000);

app.use(sassMiddleware({
    src: path.join(__dirname, 'sass'),
    dest: path.join(__dirname, 'dist'),
    debug: true,
    outputStyle: 'nested',
    sourceMap: path.join(__dirname, 'dist', 'bundle.css.map')
}));

app.use(webpackMiddleware(webpack(require('./webpack.config')), {
    noInfo: false,
    quiet: false,
    lazy: true,
    publicPath: "/",
    stats: {
        colors: true
    }
}));

app.use(express.static(path.join(__dirname, 'dist')));
app.use(require('connect-livereload')());  // runs livereload server and serves livereload.js
require('express-livereload')(app, { watchDir: path.join(__dirname) });  // inserts <script> reference to livereload.js
app.use('/', express.static(path.join(__dirname, 'views')));

let server = app.listen(default_port, function () {
  let port = server.address().port;
  console.log('Listening on port ' + port);
});

Add sourceMap in node-sass-middleware for dev


var http = require('http');
var express = require('express');

var app = express();
app.set('view engine', 'ejs');

// Setup the index page view
app.get('/', function(req, res) {
	res.render('pages/index');
});

app.listen(8080);
/*
 * Returns a fomatted date as a String in brackets, for logging purposes
 */
function getFormattedDate() {
    return "[" + new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '') + "] ";
}

/*
 * Overloads the logging function
 */
console.log = console.error = function(message) {
    log_file.write(util.format(message) + '\n');
    log_stdout.write(util.format(message) + '\n');
};

var http = require('http');
var express = require('express');

var app = express();
app.set('view engine', 'ejs');

// Setup the index page view
app.get('/', function(req, res) {
	res.render('pages/index');
    // Defines error handling
    app.use(function(req, res, next) {
        res.status(404);

        // Respond with HTML page
        if (req.accepts('html')) {
            res.render('404', {
                url: req.url
            });
            return;
        }

        // Respond with JSON
        if (req.accepts('json')) {
            res.send({
                error: 'Not found'
            });
            return;
        }

        // Default to plain-text
        res.type('txt').send('Not found');
    });

    // Bind the server process on the port
    var server = app.listen(port, function() {
        console.log("Server successfully started!");
    });
});

/*
 * Returns a fomatted date as a String in brackets, for logging purposes
 */
function getFormattedDate() {
    return "[" + new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '') + "] ";
}

/*
 * Overloads the logging function
 */
console.log = console.error = function(message) {
    log_file.write(util.format(message) + '\n');
    log_stdout.write(util.format(message) + '\n');
};

Define 404 error handling functions


var express = require('express'),
  OpenedCaptions = require('opened-captions');

// Make the server
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);

// Serve static content from "public" directory
app.use(express.static(__dirname + '/public'));

server.listen(8080);

var oc = new OpenedCaptions({
  io: io
});

oc.addStream('server', {
  host: 'https://openedcaptions.com',
  port: 443,
  description: "CSPAN"
});

var express = require('express'),
  OpenedCaptions = require('opened-captions');

// Make the server
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);

// Serve static content from "public" directory
app.use(express.static(__dirname + '/public'));

server.listen(8080);

var oc = new OpenedCaptions({
  io: io
});

oc.addStream('server', {
  host: 'http://openedcaptions.media.mit.edu',
  port: 8080,
  description: "C-SPAN"
});

Use HTTP stream rather than HTTPS


import angular from 'angular';
import uiRouter from 'angular-ui-router';

import view from './view';

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

export default angular.module('xoWebApp.login', [
  uiRouter,
])
  .config(function ($stateProvider) {
    $stateProvider.state('login', {
      url: '/login',
      controller: 'LoginCtrl',
      template: view,
    });
  })
  .controller('LoginCtrl', function($scope, $state, $rootScope, xoApi) {
    var toState, toStateParams;
    {
      let state = $rootScope._login;
      if (state && (state = state.state)) {
        toState = state.name;
        toStateParams = state.stateParams;
        delete $rootScope._login;
      } else {
        toState = 'index';
      }
    }

    $scope.$watch(() => xoApi.user, function (user) {
      // When the user is logged in, go the wanted view, fallbacks on
      // the index view if necessary.
      if (user) {
        $state.go(toState, toStateParams).catch(function () {
          $state.go('index');
        });
      }
    });

    Object.defineProperties($scope, {
      user: {
        get() {
          return xoApi.user;
        },
      },
      status: {
        get() {
          return xoApi.status;
        }
      },
    });
    $scope.logIn = xoApi.logIn;
  })

  // A module exports its name.
  .name
;

import angular from 'angular';
import uiRouter from 'angular-ui-router';

import view from './view';

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

export default angular.module('xoWebApp.login', [
  uiRouter,
])
  .config(function ($stateProvider) {
    $stateProvider.state('login', {
      url: '/login',
      controller: 'LoginCtrl',
      template: view,
    });
  })
  .controller('LoginCtrl', function($scope, $state, $rootScope, xoApi) {
    var toState, toStateParams;
    {
      let tmp = $rootScope._login;
      if (tmp) {
        toState = tmp.state.name;
        toStateParams = tmp.stateParams;
        delete $rootScope._login;
      } else {
        toState = 'index';
      }
    }

    $scope.$watch(() => xoApi.user, function (user) {
      // When the user is logged in, go the wanted view, fallbacks on
      // the index view if necessary.
      if (user) {
        $state.go(toState, toStateParams).catch(function () {
          $state.go('index');
        });
      }
    });

    Object.defineProperties($scope, {
      user: {
        get() {
          return xoApi.user;
        },
      },
      status: {
        get() {
          return xoApi.status;
        }
      },
    });
    $scope.logIn = xoApi.logIn;
  })

  // A module exports its name.
  .name
;

Fix incorrect redirection after log in.


var Rooms = {
    anonymous_room: false,

    refresh: function() {
        var items = document.querySelectorAll('#rooms_widget ul li:not(.subheader)');
        var i = 0;
        while(i < items.length)
        {
            if(items[i].dataset.jid != null) {
                items[i].onclick = function(e) {
                    Chats.refresh();

                    Chat_ajaxGetRoom(this.dataset.jid);
                    MovimUtils.removeClassInList('active', items);
                    MovimUtils.addClass(this, 'active');
                }
            }

            MovimUtils.removeClass(items[i], 'active');

            i++;
        }
    },

    /**
     * @brief Connect to an anonymous server
     * @param The jid to remember
     */
    anonymousInit : function() {
        MovimWebsocket.register(function()
        {
            form = document.querySelector('form[name="loginanonymous"]');
            form.onsubmit = function(e) {
                e.preventDefault();
                // We login
                LoginAnonymous_ajaxLogin(this.querySelector('input#nick').value);
            }
        });
    },

    /**
     * @brief Join an anonymous room
     * @param The jid to remember
     */
    anonymousJoin : function() {
        // We display the room
        Chat_ajaxGetRoom(Rooms.anonymous_room);
        // And finally we join
        Rooms_ajaxExit(Rooms.anonymous_room);
        Rooms_ajaxJoin(Rooms.anonymous_room);
    }
}

MovimWebsocket.attach(function() {
    Rooms.refresh();
    Rooms.anonymousInit();
    Rooms_ajaxDisplay();
});

var Rooms = {
    anonymous_room: false,

    refresh: function() {
        var items = document.querySelectorAll('#rooms_widget ul li:not(.subheader)');
        var i = 0;
        while(i < items.length)
        {
            if(items[i].dataset.jid != null) {
                items[i].onclick = function(e) {
                    Chats.refresh();

                    Chat_ajaxGetRoom(this.dataset.jid);
                    MovimUtils.removeClassInList('active', items);
                    MovimUtils.addClass(this, 'active');
                }
            }

            MovimUtils.removeClass(items[i], 'active');

            i++;
        }

        Notification_ajaxGet();
    },

    /**
     * @brief Connect to an anonymous server
     * @param The jid to remember
     */
    anonymousInit : function() {
        MovimWebsocket.register(function()
        {
            form = document.querySelector('form[name="loginanonymous"]');
            form.onsubmit = function(e) {
                e.preventDefault();
                // We login
                LoginAnonymous_ajaxLogin(this.querySelector('input#nick').value);
            }
        });
    },

    /**
     * @brief Join an anonymous room
     * @param The jid to remember
     */
    anonymousJoin : function() {
        // We display the room
        Chat_ajaxGetRoom(Rooms.anonymous_room);
        // And finally we join
        Rooms_ajaxExit(Rooms.anonymous_room);
        Rooms_ajaxJoin(Rooms.anonymous_room);
    }
}

MovimWebsocket.attach(function() {
    Rooms.anonymousInit();
    Rooms_ajaxDisplay();
});

Fix missing notifications in Rooms


module.exports = {
  test_page: 'tests/index.html?hidepassed',
  disable_watching: true,
  launch_in_ci: [
    'Chrome'
  ],
  launch_in_dev: [
    'Chrome'
  ],
  browser_args: {
    Chrome: {
      ci: [
        // --no-sandbox is needed when running Chrome inside a container
        process.env.CI ? '--no-sandbox' : null,
        '--headless',
        '--disable-gpu',
        '--disable-dev-shm-usage',
        '--disable-software-rasterizer',
        '--mute-audio',
        '--remote-debugging-port=0',
        '--window-size=1440,900'
      ].filter(Boolean)
    }
  }
};

module.exports = {
  test_page: 'tests/index.html?hidepassed',
  disable_watching: true,
  launch_in_ci: [
    'Chrome'
  ],
  launch_in_dev: [
    'Chrome'
  ],
  browser_args: {
    Chrome: {
      ci: [
        // --no-sandbox is needed when running Chrome inside a container
        process.env.CI ? '--no-sandbox' : null,
        '--headless',
        '--disable-dev-shm-usage',
        '--disable-software-rasterizer',
        '--mute-audio',
        '--remote-debugging-port=0',
        '--window-size=1440,900'
      ].filter(Boolean)
    }
  }
};

Remove --disable-gpu flag when starting headless chrome


/* eslint-disable */

module.exports = {
  "framework": "qunit",
  "test_page": "tests/index.html?hidepassed",
  "disable_watching": true,
  "launch_in_ci": [
    "Chrome"
  ],
  "launch_in_dev": [
    "Chrome"
  ]
};

/* eslint-disable */

module.exports = {
  "framework": "qunit",
  "test_page": "tests/index.html?hidepassed&nocontainer",
  "disable_watching": true,
  "launch_in_ci": [
    "Chrome"
  ],
  "launch_in_dev": [
    "Chrome"
  ]
};

Hide container by default when running tests


var TaskTableHeaderLabels = {
  cpus: 'CPU',
  disk: 'DISK',
  host: 'HOST',
  mem: 'MEM',
  id: 'TASK NAME',
  name: 'TASK NAME',
  status: 'STATUS',
  updated: 'UPDATED',
  version: 'VERSION'
};

module.exports = TaskTableHeaderLabels;

var TaskTableHeaderLabels = {
  cpus: 'CPU',
  disk: 'DISK',
  host: 'HOST',
  mem: 'MEM',
  id: 'TASK ID',
  name: 'TASK NAME',
  status: 'STATUS',
  updated: 'UPDATED',
  version: 'VERSION'
};

module.exports = TaskTableHeaderLabels;

Correct heading for task table ID column


// We load the Safari fix before document-register-element because DRE
// overrides attachShadow() and calls back the one it finds on HTMLElement.
import './fix/safari';
import 'document-register-element';
import '@webcomponents/shadydom';
import '@webcomponents/shadycss';

// We load the Safari fix before document-register-element because DRE
// overrides attachShadow() and calls back the one it finds on HTMLElement.
import './fix/safari';
import 'document-register-element';
import '@webcomponents/shadycss';
import '@webcomponents/shadydom';

Revert "fix: You have to include shadydom before shadycss else shadycss will not work."


import {inspect} from "util";
import {getProperties, isImmutable, isNumeric} from "./helpers";

// LENS ============================================================================================
function createGetter(key) {
  return function getter(data) {
    if (key) {
      if (isImmutable(data)) {
        throw new Error(`can't get key ${inspect(key)} from immutable data ${inspect(data)}`);
      } else {
        if (data.meta.kind == "dict") {
          return data.meta.codomain;
        } else if (data.meta.kind == "struct") {
          return data.meta.props[key];
        } else if (data.meta.kind == "list") {
          return data.meta.type;
        } else {
          // TODO possible situation?!
          return data[key];
        }
      }
    } else {
      return data;
    }
  };
}

function createLens(getter) {
  return {
    get: getter,

    compose(nextLens) {
      return createLens(
        (data) => nextLens.get(getter(data))
      );
    }
  };
}

export default function Lens(key) {
  if (typeof key != "string") {
    throw new Error(`key must be of string type, got ${typeof key}`);
  }
  let lens = key.split(".").map(k => createLens(createGetter(k)));
  return lens.reduce((lens, nextLens) => lens.compose(nextLens));
}

import {inspect} from "util";
import {getProperties, isImmutable, isNumeric} from "./helpers";

// LENS ============================================================================================
function createGetter(key) {
  return function getter(data) {
    if (key) {
      if (isImmutable(data)) {
        throw new Error(`can't get key ${inspect(key)} from immutable data ${inspect(data)}`);
      } else {
        if (data.meta && data.meta.kind == "dict") {
          return data.meta.codomain;
        } else if (data.meta && data.meta.kind == "struct") {
          return data.meta.props[key];
        } else if (data.meta && data.meta.kind == "list") {
          return data.meta.type;
        } else {
          return data[key];
        }
      }
    } else {
      return data;
    }
  };
}

function createLens(getter) {
  return {
    get: getter,

    compose(nextLens) {
      return createLens(
        (data) => nextLens.get(getter(data))
      );
    }
  };
}

export default function Lens(key) {
  if (typeof key != "string") {
    throw new Error(`key must be of string type, got ${typeof key}`);
  }
  let lens = key.split(".").map(k => createLens(createGetter(k)));
  return lens.reduce((lens, nextLens) => lens.compose(nextLens));
}

Support native objects in getter


import chain from './chain';
import {clone} from './utils';

function vq(el, props, opts = null) {
  if (!el || !props) throw new Error('Must have two or three args');

  if (!opts) {
    if (!('p' in props && 'o' in props)) {
      throw new Error('2nd arg must have `p` and `o` property when only two args is given');
    }

    opts = props.o;
    props = props.p;
  }

  // use `props` as progress callback if it is a function
  if (typeof props === 'function') {
    opts.progress = props;
    props = {
      tween: [1, 0]
    };
  }

  // Avoid changing original props and opts
  // vq may mutate these values internally
  props = clone(props);
  opts = clone(opts);

  return chain(el, props, opts);
}

vq.sequence = function sequence(seq) {
  const head = seq[0];
  const tail = seq.slice(1);

  if (typeof head !== 'function') return;

  if (head.length > 0) {
    // Ensure there is a callback function as 1st argument
    return head(function() {
      sequence(tail);
    });
  }

  const res = head();

  // Wait until the head function is terminated if the returned value is thenable
  if (res && typeof res.then === 'function') {
    return res.then(() => sequence(tail));
  }

  return sequence(tail);
};

module.exports = vq;

import chain from './chain';
import {clone} from './utils';

function vq(el, props, opts = null) {
  if (!el || !props) throw new Error('Must have two or three args');

  if (!opts) {
    if (!('p' in props && 'o' in props)) {
      throw new Error('2nd arg must have `p` and `o` property when only two args is given');
    }

    opts = props.o;
    props = props.p;
  }

  // use `props` as progress callback if it is a function
  if (typeof props === 'function') {
    opts.progress = props;
    props = {
      tween: [1, 0]
    };
  }

  // Avoid changing original props and opts
  // vq may mutate these values internally
  props = clone(props);
  opts = clone(opts);

  return chain(el, props, opts);
}

vq.sequence = function sequence(seq) {
  if (seq.length === 0) return;

  const head = unify(seq[0]);
  const tail = seq.slice(1);

  return head(() => sequence(tail));
};

function unify(fn) {
  return function(done) {
    if (typeof fn !== 'function') return done();

    if (fn.length > 0) {
      // Ensure there is a callback function as 1st argument
      return fn(done);
    }

    const res = fn();

    // Wait until the function is terminated if the returned value is thenable
    if (res && typeof res.then === 'function') {
      return res.then(done);
    }

    return done();
  };
}

module.exports = vq;

Split the function for call and wait processes


import React from 'react';
import ReactDOM from 'react-dom';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';

import Main from './components/Main';
import reducer from './reducers';
import { SHOW_DEVTOOLS } from './constants';

const middlewares = [
  applyMiddleware(thunk),
];

if (SHOW_DEVTOOLS) {
  middlewares.push(window.devToolsExtension ? window.devToolsExtension() : f => f);
}

const composedCreateStore = compose.apply(this, middlewares)(createStore);
const store = composedCreateStore(reducer);

ReactDOM.render(
  <Provider store={ store }>
    <Main />
  </Provider>,
  document.getElementById('main')
);

import React from 'react';
import ReactDOM from 'react-dom';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';

import reducer from './reducers';
import { SHOW_DEVTOOLS } from './constants';

const middlewares = [
  applyMiddleware(thunk),
];

if (SHOW_DEVTOOLS) {
  middlewares.push(window.devToolsExtension ? window.devToolsExtension() : f => f);
}

const composedCreateStore = compose.apply(this, middlewares)(createStore);
const store = composedCreateStore(reducer);
const rootEl = document.getElementById('main');
const render = () => {
  // See here for explanation of why this require() is needed:
  // https://github.com/reactjs/redux/pull/1455/files#r54380102
  const Main = require('./components/Main').default; // eslint-disable-line global-require

  ReactDOM.render(
    <Provider store={ store }>
      <Main />
    </Provider>,
    rootEl
  );
};

if (module.hot) {
  module.hot.accept('./components/Main', () => {
    render();
  });
}

render();

Fix HMR with some help from my good friend Dan


import React, { PropTypes } from 'react';
import ProjectedLayer from './projected-layer';
import {
  anchors,
  OverlayPropTypes,
} from './util/overlays';

const defaultClassName = ['mapboxgl-popup'];

export default class Popup extends React.Component {
  static propTypes = {
    coordinates: PropTypes.arrayOf(PropTypes.number).isRequired,
    anchor: OverlayPropTypes.anchor,
    offset: OverlayPropTypes.offset,
    children: PropTypes.node,
    onClick: PropTypes.func,
    style: PropTypes.object,
  };

  static defaultProps = {
    anchor: anchors[0]
  };

  render() {
    const { coordinates, anchor, offset, onClick, children, style } = this.props;

    if (anchor) {
      defaultClassName.push(`mapboxgl-popup-anchor-${anchor}`);
    }

    return (
      <ProjectedLayer
        style={style}
        onClick={onClick}
        offset={offset}
        anchor={anchor}
        coordinates={coordinates}
        className={defaultClassName.join(' ')}>

          { children }

      </ProjectedLayer>
    );
  }
}

import React, { PropTypes } from 'react';
import ProjectedLayer from './projected-layer';
import {
  anchors,
  OverlayPropTypes,
} from './util/overlays';

export default class Popup extends React.Component {
  static propTypes = {
    coordinates: PropTypes.arrayOf(PropTypes.number).isRequired,
    anchor: OverlayPropTypes.anchor,
    offset: OverlayPropTypes.offset,
    children: PropTypes.node,
    onClick: PropTypes.func,
    style: PropTypes.object,
  };

  static defaultProps = {
    anchor: anchors[0]
  };

  render() {
    const { coordinates, anchor, offset, onClick, children, style } = this.props;

    return (
      <ProjectedLayer
        style={style}
        onClick={onClick}
        offset={offset}
        anchor={anchor}
        coordinates={coordinates}
        className={`mapboxgl-popup mapboxgl-popup-anchor-${anchor}`}>

          { children }

      </ProjectedLayer>
    );
  }
}

Fix mutable className array in Popup


import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import { browserHistory } from 'react-router'
import { syncHistory } from 'react-router-redux'
import { combineReducers, compose, createStore, applyMiddleware } from 'redux'
import { autoRehydrate } from 'redux-persist'
import { analytics, authentication, requester, uploader } from './middleware'
import * as reducers from './reducers'

const reducer = combineReducers(reducers)
const reduxRouterMiddleware = browserHistory ? syncHistory(browserHistory) : null

let store = null
if (typeof window !== 'undefined') {
  const logger = createLogger({ collapsed: true, predicate: () => ENV.APP_DEBUG })
  store = compose(
    autoRehydrate(),
    applyMiddleware(
      thunk,
      reduxRouterMiddleware,
      uploader,
      requester,
      authentication,
      analytics,
      logger
    ),
  )(createStore)(reducer, window.__INITIAL_STATE__ || {})
} else {
  store = compose(
    applyMiddleware(thunk, uploader, requester, analytics),
  )(createStore)(reducer, {})
}

export default store

import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import { browserHistory } from 'react-router'
import { syncHistory } from 'react-router-redux'
import { combineReducers, compose, createStore, applyMiddleware } from 'redux'
import { autoRehydrate } from 'redux-persist'
import { analytics, authentication, requester, uploader } from './middleware'
import * as reducers from './reducers'

const reducer = combineReducers(reducers)
const reduxRouterMiddleware = browserHistory ? syncHistory(browserHistory) : null

let store = null
if (typeof window !== 'undefined') {
  const logger = createLogger({ collapsed: true, predicate: () => ENV.APP_DEBUG })
  store = compose(
    autoRehydrate(),
    applyMiddleware(
      thunk,
      authentication,
      reduxRouterMiddleware,
      uploader,
      requester,
      analytics,
      logger
    ),
  )(createStore)(reducer, window.__INITIAL_STATE__ || {})
} else {
  store = compose(
    applyMiddleware(thunk, uploader, requester, analytics),
  )(createStore)(reducer, {})
}

export default store

Move authentication higher up the food chain


var gulp = require('gulp');
var gulpB = require('../');
var expect = require('chai').expect;
var es = require('event-stream');
var path = require('path');
var browserify = require('browserify');

describe('gulp-browserify', function() {
	var testFile = path.join(__dirname, './test.js');
	var fileContents;

	beforeEach(function(done) {
		gulp.src(testFile)
			.pipe(gulpB())
			.pipe(es.map(function(file){
				fileContents = file.contents;
				done();
			}))
	})

	it('should return a buffer', function(done) {
		expect(fileContents).to.be.an.instanceof(Buffer);
		done();
	})

	it('should bundle modules', function(done) {
		var b = browserify();
		var chunk = '';
		b.add(testFile)
		b.bundle().on('data', function(data) {
			chunk += data;
		}).on('end', function() {
			expect(fileContents.toString()).to.equal(chunk);
			done();
		})
	})
})

var gulp = require('gulp');
var gulpB = require('../');
var expect = require('chai').expect;
var es = require('event-stream');
var path = require('path');
var browserify = require('browserify');

describe('gulp-browserify', function() {
	var testFile = path.join(__dirname, './test.js');
	var fileContents;

	beforeEach(function(done) {
		gulp.src(testFile)
			.pipe(gulpB())
			.pipe(es.map(function(file){
				fileContents = file.contents;
				done();
			}))
	})

	it('should return a buffer', function(done) {
		expect(fileContents).to.be.an.instanceof(Buffer);
		done();
	})

	it('should bundle modules', function(done) {
		var b = browserify();
		var chunk = '';
		b.add(testFile)
		b.bundle().on('data', function(data) {
			chunk += data;
		}).on('end', function() {
			expect(fileContents.toString()).to.equal(chunk);
			done();
		})
	})
	it('should use the gulp version of the file', function(done) {
		gulp.src(testFile)
			.pipe(es.map(function(file, cb) {
				file.contents = new Buffer('var abc=123;');
				cb(null, file);
			}))
			.pipe(gulpB())
			.pipe(es.map(function(file) {
				expect(file.contents.toString()).to.not.equal(fileContents.toString());
				expect(file.contents.toString()).to.match(/var abc=123;/);
				done();
			}))
	})
})

Add test to verify usage of gulp version of file


/* eslint-disable no-console, no-duplicate-imports, import/no-duplicates */
import proxyquire from 'proxyquire';
import describe from '../src';
import { specStream } from '../src';

describe('RxT', (it) => {
    it('should run a simple passing and failing given/when/then test', test => test
        .given('givenWhenThen')
        .whenObserving((testFile) => {
            const spec = proxyquire(`./samples/${testFile}`, {
                '../../src': {
                    default: specStream,
                },
            });
            return spec;
        })
        .then(
            (result) => {
                const expected = [
                    ['should capitalize just hello'],
                    [
                        'should capitalize just hello',
                        'should fail to assert the proper hello',
                    ],
                ];
                result.results.should.have.keys(...expected[result.step]);
            },
        )
    );
});

/* eslint-disable no-console, no-duplicate-imports, import/no-duplicates */
import _ from 'lodash';
import proxyquire from 'proxyquire';
import describe from '../src';
import { specStream } from '../src';

describe('RxT', (it) => {
    it('should run a simple passing and failing given/when/then test', test => test
        .given('givenWhenThen')
        .whenObserving((testFile) => {
            const spec = proxyquire(`./samples/${testFile}`, {
                '../../src': {
                    default: specStream,
                },
            });
            return spec;
        })
        .then(
            (result) => {
                const expected = [
                    {
                        'should capitalize just hello': 'pass',
                    },
                    {
                        'should capitalize just hello': 'pass',
                        'should fail to assert the proper hello': 'fail',
                    },
                ];
                result.results.should.have.keys(..._.keys(expected[result.step]));
                _.forIn(expected[result.step], (val, key) => {
                    result.results[key].result.should.equal(val);
                });
            },
        )
    );
});

Test the actual test result.


"use strict";

// Provides the global arethusaUtil object which comes with several
// utility functions

window.arethusaUtil = {
  // Pads a number with zeros
  formatNumber: function(number, length) {
    // coerce a fixnum to a string
    var n = "" + number;
    while (n.length < length) { n = "0" + n; }
    return n;
  }
};

"use strict";

// Provides the global arethusaUtil object which comes with several
// utility functions

var arethusaUtil = {
  // Pads a number with zeros
  formatNumber: function(number, length) {
    // coerce a fixnum to a string
    var n = "" + number;
    while (n.length < length) { n = "0" + n; }
    return n;
  },

  /* global X2JS */
  xmlParser: new X2JS(),

  xml2json: function(xml) {
    return arethusaUtil.xmlParser.xml2json(xml);
  }
};

Add some xml functions to arethusaUtil


import Ember from 'ember';

export default Ember.Route.extend({

	renderTemplate() {
		this.render( 'admin', {
			controller: 'dashboard'
		});
	}

});

import Ember from 'ember';

export default Ember.Route.extend({

	activate() {
		$( 'body' ).removeClass( 'login' )
	},

	renderTemplate() {
		this.render( 'admin', {
			controller: 'dashboard'
		});
	}

});

Remove "login" class after transition


// web.js
var express = require("express");
var logfmt = require("logfmt");
var app = express();

app.use(logfmt.requestLogger());

app.get('/', function(req, res) {
  res.send('Hello World!');
});

var port = Number(process.env.PORT || 8000);
app.listen(port, function() {
  console.log("Listening on " + port);
});

// web.js
var express = require("express");
var logfmt = require("logfmt");
var app = express();

app.use(logfmt.requestLogger());

app.get('*', function(req, res) {
  res.sendfile('./app/index.html'); // load our app/index.html file
});

var port = Number(process.env.PORT || 8000);
app.listen(port, function() {
  console.log("Listening on " + port);
});

Make index page appear on heroku


const updateStructure = newState => {
  return { type: 'UPDATE_VERT_STRUCTURE', newState };
};

const highlightNode = (delay, unHighlight, nodeId) => {
  setTimeout(() => unHighlight(nodeId), delay / 1.1);
  return { type: 'HIGHLIGHT_NODE', nodeId };
};

const unHighlightNode = nodeId => {
  return { type: 'UNHIGHLIGHT_NODE', nodeId };
};

export default {
  updateStructure,
  highlightNode,
  unHighlightNode
};

const updateStructure = newState => ({ type: 'UPDATE_VERT_STRUCTURE', newState });

const highlightNode = nodeId => (dispatch, getState) => {
  setTimeout(() => dispatch(unHighlightNode(nodeId)), getState().async.delay / 1.1);
  dispatch({ type: 'HIGHLIGHT_NODE', nodeId });
};

const unHighlightNode = nodeId => ({ type: 'UNHIGHLIGHT_NODE', nodeId });

export default {
  updateStructure,
  highlightNode,
  unHighlightNode
};

Use thunk to access delay state


import Ember from 'ember';
import layout from '../templates/components/karbon-sortable-item';

export default Ember.Component.extend({
  tagName: 'li',
  classNames: ['spacer'],
  classNameBindings: ['handleClass', 'isSection:section', 'isNested:nested'],
  attributeBindings: ['draggable', 'pkid:data-pkid'],
  handleClass: 'droppable',
  draggable: 'true',
  isSection: Ember.computed.alias('data.isSection'),
  isNested: Ember.computed.alias('data.isChild'),
  pkid: Ember.computed.alias('data.id'),
  layout,

  didInsertElement() {
    // We don't need to pass any data (yet), but FF won't drag unless this is set
    this.$().attr('ondragstart', "event.dataTransfer.setData('text/plain', 'text')");
  },

  click() {
    const data = this.get('data');

    if (data.get('isSection')) {
      this.get('toggleSection')(data);
      return false;
    }
  }
});

import Ember from 'ember';
import layout from '../templates/components/karbon-sortable-item';

export default Ember.Component.extend({
  tagName: 'li',
  classNames: ['spacer'],
  classNameBindings: ['handleClass', 'isSection:section', 'isNested:nested'],
  attributeBindings: ['draggable', 'pkid:data-pkid'],
  handleClass: 'droppable',
  // temporary
  draggable: Ember.computed.not('data.isSection'),
  isSection: Ember.computed.alias('data.isSection'),
  isNested: Ember.computed.alias('data.isChild'),
  pkid: Ember.computed.alias('data.id'),
  layout,

  didInsertElement() {
    // We don't need to pass any data (yet), but FF won't drag unless this is set
    this.$().attr('ondragstart', "event.dataTransfer.setData('text/plain', 'text')");
  },

/*
  click() {
    const data = this.get('data');

    if (data.get('isSection')) {
      this.get('toggleSection')(data);
      return false;
    }
  }
  */
});

Disable dragging sections for now.