/**
 * Common utilities
 * @module glMatrix
 */

// Configuration Constants
export const EPSILON = 0.000001;
export let ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
export const RANDOM = Math.random;

/**
 * Sets the type of array used when creating new vectors and matrices
 *
 * @param {Type} type Array type, such as Float32Array or Array
 */
export function setMatrixArrayType(type) {
  ARRAY_TYPE = type;
}

const degree = Math.PI / 180;

/**
 * Convert Degree To Radian
 *
 * @param {Number} a Angle in Degrees
 */
export function toRadian(a) {
  return a * degree;
}

/**
 * Tests whether or not the arguments have approximately the same value, within an absolute
 * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less
 * than or equal to 1.0, and a relative tolerance is used for larger values)
 *
 * @param {Number} a The first number to test.
 * @param {Number} b The second number to test.
 * @returns {Boolean} True if the numbers are approximately equal, false otherwise.
 */
export function equals(a, b) {
  return Math.abs(a - b) <= EPSILON*Math.max(1.0, Math.abs(a), Math.abs(b));
}

/**
 * Common utilities
 * @module glMatrix
 */

// Configuration Constants
export const EPSILON = 0.000001;
export let ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
export const RANDOM = Math.random;

/**
 * Sets the type of array used when creating new vectors and matrices
 *
 * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array
 */
export function setMatrixArrayType(type) {
  ARRAY_TYPE = type;
}

const degree = Math.PI / 180;

/**
 * Convert Degree To Radian
 *
 * @param {Number} a Angle in Degrees
 */
export function toRadian(a) {
  return a * degree;
}

/**
 * Tests whether or not the arguments have approximately the same value, within an absolute
 * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less
 * than or equal to 1.0, and a relative tolerance is used for larger values)
 *
 * @param {Number} a The first number to test.
 * @param {Number} b The second number to test.
 * @returns {Boolean} True if the numbers are approximately equal, false otherwise.
 */
export function equals(a, b) {
  return Math.abs(a - b) <= EPSILON*Math.max(1.0, Math.abs(a), Math.abs(b));
}

Set correct type for setMatrixArrayType


var _ = require('underscore');

var deepSet = function (obj, pathString, value) {
  var path = pathString.split('.');
  var len = path.length;
  for (var i = 0; i < len; i++) {
    if (i == len - 1) {
      obj[path[i]] = value;
    } else {
      if (!_.has(obj, path[i])) {
        obj[path[i]] = {};
      }
      obj = obj[path[i]];
    }
  }
};

var deepUnset = function (obj, pathString) {
  var path = pathString.split('.');
  var len = path.length;
  for (var i = 0; i < len; i++) {
    if (i == len - 1) {
      delete obj[path[i]];
    } else {
      if (!_.has(obj, path[i])) {
        break;
      }
      obj = obj[path[i]];
    }
  }
};

var DataManager = function (joist) {
  this.data = {};
};

DataManager.prototype.patch = function (set, unset) {
  var that = this;
  _.each(set, function (value, key) {
    deepSet(that.data, key, value);
  });

  _.each(unset, function (key) {
    deepUnset(that.data, key);
  });

  return this.data;
};

DataManager.prototype.getData = function () {
  return JSON.parse(JSON.stringify(this.data));
};

module.exports = DataManager;

var _ = require('underscore');

var deepSet = function (obj, pathString, value) {
  var path = pathString.split('.');
  var len = path.length;
  for (var i = 0; i < len; i++) {
    if (i == len - 1) {
      obj[path[i]] = value;
    } else {
      if (!_.has(obj, path[i])) {
        obj[path[i]] = {};
      }
      obj = obj[path[i]];
    }
  }
};

var deepUnset = function (obj, pathString) {
  var path = pathString.split('.');
  var len = path.length;
  for (var i = 0; i < len; i++) {
    if (i == len - 1) {
      delete obj[path[i]];
    } else {
      if (!_.has(obj, path[i])) {
        break;
      }
      obj = obj[path[i]];
    }
  }
};

var DataManager = function (joist) {
  this._private_data = {};
};

DataManager.prototype.patch = function (set, unset) {
  var that = this;
  _.each(set, function (value, key) {
    deepSet(that._private_data, key, value);
  });

  _.each(unset, function (key) {
    deepUnset(that._private_data, key);
  });

  return this.getData();
};

DataManager.prototype.getData = function () {
  return JSON.parse(JSON.stringify(this._private_data));
};

module.exports = DataManager;

Make it clear that you should never access this._private_data directly.


import React, {PropTypes} from 'react';
import Paper from 'material-ui/lib/paper';

export default class ResumeHeader extends React.Component {
  static propTypes = {
    body: PropTypes.string
  }

  static contextTypes = {
    store: React.PropTypes.object
  }

  render() {
    const userInput = this.context.store.getState().userFormReducer;

    const styles = {
      name: {
        fontWeight: '700',
        fontSize: '28px',
        textAlign: 'center',
        marginLeft: '10px'
      },
      email: {
        color: 'blue',
        fontSize: '16px',
        marginLeft: '10px'

      },
      phone: {
        fontSize: '16px',
        marginLeft: '10px'
      },
      city: {
        marginLeft: '10px'
      },
      url: {
        textAlign: 'right',
        marginRight: '10px'
      }
    };

    return (

        <Paper zDepth={1}>

            {userInput.name}

            {userInput.email}

            {userInput.phone}

            {userInput.city}, {userInput.state}

            {userInput.linkedinUrl}

            {userInput.githubUrl}

        </Paper>

    );
  }
}

import React, {PropTypes} from 'react';
import Paper from 'material-ui/lib/paper';

export default class ResumeHeader extends React.Component {
  static propTypes = {
    body: PropTypes.string
  }

  static contextTypes = {
    store: React.PropTypes.object
  }

  render() {
    const userInput = this.context.store.getState().userFormReducer;

    const styles = {
      name: {
        fontWeight: '700',
        fontSize: '28px',
        textAlign: 'center',
        marginLeft: '10px'
      },
      email: {
        color: 'blue',
        fontSize: '16px',
        marginLeft: '10px'

      },
      phone: {
        fontSize: '16px',
        marginLeft: '10px'
      },
      city: {
        marginLeft: '10px'
      },
      url: {
        textAlign: 'right',
        marginRight: '10px'
      }
    };

    return (

        <Paper zDepth={1}>

            Your Name Here

            email@website.com

            123-456-7890

            San Francisco, CA

            linkedin.com/michaeljordan

            github.com/number23

        </Paper>

    );
  }
}

Add placeholder text to resumer header


// Sieve of Eratosthenes

/*RULES:
  Function takes one parameter
  Return an array of all prime numbers from 0-parameter
*/

/*PSEUDOCODE:
  1) Find square root of parameter
  2) Create an array of numbers from 0-parameter
  3) Loop through numbers, but stop until square root (if a float, stop after number rounded up?)
  4) Return array
*/

function sieveOfEratosthenes(n){
  var squareRoot = Math.sqrt(n);
  var primes = [];

  for (var i = 0; i <= n; i++){
    primes[i] = true;
  }

  primes[0] = false;
  primes[1] = false;

  for (var i = 2; i <= squareRoot; i++){
    for (var j = 2; j * i <= n; j++){
      primes[i * j] = false;
    }
  }

  var result = []
  for (var i = 0; i < primes.length; i++){
    if (primes[i]){
      result.push(i)
    }
  }

  return result;

}

// Sieve of Eratosthenes

/*RULES:
  Function takes one parameter
  Return an array of all prime numbers from 0-parameter
*/

/*PSEUDOCODE:
  1) Find square root of parameter
  2) Create an array of numbers from 0-parameter
  3) Loop through numbers, but stop until square root (if a float, stop after number rounded up?)
  4) Return array
*/

function sieveOfEratosthenes(n){
  var squareRoot = Math.sqrt(n);
  var primes = [];

  //Turn all elements to true by default
  for (var i = 0; i <= n; i++){
    primes[i] = true;
  }

  //These are never prime so mark those false
  primes[0] = false;
  primes[1] = false;

  //Nested loop.  For each number, starting from index 2,
  for (var i = 2; i <= squareRoot; i++){
    // check and see if the multiples are found within the original array (make sure they don't exceed the max).  If they are, mark them false;
    for (var j = 2; j * i <= n; j++){
      primes[i * j] = false;
    }
  }

  //Create new array
  var result = []
  //Check all values from original array.  If they are true, push their index to the new array
  for (var i = 0; i < primes.length; i++){
    if (primes[i]){
      result.push(i)
    }
  }

  //Return new array
  return result;
}

Add comments to solution to better understand


import React, { PropTypes } from 'react'
import { connect } from 'react-redux'

import { incrementCounter, decrementCounter } from '../../actions/counter'

import {} from './app.css'

let Counter = ({ counter, onIncrementCounter, onDecrementCounter }) => (

{counter.toString()}

    <button onClick={onIncrementCounter} className="counter__button">+</button>
    <button onClick={onDecrementCounter} className="counter__button">-</button>

)

Counter.propTypes = {
  counter: PropTypes.number.isRequired,
  onIncrementCounter: PropTypes.func.isRequired,
  onDecrementCounter: PropTypes.func.isRequired
}

const mapStateToProps = (state) => {
  return {
    counter: state.counter
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    onIncrementCounter () {
      dispatch(incrementCounter())
    },
    onDecrementCounter () {
      dispatch(decrementCounter())
    }
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Counter)

import React, { PropTypes } from 'react'
import { connect } from 'react-redux'

import { incrementCounter, decrementCounter } from '../../actions/counter'

import {} from './app.css'

let Counter = ({ counter, onIncrementCounter, onDecrementCounter }) => (

{counter}

    <button onClick={onIncrementCounter} className="counter__button">+</button>
    <button onClick={onDecrementCounter} className="counter__button">-</button>

)

Counter.propTypes = {
  counter: PropTypes.number.isRequired,
  onIncrementCounter: PropTypes.func.isRequired,
  onDecrementCounter: PropTypes.func.isRequired
}

const mapStateToProps = (state) => {
  return {
    counter: state.counter
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    onIncrementCounter () {
      dispatch(incrementCounter())
    },
    onDecrementCounter () {
      dispatch(decrementCounter())
    }
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Counter)

Remove unneeded call to toString()


// Stopgap atom.js file for handling normal browser things that atom
// does not yet have stable from the browser-side API.
// - Opening external links in default web browser
// - Saving files/downloads to disk
$(document).ready(function() {
    if (typeof process === 'undefined') return;
    if (typeof process.versions['atom-shell'] === undefined) return;

    var remote = require('remote');
    var shell = require('shell');
    var http = require('http');
    var url = require('url');
    var fs = require('fs');

    $('body').on('click', 'a', function(ev) {
        var uri = url.parse(ev.currentTarget.href);

        // Opening external URLs.
        if (uri.hostname && uri.hostname !== 'localhost') {
            shell.openExternal(ev.currentTarget.href);
            return false;
        }

        // File saving.
        var extensions = /(\.tm2z|\.mbtiles|\.png|\.jpg)$/;
        var ext = extensions.exec(uri.pathname);
        if (ext) {
            var filepath = remote.require('dialog').showSaveDialog({
                title: 'Save file',
                defaultPath: ext[0]
            });
            if (filepath) {
                uri.method = 'GET';
                var writestream = fs.createWriteStream(filepath);
                var req = http.request(uri, function(res) {
                    if (res.statusCode !== 200) return;
                    res.pipe(writestream);
                });
                req.end();
            }
            return false;
        }

        // Passthrough evthing else.
    });
});

// Stopgap atom.js file for handling normal browser things that atom
// does not yet have stable from the browser-side API.
// - Opening external links in default web browser
// - Saving files/downloads to disk
$(document).ready(function() {
    if (typeof process === 'undefined') return;
    if (typeof process.versions['atom-shell'] === undefined) return;

    var remote = require('remote');
    var shell = require('shell');
    var http = require('http');
    var url = require('url');
    var fs = require('fs');

    $('body').on('click', 'a', function(ev) {
        var uri = url.parse(ev.currentTarget.href);

        // Opening external URLs.
        if (uri.hostname && uri.hostname !== 'localhost') {
            shell.openExternal(ev.currentTarget.href);
            return false;
        }

        // File saving.
        var extensions = /(\.tm2z|\.mbtiles|\.png|\.jpg|\.jpeg)$/;
        var ext = extensions.exec(uri.pathname);
        if (ext) {
            var filepath = remote.require('dialog').showSaveDialog({
                title: 'Save file',
                defaultPath: ext[0]
            });
            if (filepath) {
                uri.method = 'GET';
                var writestream = fs.createWriteStream(filepath);
                var req = http.request(uri, function(res) {
                    if (res.statusCode !== 200) return;
                    res.pipe(writestream);
                });
                req.end();
            }
            return false;
        }

        // Passthrough evthing else.
    });
});

Include .jpeg in extensions that should trigger a save dialog.


var TrieNode = require('trie-node');

var Trie = (function() {
  function Trie() {
    this.root = new TrieNode();
  }

  Trie.prototype.add = function(string) {
    this.root.add(string.trim(), 0);
  };

  Trie.prototype.search = function(string) {
    return this.root.search(string.trim(), 0);
  };

  Trie.prototype.find = function(string) {
    return this.root.find(string.trim(), 0);
  };

  return Trie;
})();

module.exports = Trie;

var TrieNode = require('./trie-node');

var Trie = (function() {
  function Trie() {
    this.root = new TrieNode();
  }

  Trie.prototype.add = function(string) {
    this.root.add(string.trim(), 0);
  };

  Trie.prototype.search = function(string) {
    return this.root.search(string.trim(), 0);
  };

  Trie.prototype.find = function(string) {
    return this.root.find(string.trim(), 0);
  };

  return Trie;
})();

module.exports = Trie;

Change require to use current dir: mocha runs node


/**
 * Allows users to see what screen readers would see.
 */

let $ = require("jquery");
let Plugin = require("../base");

require("./style.less");

class A11yTextWand extends Plugin {
    getTitle() {
        return "Screen Reader Wand";
    }

    getDescription() {
        return "Hover over elements to view them as a screen reader would";
    }

    run() {
        // HACK(jordan): We provide a fake summary to force the info panel to
        //     render.
        this.summary(" ");
        this.panel.render();

        $(document).on("mousemove.wand", function(e) {
            let element = document.elementFromPoint(e.clientX, e.clientY);

            let textAlternative = $.axs.properties.findTextAlternatives(
                element, {});

            $(".tota11y-outlined").removeClass("tota11y-outlined");
            $(element).addClass("tota11y-outlined");

            if (!textAlternative) {
                $(".tota11y-info-section.active").html(
                    <i className="tota11y-nothingness">
                        No text visible to a screen reader
                    </i>
                );
            } else {
                $(".tota11y-info-section.active").text(textAlternative);
            }
        });
    }

    cleanup() {
        $(document).off("mousemove.wand");
    }
}

module.exports = A11yTextWand;

/**
 * Allows users to see what screen readers would see.
 */

let $ = require("jquery");
let Plugin = require("../base");

require("./style.less");

class A11yTextWand extends Plugin {
    getTitle() {
        return "Screen Reader Wand";
    }

    getDescription() {
        return "Hover over elements to view them as a screen reader would";
    }

    run() {
        // HACK(jordan): We provide a fake summary to force the info panel to
        //     render.
        this.summary(" ");
        this.panel.render();

        $(document).on("mousemove.wand", function(e) {
            let element = document.elementFromPoint(e.clientX, e.clientY);

            let textAlternative = $.axs.properties.findTextAlternatives(
                element, {});

            $(".tota11y-outlined").removeClass("tota11y-outlined");
            $(element).addClass("tota11y-outlined");

            if (!textAlternative) {
                $(".tota11y-info-section.active").html(
                    <i className="tota11y-nothingness">
                        No text visible to a screen reader
                    </i>
                );
            } else {
                $(".tota11y-info-section.active").text(textAlternative);
            }
        });
    }

    cleanup() {
        $(".tota11y-outlined").removeClass("tota11y-outlined");
        $(document).off("mousemove.wand");
    }
}

module.exports = A11yTextWand;

Make wand plugin cleanup after itself.


import React, { useState } from 'react';
import { IconExternalLinkSmallOutline } from '@teamleader/ui-icons';

import Box from '../../box';
import Link from '../../link';

import theme from './theme.css';

const findLinkEntities = (contentBlock, callback, contentState) => {
  contentBlock.findEntityRanges((character) => {
    const entityKey = character.getEntity();
    return entityKey !== null && contentState.getEntity(entityKey).getType() === 'LINK';
  }, callback);
};

const LinkEntity = ({ entityKey, contentState, children }) => {
  const [showOpenLinkIcon, setShowOpenLinkIcon] = useState();
  const { url } = contentState.getEntity(entityKey).getData();

  const openLink = () => {
    let prefixedUrl = url;
    if (!url.includes('//')) {
      prefixedUrl = '//' + url;
    }
    window.open(prefixedUrl, '_blank');
  };

  const toggleShowOpenLinkIcon = () => {
    setShowOpenLinkIcon(!showOpenLinkIcon);
  };

  return (
    <Box display="inline-block" onMouseEnter={toggleShowOpenLinkIcon} onMouseLeave={toggleShowOpenLinkIcon}>
      <Link className={theme['link']} href="" inherit={false} onClick={(event) => event.preventDefault()}>
        {children}
      </Link>
      {showOpenLinkIcon && <IconExternalLinkSmallOutline onClick={openLink} className={theme['icon']} />}
    </Box>
  );
};

export default {
  strategy: findLinkEntities,
  component: LinkEntity,
};

import React, { useState } from 'react';
import { IconExternalLinkSmallOutline } from '@teamleader/ui-icons';

import Box from '../../box';
import Link from '../../link';

import theme from './theme.css';

const findLinkEntities = (contentBlock, callback, contentState) => {
  contentBlock.findEntityRanges((character) => {
    const entityKey = character.getEntity();
    return entityKey !== null && contentState.getEntity(entityKey).getType() === 'LINK';
  }, callback);
};

const LinkEntity = ({ entityKey, contentState, children }) => {
  const [showOpenLinkIcon, setShowOpenLinkIcon] = useState();
  const { url } = contentState.getEntity(entityKey).getData();

  const openLink = () => {
    let prefixedUrl = url;
    if (!url.includes('//')) {
      prefixedUrl = '//' + url;
    }
    window.open(prefixedUrl, '_blank');
  };

  const toggleShowOpenLinkIcon = () => {
    setShowOpenLinkIcon(!showOpenLinkIcon);
  };

  return (
    <Box display="inline-block" onMouseEnter={toggleShowOpenLinkIcon} onMouseLeave={toggleShowOpenLinkIcon}>
      <Link className={theme['link']} inherit={false} onClick={(event) => event.preventDefault()}>
        {children}
      </Link>
      {showOpenLinkIcon && <IconExternalLinkSmallOutline onClick={openLink} className={theme['icon']} />}
    </Box>
  );
};

export default {
  strategy: findLinkEntities,
  component: LinkEntity,
};

Remove href attribute from link decorator of WysiwygEditor


/*
    Extension helper for generating a CurvePath from an array of supplied points.
    Accepts an array of [Vector3] points to contruct the path from.
    ---

    points      Array       List of Vector3 points
    scale       Number      Scale factor

*/

import { Vector3, LineCurve3, CurvePath } from 'three';

export default class CurvePathFromPoints extends CurvePath {

    constructor(points, scale = 10) {

        super();

        this._points = points;
        this._scale = scale;

        this._createCurves();
    }

    _createCurves() {

        for ( var i = 0, len = this._points.length; i < len; i++ ) {

            let next = i === len - 1 ? this._points[ 0 ] : this._points[ i + 1 ];

            let line_curve = new LineCurve3( this._points[ i ].multiplyScalar( this._scale ), next );

            this.add( line_curve );
        }
    }
}

/*
    Extension helper for generating a CurvePath from an array of supplied points.
    Accepts an array of [Vector3] points to contruct the path from.
    Note: Currently assumes a closed path, and uses the first point as the final.
    ---

    points      Array       List of Vector3 points
    width       Number      optional - Width of the path, useful when using normalised X
    height      Number      optional - Height of the path, useful when using normalised Y
    scale       Number      optional - Scale factor

*/

import { Vector3, LineCurve3, CurvePath } from 'three';
import {PI, TWO_PI, HALF_PI} from '../math/constants';

export default class CustomCurvePath extends CurvePath {

    constructor(

        points,

        width = 1,
        height = 1,
        scale = 1

    ) {

        super();

        this._path_config = {
            points: points,
            width: width,
            height: height,
            scale: scale
        };

        this._createCurves();
    }

    _createCurves() {

        for ( var i = 0, len = this._path_config.points.length; i < len; i++ ) {

            let v1 = this._path_config.points[ i ];
            let v2 = i === len - 1 ? this._path_config.points[ 0 ] : this._path_config.points[ i + 1 ];

            // Apply dimensions
            v1.x *= this._path_config.width * this._path_config.scale;
            v1.y *= this._path_config.height * this._path_config.scale;
            v1.z *= this._path_config.height * this._path_config.scale; // Assume depth == height

            let line_curve = new LineCurve3( v1, v2 );

            this.add( line_curve );
        }
    }
}

Update curve path from points util


import _ from 'lodash'

export { removeEntries }

function removeEntries (db, ids) {
  if (!db) throw new Error('Please provide a couchdb instance')
  if (!ids) throw new Error('Please provide an array of ids')

  return db.allDocs({ keys: ids, include_docs: true })
  .then(({ rows }) => {
    //  Mark all docs as deleted
    var docs = _.chain(rows)
    .pluck('doc')
    .forEach(doc => doc._deleted = true)
    .value()

    //  Bulk delete form db
    return db.bulkDocs(docs)
    .then(() => docs)
  })
  .catch(err => console.log(err));
}

import _ from 'lodash'

export { removeEntries }

function removeEntries (db, ids) {
  if (!db) throw new Error('Please provide a couchdb instance')
  if (!ids) throw new Error('Please provide an array of ids')

  return db.allDocs({ keys: ids, include_docs: true })
  .then(({ rows }) => {
    //  Mark all docs as deleted
    var docs = _.chain(rows)
    .pluck('doc')
    .forEach(doc => doc._deleted = true)
    .value()

    //  Bulk delete form db
    return db.bulkDocs(docs)
    .then(() => docs)
  })
  .catch(err => console.error(chalk.bgRed('error'), err));
}

Make db console errors consistant


import Ember from 'ember';

/**
 * @module components
 * @class sl-loading-icon
 */
export default Ember.Component.extend({

    /**
     * Class name bindings for the root element
     *
     * @property {array} classNameBindings
     */
    classNameBindings: [ 'inverse:sl-loading-icon-light:sl-loading-icon-dark' ],

    /**
     * Class names for the root element
     *
     * @property {array} classNames
     */
    classNames: [ 'sl-loading-icon' ],

    /**
     * Whether to use the inverse (lighter colored) icon
     *
     * @property {boolean} inverse
     * @default false
     */
    inverse: false,

    /**
     * The HTML element type for this component
     *
     * @property {string} tagName
     * @default "span"
     */
    tagName: 'span'
});

import Ember from 'ember';

/** @module sl-components/components/sl-loading-icon */
export default Ember.Component.extend({

    /**
     * The HTML element type for this component
     *
     * @property {Ember.String} tagName
     * @default  "span"
     */
    tagName: 'span',

    /**
     * Class names for the root element
     *
     * @property {Ember.Array} classNames
     */
    classNames: [ 'sl-loading-icon' ],

    /**
     * Class name bindings for the root element
     *
     * @property {Ember.Array} classNameBindings
     */
    classNameBindings: [ 'inverse:sl-loading-icon-light:sl-loading-icon-dark' ],

    /**
     * Whether to use the inverse (lighter colored) icon
     *
     * @property {boolean} inverse
     * @default  false
     */
    inverse: false
});

Refactor to follow style guides


import * as path from 'path'

import { Loader } from './loader'

var loader

const system = () => {
  if (typeof loader === 'undefined') {
    let scope = new URL(self.registration.scope)
    let base = new URL(path.join(scope.pathname, path.resolve(kernel_conf.base)), scope)

    loader = new Loader({
      base: base
    })

    if (KERNEL_CONFIG_WORKER_EMBED) {
      loader.set(KERNEL_CONFIG_WORKER_INIT, require(KERNEL_CONFIG_WORKER_INIT))
    }
  }

  return loader
}

const init = async (fn) => {
  return system().import(path.resolve(kernel_conf.initsw)).then(fn)
}

export default function() {
  this.addEventListener('install', (event) => {
    event.waitUntil(init(worker => worker.install(event)))
  })

  this.addEventListener('activate', (event) => {
    event.waitUntil(init(worker => worker.activate(event)))
  })

  this.addEventListener('fetch', (event) => {
    event.waitUntil(init(worker => worker.fetch(event)))
  })

  this.addEventListener('message', (event) => {
    if(event.data === 'kernel:sw-force-reload') {
      loader = undefined
    }

    event.waitUntil(init(worker => worker.message(event)))
  })
}

import * as path from 'path'

import { Loader } from './loader'

var loader

const system = () => {
  if (typeof loader === 'undefined') {
    let scope = new URL(self.registration.scope)
    let base = scope

    if (KERNEL_CONFIG_BASE) {
      let base = new URL(path.join(scope.pathname, path.resolve(KERNEL_CONFIG_BASE)), scope)
    }

    loader = new Loader({
      base: base
    })

    if (KERNEL_CONFIG_WORKER_EMBED) {
      loader.set(KERNEL_CONFIG_WORKER_INIT, require(KERNEL_CONFIG_WORKER_INIT))
    }
  }

  return loader
}

const init = async (fn) => {
  return system().import(path.resolve(KERNEL_CONFIG_WORKER_INIT)).then(fn)
}

export default function() {
  this.addEventListener('install', (event) => {
    event.waitUntil(init(worker => worker.install(event)))
  })

  this.addEventListener('activate', (event) => {
    event.waitUntil(init(worker => worker.activate(event)))
  })

  this.addEventListener('fetch', (event) => {
    event.waitUntil(init(worker => worker.fetch(event)))
  })

  this.addEventListener('message', (event) => {
    if(event.data === 'kernel:sw-force-reload') {
      loader = undefined
    }

    event.waitUntil(init(worker => worker.message(event)))
  })
}

Fix legacy kernel config usage


var srcDir   = __dirname + "/../";

module.exports = {
    all: {
        src: [
                srcDir + "*.js",
                srcDir + "lib/*.js",
                srcDir + "adapter/example/*.js",
                srcDir + "tasks/**/*.js",
                srcDir + "www/**/*.js",
                '!' + srcDir + "www/lib/**/*.js",
                '!' + srcDir + 'node_modules/**/*.js',
                '!' + srcDir + 'adapter/*/node_modules/**/*.js'
        ],
        options: require('./jscsRules.js')
    }
};

Revert "fix util.js usage and use utils.Adapter"


module.exports = {
    extends: ["matrix-org"],
    plugins: [
        "babel",
    ],
    env: {
        browser: true,
        node: true,
    },

    rules: {
        "no-var": ["warn"],
        "prefer-rest-params": ["warn"],
        "prefer-spread": ["warn"],
        "one-var": ["warn"],
        "padded-blocks": ["warn"],
        "no-extend-native": ["warn"],
        "camelcase": ["warn"],
        "no-multi-spaces": ["error", { "ignoreEOLComments": true }],
        "space-before-function-paren": ["error", {
            "anonymous": "never",
            "named": "never",
            "asyncArrow": "always",
        }],
        "arrow-parens": "off",
        "prefer-promise-reject-errors": "off",
        "quotes": "off",
        "indent": "off",
        "no-constant-condition": "off",
        "no-async-promise-executor": "off",
    },
    overrides: [{
        "files": ["src/**/*.{ts, tsx}"],
        "extends": ["matrix-org/ts"],
        "rules": {
            // While we're converting to ts we make heavy use of this
            "@typescript-eslint/no-explicit-any": "off",
            "quotes": "off",
        },
    }],
};

module.exports = {
    extends: ["matrix-org"],
    plugins: [
        "babel",
    ],
    env: {
        browser: true,
        node: true,
    },

    rules: {
        "no-var": ["warn"],
        "prefer-rest-params": ["warn"],
        "prefer-spread": ["warn"],
        "one-var": ["warn"],
        "padded-blocks": ["warn"],
        "no-extend-native": ["warn"],
        "camelcase": ["warn"],
        "no-multi-spaces": ["error", { "ignoreEOLComments": true }],
        "space-before-function-paren": ["error", {
            "anonymous": "never",
            "named": "never",
            "asyncArrow": "always",
        }],
        "arrow-parens": "off",
        "prefer-promise-reject-errors": "off",
        "quotes": "off",
        "indent": "off",
        "no-constant-condition": "off",
        "no-async-promise-executor": "off",
    },
    overrides: [{
        "files": ["src/**/*.ts"],
        "extends": ["matrix-org/ts"],
        "rules": {
            // While we're converting to ts we make heavy use of this
            "@typescript-eslint/no-explicit-any": "off",
            "quotes": "off",
        },
    }],
};

Fix eslint ts override tsx matching


/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-present Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import loadComponent from '../../../helpers/loadComponent';
import LayoutContainer from '../../../components/Layout/LayoutContainer';

const title = 'About / Privacy';

// try to fix a strange ReferenceError in production server build
// by defining and assigning About first
let About = () => null;

export default {

  path: '/about',

  async action(context) {
    About = await loadComponent(
      () => require.ensure([], require => require('./About').default, 'about')
    );

    return {
      title,
      chunk: 'about',
      component: (
        <LayoutContainer path={context.url}>
          <About />
        </LayoutContainer>
      ),
    };
  },

};

/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-present Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import loadComponent from '../../../helpers/loadComponent';
import LayoutContainer from '../../../components/Layout/LayoutContainer';

const title = 'About / Privacy';

export default {

  path: '/about',

  action(context) {
    return loadComponent(
      () => require.ensure([], require => require('./About').default, 'about')
    ).then(About => ({
      title,
      chunk: 'about',
      component: (
        <LayoutContainer path={context.url}>
          <About />
        </LayoutContainer>
      ),
    }));
  },

};

Undo async decorator to attempt fix to About page


const argv = require('minimist')(process.argv.slice(2))

if (argv.f) {
  require('./fake.js')
} else if (argv.a) {
  require('./api.js')
} else if (argv.t) {
  require('./transactionRunner.js')
} else {
  require('./fake.js')
  require('./api.js')
  require('./transactionRunner.js')
}

Allow specification of test suite via command line arg.


var config = require('../config.json');
var RedisPool = require('../../index');

var redisPool;

beforeAll(function() {
  redisPool = new RedisPool(config.redis, {
    max: 10,
    min: 2
  });
});

Add beforeAll to setup redisPool


'use strict';
let expect = require('chai').expect;
let errorHandler = require('../Utils/errorHandler.js');
describe('Error handling', function() {
  it('converts error string to error number', function() {
    let validStringToNumber = errorHandler.findError('SECURITY_DECRYPTION_FAILURE');
    let invalidStringToNumber = errorHandler.findError(
      'SOME_RANDOM_ERROR_HERE_WHICH_IS_REALLY_LONG_AND_INVALID'
    );
    expect(validStringToNumber).to.equal(18);
    expect(invalidStringToNumber).to.equal(0);
  });
  it('converts error number to error string', function() {
    let validNumberToString = errorHandler.findError(17);
    let invalidNumberToString = errorHandler.findError(-1);
    expect(validNumberToString).to.equal('SECURITY_ENCRYPTION_FAILURE');
    expect(invalidNumberToString).to.equal('UNKNOWN_ERROR');
  });
  it('returns correct type when it\'s defined', function() {
    let numberToNumber = errorHandler.findError(16, 'number');
    let stringToString = errorHandler.findError('DATABASE_GENERIC', 'string');
    expect(numberToNumber).to.equal(16);
    expect(stringToString).to.equal('DATABASE_GENERIC');
  });
});

'use strict';
let expect = require('chai').expect;
let errorHandler = require('../error/errorHandler.js');
describe('Error handling', function() {
  it('converts error object to error instance', function() {
    let validError = errorHandler.createError({
      name: 'SecurityEncryptionFailure',
      message: 'valid error'
    });
    let invalidError = errorHandler.createError({
      name: 'SomeInvalidErrorThatCannotBeFound',
      message: 'invalid error'
    });
    expect(validError.toString()).to.equal('SecurityEncryptionFailure: valid error');
    expect(invalidError.toString()).to.equal('Error: invalid error');
  });
});

Update errorHandler's tests to take into account new functionality


import {
  isArray,
  validateIsArray,
  combine,
  createValidateMinCount,
  createValidateMaxCount,
} from '../validators.js';

const pluginArray = {
  compile(compiler, schemaDef, schemaOptions) {
    if (isArray(schemaDef) && schemaDef.length === 1) {
      if (schemaDef.length !== 1) {
        throw new Error('SchemaDef must be an array of length 1');
      }
      const items = compiler.compile(schemaDef[0], schemaOptions);
      const { minCount, maxCount } = schemaOptions;
      return {
        items,
        isArray: true,
        compiled: true,
        validate: combine([
          validateIsArray,
          minCount !== undefined && createValidateMinCount(minCount),
          maxCount !== undefined && createValidateMaxCount(maxCount),
          (value) => {
            const errors = value.map(member => items.validate(member));
            return errors.some(err => !!err) ? { errors } : undefined;
          },
        ]),
      };
    }
    return null;
  },
};

export default pluginArray;

import {
  isArray,
  validateIsArray,
  combine,
  createValidateMinCount,
  createValidateMaxCount,
} from '../validators.js';

const pluginArray = {
  compile(compiler, schemaDef, schemaOptions) {
    if (isArray(schemaDef) && schemaDef.length === 1) {
      const items = compiler.compile(schemaDef[0], schemaOptions);
      const { minCount, maxCount } = schemaOptions;
      return {
        items,
        isArray: true,
        compiled: true,
        validate: combine([
          validateIsArray,
          minCount !== undefined && createValidateMinCount(minCount),
          maxCount !== undefined && createValidateMaxCount(maxCount),
          (value) => {
            const errors = value.map(member => items.validate(member));
            return errors.some(err => !!err) ? { errors } : undefined;
          },
        ]),
      };
    }
    return null;
  },
};

export default pluginArray;

Remove an unnecessary condition check


Kwf.Utils.ResponsiveEl('.kwcBasicTable.responsiveFlipScroll', function(el) {
    var addArrow = function(el) {
        if (el.hasClass('flipScroll')) {
            var tbody = el.children('tbody');
            if (tbody.scrollLeft == 0 && tbody.width > el.width()) {
                el.addClass('arrowRight');
            } else {
                el.removeClass('arrowRight');
            }
        }
    };

    if (el.hasClass('flipScroll')) {
        if (el.width() > el.flipScrollSetAt) {
            el.removeClass('flipScroll');
        }
    }
    if (el.width() < el.children('table').width() && !el.hasClass('flipScroll')) {
        el.addClass('flipScroll');
        addArrow(el);
        if (!el.flipScrollSetAt) {
            el.children('tbody').on('scroll', function(ev) {
                addArrow($(this).closest('.kwcBasicTable'));
            });
        }
        el.flipScrollSetAt = el.width();
    }
});

Kwf.Utils.ResponsiveEl('.kwcBasicTable.responsiveFlipScroll', function(el) {
    var addArrow = function(el) {
        if (el.hasClass('flipScroll')) {
            var tbody = el.children('tbody');
            if (tbody.scrollLeft() == 0 && tbody.width() > el.width()) {
                el.addClass('arrowRight');
            } else {
                el.removeClass('arrowRight');
            }
        }
    };

    if (el.hasClass('flipScroll')) {
        if (el.width() > el.get(0).flipScrollSetAt) {
            el.removeClass('flipScroll');
        }
    }
    if (el.width() < el.children('table').width() && !el.hasClass('flipScroll')) {
        el.addClass('flipScroll');
        addArrow(el);
        if (!el.flipScrollSetAt) {
            el.children('tbody').on('scroll', function(ev) {
                addArrow($(this).closest('.kwcBasicTable'));
            });
        }
        el.get(0).flipScrollSetAt = el.width();
    }
});

Repair Table js - some bugs from ext to jquery update


import cli from 'cli';
import {Gpio} from 'chip-gpio';
import temp from 'ds18x20';

var options = cli.parse();

var interval = 2000;
var threshold = 25;

var heater = new Gpio(0, 'out');

function setHeater(on) {
  console.log('Heater:', on ? 'on' : 'off');
  heater.write(on ? 0 : 1);
}
function setHeaterOn() {
  setHeater(true);
}
function setHeaterOff() {
  setHeater(false);
}

sensor.isDriverLoaded((err, isLoaded) => {
  console.log(isLoaded);
  sensor.list((err, listOfDeviceIds) => {
    console.log(listOfDeviceIds);
  });
  setInterval(() => {
    sensor.getAll((err, tempObj) => {
      var sum = 0;
      var len = 0;
      tempObj.forEach(obj => {
        console.log(obj);
        sum += obj;
        len++;
      });

      var average = sum / len;

      console.log(average);

      setHeater(average < threshold);
    });
  }, interval);
});

import cli from 'cli';
import {Gpio} from 'chip-gpio';
import sensor from 'ds18x20';

var options = cli.parse();

var interval = 2000;
var threshold = 25;

var heater = new Gpio(0, 'out');

function setHeater(on) {
  console.log('Heater:', on ? 'on' : 'off');
  heater.write(on ? 0 : 1);
}
function setHeaterOn() {
  setHeater(true);
}
function setHeaterOff() {
  setHeater(false);
}

sensor.isDriverLoaded((err, isLoaded) => {
  console.log(isLoaded);
  sensor.list((err, listOfDeviceIds) => {
    console.log(listOfDeviceIds);
  });
  setInterval(() => {
    sensor.getAll((err, tempObj) => {
      var sum = 0;
      var len = 0;
      tempObj.forEach(obj => {
        console.log(obj);
        sum += obj;
        len++;
      });

      var average = sum / len;

      console.log(average);

      setHeater(average < threshold);
    });
  }, interval);
});

Use better name and fix undefined references


import express from 'express'
import webpack from 'webpack'
import { logError, log } from '../util/log'

export default function startDevelop (webpackConfig) {
  const app = express()
  const compiler = webpack(webpackConfig)

  app.use(require('webpack-dev-middleware')(compiler, {
    noInfo: true,
    publicPath: webpackConfig.output.publicPath
  }))

  app.use(require('webpack-hot-middleware')(compiler))

  app.listen(3000, 'localhost', onServerStarted)
}

function onServerStarted (err) {
  if (err) {
    logError(err)
    return
  }

  log('Listening at http://localhost:3000')
}

import express from 'express'
import webpack from 'webpack'
import { logError, log } from '../util/log'

export default function startDevelop (webpackConfig) {
  const app = express()
  const compiler = webpack(webpackConfig)

  app.use(require('webpack-dev-middleware')(compiler, {
    noInfo: true,
    publicPath: webpackConfig.output.publicPath
  }))

  app.use(require('webpack-hot-middleware')(compiler))

  app.listen(3000, '0.0.0.0', onServerStarted)
}

function onServerStarted (err) {
  if (err) {
    logError(err)
    return
  }

  log('Listening at http://localhost:3000')
}

Allow development server to be accessible from any IP


define(function(require) {
  var DateTime = require('../main/DateTime')
  var DateFormat = require('../main/DateFormat')
  var jQuery = $ = require('jquery')

  return {
    toHaveLength             : function(length) {
      var result = $(this.actual).length == length
      if(this.actual instanceof jQuery) {
        this.actual = $('

').append(this.actual.clone()).html()
      }
      return result
    },
    toHaveDate               : function(date_str) { return this.actual.hasDate(new DateTime(date_str)) },
    toBeInside               : function(range) { return this.actual.isInside(range) },
    toBeValidRange           : function() { return this.actual.isValid() },
    toPrintDefiningDurationOf: function(duration_str, locale) { return DateFormat.formatDefiningRangeDuration(this.actual, locale) == duration_str }
  }
})

define(function(require) {
  var DateTime = require('../main/DateTime')
  var DateFormat = require('../main/DateFormat')
  var jQuery = $ = require('jquery')

  return {
    toHaveLength             : function(length) {
      var result = $(this.actual).length == length
      if(this.actual instanceof jQuery) {
        this.actual = $('

').append(this.actual.clone()).html()
      }
      return result
    },
    toHaveDate               : function(date_str) { return this.actual.hasDate(new DateTime(date_str)) },
    toBeInside               : function(range) { return this.actual.isInside(range) },
    toBeValidRange           : function() { return this.actual.isValid() },
    toPrintDefiningDurationOf: function(duration_str, locale) { return DateFormat.formatDefiningRangeDuration(this.actual, locale) == duration_str },
    toCompareWith: function(expected) {
      return this.actual.compareTo(expected) === 0
    }
  }
})

Add toCompareWith custom matcher for comparing DateTimes


import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { init } from './redux/page';
import Page from './components/Page';

class FrontendApp extends Component {
  componentWillMount() {
    const path = window.location.pathname;
    const options = { mode: 'no-cors' };

    if (typeof fetch === 'undefined' || !fetch) {
      return;
    }

    fetch(`/api/content${path}index.json`, options)
      .then(res => res.json())
      .then(json => this.props.initPage(json))
      .catch(err => console.error(`Unable to parse content for "${path}".`, err))
  }

  render() {
    const {
      title,
      description,
      children:blocks = [],
    } = this.props.page;
    return (
      <Page
        title={title}
        description={description}
        blocks={blocks}
      />
    )
  }
}

FrontendApp.propTypes = {
  page: PropTypes.object,
  init: PropTypes.func,
};

export default connect(
  (state) => ({
    page: state.page,
  }),
  { initPage: init }
)(FrontendApp);

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { init } from './redux/page';
import Page from './components/Page';

class FrontendApp extends Component {
  componentWillMount() {
    const path = window.location.pathname
        .replace(/^\//, '')
        .replace(/\/$/, '');
    const options = { mode: 'no-cors' };

    if (typeof fetch === 'undefined' || !fetch) {
      return;
    }

    fetch(`/api/content/${path}/index.json`, options)
      .then(res => res.json())
      .then(json => this.props.initPage(json))
      .catch(err => console.error(`Unable to parse content for "${path}".`, err))
  }

  render() {
    const {
      title,
      description,
      children:blocks = [],
    } = this.props.page;
    return (
      <Page
        title={title}
        description={description}
        blocks={blocks}
      />
    )
  }
}

FrontendApp.propTypes = {
  page: PropTypes.object,
  init: PropTypes.func,
};

export default connect(
  (state) => ({
    page: state.page,
  }),
  { initPage: init }
)(FrontendApp);

Fix fetching content for paths without dashes


goog.provide('ol.format.filter.Spatial');

goog.require('ol');
goog.require('ol.format.filter.Filter');

/**
 * @classdesc
 * Represents a spatial operator to test whether a geometry-valued property
 * relates to a given geometry.
 *
 * @constructor
 * @param {!string} tagName The XML tag name for this filter.
 * @param {!string} geometryName Geometry name to use.
 * @param {!ol.geom.Geometry} geometry Geometry.
 * @param {string=} opt_srsName SRS name. No srsName attribute will be
 *    set on geometries when this is not provided.
 * @extends {ol.format.filter.Filter}
 * @api
 */
ol.format.filter.Spatial = function(tagName, geometryName, geometry, opt_srsName) {

  ol.format.filter.Filter.call(this, tagName);

  /**
   * @public
   * @type {!string}
   */
  this.geometryName = geometryName || 'the_geom';

  /**
   * @public
   * @type {ol.geom.Geometry}
   */
  this.geometry = geometry;

  /**
   * @public
   * @type {string|undefined}
   */
  this.srsName = opt_srsName;
};
ol.inherits(ol.format.filter.Spatial, ol.format.filter.Filter);

goog.provide('ol.format.filter.Spatial');

goog.require('ol');
goog.require('ol.format.filter.Filter');

/**
 * @classdesc
 * Abstract class; normally only used for creating subclasses and not instantiated in apps.
 * Represents a spatial operator to test whether a geometry-valued property
 * relates to a given geometry.
 *
 * @constructor
 * @param {!string} tagName The XML tag name for this filter.
 * @param {!string} geometryName Geometry name to use.
 * @param {!ol.geom.Geometry} geometry Geometry.
 * @param {string=} opt_srsName SRS name. No srsName attribute will be
 *    set on geometries when this is not provided.
 * @extends {ol.format.filter.Filter}
 * @api
 */
ol.format.filter.Spatial = function(tagName, geometryName, geometry, opt_srsName) {

  ol.format.filter.Filter.call(this, tagName);

  /**
   * @public
   * @type {!string}
   */
  this.geometryName = geometryName || 'the_geom';

  /**
   * @public
   * @type {ol.geom.Geometry}
   */
  this.geometry = geometry;

  /**
   * @public
   * @type {string|undefined}
   */
  this.srsName = opt_srsName;
};
ol.inherits(ol.format.filter.Spatial, ol.format.filter.Filter);

Mark ol.format.filter.Spatial as abstract class


// Main script
// -----------

var blackbird = blackbird || {};

blackbird.player = {};

$(document).ready(function() {

    blackbird.player = new blackbird.Player(blackbird.api_root);

    // First play
    blackbird.player.next();

    // Create seek slider
    $("#seek-bar").slider({
        min: 0,
        max: 100,
        value: 0,
        range: "min",
        animate: true,
        slide: function(event, ui) {
            blackbird.player.seek(ui.value);
        }
    });

    // Player control logic
    $("#prev-btn").click(function() {
        blackbird.player.previous();
    });

    $("#next-btn").click(function() {
        blackbird.player.next();
    });

    $("#play-btn").click(function() {
        blackbird.player.pause();
    });

    // Command line entry
    $(document).keydown(function(e) {
        if (e.keyCode==88 && e.altKey) {
            $("#command-input").val("");
            $("#command-input").focus();
        }
    });

    // Command line
    $(document).on("keypress", "#command-input", function(e) {
        if (e.which == 13) {
            var cmd = $("#command-input").val();
            // Show loading
            $.get(
                blackbird.player.root + "command",
                {command: cmd},
                function(data) {
                    // Do things here
                }
            );
        }
    });
});

// Main script
// -----------

var blackbird = blackbird || {};

blackbird.player = {};

$(document).ready(function() {

    blackbird.player = new blackbird.Player(blackbird.api_root);

    // First play
    blackbird.player.next();

    // Create seek slider
    $("#seek-bar").slider({
        min: 0,
        max: 100,
        value: 0,
        range: "min",
        animate: true,
        slide: function(event, ui) {
            blackbird.player.seek(ui.value);
        }
    });

    // Player control logic
    $("#prev-btn").click(function() {
        blackbird.player.previous();
    });

    $("#next-btn").click(function() {
        blackbird.player.next();
    });

    $("#play-btn").click(function() {
        blackbird.player.pause();
    });

    // Command line entry
    $(document).keydown(function(e) {
        if (e.keyCode==88 && e.altKey) {
            $("#command-input").val("");
            $("#command-input").focus();
        }
    });

    // Command line
    $(document).on("keypress", "#command-input", function(e) {
        if (e.which == 13) {
            var cmd = $("#command-input").val();
            blackbird.loading(true);
            $.get(
                blackbird.player.root + "command",
                {command: cmd},
                function(data) {
                    if (data == "nf") {
                        blackbird.flash();
                    }
                    blackbird.loading(false);
                }
            );
        }
    });
});

Connect loading and error events to UI


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

const minimist = require('minimist');

const init = require('../lib/init');
const { showHelp, showVersion } = require('../lib/interactions');

const minimistConfig = {
  boolean: ['ssh'],
  default: {
    ssh: false,
  },
  alias: {
    h: 'help',
    v: 'version',
    s: 'ssh',
  },
};

const command = minimist(process.argv.slice(2), minimistConfig);
const config = {};

config.options = Object.assign({}, command);

delete config.options['_'];
Object.keys(minimistConfig.alias).forEach((key) => {
  delete config.options[key];
});

switch (command['_'].length) {
  case 0:
    break;
  case 1:
    config.name = command['_'][0];
    break;
  case 2:
    config.name = command['_'][0];
    config.template = command['_'][1];
    break;
  default:
    showHelp();
}

if (config.help) {
  return showHelp();
} else if (config.version) {
  return showVersion();
}

init(config);

Clean up the configuration object passed to init func


var User = require('../models/user.js'),
    utils   = require('../../lib/utils.js');

module.exports = (function(){
	function destroy(req, res) {
		res.send({
      success: true,
			session: req.session
		})
	}

	function create(req, res) {
		req.session.session = null
		var user, valid
		if (req.body.name && req.body.password) {
			User.findAll({ where: { name: req.body.name }})
			.error(function(err){
				res.send({ error: 'user not found' })
			})
			.success(function(results){
				user = results[0]
				if (user) {
					valid = utils.verifyPassword(req.body.password, user.salt, user.passwordHash)
					if (valid) {
						req.session.username = user.name
            req.session.username = user.name
            res.send({ success: true, session: { username: user.name } })
					}
				} else {
					res.send({ error: 'user not found' })
				}
			})
		} else {
			res.send({ error: 'required params: name, password' })
		}
	}

  function show(req, res) {
    res.send({
      success: true,
      session: { username: req.session.username }
    })
  }

	return {
		create: create,
		destroy: destroy,
    show: show
	}
})()

var User = require('../models/user.js'),
    utils   = require('../../lib/utils.js');

module.exports = (function(){
	function destroy(req, res) {
    req.session = null
		res.send({
      success: true,
			session: req.session
		})
	}

	function create(req, res) {
		req.session.session = null
		var user, valid
		if (req.body.name && req.body.password) {
			User.findAll({ where: { name: req.body.name }})
			.error(function(err){
				res.send({ error: 'user not found' })
			})
			.success(function(results){
				user = results[0]
				if (user) {
					valid = utils.verifyPassword(req.body.password, user.salt, user.passwordHash)
					if (valid) {
						req.session.username = user.name
            req.session.username = user.name
            res.send({ success: true, session: { username: user.name } })
					}
				} else {
					res.send({ error: 'user not found' })
				}
			})
		} else {
			res.send({ error: 'required params: name, password' })
		}
	}

  function show(req, res) {
    res.send({
      success: true,
      session: { username: req.session.username }
    })
  }

	return {
		create: create,
		destroy: destroy,
    show: show
	}
})()

Clear session on delete method


var myArray = [];
document.write("
");
document.write("
");
$("#submit").on('click', function(value) {
	myArray = $('textarea').val().split('\n');
	for( var i = 0; i<myArray.length; i++ ) {
	var newValue = myArray[i].toLowerCase().replace(/ /g, "-");
	$('ul').append("
" + newValue + "
");

	}

}
);

$("#reset_button").on('click', function(value) {
	$('li').remove();
}
);

Add event handler on reset button


import Notification from 'flarum/components/Notification';
import username from 'flarum/helpers/username';

export default class NewPostNotification extends Notification {
  icon() {
    return 'star';
  }

  href() {
    const notification = this.props.notification;
    const discussion = notification.subject();
    const content = notification.content() || {};

    return app.route.discussion(discussion, content.postNumber);
  }

  content() {
    return app.translator.trans('flarum-subscriptions.forum.notifications:new_post_text', {user: this.props.notification.sender()});
  }
}

import Notification from 'flarum/components/Notification';
import username from 'flarum/helpers/username';

export default class NewPostNotification extends Notification {
  icon() {
    return 'star';
  }

  href() {
    const notification = this.props.notification;
    const discussion = notification.subject();
    const content = notification.content() || {};

    return app.route.discussion(discussion, content.postNumber);
  }

  content() {
    return app.translator.trans('flarum-subscriptions.forum.notifications.new_post_text', {user: this.props.notification.sender()});
  }
}

Fix typo in new post notification translation key


import last from '../util/last'

export default class SimpleChangeHistory {
  constructor (editorSession) {
    this._editorSession = editorSession
    this._done = []
    this._undone = []
  }

  canUndo () {
    return this._done.length > 0
  }

  canRedo () {
    return this._undone.length > 0
  }

  getChanges () {
    return this._done.slice()
  }

  addChange (change) {
    this._done.push(change)
    // undone changes are cleared whenever a new change is recorded
    if (this._undone.length > 0) {
      this._undone.length = 0
    }
  }

  undo () {
    let change = last(this._done)
    if (change) {
      let inverted = change.invert()
      this._editorSession.applyChange(inverted, { replay: true })
      this._done.pop()
      this._undone.push(change)
    }
  }

  redo () {
    let change = last(this._undone)
    if (change) {
      this._editorSession.applyChange(change, { replay: true })
      this._undone.pop()
      this._done.push(change)
    }
  }
}

import last from '../util/last'

export default class SimpleChangeHistory {
  constructor (editorSession) {
    this._editorSession = editorSession
    this._done = []
    this._undone = []
  }

  canUndo () {
    return this._done.length > 0
  }

  canRedo () {
    return this._undone.length > 0
  }

  getChanges () {
    return this._done.slice()
  }

  addChange (change) {
    this._done.push(change)
    // undone changes are cleared whenever a new change is recorded
    if (this._undone.length > 0) {
      this._undone.length = 0
    }
  }

  undo () {
    let change = last(this._done)
    if (change) {
      let inverted = this._editorSession.getDocument().invert(change)
      this._editorSession.applyChange(inverted, { replay: true })
      this._done.pop()
      this._undone.push(change)
    }
  }

  redo () {
    let change = last(this._undone)
    if (change) {
      this._editorSession.applyChange(change, { replay: true })
      this._undone.pop()
      this._done.push(change)
    }
  }
}

Use document instance to invert change.


/* eslint-disable prefer-arrow-callback, func-names */
import loader from 'graphql-tag/loader';

function GraphQLCompiler() {}
GraphQLCompiler.prototype.processFilesForTarget = function (files) {
  files.forEach(function (file) {
    // Fake webpack context
    // See https://github.com/apollographql/graphql-tag/blob/master/loader.js#L26
    const context = {
      cacheable() {},
    };

    const output = loader.call(context, file.getContentsAsString());
    file.addJavaScript({ data: output, path: `${file.getPathInPackage()}.js` });
  });
};

export default GraphQLCompiler;

/* eslint-disable prefer-arrow-callback, func-names */
import loader from 'graphql-tag/loader';

function GraphQLCompiler() {}
GraphQLCompiler.prototype.processFilesForTarget = function (files) {
  files.forEach(function (file) {
    // Fake webpack context
    // See https://github.com/apollographql/graphql-tag/blob/master/loader.js#L26
    const context = {
      cacheable() {},
    };

    const content = file.getContentsAsString().trim();
    let output = '';

    if (content) {
      output = loader.call(context, file.getContentsAsString());
    }

    file.addJavaScript({ data: output, path: `${file.getPathInPackage()}.js` });
  });
};

export default GraphQLCompiler;

Make sure it doesn't crash on empty files


Package.describe({
  name: 'meteortesting:mocha',
  summary: 'Run Meteor package or app tests with Mocha',
  git: 'https://github.com/meteortesting/meteor-mocha.git',
  documentation: '../README.md',
  version: '1.1.5',
  testOnly: true,
});

Package.onUse(function onUse(api) {
  api.use([
    'meteortesting:mocha-core@7.0.0',
    'ecmascript@0.3.0',
    'lmieulet:meteor-coverage@1.1.4 || 2.0.1 || 3.0.0',
  ]);

  api.use(['meteortesting:browser-tests@1.3.2', 'http@1.0.0'], 'server');
  api.use('browser-policy@1.0.0', 'server', { weak: true });

  api.mainModule('client.js', 'client');
  api.mainModule('server.js', 'server');
});

Package.describe({
  name: 'meteortesting:mocha',
  summary: 'Run Meteor package or app tests with Mocha',
  git: 'https://github.com/meteortesting/meteor-mocha.git',
  documentation: '../README.md',
  version: '1.1.5',
  testOnly: true,
});

Package.onUse(function onUse(api) {
  api.use([
    'meteortesting:mocha-core@7.0.0',
    'ecmascript@0.3.0',
  ]);

  api.use(['meteortesting:browser-tests@1.3.2', 'http@1.0.0'], 'server');
  api.use('browser-policy@1.0.0', 'server', { weak: true });
  api.use('lmieulet:meteor-coverage@1.1.4 || 2.0.1 || 3.0.0', 'client', { weak: true });

  api.mainModule('client.js', 'client');
  api.mainModule('server.js', 'server');
});

Make `lmieulet:meteor-coverage` a weak dependency


// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')

module.exports = {
  build: {
    env: require('./prod.env'),
    index: path.resolve(__dirname, '../dist/index.html'),
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    productionSourceMap: true,
    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  },
  dev: {
    env: require('./dev.env'),
    port: 8080,
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {},
    // CSS Sourcemaps off by default because relative paths are "buggy"
    // with this option, according to the CSS-Loader README
    // (https://github.com/webpack/css-loader#sourcemaps)
    // In our experience, they generally work as expected,
    // just be aware of this issue when enabling this option.
    cssSourceMap: false
  }
}

// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')

module.exports = {
  build: {
    env: require('./prod.env'),
    index: path.resolve(__dirname, '../dist/index.html'),
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/codemash-vue',
    productionSourceMap: true,
    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  },
  dev: {
    env: require('./dev.env'),
    port: 8080,
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {},
    // CSS Sourcemaps off by default because relative paths are "buggy"
    // with this option, according to the CSS-Loader README
    // (https://github.com/webpack/css-loader#sourcemaps)
    // In our experience, they generally work as expected,
    // just be aware of this issue when enabling this option.
    cssSourceMap: false
  }
}

Fix the build path for hosting on Github pages


idClock = 0;
function getId() {
	idClock++;
	return "attribute-list-" + idClock;
}

function parentIdCleanup(parentId) {
	parentId = parentId.replace(/:/g, "\\:");
	parentId = parentId.replace(/\$/g, "\\$");
	parentId = parentId.replace(/\./g, "\\.");

	return "#" + parentId;
}

function typeChooser(obj, parentId) {
	for (property in obj) {
		if (property.indexOf("_") == 0) { continue; }
		switch ($.type(obj[property])) {
		case "function":
			break;
		case "object":
			renderObject(obj[property], property, "object", parentId);
			break;
		case "array":
			renderObject(obj[property], property, "array", parentId);
			break;
		default:
			addHtml(valueAsHtml(obj[property], property), parentId);
			break;
		}
	}
}

function renderObject(obj, propertyName, type, parentId) {
	thisId = getId();
	addHtml(objAsHtml(propertyName, type, thisId), parentId);
	addHtml(controlToolbar(thisId, true, true), thisId + "-header", true);
	typeChooser(obj, thisId);
}

function addHtml(html, parentId, shouldPrepend) {
	parent = $(parentIdCleanup(parentId));
	if (shouldPrepend) { parent.prepend(html); }
	else { $(parentIdCleanup(parentId)).append(html); }
}

idClock = 0;
function getId() {
	idClock++;
	return "attribute-list-" + idClock;
}

function parentIdCleanup(parentId) {
	parentId = parentId.replace(/:/g, "\\:");
	parentId = parentId.replace(/\$/g, "\\$");
	parentId = parentId.replace(/\./g, "\\.");

	return "#" + parentId;
}

function typeChooser(obj, parentId) {
	for (property in obj) {
		if (property.indexOf("_") == 0) { continue; }
		if (property.indexOf("HarvestInformation") == 0) { continue; }
		switch ($.type(obj[property])) {
		case "function":
			break;
		case "object":
			renderObject(obj[property], property, "object", parentId);
			break;
		case "array":
			renderObject(obj[property], property, "array", parentId);
			break;
		default:
			addHtml(valueAsHtml(obj[property], property), parentId);
			break;
		}
	}
}

function renderObject(obj, propertyName, type, parentId) {
	thisId = getId();
	addHtml(objAsHtml(propertyName, type, thisId), parentId);
	addHtml(controlToolbar(thisId, true, true), thisId + "-header", true);
	typeChooser(obj, thisId);
}

function addHtml(html, parentId, shouldPrepend) {
	parent = $(parentIdCleanup(parentId));
	if (shouldPrepend) { parent.prepend(html); }
	else { $(parentIdCleanup(parentId)).append(html); }
}

Adjust editor UI to ignore harvest information. This may serve as a precedent for dealing exclusively with other pieces of content.


export default {
    name: 'authentication',

    initialize: function(container, application) {
        application.inject('model', 'session', 'simple-auth-session:main');
    }
};

export default {
    name: 'authentication',

    initialize: function(container, application) {
        application.inject('model', 'session', 'simple-auth-session:main');
        application.inject('adapter', 'session', 'simple-auth-session:main');
    }
};

Make sure adapters have access to session.


require.config({
	baseUrl: 'app',

	paths : {
		jquery: '../components/jquery/jquery.min',
		modernizr: '../components/modernizer/modernizr'
	}
});

require(['jquery', 'modernizr'], function($, modernizer) {
	// use app here
	$('#status').html('If you can read this text, your stack should be alright.');
});

require.config({
	baseUrl: 'app',

	paths : {
		jquery: '../components/jquery/jquery.min',
		modernizr: '../components/modernizr/modernizr'
	}
});

require(['jquery', 'modernizr'], function($, modernizer) {
	// use app here
	$('#status').html('If you can read this text, your stack should be alright.');
});

Fix typo in modernizr require path


$(function() {
    const $tool = $('#id_tool');
    const $toolOptions = $('#row-tool_options');

    if ($tool.length === 1 && $toolOptions.length === 1) {
        const $itemAboveOptions = $toolOptions.prev();

        function changeToolVisibility() {
            const selectedTool = parseInt($tool.val(), 10);
            let $lastVisibleChild = null;

            $toolOptions.find('.form-row').each((i, el) => {
                const $el = $(el);

                if ($el.data('tool-id') === selectedTool) {
                    $el.show();
                    $lastVisibleChild = $el;
                } else {
                    $el.hide();
                }
            });

            /*
             * Normally, the :last-child rule would hide this border. Instead,
             * we have to override it because the parent has a bunch of other
             * children after the last one that happen to be hidden.
             */
            if ($lastVisibleChild !== null) {
                $lastVisibleChild.css('border-bottom', 0);
                $itemAboveOptions.css('border-bottom', '');
            } else {
                $itemAboveOptions.css('border-bottom', 0);
            }
        }

        $tool.change(() => changeToolVisibility());
        changeToolVisibility();
    }
});

$(function() {
    const $tool = $('#id_tool');
    const $toolOptions = $('#row-tool_options');

    if ($tool.length === 1 && $toolOptions.length === 1) {
        const $itemAboveOptions = $toolOptions.prev();

        function changeToolVisibility() {
            const selectedTool = parseInt($tool.val(), 10);
            let $lastVisibleChild = null;

            $toolOptions.find('.form-row').each((i, el) => {
                const $el = $(el);
                const $input = $toolOptions.find('input, select, textarea');

                if ($el.data('tool-id') === selectedTool) {
                    $el.show();
                    $lastVisibleChild = $el;

                    /*
                     * Chrome validation will go nuts even on form fields that
                     * aren't visible unless they're also disabled.
                     */
                    $input.prop('disabled', true);
                } else {
                    $el.hide();
                    $input.prop('disabled', false);
                }
            });

            /*
             * Normally, the :last-child rule would hide this border. Instead,
             * we have to override it because the parent has a bunch of other
             * children after the last one that happen to be hidden.
             */
            if ($lastVisibleChild !== null) {
                $lastVisibleChild.css('border-bottom', 0);
                $itemAboveOptions.css('border-bottom', '');
            } else {
                $itemAboveOptions.css('border-bottom', 0);
            }
        }

        $tool.change(() => changeToolVisibility());
        changeToolVisibility();
    }
});

Work around Chrome's over-eager validation of integration config form.


'use strict';

const Server = require('./server');

class ServersManager {
  constructor() {
    this.servers = [];
  }

  addServer(options) {
    if (this.servers.filter(s => s.port === options.port).length > 0) {
      throw new Error('This port is already in use.');
    }
    try {
      let server = new Server(options);
      this.servers.push(server);
    } catch(_) {
      throw new Error('This port is already in use.');
    }
  }

  removeServer(server) {
    server.stop();
    const indexToRemove = this.servers.indexOf(server);
    if (indexToRemove > -1) {
      this.servers.splice(indexToRemove, 1);
    }
  }
}

module.exports = ServersManager;

'use strict';

const Server = require('./server');

class ServersManager {
  constructor() {
    this.servers = [];
  }

  addServer(options) {
    if (this.servers.filter(s => s.port === options.port).length > 0) {
      throw new Error('This port is already in use.');
    }
    // Path and port are mandatory
    if (!options.path && !options.port) {
      throw new Error('You have to chose a directory and a port');
    }
    if (!options.path) {
      throw new Error('You have to chose a directory');
    }
    if (!options.port) {
      throw new Error('You have to chose a port');
    }
    try {
      let server = new Server(options);
      this.servers.push(server);
    } catch(e) {
      console.log(e);
      throw new Error('This port is already in use.');
    }
  }

  removeServer(server) {
    server.stop();
    const indexToRemove = this.servers.indexOf(server);
    if (indexToRemove > -1) {
      this.servers.splice(indexToRemove, 1);
    }
  }
}

module.exports = ServersManager;

Handle options errors in server-manager


'use strict';
var assert = require('assert');

exports = module.exports = promissory;

function promissory(fn) {
	assert(typeof fn == 'function', 'function required');

	return function() {
		var args = arrayFrom(arguments);
		var ctx = this;

		return new Promise(function(resolve, reject) {
			args.push(function promisedWork() {
				var args = arrayFrom(arguments);

				if (args[0]) {
					reject(args[0]);
				} else if (args.length == 2) {
					resolve(args[1]);
				} else {
					resolve(args.slice(1));
				}
			});
			fn.apply(ctx, args);
		});
	};
}

function arrayFrom(oldArgs) {
	var args = new Array(oldArgs.length);
	var i;

	for (i = 0; i < args.length; i++) {
		args[i] = oldArgs[i];
	}
	return args;
}

'use strict';
var assert = require('assert');

exports = module.exports = promissory;

function promissory(fn) {
	assert(typeof fn == 'function', 'function required');

	return function() {
		var args = new Array(arguments.length);
		var ctx = this;
		var i;

		for (i = 0; i < arguments.length; i++) {
			args[i] = arguments[i];
		}

		return new Promise(function(resolve, reject) {
			args.push(function promisedWork() {
				var args = new Array(arguments.length);
				var i;

				for (i = 0; i < arguments.length; i++) {
					args[i] = arguments[i];
				}

				if (args[0]) {
					reject(args[0]);
				} else if (args.length == 2) {
					resolve(args[1]);
				} else {
					resolve(args.slice(1));
				}
			});
			fn.apply(ctx, args);
		});
	};
}

Change args change to be optimizable


/*global Playground*/

(function() {
  "use strict";

  Playground.VideoService = Conductor.Oasis.Service.extend({
    initialize: function (port) {
      this.sandbox.videoPort = port;
    },

    events: {
      videoWatched: function () {
      }
    }
  });

  Playground.SurveyService = Conductor.Oasis.Service.extend({
    initialize: function (port) {
      this.sandbox.surveyPort = port;
    },

    events: {
      surveyTaken: function () {
      }
    }
  });

  Playground.SlotMachine = Conductor.Oasis.Service.extend({
    initialize: function (port) {
      this.sandbox.slotMachinePort = port;
    },

    events: {
      getCoins: function () {
      }
    }
  });

  Playground.AdPlaylistService = Conductor.Oasis.Service.extend({
    initialize: function (port) {
      this.sandbox.adPlaylistPort = port;
    },

    events: {
      surveyTaken: function (data) {
        this.sandbox.slotMachinePort.send('addCoin');
      }
    }
  });

  $.extend(Playground, {
    initializeServices: function () {
      Conductor.services.video = Playground.VideoService;
      Conductor.services.survey = Playground.SurveyService;
      Conductor.services.slotMachine = Playground.SlotMachine;
    }
  });
})();

/*global Playground*/

(function() {
  "use strict";

  Playground.VideoService = Conductor.Oasis.Service.extend({
    initialize: function (port) {
      this.sandbox.videoPort = port;
    }
  });

  Playground.SurveyService = Conductor.Oasis.Service.extend({
    initialize: function (port) {
      this.sandbox.surveyPort = port;
    }
  });

  Playground.SlotMachine = Conductor.Oasis.Service.extend({
    initialize: function (port) {
      this.sandbox.slotMachinePort = port;
    }
  });

  Playground.AdPlaylistService = Conductor.Oasis.Service.extend({
    initialize: function (port) {
      this.sandbox.adPlaylistPort = port;
    },

    events: {
      surveyTaken: function (data) {
        this.sandbox.slotMachinePort.send('addCoin');
      }
    }
  });

  $.extend(Playground, {
    initializeServices: function () {
      Conductor.services.video = Playground.VideoService;
      Conductor.services.survey = Playground.SurveyService;
      Conductor.services.slotMachine = Playground.SlotMachine;
    }
  });
})();

Remove no-op event handlers in playground.


'use strict';

module.exports = [
    'webmap.cgi',
    'helpdesk.cgi',
    'info.cgi',
    'administrator.cgi',
    'index.cgi',
    'admin.cgi',
    'whois.cgi',
    'report.cgi',
    'main.cgi',
    'index2.cgi',
    'reboot.cgi',
    'firewall.cgi',
    'kontakt.cgi',
    'query.cgi',
    'concept.cgi',
    'cgi-bin/printenv',
    'backup.cgi',
    'counter.cgi',
    'supply.cgi',
    'test.sh',
    'formmail.cgi',
    'count.cgi',
    'testproxy.php', // open proxy test
    'tmunblock.cgi',
    'getheaders9.php',
    'getheaders2.php',
    'cgi-bin/common/attr', // open proxy test
    'scripts/setup.php', // phpMyAdmin setup path
    'muieblackcat' // Muieblackcat http://eromang.zataz.com/2011/08/14/suc027-muieblackcat-setup-php-web-scanner-robot/
];

'use strict';

module.exports = [
    'admin.cgi',
    'administrator.cgi',
    'backup.cgi',
    'cgi-bin/common/attr', // open proxy test
    'cgi-bin/printenv',
    'concept.cgi',
    'count.cgi',
    'counter.cgi',
    'firewall.cgi',
    'formmail.cgi',
    'getheaders2.php',
    'getheaders9.php',
    'helpdesk.cgi',
    'index.cgi',
    'index2.cgi',
    'info.cgi',
    'kontakt.cgi',
    'main.cgi',
    'muieblackcat', // Muieblackcat http://eromang.zataz.com/2011/08/14/suc027-muieblackcat-setup-php-web-scanner-robot/
    'query.cgi',
    'reboot.cgi',
    'report.cgi',
    'scripts/setup.php', // phpMyAdmin setup path
    'supply.cgi',
    'test.sh',
    'testproxy.php', // open proxy test
    'tmunblock.cgi',
    'webmap.cgi',
    'whois.cgi'
];

Sort alphabetically to avoid duplicates


//
// Tests for basecoin
//

const Promise = require('bluebird');
const co = Promise.coroutine;
const _ = require('lodash');

require('should');

const TestV2BitGo = require('../../lib/test_bitgo');
const bitgo = new TestV2BitGo({ env: 'test' });
bitgo.initializeTestVars();

describe('V2 Base Coin:', function() {

  describe('fee estimate call', function() {

    before(() => require('nock').restore());

    _.forEach(['tbtc', 'trmg', 'tltc', 'tbch', 'tbtg'], function(coin) {
      const basecoin = bitgo.coin(coin);

      it('should fetch fee info for utxo coins', co(function *() {
        const feeInfo = yield basecoin.feeEstimate();
        feeInfo.should.have.property('feePerKb');
        feeInfo.should.have.property('numBlocks');
      }));
    });

    _.forEach(['teth', 'txrp'], function(coin) {
      const basecoin = bitgo.coin(coin);

      it('should fail to to fetch fee info for account coin', co(function *() {
        try {
          yield basecoin.feeEstimate();
          throw new Error();
        } catch (err) {
          err.message.should.equal('cannot get fee estimate data for ' + coin);
        }
      }));
    });
  });
});

//
// Tests for basecoin
//

const Promise = require('bluebird');
const co = Promise.coroutine;
const _ = require('lodash');

require('should');

const TestV2BitGo = require('../../lib/test_bitgo');
const bitgo = new TestV2BitGo({ env: 'test' });
bitgo.initializeTestVars();

describe('V2 Base Coin:', function() {

  describe('fee estimate call', function() {

    before(() => require('nock').restore());

    _.forEach(['tbtc', 'trmg', 'tltc', 'tbch'], function(coin) {
      const basecoin = bitgo.coin(coin);

      it('should fetch fee info for utxo coins', co(function *() {
        const feeInfo = yield basecoin.feeEstimate();
        feeInfo.should.have.property('feePerKb');
        feeInfo.should.have.property('numBlocks');
      }));
    });

    _.forEach(['teth', 'txrp'], function(coin) {
      const basecoin = bitgo.coin(coin);

      it('should fail to to fetch fee info for account coin', co(function *() {
        try {
          yield basecoin.feeEstimate();
          throw new Error();
        } catch (err) {
          err.message.should.equal('cannot get fee estimate data for ' + coin);
        }
      }));
    });
  });
});

Remove TBTG fee info test


// !!
// This module defines ProseMirror's document model, the data
// structure used to define and inspect content documents. It
// includes:
//
// * The [node](#Node) type that represents document elements
//
// * The [schema](#Schema) types used to tag and constrain the
//   document structure
//
// * The data type for document [positions](#Pos)

export {Node} from "./node"
export {Fragment, emptyFragment} from "./fragment"
export {Mark} from "./mark"

export {SchemaSpec, Schema, SchemaError,
        NodeType, Block, Textblock, Inline, Text,
        MarkType, Attribute} from "./schema"
export {defaultSchema, Doc, BlockQuote, OrderedList, BulletList, ListItem,
        HorizontalRule, Paragraph, Heading, CodeBlock, Image, HardBreak,
        CodeMark, EmMark, StrongMark, LinkMark} from "./defaultschema"

export {Pos} from "./pos"

export {findDiffStart, findDiffEnd} from "./diff"

// !!
// This module defines ProseMirror's document model, the data
// structure used to define and inspect content documents. It
// includes:
//
// * The [node](#Node) type that represents document elements
//
// * The [schema](#Schema) types used to tag and constrain the
//   document structure
//
// * The data type for document [positions](#Pos)
//
// This module does not depend on the browser API being available
// (i.e. you can load it into any JavaScript environment).

export {Node} from "./node"
export {Fragment, emptyFragment} from "./fragment"
export {Mark} from "./mark"

export {SchemaSpec, Schema, SchemaError,
        NodeType, Block, Textblock, Inline, Text,
        MarkType, Attribute} from "./schema"
export {defaultSchema, Doc, BlockQuote, OrderedList, BulletList, ListItem,
        HorizontalRule, Paragraph, Heading, CodeBlock, Image, HardBreak,
        CodeMark, EmMark, StrongMark, LinkMark} from "./defaultschema"

export {Pos} from "./pos"

export {findDiffStart, findDiffEnd} from "./diff"

Add note about model/transform modules not depending on the browser


import { HeaderService } from "./header.service.js";

export class HeaderTemplate {
    static update(render) {
        const start = Date.now();

        /* eslint-disable indent */
        render`

                        ConPA 5
                        Asset Allocation App

                        <toasts></toasts>

${{
                            any: HeaderService.getStatus().then(({ namespace: status }) => {
                                const end = Date.now();

                                return `${status.message} (${end - start}ms)`;
                            }),
                            placeholder: "Loading..."
                        }}

        `;
        /* eslint-enable indent */
    }
}

Improve status and toasts in header.


$(document).ready(function() {
	current_url = window.location.href
	if (current_url.match("&closewin=true")) {
		window.close();
	}
});

$(document).ready(function() {
  if (location.search.match("&closewin=true")) {
		if (window.opener) {
			var msgDiv = $("div.messages");
			var msg = msgDiv.children("p").text();
			var status = msgDiv.hasClass("success") ?
				'success' : 'unknown';
			var url = $(".tool.link")[0].href;
			window.opener.postMessage({"wallabag-status": status,
				"wallabag-msg": msg,
				"wallabag-url": url }, "*");
		}
		window.close();
	}
});

Send postMessage to opener before autoclose


module.exports = {
  content: ['frontend/javascript/*.js','./output/**/*.html'],
  output: "./output/_bridgetown/static"
}

module.exports = {
  content: ['frontend/javascript/*.js','./output/**/*.html'],
  // https://stackoverflow.com/questions/65554596/purgecss-and-tailwind-css-how-to-preserve-responsive-classes-using-the-command
  // defaultExtractor: (content) => content.match(/[\w-/:]+(?<!:)/g) || [],
  defaultExtractor: (content) => content.match(/[\w-/:.]+(?<!:)/g) || [],
  output: "./output/_bridgetown/static"
}

Add tailwind specific extractor to purgeCSS


jA.fn.formExplode = function()
{
    var formData = {};

    this.find('[name]').each(function()
    {
        formData[this.name] = this.value == '' ? undefined : this.value;
    });

    return formData;
}

jA.fn.formExplode = function()
{
    var formData = {};

    this.find('[name]').each(function()
    {
        if(this.type !== 'file')
            formData[this.name] = this.value == '' ? undefined : this.value;
    });

    return formData;
}

Remove the file field from the formExplode().


const assert = require('assert');
const expect = require('chai').expect;

const Doorman = require('../lib/doorman');
const Service = require('../lib/service');

const EventEmitter = require('events').EventEmitter;

describe('Doorman', function () {
  it('should expose a constructor', function () {
    assert(Doorman instanceof Function);
  });

  it('can handle a message', function (done) {
    let doorman = new Doorman();
    let source = new EventEmitter();
    let sample = { 'test': 'Successfully handled!' };

    doorman.use(sample);

    doorman.on('response', function (message) {
      assert.equal(message.parent, 'local/messages/test');
      assert.equal(message.response, sample.test);
      done();
    });

    doorman.start();

    doorman.services.local.emit('message', {
      id: 'test',
      actor: 'Alice',
      target: 'test',
      object: 'Hello, world!  This is a !test of the message handling flow.'
    });
  });
});

const assert = require('assert');
const expect = require('chai').expect;

const Doorman = require('../lib/doorman');
const Service = require('../lib/service');

const EventEmitter = require('events').EventEmitter;

describe('Doorman', function () {
  it('should expose a constructor', function () {
    assert(Doorman instanceof Function);
  });

  it('can handle a message', function (done) {
    let doorman = new Doorman();
    let source = new EventEmitter();
    let sample = { 'test': 'Successfully handled!' };

    doorman.use(sample);

    doorman.on('response', function (message) {
      assert.equal(message.parent.id, 'local/messages/test');
      assert.equal(message.response, sample.test);
      done();
    });

    doorman.start();

    doorman.services.local.emit('message', {
      id: 'test',
      actor: 'Alice',
      target: 'test',
      object: 'Hello, world!  This is a !test of the message handling flow.'
    });
  });
});

Update message/response test to use new API


/*!
 * ${copyright}
 */

// Provides the Design Time Metadata for the sap.m.Select control
sap.ui.define([],
	function() {
	"use strict";

	return {
		palette: {
			group: "INPUT",
			icons: {
				svg: "sap/m/designtime/Select.icon.svg"
			}
		},
		aggregations : {
			items : {
				domRef : ":sap-domref"
			}
		},
		templates: {
			create: "sap/m/designtime/Select.create.fragment.xml"
		}
	};

}, /* bExport= */ false);

/*!
 * ${copyright}
 */

// Provides the Design Time Metadata for the sap.m.Select control
sap.ui.define([],
	function() {
	"use strict";

	return {
		palette: {
			group: "INPUT",
			icons: {
				svg: "sap/m/designtime/Select.icon.svg"
			}
		},
		aggregations : {
			items : {
				domRef : ":sap-domref"
			},
			picker: {
				ignore: true
			}
		},
		templates: {
			create: "sap/m/designtime/Select.create.fragment.xml"
		}
	};

}, /* bExport= */ false);

Disable picker aggregation in sap.m.Select


l = console.log();

module.exports = {

    VERSION: "Jofogas's Zsozsobot v3",

  compute_avg_stack: function(players) {
      var sum = 0;
      for (var i in players) {
          sum += players.stack;
      }
      return sum / players.count;
  },

  bet_request: function(g) {
    var myself = g.players[g.in_action];

    if (myself.status != "active") {
        return "OK";
    }
    if (myself.hole_cards[1].rank == myself.hole_cards[1].rank) {
        return player.stack;
    }
    var average_stack = compute_avg_stack(g.players);

    if (myself.stack > average_stack) {
        /* brave */
        var bet = g.current_buy_in - myself["bet"] + g.minimum_raise * 2;
        l("fearlessly raising: ", bet);
        return bet;
    }
    else {
        /* tight */
        l("fearfully not raising: ", 0);
        return 0;
    }
  },

    showdown: function(g) {

    }
};

l = console.log();

function toNum(c) {
    switch(c) {
        case 'J':
            return 11;
            break;
        case 'Q':
            return 12;
            break;
        case 'K':
            return 13;
            break;
        case 'A':
            return 14;
            break;

        default:
            return card
    }
}

module.exports = {

    VERSION: "Jofogas's Zsozsobot v3",

  compute_avg_stack: function(players) {
      var sum = 0;
      for (var i in players) {
          sum += players.stack;
      }
      return sum / players.count;
  },

  bet_request: function(g) {
    var myself = g.players[g.in_action];

    if (myself.status != "active") {
        return "OK";
    }
    if (myself.hole_cards[1].rank == myself.hole_cards[1].rank) {
        return player.stack;
    }
    var average_stack = compute_avg_stack(g.players);

    if (myself.stack > average_stack) {
        /* brave */
        var bet = g.current_buy_in - myself["bet"] + g.minimum_raise * 2;
        l("fearlessly raising: ", bet);
        return bet;
    }
    else {
        /* tight */
        l("fearfully not raising: ", 0);
        return 0;
    }
  },

    showdown: function(g) {

    }
};

Add card to number converter


/* global exports, console */
"use strict";

// module Debug.Trace

exports.traceAny = function (x) {
  return function (k) {
    console.log(x);
    return k({});
  };
};

/* global exports, console, require */
"use strict";

// module Debug.Trace

exports.traceAny = function (x) {
  return function (k) {
    // node only recurses two levels into an object before printing
    // "[object]" for further objects when using console.log()
    if (require !== undefined) {
      var util = require("util");
      console.log(util.inspect(x, { depth: null, colors: true }));
    } else {
      console.log(x);
    }

    return k({});
  };
};

Use util.inspect with depth: null for traceAny on node.js


import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

moduleForComponent('editable-field', 'Integration | Component | editable field', {
  integration: true
});

test('it renders', function(assert) {
  assert.expect(2);

  // Set any properties with this.set('myProperty', 'value');
  // Handle any actions with this.on('myAction', function(val) { ... });

  // We can pass text to show when editing
  this.render(hbs`
    {{#editable-field}}
      show when editing
    {{/editable-field}}
  `);

  assert.ok(!this.$().text().includes('show when editing'));

  // After clicking on the placeholder, we should see our passed text
  this.$().find('a').click();
  assert.ok(this.$().text().includes('show when editing'));
});

import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import Ember from 'ember';

moduleForComponent('editable-field', 'Integration | Component | editable field', {
  integration: true
});

test('it renders', function(assert) {
  assert.expect(2);

  // Set any properties with this.set('myProperty', 'value');
  // Handle any actions with this.on('myAction', function(val) { ... });

  // We can pass text to show when editing
  this.render(hbs`
    {{#editable-field}}
      show when editing
    {{/editable-field}}
  `);

  assert.ok(!this.$().text().includes('show when editing'));

  // After clicking on the placeholder, we should see our passed text
  this.$().find('a').click();
  assert.ok(this.$().text().includes('show when editing'));
});

test('clicking on the body cancels editing', function(assert) {
  assert.expect(2);

  this.render(hbs`

Click me

    {{#editable-field}}
      editing
    {{/editable-field}}
  `);

  Ember.run(() => this.$().find('a').click());
  assert.ok(this.$().text().includes('editing'));

  // After clicking somewhere on the document body, we should return to normal mode
  Ember.run(() => this.$().find('#cancel').click());
  assert.ok(!this.$().text().includes('editing'));
});

Add testcase for canceling edit mode by clicking elsewhere in the document


jest.dontMock('../Util');

var Util = require('../Util');

describe('Util', function() {

  describe('#extend', function () {
    beforeEach(function () {
      this.originalObj = {
        a: 5,
        b: 10,
        c: 15
      };
    });

    it('should not change any properties if passed a single argument', function () {
      var newObj = Util.extend(this.originalObj);

      for (var key in newObj) {
        expect(newObj[key]).toEqual(this.originalObj[key]);
      }
    });

    it('should combine properties with the source', function () {
      var source = {
        a: 'changed prop'
      };

      var newObj = Util.extend(this.originalObj, source);
      expect(newObj.a).toEqual('changed prop');
    });

    it('should handle multiple arguments', function () {
      var obj1 = {
        a: 'changed prop',
        b: 'changed prop'
      };

      var obj2 = {
        a: 'overrode prop'
      };

      var newObj = Util.extend(this.originalObj, obj1, obj2);
      expect(newObj.a).toEqual('overrode prop');
      expect(newObj.b).toEqual('changed prop');
    });
  });

});

jest.dontMock('../Util');

var Util = require('../Util');

describe('Util', function() {

  describe('#extend', function () {
    beforeEach(function () {
      this.originalObj = {
        a: 5,
        b: 10,
        c: 15
      };
    });

    it('should not change any properties if passed a single argument', function () {
      var newObj = Util.extend(this.originalObj);

      for (var key in this.originalObj) {
        expect(newObj[key]).toEqual(this.originalObj[key]);
      }
    });

    it('should combine properties with the source', function () {
      var source = {
        a: 'changed prop'
      };

      var newObj = Util.extend(this.originalObj, source);
      expect(newObj.a).toEqual('changed prop');
    });

    it('should handle multiple arguments', function () {
      var obj1 = {
        a: 'changed prop',
        b: 'changed prop'
      };

      var obj2 = {
        a: 'overrode prop'
      };

      var newObj = Util.extend(this.originalObj, obj1, obj2);
      expect(newObj.a).toEqual('overrode prop');
      expect(newObj.b).toEqual('changed prop');
    });
  });

});

Test properties from originalObj, not newObj


import React from 'react';
import TestUtils from 'react-dom/test-utils';
import Fieldset from './fieldset';
import Textbox from './../textbox';
import { shallow } from 'enzyme';
import { elementsTagTest, rootTagTest } from '../../utils/helpers/tags/tags-specs';

describe('Fieldset', () => {
  let instance;

  beforeEach(() => {
    instance = TestUtils.renderIntoDocument(<Fieldset><Textbox /></Fieldset>);
  });

  it('renders its children', () => {
    let child = TestUtils.findRenderedComponentWithType(instance, Textbox);
    expect(child).toBeDefined();
  });

  it('applies any props to the fieldset', () => {
    instance = TestUtils.renderIntoDocument(<Fieldset id="foo"><Textbox /></Fieldset>);
    let child = TestUtils.findRenderedDOMComponentWithTag(instance, 'fieldset');
    expect(child.id).toEqual('foo');
  });

  describe('if a legend is supplied', () => {
    it('renders its legend', () => {
      instance = TestUtils.renderIntoDocument(<Fieldset legend="foo"><Textbox /></Fieldset>);
      let child = TestUtils.findRenderedDOMComponentWithTag(instance, 'legend');
      expect(child).toBeDefined();
    });
  });

  describe("tags", () => {
    describe("on component", () => {
      let wrapper = shallow(<Fieldset data-element='bar' data-role='baz' />);

      it('include correct component, element and role data tags', () => {
        rootTagTest(wrapper, 'fieldset', 'bar', 'baz');
      });
    });

    describe("on internal elements", () => {
      let wrapper = shallow(<Fieldset legend='test' />);

      elementsTagTest(wrapper, [
        'legend'
      ]);
    });
  });
});

import React from 'react';
import { shallow } from 'enzyme';
import Fieldset from './fieldset.component';
import Textbox from '../textbox';
import { LegendStyle } from './fieldset.style';

function render(props, renderType = shallow) {
  return renderType(
    <Fieldset { ...props }>
      <Textbox />
    </Fieldset>
  );
}

describe('Fieldset', () => {
  it('renders its children', () => {
    const wrapper = render();
    expect(wrapper.find(Textbox).length).toEqual(1);
  });

  describe('Fieldset Legend', () => {
    it('is rendered if supplied', () => {
      const wrapper = render({ legend: 'Legend' });
      expect(wrapper.find(LegendStyle).length).toEqual(1);
    });
  });
});

Update Specs for New Fieldset


import cluster from "cluster";

export default class StartServerPlugin {
  constructor() {
    this.afterEmit = this.afterEmit.bind(this);
    this.apply = this.apply.bind(this);
    this.startServer = this.startServer.bind(this);

    this.worker = null;
  }

  afterEmit(compilation, callback) {
    if (this.worker && this.worker.isConnected()) {
      return callback();
    }

    this.startServer(compilation, callback);
  }

  apply(compiler) {
    compiler.plugin("after-emit", this.afterEmit);
  }

  startServer(compilation, callback) {
    const entry = Object.keys(compilation.assets).shift();
    const { existsAt } = compilation.assets[entry];

    cluster.setupMaster({ exec: existsAt });

    cluster.on("online", (worker) => {
      this.worker = worker;
      callback();
    });

    cluster.fork();
  }
}

import cluster from "cluster";

export default class StartServerPlugin {
  constructor(entry) {
    this.entry = entry;
    this.afterEmit = this.afterEmit.bind(this);
    this.apply = this.apply.bind(this);
    this.startServer = this.startServer.bind(this);

    this.worker = null;
  }

  afterEmit(compilation, callback) {
    if (this.worker && this.worker.isConnected()) {
      return callback();
    }

    this.startServer(compilation, callback);
  }

  apply(compiler) {
    compiler.plugin("after-emit", this.afterEmit);
  }

  startServer(compilation, callback) {
    let entry;
    const entries = Object.keys(compilation.assets);
    if (this.entry) {
      entry = this.entry;
      if (!compilation.assets[entry]) {
        console.error("Entry " + entry + " not found. Try one of: " + entries.join(" "));
    } else {
      entry = entries[0];
      if (entries.length > 1) {
        console.log("More than one entry built, selected " + entry + ". All entries: " + entries.join(" "));
      }
    }
    const { existsAt } = compilation.assets[entry];

    cluster.setupMaster({ exec: existsAt });

    cluster.on("online", (worker) => {
      this.worker = worker;
      callback();
    });

    cluster.fork();
  }
}

Allow specifying entry to run