(function () {
    'use strict';

    document.addEventListener('DOMContentLoaded', function () {
        var instructions = document.querySelector('#instructions');
        var paste_bin = document.querySelector('#paste-bin');
        var output = document.querySelector('#output');
        var output_wrapper = document.querySelector('#output-wrapper');
        var clear = document.querySelector('#clear');

        document.addEventListener('keydown', function (event) {
            if (event.ctrlKey || event.metaKey) {
                if (String.fromCharCode(event.which).toLowerCase() === 'v') {
                    paste_bin.innerHTML = '';
                    paste_bin.focus();
                    instructions.classList.add('hidden');
                    output_wrapper.classList.add('hidden');
                }
            }
        });

        paste_bin.addEventListener('paste', function () {
            setTimeout(read_paste_bin, 200);
        });

        var read_paste_bin = function () {
            var text_html = paste_bin.innerHTML;
            var text_markdown = html2markdown(text_html, {
                inlineStyle: true
            });
            output.value = text_markdown;
            output_wrapper.classList.remove('hidden');
        };

        clear.addEventListener('click', function () {
            output.value = '';
            output_wrapper.classList.add('hidden');
        });

    });
})();

function trim(value) {
    return value.replace(/^\s+|\s+$/g, "");
}

function asciify(str) {
    return str.replace(/[\u2018\u2019]/g, "'")
              .replace(/[\u201c\u201d]/g, '"')
              .replace(/\u2013/g, "--")
              .replace(/\u2014/g, "---")
              .replace(/\u2026/g, "...");
}

(function () {
    'use strict';

    document.addEventListener('DOMContentLoaded', function () {
        var instructions = document.querySelector('#instructions');
        var paste_bin = document.querySelector('#paste-bin');
        var output = document.querySelector('#output');
        var output_wrapper = document.querySelector('#output-wrapper');
        var clear = document.querySelector('#clear');

        document.addEventListener('keydown', function (event) {
            if (event.ctrlKey || event.metaKey) {
                if (String.fromCharCode(event.which).toLowerCase() === 'v') {
                    paste_bin.innerHTML = '';
                    paste_bin.focus();
                    instructions.classList.add('hidden');
                    output_wrapper.classList.add('hidden');
                }
            }
        });

        paste_bin.addEventListener('paste', function () {
            setTimeout(read_paste_bin, 200);
        });

        var read_paste_bin = function () {
            var text_html = paste_bin.innerHTML;
            var text_markdown = trim(asciify(html2markdown(text_html, {
                inlineStyle: true
            })));
            output.value = text_markdown;
            output_wrapper.classList.remove('hidden');
        };

        clear.addEventListener('click', function () {
            output.value = '';
            output_wrapper.classList.add('hidden');
        });

    });
})();

Convert punctuation to pure ASCII


var express = require('express');
var router = express.Router();
var request = require('request');

router.post('/', function(req, res) {
  if (req.query.secret !== process.env.SECRET) {
    res.sendStatus(404).end();
  } else if (req.body.build.status !== 'success') {
    var payload = {
      channel: '#hackers',
      username: 'DoomGuy',
      icon_emoji: ':godmode:',
      attachments: [{
        fallback: 'Alert',
        color: 'danger',
        text: '<!channel>',
        fields: [{
          title: 'Alert From',
          value: 'CodeShip',
          short: 'true'
        }, {
          title: 'Build Failed',
          value: '<' + req.body.build.build_url + '|' + req.body.build.message + '>',
          short: 'true'
        }, {
          title: 'Shame upon',
          value: '<' + req.body.build.commit_url + '|' + req.body.build.commiter + '>',
          short: 'true'
        }]
      }]
    };

    request({
      url: process.env.URL,
      method: 'POST',
      body: JSON.stringify(payload)
    }, function() {
      res.end();
    });
  } else {
    res.end();
  }
});

module.exports = router;

var express = require('express');
var router = express.Router();
var request = require('request');

router.post('/', function(req, res) {
  if (req.query.secret !== process.env.SECRET) {
    res.sendStatus(404).end();
  } else if (req.body.build.status !== 'testing' && req.body.build.status !== 'success') {
    var payload = {
      channel: '#hackers',
      username: 'DoomGuy',
      icon_emoji: ':godmode:',
      attachments: [{
        fallback: 'Alert',
        color: 'danger',
        text: '<!channel>',
        fields: [{
          title: 'Alert From',
          value: 'CodeShip',
          short: 'true'
        }, {
          title: 'Build Failed',
          value: '<' + req.body.build.build_url + '|' + req.body.build.message + '>',
          short: 'true'
        }, {
          title: 'Shame upon',
          value: '<' + req.body.build.commit_url + '|' + req.body.build.committer + '>',
          short: 'true'
        }]
      }]
    };

    request({
      url: process.env.URL,
      method: 'POST',
      body: JSON.stringify(payload)
    }, function() {
      res.end();
    });
  } else {
    res.end();
  }
});

module.exports = router;

Add skip for testing status.


// This code is injected into every page
(function () {
    'use strict';
    /*jslint browser: true */
    /*global chrome, console */

    var parents;

    // Get the position of a element in the list of its siblings
    function getElementPosition(element, siblings) {
        var position = 0,
            i = 0;

        for (i = 0; i < siblings.length; i += 1) {
            if (element === siblings[i]) {
                position = i;
                break;
            }
        }

        return position;
    }

    // Get the list of parents and position of the clicked element
    function getParents(clicked) {
        var el = clicked,
            parents = [],
            position = 0;

        while (el.parentElement.nodeName !== 'HTML') {
            position = getElementPosition(el, el.parentElement.children);
            el = el.parentElement;
            parents.push(position);
        }

        return parents;
    }

    // Click handler
    document.onmousedown = function (evt) {
        parents = getParents(evt.target);
    };

    // Return the list of node positions
    function getSource() {
        var message = {
            method: "returnSource",
            parents: parents
        };

        return message;
    }

    // Add listener to send the data when requested
    chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
        if (request.method === "sendSource") {
            sendResponse(getSource());
        }
    });
}());

// This code is injected into every page
(function () {
    'use strict';
    /*jslint browser: true */
    /*global chrome, console */

    var parents;

    // Get the position of a element in the list of its siblings
    function getElementPosition(element, siblings) {
        var position = 0,
            i = 0;

        for (i = 0; i < siblings.length; i += 1) {
            if (element === siblings[i]) {
                position = i;
                break;
            }
        }

        return position;
    }

    // Get the list of parents and position of the clicked element
    function getParents(clicked) {
        var el = clicked,
            parents = [],
            position = 0;

        if (!el.parentElement) {
            return [];
        }

        while (el.parentElement.nodeName !== 'HTML') {
            position = getElementPosition(el, el.parentElement.children);
            el = el.parentElement;
            parents.push(position);
        }

        return parents;
    }

    // Click handler
    document.onmousedown = function (evt) {
        parents = getParents(evt.target);
    };

    // Return the list of node positions
    function getSource() {
        var message = {
            method: "returnSource",
            parents: parents
        };

        return message;
    }

    // Add listener to send the data when requested
    chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
        if (request.method === "sendSource") {
            sendResponse(getSource());
        }
    });
}());

Fix uncaught error when the click is on the HTML element


"use strict";

var sphero = require("../");
var orb = sphero(process.env.PORT);

orb.connect().then(function() {
  return orb.color({ red: 255, green: 0, blue: 255 });
}).then(function() {
  return orb.getBluetoothInfo();
}).then(function(data) {
  console.log("bluetoothInfo:");
  console.log("  name:", data.name);
  console.log("  btAddress:", data.btAddress);
  console.log("  separator:", data.separator);
  console.log("  colors:", data.colors);
});

"use strict";

var sphero = require("../");
var orb = sphero(process.env.PORT);

orb.connect().then(function() {
  return orb.color("FF00FF");
}).then(function() {
  return orb.getBluetoothInfo();
}).then(function(data) {
  console.log("bluetoothInfo:");
  console.log("  name:", data.name);
  console.log("  btAddress:", data.btAddress);
  console.log("  separator:", data.separator);
  console.log("  colors:", data.colors);
}).catch(function(err) {
  console.error("err:", err);
});

Add catch to promise bluetooth info example


import React, { Component } from 'react'
import firebase, { reference, signIn } from '../firebase';
import Message from './Message';

const MessageContainer = ({messages}) => {
  const newMessage = messages.map((message, i, array) => {
    return (

{message.time}

{message.user}

          {array[i].message}

    )
  })

  return (

      {newMessage}

  )
}

module.exports = MessageContainer;

Add key to each message to get rid of annoying error message


var ServiceModel = require('../core/service-model');
module.exports = ServiceModel.create("Story", {

  url: '/story',

  userSpace: {
    field: "_user"
  },
  timestamps: true,

  schema: {
    id: {
      type: Number,
      required: true,
      min: 1,
      autoIncrement: true,
      idField: true
    },
    title: {
      type: String,
      required: true
    },
    description: String,
    status: {
      type: String,
      required: true,
      default: 'new',
      enum: ['new', 'progress', 'done', 'hold']
    },
    createdDate: {
      type: Date,
      required: true,
      default: Date.now
    }
  },

  permissions: function() {
    return {
      item: {
        read: ['None'],
        write: ['None'],
        delete: ['None']
      },
      bulk: {
        read: ['None'],
        write: ['None'],
        delete: ['None']
      }
    };
  },

  configure: function() {
    console.log('configure');
    // this.model.path('name').set(function(v) {
    //   return capitalize(v);
    // });
  }
});

var ServiceModel = require('../core/service-model');
module.exports = ServiceModel.create("Story", {

  url: '/story',

  userSpace: {
    field: "_user"
  },
  timestamps: true,

  schema: {
    id: {
      type: Number,
      required: true,
      min: 1,
      autoIncrement: true,
      idField: true
    },
    title: {
      type: String,
      required: true
    },
    description: String,
    status: {
      type: String,
      required: true,
      default: 'new',
      enum: ['new', 'progress', 'done', 'hold']
    },
    createdDate: {
      type: Date,
      required: true,
      default: Date.now
    }
  },

  // permissions: function() {
  //   return {
  //     item: {
  //       read: ['None'],
  //       write: ['None'],
  //       delete: ['None']
  //     },
  //     bulk: {
  //       read: ['None'],
  //       write: ['None'],
  //       delete: ['None']
  //     }
  //   };
  // },

  configure: function() {
    // this.model.path('name').set(function(v) {
    //   return capitalize(v);
    // });
  }
});

Check in @ Fri Apr 29 10:34:20 IST 2016


/*
 * Copyright 2021 Simon Edwards <simon@simonzone.com>
 *
 * This source code is licensed under the MIT license which is detailed in the LICENSE.txt file.
 */
import * as https from 'node:https';

const log = console.log.bind(console);

/**
 * @param {string} url
 * @return {Promise<Buffer>}
 */
async function fetchUrl(url) {
  log(`Downloading ${url}`);
  return new Promise( (resolve, reject) => {
    https.get(url, {}, (resp) => {
      // log(resp.headers);
      // log(`statusCode: ${resp.statusCode}`);

      if (resp.statusCode === 302) {
        fetchUrl(resp.headers.location).then(data => resolve(data));
        return;
      }

      const data = [];
      resp.on('data', (chunk) => {
        data.push(chunk);
      });

      resp.on('end', () => {
        resolve(Buffer.concat(data));
      });
    }).on("error", (err) => {
      log("Error: " + err.message);
      reject("Error: " + err.message);
    });
  });
}
exports.fetchUrl = fetchUrl;

/*
 * Copyright 2021 Simon Edwards <simon@simonzone.com>
 *
 * This source code is licensed under the MIT license which is detailed in the LICENSE.txt file.
 */
import * as https from 'node:https';

const log = console.log.bind(console);

/**
 * @param {string} url
 * @return {Promise<Buffer>}
 */
export async function fetchUrl(url) {
  log(`Downloading ${url}`);
  return new Promise( (resolve, reject) => {
    https.get(url, {}, (resp) => {
      // log(resp.headers);
      // log(`statusCode: ${resp.statusCode}`);

      if (resp.statusCode === 302) {
        fetchUrl(resp.headers.location).then(data => resolve(data));
        return;
      }

      const data = [];
      resp.on('data', (chunk) => {
        data.push(chunk);
      });

      resp.on('end', () => {
        resolve(Buffer.concat(data));
      });
    }).on("error", (err) => {
      log("Error: " + err.message);
      reject("Error: " + err.message);
    });
  });
}

Fix a ESM bug in build script


define(['jquery'], function() {
    'use strict';

    $.fn.removePrefixedClasses = function(prefix) {

        return this.each(function() {
            var el = $(this),
                classes = el[0].className.split(/\s+/),
                prefixes = prefix.split(/\s+/);

            classes.forEach(function(cls) {
                prefixes.forEach(function(prefix) {
                    if (cls.indexOf(prefix) === 0) {
                        el.removeClass(cls);
                    }
                });
            });
        });
    };
});

define(['jquery'], function() {
    'use strict';

    $.fn.removePrefixedClasses = function(prefix) {

        return this.each(function() {
            var el = $(this),
                classes = el[0].className.split(/\s+/),
                prefixes = prefix.split(/\s+/),
                toRemove = [];

            classes.forEach(function(cls) {
                prefixes.forEach(function(prefix) {
                    if (cls.indexOf(prefix) === 0) {
                        toRemove.push(cls);
                    }
                });
            });
            el.removeClass(toRemove.join(' '));
        });
    };
});

Improve performance of remove prefixedclasses


//= require_tree .

$(document).ready(function() {
  $('#example').erToc({'goTopNode':'#example', 'startLevel': 'h2', 'numberedSuffix':'. '});
  $('.refills-menu-anchor').fixedsticky();
});

//= require jquery.erToc
//= require jquery.glide
//= require menuAnchorAnimation
//= require_directory ./vendor
//= require_directory ./refills

$(document).ready(function() {
  $('#example').erToc({'goTopNode':'#example', 'startLevel': 'h2', 'numberedSuffix':'. '});
  $('.refills-menu-anchor').fixedsticky();
});

Exclude coffeescript from being loaded


import configurePlugins from '../src/util/configurePlugins'

test('setting a plugin to false removes it', () => {
  const plugins = {
    fontSize: (options) => {
      return {
        plugin: 'fontSize',
        options,
      }
    },
    display: (options) => {
      return {
        plugin: 'display',
        options,
      }
    },
    backgroundPosition: (options) => {
      return {
        plugin: 'backgroundPosition',
        options,
      }
    },
  }

  const configuredPlugins = configurePlugins(plugins, {
    fontSize: {},
    display: false,
    backgroundPosition: {},
  })

  expect(configuredPlugins).toEqual([
    { plugin: 'fontSize', options: {} },
    { plugin: 'backgroundPosition', options: {} },
  ])
})

test('setting a plugin to an object configures that plugin', () => {
  const plugins = {
    fontSize: (options) => {
      return {
        plugin: 'fontSize',
        options,
      }
    },
    display: (options) => {
      return {
        plugin: 'display',
        options,
      }
    },
    backgroundPosition: (options) => {
      return {
        plugin: 'backgroundPosition',
        options,
      }
    },
  }

  const configuredPlugins = configurePlugins(plugins, {
    fontSize: { variants: ['responsive', 'hover'], values: { '12': '12px', '14': '14px', '16': '16px', } },
    display: { variants: ['responsive'] },
    backgroundPosition: {},
  })

  expect(configuredPlugins).toEqual([
    { plugin: 'fontSize', options: { variants: ['responsive', 'hover'], values: { '12': '12px', '14': '14px', '16': '16px', } } },
    { plugin: 'display', options: { variants: ['responsive'] } },
    { plugin: 'backgroundPosition', options: {} },
  ])
})

Test overriding a core plugin's config


/* global BigScreen */

import Component from '@ember/component';
import { action } from '@ember/object';

import $ from 'jquery';

export default Component.extend({
  tagName: '',

  toggle: action(function () {
    let element = this.fullscreenElement;
    BigScreen.toggle($(element)[0]);
  }),
});

/* global BigScreen */

import Component from '@ember/component';
import { action } from '@ember/object';

export default Component.extend({
  tagName: '',

  toggle: action(function () {
    let element = this.fullscreenElement;
    BigScreen.toggle(document.querySelector(element));
  }),
});

Use `querySelector()` instead of jQuery


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

/**
 * The Actions on Google client library.
 * https://developers.google.com/actions/
 */

'use strict';

const { AssistantApp, State } = require('./assistant-app');
const ActionsSdkApp = require('./actions-sdk-app');
const DialogflowApp = require('./dialogflow-app');
const Transactions = require('./transactions');
const Responses = require('./response-builder');

module.exports = {
  AssistantApp,
  State,
  ActionsSdkApp,
  DialogflowApp,
  Transactions,
  Responses,
  // Backwards compatibility
  Assistant: AssistantApp,
  ActionsSdkAssistant: ActionsSdkApp,
  ApiAiAssistant: DialogflowApp,
  ApiAiApp: DialogflowApp
};

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

/**
 * The Actions on Google client library.
 * https://developers.google.com/actions/
 */

'use strict';

const { AssistantApp, State } = require('./assistant-app');
const ActionsSdkApp = require('./actions-sdk-app');
const DialogflowApp = require('./dialogflow-app');
const Transactions = require('./transactions');
const Responses = require('./response-builder');

module.exports = {
  AssistantApp,
  State,
  ActionsSdkApp,
  DialogflowApp,
  Transactions,
  Responses,
  // Backwards compatibility
  get Assistant () {
    console.log('Importing the class name Assistant is *DEPRECATED*, use AssistantApp');
    return AssistantApp;
  },
  get ActionsSdkAssistant () {
    console.log('Importing the class name ActionsSdkAssistant is *DEPRECATED*, use ActionsSdkApp');
    return ActionsSdkApp;
  },
  get ApiAiAssistant () {
    console.log('Importing the class name ApiAiAssistant is *DEPRECATED*, use DialogflowApp');
    return DialogflowApp;
  },
  get ApiAiApp () {
    console.log('Importing the class name ApiAiApp is *DEPRECATED*, use DialogflowApp');
    return DialogflowApp;
  }
};

Add deprecation warning if importing deprecated class names


/**
 * Created by xubt on 22/11/2016.
 */
kanbanApp.remote_entrance = "http://127.0.0.1:8096/kanban/entrance";

/**
 * Created by xubt on 22/11/2016.
 */
kanbanApp.remote_entrance = "http://www.thiki.org/kanban/entrance";

Modify entrance url to prod.


// Swedish

$.extend( $.fn.pickadate.defaults, {
    monthsFull: [ 'januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december' ],
    monthsShort: [ 'jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec' ],
    weekdaysFull: [ 'söödag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag', 'lö̈ödag' ],
    weekdaysShort: [ 'sön', 'mån', 'tis', 'ons', 'tor', 'fre', 'lör' ],
    firstDay: 1,
    format: 'd/m yyyy',
    formatSubmit: 'yyyy-mm-dd'
})

// Swedish

$.extend( $.fn.pickadate.defaults, {
    monthsFull: [ 'januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december' ],
    monthsShort: [ 'jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec' ],
    weekdaysFull: [ 'söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag', 'lördag' ],
    weekdaysShort: [ 'sön', 'mån', 'tis', 'ons', 'tor', 'fre', 'lör' ],
    firstDay: 1,
    format: 'd/m yyyy',
    formatSubmit: 'yyyy-mm-dd'
})

Fix typos in Swedish weekdays translation


import Ember from 'ember';

export default [
//  Ember.Object.create({ value: 0, label: "Daily" }),
  Ember.Object.create({ value: 1, label: "Weekly" }),
  Ember.Object.create({ value: 2, label: "Montly" }),
//  Ember.Object.create({ value: 3, label: "Yearly" })
];

import Ember from 'ember';

export default [
  Ember.Object.create({ value: 0, label: "Daily" }),
  Ember.Object.create({ value: 1, label: "Weekly" }),
  Ember.Object.create({ value: 2, label: "Montly" }),
  Ember.Object.create({ value: 3, label: "Yearly" })
];

Revert "We don't support some recurrences by now"


import Component from '@ember/component';

export default Component.extend({
  onHamburgerClick() {},
});

import Component from '@ember/component';
import { next } from '@ember/runloop';
import { computed } from '@ember/object';
import { inject as service } from '@ember/service';

export default Component.extend({
  system: service(),
  router: service(),
  store: service(),

  onHamburgerClick() {},

  sortedRegions: computed('system.regions', function() {
    return this.get('system.regions')
      .toArray()
      .sort();
  }),

  gotoRegion(region) {
    this.get('system').reset();
    this.get('store').unloadAll();
    next(() => {
      this.get('router').transitionTo('jobs', {
        queryParams: { region },
      });
    });
  },
});

Add region switcher to the global header


// Parse CSS and add vendor prefixes
//
// grunt-postcss: <https://github.com/nDmitry/grunt-postcss>
// Autoprefixer: <https://github.com/postcss/autoprefixer>

'use strict';

var autoprefixer = require('autoprefixer');

module.exports = {

  options: {<% if (cfg.cssSourceMap) { %>
    map: {
      inline: false
    },<% } %>
    processors: [
      autoprefixer({
        // Targeting notation: <https://github.com/ai/browserslist#queries>
        browsers: [
          'last 2 versions',
          'Explorer >= 8',
          'Firefox ESR',
          'Android >= 2.3',
          'iOS >= 7'
        ]
      })
    ]
  },

  compile: {
    files: [{
      expand: true<% if (cfg.css) { %>,
      cwd: '<%%= path.styles %>'<% } else { %>,
      cwd: '<%%= path.css %>'<% } %>,
      dest: '<%%= path.css %>',
      src: '**/*.css'
    }]
  }

};

// Parse CSS and add vendor prefixes
//
// grunt-postcss: <https://github.com/nDmitry/grunt-postcss>
// Autoprefixer: <https://github.com/postcss/autoprefixer>

'use strict';

var autoprefixer = require('autoprefixer');

module.exports = {

  options: {<% if (cfg.cssSourceMap) { %>
    map: {
      inline: false
    },<% } %>
    processors: [
      autoprefixer({
        // Targeting notation: <https://github.com/ai/browserslist#queries>
        browsers: [
          'last 2 versions',
          'Explorer >= 8',
          'Firefox ESR',
          'Android >= 4',
          'iOS >= 7'
        ]
      })
    ]
  },

  compile: {
    files: [{
      expand: true<% if (cfg.css) { %>,
      cwd: '<%%= path.styles %>'<% } else { %>,
      cwd: '<%%= path.css %>'<% } %>,
      dest: '<%%= path.css %>',
      src: '**/*.css'
    }]
  }

};

Drop Android 2.3 from autoprefixer option


import semver from 'semver';

(function () {
/**
 * Install plugin
 * @param app
 * @param axios
 */

function plugin(app, axios) {
  if (plugin.installed) {
    return;
  }

  if (!axios) {
    console.error('You have to install axios');
    return;
  }

  if (semver.valid(app.version) == null) {
    console.error('Unkown vue version');
    return;
  }

  plugin.installed = true;

  if (semver.lt(app.version, '3.0.0')) {
    Object.defineProperties(app.prototype, {

      axios: {
        get: function get() {
          return axios;
        }
      },

      $http: {
        get: function get() {
          return axios;
        }
      }

    });
  } else {
    app.config.globalProperties.axios = axios;
    app.config.globalProperties.$http = axios;
  }

  app.axios = axios;
  app.$http = axios;
}

if (typeof exports == "object") {
  module.exports = plugin;
} else if (typeof define == "function" && define.amd) {
  define([], function(){ return plugin });
} else if (window.Vue && window.axios) {
  Vue.use(plugin, window.axios);
}
})();

import semver from 'semver';

(function () {
/**
 * Install plugin
 * @param app
 * @param axios
 */

function plugin(app, axios) {
  if (plugin.installed) {
    return;
  }

  if (!axios) {
    console.error('You have to install axios');
    return;
  }

  if (semver.valid(app.version) == null) {
    console.error('Unkown vue version');
    return;
  }

  plugin.installed = true;

  if (semver.lt(app.version, '3.0.0')) {
    Object.defineProperties(app.prototype, {

      axios: {
        get: function get() {
          return axios;
        }
      },

      $http: {
        get: function get() {
          return axios;
        }
      }

    });
  } else {
    app.config.globalProperties.axios = axios;
    app.config.globalProperties.$http = axios;
  }

  app.axios = axios;
  app.$http = axios;
}

if (typeof exports == "object") {
  module.exports = plugin;
} else if (typeof define == "function" && define.amd) {
  define([], function(){ return plugin });
} else if (window.Vue && window.axios && window.Vue.use) { // Vue.use is only available in VueJS 2.0
  Vue.use(plugin, window.axios);
}
})();

Check window.Vue.use for vue 2


/*global describe, it*/

'use strict';

var fs      = require('fs');
var path    = require('path');
var assert  = require('assert');

var pako    = require('../index');
var cmp     = require('./helpers').cmpBuf;

describe('ArrayBuffer', function () {

  var file   = path.join(__dirname, 'fixtures/samples/lorem_utf_100k.txt');
  var sample = new Uint8Array(fs.readFileSync(file));
  var deflated = pako.deflate(sample);

  it('Deflate ArrayBuffer', function () {
    assert.ok(cmp(deflated, pako.deflate(sample.buffer)));
  });

  it('Inflate ArrayBuffer', function () {
    assert.ok(cmp(sample, pako.inflate(deflated.buffer)));
  });

  it('Simplified minified version test', function () {
    // At some point minifier started to corrupt str2buf function
    // https://github.com/nodeca/pako/issues/161#issuecomment-468420555
    var minified = require('../dist/pako.min.js');

    assert.ok(cmp(minified.deflate('→'), pako.deflate('→')));
  });
});

/*global describe, it*/

'use strict';

var fs      = require('fs');
var path    = require('path');
var assert  = require('assert');

var pako    = require('../index');
var cmp     = require('./helpers').cmpBuf;

describe('ArrayBuffer', function () {

  var file   = path.join(__dirname, 'fixtures/samples/lorem_utf_100k.txt');
  var sample = new Uint8Array(fs.readFileSync(file));
  var deflated = pako.deflate(sample);

  it('Deflate ArrayBuffer', function () {
    assert.ok(cmp(deflated, pako.deflate(sample.buffer)));
  });

  it('Inflate ArrayBuffer', function () {
    assert.ok(cmp(sample, pako.inflate(deflated.buffer)));
  });
});

Remove outdated test to cleanup coverage report


/*
---
description: Provides a fallback for the placeholder property on input elements for older browsers.

license:
  - MIT-style license

authors:
  - Matthias Schmidt (http://www.m-schmidt.eu)

requires:
  core/1.2.5: '*'

provides:
  - Form.Placeholder

...
*/
(function(){if(!this.Form){this.Form={}}var a=("placeholder" in document.createElement("input"));if(!("supportsPlaceholder" in this)&&this.supportsPlaceholder!==false&&a){return}this.Form.Placeholder=new Class({Implements:Options,options:{color:"#A9A9A9"},initialize:function(c,b){this.setOptions(b);this.element=$(c);this.placeholder=this.element.get("placeholder");this.original_color=this.element.getStyle("color");if(this.element.get("value")==""){this.element.setStyle("color",this.options.color);this.element.set("value",this.placeholder)}this.element.addEvents({focus:function(){if(this.element.get("value")==this.placeholder){this.element.set("value","");this.element.setStyle("color",this.original_color)}}.bind(this),blur:function(){if(this.element.get("value")==""){this.element.setStyle("color",this.options.color);this.element.set("value",this.placeholder)}}.bind(this)})}})})();

Add headers to minified version.


(($) => {
  'use strict';

  window.addEventListener('load', WindowLoad, false);

  function WindowLoad(event) {
    setTimeout(() => {
      $('<button/>')
        .text('++')
        .addClass('supchat-style')
        .insertAfter('.sup-chats h1:last button:last')
        .click(() => {
          alert(1);
          $('.convo-enlarge:contains(+)').click();
        });

    }, 5000);
  }
})(jQuery);

(($) => {
  'use strict';

  window.addEventListener('load', WindowLoad, false);

  function WindowLoad(event) {
    setTimeout(() => {
      $('<button/>')
        .text('++')
        // .addClass('supchat-style')
        .insertAfter('.sup-chats h1:last button:last')
        .click(() => {
          alert(1);
          $('.convo-enlarge:contains(+)').click();
        });

    }, 5000);
  }
})(jQuery);

Update extension with debug alert.


var React = require('react');

/**
 * A mixin for components that need to know the routes, URL
 * params and query that are currently active.
 */
var ActiveState = {

  contextTypes: {
    activeRoutes: React.PropTypes.array.isRequired,
    activeParams: React.PropTypes.object.isRequired,
    activeQuery: React.PropTypes.object.isRequired,
    isActive: React.PropTypes.func.isRequired
  },

  /**
   * Returns an array of the routes that are currently active.
   */
  getActiveRoutes: function () {
    return this.context.activeRoutes;
  },

  /**
   * Returns an object of the URL params that are currently active.
   */
  getActiveParams: function () {
    return this.context.activeParams;
  },

  /**
   * Returns an object of the query params that are currently active.
   */
  getActiveQuery: function () {
    return this.context.activeQuery;
  },

  /**
   * A helper method to determine if a given route, params, and query
   * are active.
   */
  isActive: function (to, params, query) {
    return this.context.isActive(to, params, query);
  }

};

module.exports = ActiveState;

var React = require('react');

/**
 * A mixin for components that need to know the routes, URL
 * params and query that are currently active.
 *
 * Example:
 *
 *   var AboutLink = React.createClass({
 *     mixins: [ Router.ActiveState ],
 *     render: function () {
 *       var className = this.props.className;
 *
 *       if (this.isActive('about'))
 *         className += ' is-active';
 *
 *       return React.DOM.a({ className: className }, this.props.children);
 *     }
 *   });
 */
var ActiveState = {

  contextTypes: {
    activeRoutes: React.PropTypes.array.isRequired,
    activeParams: React.PropTypes.object.isRequired,
    activeQuery: React.PropTypes.object.isRequired,
    isActive: React.PropTypes.func.isRequired
  },

  /**
   * Returns an array of the routes that are currently active.
   */
  getActiveRoutes: function () {
    return this.context.activeRoutes;
  },

  /**
   * Returns an object of the URL params that are currently active.
   */
  getActiveParams: function () {
    return this.context.activeParams;
  },

  /**
   * Returns an object of the query params that are currently active.
   */
  getActiveQuery: function () {
    return this.context.activeQuery;
  },

  /**
   * A helper method to determine if a given route, params, and query
   * are active.
   */
  isActive: function (to, params, query) {
    return this.context.isActive(to, params, query);
  }

};

module.exports = ActiveState;

Add example to doc comment


'use strict';

var cheerio = require('cheerio');

module.exports = function (html, options) {
    var results = {};
    var $ = cheerio.load(html);

    results.hrefs = [];

    $('link').each(function (index, element) {
        var $el = $(element);
        if ($el.attr('rel').toLowerCase() === 'stylesheet') {
            if (options.applyLinkTags) {
                results.hrefs.push($el.attr('href'));
            }
            if (options.removeLinkTags) {
                $el.remove();
            }
        }
    });

    results.html = $.html();

    return results;
};

'use strict';

var cheerio = require('cheerio');

module.exports = function (html, options) {
    var results = {};
    var $ = cheerio.load(html, {
            decodeEntities: false
        });

    results.hrefs = [];

    $('link').each(function (index, element) {
        var $el = $(element);
        if ($el.attr('rel').toLowerCase() === 'stylesheet') {
            if (options.applyLinkTags) {
                results.hrefs.push($el.attr('href'));
            }
            if (options.removeLinkTags) {
                $el.remove();
            }
        }
    });

    results.html = $.html();

    return results;
};

Set decodeEntities to false for cheerio.


import { app, html } from "flea"

const model = 0

const view = (model, dispatch) => html`

${model}

        <button onclick=${_ => dispatch("INCREMENT")}>+</button>
        <button onclick=${_ => dispatch("DECREMENT")}>-</button>

`

const update = {
    INCREMENT: model => model + 2,
    DECREMENT: model => model - 1
}

app(model, view, update)

import { app, html } from "flea"

const model = 0

const view = (model, dispatch) => html`

        <button onclick=${_ => dispatch("INCREMENT")}>+</button>

${model}

        <button onclick=${_ => dispatch("DECREMENT")} disabled=${model <= 0}>-</button>

`

const update = {
    INCREMENT: model => model + 1,
    DECREMENT: model => model - 1
}

app(model, view, update)

Increment by one. Show how to use disabled attribute with boolean var.


var jstrans = function (path) {
    if (selector = document.querySelector('input[name=\"jstrans-value-for-' + path + '\"]')) {
        return selector.value;
    } else {
        var json = JSON.parse('%s');
        var keys = path.split('.');

        var value = json;

        for (var i in keys) {
            var key = keys[i];
            if (typeof value[key] === 'undefined') {
                return path;
            }
            value = value[key];
        }

        return value;
    }
}

var jstrans = function (path) {
    if (typeof path === 'undefined') {
        return null;
    }

    if (selector = document.querySelector('input[name=\"jstrans-value-for-' + path + '\"]')) {
        return selector.value;
    } else {
        var json = JSON.parse('%s');
        var keys = path.split('.');

        var value = json;

        for (var i in keys) {
            var key = keys[i];
            if (typeof value[key] === 'undefined') {
                return path;
            }
            value = value[key];
        }

        return value;
    }
}

Return null if path is not specified


import pageLoader from './pageLoader';

// All your dataloaders
const rootLoaders = {
  ...pageLoader
}

export default function loaders () {
  return rootLoaders
}

import pageLoader from './pageLoader';

// All your dataloaders
const allLoaders = {
  ...pageLoader
}

export default function loaders () {
  return allLoaders
}

Change name to be more noob friendly


// Index page module.
module.exports = function(utils, $, _) {
    console.log('index page module loaded');
}

// Index page module.
module.exports = function(utils, $, _) {
    window.$ = $; window.jQuery = $;
    console.log('jQuery added as window.$ for development');
}

Make jQuery available outside webapp sandbox.


{{#JSTSynonym}}
function {{jstDetail.jstConstructor}} (v) {
  this.value = v;
  this.pack = function (u8buf, offset) {
    return this.value.pack(u8buf, offset);
  };
}
{{jstDetail.jstConstructor}}.unpack = function (u8buf, offset) {
  var biVal = {{jstSynnedCtor}}.unpack(u8buf, offset);
  return new {{jstDetail.jstConstructor}}(biVal);
};

{{/JSTSynonym}}

{{#JSTSynonym}}
function {{jstDetail.jstConstructor}} (v) {
  this.value = v;
  this.pack = function (u8buf, offset) {
    return this.value.pack(u8buf, offset);
  };
}
{{jstDetail.jstConstructor}}.unpack = function (u8buf, offset) {
  var biVal = this.refTypeCtor.unpack(u8buf, offset);
  return new {{jstDetail.jstConstructor}}(biVal);
};
{{jstDetail.jstConstructor}}.refTypeCtor = {{jstSynnedCtor}};
{{/JSTSynonym}}

Use the constructor through the parent-constructor instead of listing it directly.


;(function()
{
	// CommonJS
	typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;

	function Brush()
	{
		this.regexList = [
			{ regex: /^\+\+\+.*$/gm,		css: 'color2' },
			{ regex: /^\-\-\-.*$/gm,		css: 'color2' },
			{ regex: /^\s.*$/gm,			css: 'color1' },
			{ regex: /^@@.*@@$/gm,			css: 'variable' },
			{ regex: /^\+[^\+]{1}.*$/gm,	css: 'string' },
			{ regex: /^\-[^\-]{1}.*$/gm,	css: 'comments' }
			];
	};

	Brush.prototype	= new SyntaxHighlighter.Highlighter();
	Brush.aliases	= ['diff', 'patch'];

	SyntaxHighlighter.brushes.Diff = Brush;

	// CommonJS
	typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();

;(function()
{
	// CommonJS
	typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;

	function Brush()
	{
		this.regexList = [
			{ regex: /^\+\+\+.*$/gm,		css: 'color2' },
			{ regex: /^\-\-\-.*$/gm,		css: 'color2' },
			{ regex: /^\s.*$/gm,			css: 'color1' },
			{ regex: /^@@.*@@.*$/gm,	css: 'variable' },	// location
			{ regex: /^\+[^\+]{1}.*$/gm,	css: 'string' },
			{ regex: /^\-[^\-]{1}.*$/gm,	css: 'comments' }
			];
	};

	Brush.prototype	= new SyntaxHighlighter.Highlighter();
	Brush.aliases	= ['diff', 'patch'];

	SyntaxHighlighter.brushes.Diff = Brush;

	// CommonJS
	typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();

Allow extra context after location markers


var I18n = function () {
  this.locale = jQuery.cookie('locale') || 'en';
  this.template = {
    error: "Error",
    voting: "Voting",
    vote_saved: "Voting saved",
    'vote.remove': "Remove vote",
    'vote.good': "Good",
    'vote.great': "Great",
    'vote.fav': "Favorite",
    '__default__': "no translations"
  };
  this.fetch(this.locale);
};

I18n.prototype.fetch = function (locale) {
  var th = this;
  try {
    jQuery.ajax('/assets/'+locale+'.json', {
      dataType: 'json'
    }).done(function (data) {
      th.template = data;
    });
  } catch (error) {}
  return false;
};

I18n.prototype.translate = function (label) {
  if (arguments.length > 1) {
    return this.subst(arguments);
  }
  if (arguments.length == 0) {
    return this.template['__default__'];
  }
  return this.template[label] || this.template['__default__'];
};

I18n.prototype.subst = function () {
  var args = arguments,
      tl = this.template[arguments[0]] || this.template['__default__'];
  function repl(str, p1, off, s) {
    return args[p1];
  }
  return tl.replace(/\$(\d+)/g, repl);
};

var i18n = new I18n(),
    t = function(label) {
      return i18n.translate(label);
    };

var I18n = function () {
  this.locale = jQuery.cookie('locale') || 'en';
  this.template = {
    error: "Error",
    voting: "Voting",
    vote_saved: "Voting saved",
    'vote.remove': "Remove vote",
    'vote.good': "Good",
    'vote.great': "Great",
    'vote.fav': "Favorite",
    '__default__': "no translations"
  };
  this.fetch(this.locale);
};

I18n.prototype.fetch = function (locale) {
  var th = this;
  try {
    jQuery.ajax('/assets/'+locale+'.json', {
      dataType: 'json'
    }).done(function (data) {
      th.template = data;
    });
  } catch (error) {}
  return false;
};

I18n.prototype.translate = function (label) {
  if (arguments.length > 1) {
    return this.subst(arguments);
  }
  return this.template[label] || this.template['__default__'];
};

I18n.prototype.subst = function () {
  var args = arguments,
      tl = this.template[arguments[0]] || this.template['__default__'];
  function repl(str, p1, off, s) {
    return args[p1];
  }
  return tl.replace(/\$(\d+)/g, repl);
};

var i18n = new I18n(),
    t = function(label) {
      return i18n.translate(label);
    };

Remove extraneous check on translation key


var fork = require('child_process').fork;
var async = require('async');
var amountConcurrentUsers = process.argv[2] || 200;
var host = process.argv[3] || 'http://localhost';
var initialPort = process.argv[4] || 3000;
var totalServers = process.argv[5] || 50;
var Client = require('./client');

var clientIdentifiers = [];
var clients = [];

for(var i = 0; i < amountConcurrentUsers; i++) {
    clientIdentifiers.push(i);
};

console.log('Here we go');
console.log('amountConcurrentUsers: ' + amountConcurrentUsers);
console.log('Host: ' + host);
console.log('Initial port: ' + initialPort);

for(var j = 0; j < totalServers; j++) {
    var port = initialPort + j;
    console.log('connecting to port: ' + port);
    async.each(clientIdentifiers, function(clientIdentifier) {
        // clients[clientIdentifier] = fork('client.js', [host, port, clientIdentifier] );
        console.log('Client: ' + clientIdentifier);
        clients[clientIdentifier] = Client(host, port, port + '-' + clientIdentifier);
    }, function(err){
        console.log('UPSSS! Error!');
    });
}

var fork = require('child_process').fork;
var async = require('async');
var amountConcurrentUsers = process.argv[2] || 200;
var host = process.argv[3] || 'http://localhost';
var initialPort = process.argv[4] || 3000;
var totalServers = process.argv[5] || 50;
var Client = require('./client');
var defaultHAProxyPort = 80;

var clientIdentifiers = [];
var clients = [];

for(var i = 0; i < amountConcurrentUsers; i++) {
    clientIdentifiers.push(i);
};

console.log('Here we go');
console.log('amountConcurrentUsers: ' + amountConcurrentUsers);
console.log('Host: ' + host);
console.log('Initial port: ' + initialPort);

for(var j = 0; j < totalServers; j++) {
    var port =  (isHAProxyPort(defaultHAProxyPort, port)) ? defaultHAProxyPort : initialPort + j;
    console.log('Connecting to port: ' + port);
    async.each(clientIdentifiers, function(clientIdentifier) {
        // clients[clientIdentifier] = fork('client.js', [host, port, clientIdentifier] );
        console.log('Client: ' + clientIdentifier);
        clients[clientIdentifier] = Client(host, port, port + '-' + clientIdentifier);
    }, function(err){
        console.log('UPSSS! Error!');
    });
}

function isHAProxyPort(defaultHAProxyPort, port) {

    return port === defaultHAProxyPort;
}

Add default port for HAProxy


var db = require('./db.js');
var moment = require('moment');
var _ = require('lodash');

var get = function() {
  return db.get('reservations').value();
};

var make = function(id, arrivalDate, nights, guests) {
  if (guests > 5 || !arrivalDate || !nights || !guests) {
    return false;
  }
  let reservationDetails = {
    "id":           id,
    "arrivalDate":  arrivalDate,
    "nights":       nights,
    "guests":       guests,
    "status":       'Confirmed',
    "bookedOn":      moment().format('MMMM Do YYYY'),
    "price":        nights*_.random(200,249)
  };

  db.get('reservations')
    .push(reservationDetails)
    .value();

  return reservationDetails;
};

module.exports = {
  get: get,
  make: make
};

var db = require('./db.js');
var moment = require('moment');
var _ = require('lodash');

var get = function() {
  return db.get('reservations').value();
};

var make = function(id, arrivalDate, nights, guests) {
  if (guests > 5 || !arrivalDate || !nights || !guests) {
    return false;
  }
  let reservationDetails = {
    "id":           id,
    "arrivalDate":  moment(arrivalDate).format('MMMM Do YYYY'),
    "nights":       nights,
    "guests":       guests,
    "status":       'Confirmed',
    "bookedOn":     moment().format('MMMM Do YYYY'),
    "price":        nights*_.random(200,249)
  };

  db.get('reservations')
    .push(reservationDetails)
    .value();

  return reservationDetails;
};

module.exports = {
  get: get,
  make: make
};

Format arrivalDate when creating reservation in db


'use strict';

var fs = require('fs');

function getVersion() {
  var packageContents = fs.readFileSync('./package.json', 'utf8');
  var packageJson = JSON.parse(packageContents);
  return packageJson.version;
}

function getStringToInput() {
  let version = getVersion();
  return `
  window.tripleOUiConfig = window.tripleOUiConfig || {};
  window.tripleOUiConfig.version = '${version}';
  `;
}

module.exports = function(content) {
  content = content + getStringToInput();
  return content;
};

Fix Error on Version loader


'use strict';

exports.up = function(knex) {
  return knex.schema.createTable('users', (table) => {
    table.increments();
    table.string('first_name')
    .notNullable()
    .defaultTo('');
    table.string('last_name')
      .notNullable()
      .defaultTo('');
    table.string('email')
      .unique()
      .notNullable()
      .defaultTo('');
    table.specificType('hashed_password', 'char(60)')
      .notNullable();
    table.boolean('kj')
      .notNullable()
      .defaultTo(false);
    table.string('code').defaultTo(null);
    table.boolean('accept').defaultTo('false');
    table.timestamps(true, true);
  });
};

exports.down = function(knex) {
  return knex.schema.dropTable('users');
};

'use strict';

exports.up = function(knex) {
  return knex.schema.createTable('users', (table) => {
    table.increments();
    table.string('first_name')
    .notNullable()
    .defaultTo('');
    table.string('last_name')
      .notNullable()
      .defaultTo('');
    table.string('email')
      .unique()
      .notNullable()
      .defaultTo('');
    table.specificType('hashed_password', 'char(60)')
      .notNullable();
    table.boolean('kj')
      .notNullable()
      .defaultTo(false);
    table.string('code').defaultTo('');
    table.boolean('accept').defaultTo('false');
    table.timestamps(true, true);
  });
};

exports.down = function(knex) {
  return knex.schema.dropTable('users');
};

Change users migration code to empty string


/* global google document */
import React from 'react';
import './scss/map.scss';

class VisitedMap extends React.Component {
  componentDidMount() {
    this.createMap();
  }

  createMap() {
    const map = new google.maps.Map(document.getElementById('visitedMap'), {
      center: { lat: 33.626829, lng: 18.379068 },
      zoom: 2
    });

    const whereQuery = `ISO_2DIGIT IN ('${this.props.countries.join('\', \'')}')`;
    new google.maps.FusionTablesLayer({
      query: {
        select: 'geometry',
        from: '1N2LBk4JHwWpOY4d9fobIn27lfnZ5MDy-NoqqRpk',
        where: whereQuery,
        styles: [{
          polygonOptions: {
            fillColor: '#1F3352',
            fillOpacity: 0.5
          },
          polylineOptions: {
            fillColor: '#1F3352',
            fillOpacity: 0.5
          }
        }]
      },
      map,
      suppressInfoWindows: true
    });
  }

  render() {
    return (
      <section id="visitedMap" />
    );
  }
}

VisitedMap.defaultProps = {
  countries: []
};

VisitedMap.propTypes = {
  countries: React.PropTypes.array,
};

export default VisitedMap;

/* global google document */
import React from 'react';
import './scss/map.scss';

class VisitedMap extends React.Component {
  componentDidMount() {
    this.createMap();
  }

  createMap() {
    const map = new google.maps.Map(document.getElementById('visitedMap'), {
      center: { lat: 33.626829, lng: 18.379068 },
      zoom: 2,
      disableDefaultUI: true
    });

    const whereQuery = `ISO_2DIGIT IN ('${this.props.countries.join('\', \'')}')`;
    new google.maps.FusionTablesLayer({
      query: {
        select: 'geometry',
        from: '1N2LBk4JHwWpOY4d9fobIn27lfnZ5MDy-NoqqRpk',
        where: whereQuery
      },
      map,
      suppressInfoWindows: true
    });
  }

  render() {
    return (
      <section id="visitedMap" />
    );
  }
}

VisitedMap.defaultProps = {
  countries: []
};

VisitedMap.propTypes = {
  countries: React.PropTypes.array,
};

export default VisitedMap;

Disable default Map UI + remove non-working coloring


// @flow
import type { ChooView } from "./app";
import type { ChooMiddleware } from "./app";

const app = require("choo")();
const html = require("choo/html");
const eventNames = require("./eventNames");
const defaultView = require("./views/embed/default");
const embedView = require("./views/embed/home");
const errorReducer = require("./reducers/error");
const chatReducer = require("./reducers/chat");
const apiReducer = require("./reducers/embed/api");

app.use(eventNames);
app.use(apiReducer);
app.use(errorReducer());
app.use(chatReducer);
app.route("/videochat-client/embed.html/group/:groupId", embedView);
app.route("/group/:groupId", embedView);
app.route("*", defaultView);

if (typeof document === "undefined" || !document.body) {
    throw new Error("document.body is not here");
}
document.body.appendChild(app.start());

// @flow
import type { ChooView } from "./app";
import type { ChooMiddleware } from "./app";

const app = require("choo")();
const html = require("choo/html");
const eventNames = require("./eventNames");
const defaultView = require("./views/embed/default");
const embedView = require("./views/embed/home");
const errorReducer = require("./reducers/error");
const chatReducer = require("./reducers/chat");
const apiReducer = require("./reducers/embed/api");

app.use(eventNames);
app.use(apiReducer);
app.use(errorReducer());
app.use(chatReducer);
app.route("/videochat-client/embed.html/group/:groupId", embedView);
app.route("/embed.html/group/:groupId", embedView);
app.route("/group/:groupId", embedView);
app.route("*", defaultView);

if (typeof document === "undefined" || !document.body) {
    throw new Error("document.body is not here");
}
document.body.appendChild(app.start());

Patch from bus part 2


/**
 * Event
 *
 * @author Rakume Hayashi<i@fake.moe>
 */

Faiash.ise.extend({
    bind: function() {
        var args = $.toArr(arguments);

        if (typeof args[0] === 'string') {
            if (!args[0] || !args[1]) {
                return this;
            }

            this.each(function(el) {
                el.addEventListener(args[0], args[1], (args[2] ? args[2] : false));
            });
        } else if (typeof args[0] === 'object') {
            Faiash.each(args, function(obj) {
                this.each(function(el) {
                    for (var event in obj) {
                        if (object.hasOwnProperty(event)) {
                            el.addEventListener(event, obj[event][1]);
                        }
                    }
                });
            });
        }
    },

    unbind: function() {
        var args = $.toArr(arguments);

        if (typeof args[0] === 'string') {
            this.each(function(el) {
                el.removeEventListener(args[0], args[1], args[2]);
            });
        }  else if (typeof args[0] === 'object' && args.length === 1) {
            Faiash.each(args, function(obj) {
                this.each(function(el) {
                    for (var event in obj) {
                        if (object.hasOwnProperty(event)) {
                            el.removeEventListener(event, obj[event][1]);
                        }
                    }
                });
            });
        }
    }
});

/**
 * Event
 *
 * @author Rakume Hayashi<i@fake.moe>
 */

Faiash.ise.extend({
    on: function() {
        var args = $.toArr(arguments);

        if (typeof args[0] === 'string') {
            if (!args[0] || !args[1]) {
                return this;
            }

            this.each(function(el) {
                el.addEventListener(args[0], args[1], (args[2] ? args[2] : false));
            });
        } else if (typeof args[0] === 'object') {
            Faiash.each(args, function(obj) {
                this.each(function(el) {
                    for (var event in obj) {
                        if (object.hasOwnProperty(event)) {
                            el.addEventListener(event, obj[event][1]);
                        }
                    }
                });
            });
        }
    },

    off: function() {
        var args = $.toArr(arguments);

        if (typeof args[0] === 'string') {
            this.each(function(el) {
                el.removeEventListener(args[0], args[1], args[2]);
            });
        }  else if (typeof args[0] === 'object' && args.length === 1) {
            Faiash.each(args, function(obj) {
                this.each(function(el) {
                    for (var event in obj) {
                        if (object.hasOwnProperty(event)) {
                            el.removeEventListener(event, obj[event][1]);
                        }
                    }
                });
            });
        }
    }
});

Use on, off instead of bind, unbind


import React from 'react'
import ReactDOM from 'react-dom'
import { createGlobalStyle } from 'styled-components'

import { App } from './App'
import woff2 from './fonts/source-sans-pro-v11-latin-regular.woff2'
import woff from './fonts/source-sans-pro-v11-latin-regular.woff'
import registerServiceWorker from './registerServiceWorker'

const GlobalStyle = createGlobalStyle`
  body {
    margin: 0;
    padding: 0;
    font-family: 'Source Sans Pro', sans-serif;
    overscroll-behavior-y: none;
  }

  /* source-sans-pro-regular - latin */
  @font-face {
    font-family: 'Source Sans Pro';
    font-style: normal;
    font-weight: 400;
    font-display: optional;
    src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'),
        url(${woff2}) format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
        url(${woff}) format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
  }
`

ReactDOM.render(
  <>
    <GlobalStyle />
    <App />
  </>,
  document.getElementById('root')
)
registerServiceWorker()

import React from 'react'
import ReactDOM from 'react-dom'
import { createGlobalStyle } from 'styled-components'

import { App } from './App'
import woff2 from './fonts/source-sans-pro-v11-latin-regular.woff2'
import woff from './fonts/source-sans-pro-v11-latin-regular.woff'
import registerServiceWorker from './registerServiceWorker'

const GlobalStyle = createGlobalStyle`
  html {
    box-sizing: border-box;
  }

  *, *:before, *:after {
    box-sizing: inherit;
  }

  body {
    margin: 0;
    padding: 0;
    font-family: 'Source Sans Pro', sans-serif;
    overscroll-behavior-y: none;
  }

  /* source-sans-pro-regular - latin */
  @font-face {
    font-family: 'Source Sans Pro';
    font-style: normal;
    font-weight: 400;
    font-display: optional;
    src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'),
        url(${woff2}) format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
        url(${woff}) format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
  }
`

ReactDOM.render(
  <>
    <GlobalStyle />
    <App />
  </>,
  document.getElementById('root')
)
registerServiceWorker()

Use border-box style for all elements


export default function move (array, moveIndex, toIndex) {
  /* #move - Moves an array item from one position in an array to another.

     Note: This is a pure function so a new array will be returned, instead
     of altering the array argument.

    Arguments:
    1. array     (String) : Array in which to move an item.         (required)
    2. moveIndex (Object) : The index of the item to move.          (required)
    3. toIndex   (Object) : The index to move item at moveIndex to. (required)
  */
  let item = array[moveIndex];
  let length = array.length;
  let diff = moveIndex - toIndex;

  if (diff > 0) {
    // move left
    return [
      ...array.slice(0, toIndex),
      item,
      ...array.slice(toIndex, moveIndex),
      ...array.slice(moveIndex + 1, length)
    ];
  } else if (diff < 0) {
    // move right
    return [
      ...array.slice(0, moveIndex),
      ...array.slice(moveIndex + 1, toIndex + 1),
      item,
      ...array.slice(toIndex + 1, length)
    ];
  }
  return array;
}

export default function move (array, moveIndex, toIndex) {
  /* #move - Moves an array item from one position in an array to another.

     Note: This is a pure function so a new array will be returned, instead
     of altering the array argument.

    Arguments:
    1. array     (String) : Array in which to move an item.         (required)
    2. moveIndex (Object) : The index of the item to move.          (required)
    3. toIndex   (Object) : The index to move item at moveIndex to. (required)
  */
  const item = array[moveIndex];
  const length = array.length;
  const diff = moveIndex - toIndex;

  if (diff > 0) {
    // move left
    return [
      ...array.slice(0, toIndex),
      item,
      ...array.slice(toIndex, moveIndex),
      ...array.slice(moveIndex + 1, length)
    ];
  } else if (diff < 0) {
    // move right
    const targetIndex = toIndex + 1;
    return [
      ...array.slice(0, moveIndex),
      ...array.slice(moveIndex + 1, targetIndex),
      item,
      ...array.slice(targetIndex, length)
    ];
  }
  return array;
}

Use of const and reduced duplication


import Ember from 'ember';
import moment from 'moment';
import layout from '../templates/components/ilios-calendar-week';

const {computed, run} = Ember;

export default Ember.Component.extend({
  classNames: ['ilios-calendar-week'],
  layout: layout,
  date: null,
  calendarEvents: [],
  weekOf: computed('selectedDate', function(){
    return moment(this.get('selectedDate')).startOf('week').format('MMMM Do YYYY');
  }),
  didInsertElement(){
    run.next(() => {
      this.$(".el-calendar .week").scrollTop(500);
    });
  },
  actions: {
    selectEvent(event){
      this.sendAction('selectEvent', event);
    }
  }
});

import Ember from 'ember';
import moment from 'moment';
import layout from '../templates/components/ilios-calendar-week';

const {computed, run} = Ember;

export default Ember.Component.extend({
  classNames: ['ilios-calendar-week'],
  layout: layout,
  date: null,
  calendarEvents: [],
  weekOf: computed('date', function(){
    return moment(this.get('date')).startOf('week').format('MMMM Do YYYY');
  }),
  didInsertElement(){
    run.next(() => {
      this.$(".el-calendar .week").scrollTop(500);
    });
  },
  actions: {
    selectEvent(event){
      this.sendAction('selectEvent', event);
    }
  }
});

Fix bound value for week of


//= requires "editor"

/*
 * Includes the Aspell plugin (kindly ported from FCKeditor by Christian
 * Boisjoli) which provides spell checking without relying on any
 * browser plugins or third-party web services.
 *
 * Note: you must add this to the toolbar as 'SpellCheck' rather than
 * the usual 'SpellChecker' in order to use it.
 *
 * The plugin can be configured in config/ckeditor.php:
 *   aspell.language sets which dictionary to use - by default it uses
 *     Kohana's locale configuration
 *   aspell.program sets the path to the Aspell executable with sensible
 *     defaults for both Windows and Linux
 *
 * Details on where to obtain the original plugin code are in:
 *   vendor/ckplugins/aspell/aspell.txt
 */

CKEDITOR.plugins.addExternal('aspell', "<?php echo url::site('assets/ckplugins/aspell');?>/");
CKEDITOR.config.extraPlugins = (CKEDITOR.config.extraPlugins ? (CKEDITOR.config.extraPlugins + ',') : '' ) + 'aspell';

//= requires "editor"

/*
 * Includes the Aspell plugin (kindly ported from FCKeditor by Christian
 * Boisjoli) which provides spell checking without relying on any
 * browser plugins or third-party web services.
 *
 * Note: you must add this to the toolbar as 'SpellCheck' rather than
 * the usual 'SpellChecker' in order to use it.
 *
 * The plugin can be configured in config/ckeditor.php:
 *   aspell.language sets which dictionary to use - by default it uses
 *     Kohana's locale configuration
 *   aspell.program sets the path to the Aspell executable with sensible
 *     defaults for both Windows and Linux
 *
 * Details on where to obtain the original plugin code are in:
 *   vendor/ckplugins/aspell/aspell.txt
 */

//= requires "<?php echo substr(Kohana::find_file('vendor', 'ckplugins/aspell/plugin', TRUE, 'js'), 0, -3);?>"
CKEDITOR.plugins.addExternal('aspell', "<?php echo url::site('assets/ckplugins/aspell');?>/");
CKEDITOR.config.extraPlugins = (CKEDITOR.config.extraPlugins ? (CKEDITOR.config.extraPlugins + ',') : '' ) + 'aspell';

Include Aspell JavaScript in initial load to save extra request


define(
    [
        'polygonjs/Entity',
        'polygonjs/geom/Vector3'
    ],
    function (Entity, Vector3) {

        "use strict";

        var Polygon = function (opts) {
            opts = opts || {};
            Entity.call(this, opts);
            this.type = 'polygon';

            this.vertices = opts.vertices || [];
            this.normal = opts.normal || Vector3.ONE;

            // this.initVertices();
        };

        Polygon.create = function (opts) {
            return new Polygon(opts);
        };

        Polygon.prototype = Object.create(Entity.prototype);

        // Polygon.prototype.initVertices = function () {
            // this.worldVertices = [];
            // this.viewVertices = [];
            // this.screenVertices = [];
            // var i = this.vertices.length;
            // while (--i >= 0) {
            //     // this.worldVertices.push(Vector3.create(0, 0, 0));
            //     // this.viewVertices.push(Vector3.create(0, 0, 0));
            //     // this.screenVertices.push(Vector3.create(0, 0, 0));
            // }
        // };

        // Polygon.prototype.update = function (delta) {
        //     var vertices = this.vertices,
        //         worldVertices = this.worldVertices,
        //         vertex, worldVertex,
        //         i = vertices.length,
        //         transform = this.getWorldTransform();

        //     // Apply world transformation
        //     while (--i >= 0) {
        //         vertex = vertices[i];
        //         worldVertices[i] = transform.multiplyVector(vertex); // TODO: slow!
        //     }
        // };

        // Polygon.prototype.draw = function (camera, surface) {

        //     // ...

        // };

        return Polygon;
    }
);

define(
    [
        'polygonjs/Entity',
        'polygonjs/geom/Vector3'
    ],
    function (Entity, Vector3) {

        "use strict";

        var Polygon = function (opts) {
            opts = opts || {};
            Entity.call(this, opts);
            this.type = 'polygon';

            this.vertices = opts.vertices || [];
            this.normal = opts.normal || Vector3.ONE;

            // this.initVertices();
        };

        Polygon.create = function (opts) {
            return new Polygon(opts);
        };

        Polygon.prototype = Object.create(Entity.prototype);

        // Polygon.prototype.update = function (delta) {
        //     var vertices = this.vertices,
        //         worldVertices = this.worldVertices,
        //         vertex, worldVertex,
        //         i = vertices.length,
        //         transform = this.getWorldTransform();

        //     // Apply world transformation
        //     while (--i >= 0) {
        //         vertex = vertices[i];
        //         worldVertices[i] = transform.multiplyVector(vertex); // TODO: slow!
        //     }
        // };

        // Polygon.prototype.draw = function (camera, surface) {

        //     // ...

        // };

        return Polygon;
    }
);

Delete init vertices from the polygon entity.


'use strict';

var glimpse = require('glimpse');

module.exports = {
    addListener: function (event, listener) {
        if (!this.events) {
            this.events = {};
        }

        this.events[event] = glimpse.on(event, listener);
    },
    componentWillUnmount: function () {
        if (this.events) {
            for (var key in this.events) {
                glimpse.off(this.events[key]);
            }

            this.events = null;
        }
    }
};

'use strict';

var glimpse = require('glimpse');

module.exports = {
    addListener: function (event, listener) {
        if (!this.events) {
            this.events = {};
        }

        this.events[event] = glimpse.on(event, listener);
    },
    componentWillUnmount: function () {
        if (this.events) {
            for (var key in this.events) {
                glimpse.off(key);
            }

            this.events = null;
        }
    }
};

Fix bug in how events are unloaded


const { map, isFunction } = require("lodash/fp");
const { hasOwn } = require("../util");

const transformAttrKey = require("./transform-attr-key");
const { renderStyleAttribute } = require("./style");

const mapWithKey = map.convert({ cap: false });

const attrsNotToRender = {
  children: true,
  dangerouslySetInnerHTML: true
};

/**
 * Render an object of key/value pairs into their HTML attribute equivalent.
 *
 * @param      {Object}  attrs   Attributes in object form.
 *
 * @return     {String}          Generated HTML attribute output.
 */
function renderAttrs (attrs) {
  const attrString = [];

  for (let attrKey in attrs) {
    if (
      hasOwn(attrs, attrKey) &&
      !attrsNotToRender[attrKey]
    ) {
      let attrVal = attrs[attrKey];

      if (!attrVal || isFunction(attrVal)) { continue; }

      attrKey = transformAttrKey(attrKey);

      if (attrVal === true) {
        attrVal = "";
      } else if (attrKey === "style" && typeof attrVal === "object") {
        attrVal = `="${renderStyleAttribute(attrVal)}"`;
      } else {
        attrVal = `="${attrVal}"`;
      }

      attrString.push(` ${attrKey}${attrVal}`);
    }
  }

  return attrString.join("");
}

const mapPairToString = mapWithKey((val, key) => `${key}:${key}`);
function styleObjToString (obj) {
  return mapPairToString(obj).join(";");
}

module.exports = renderAttrs;

const { isFunction } = require("lodash/fp");
const { hasOwn } = require("../util");

const transformAttrKey = require("./transform-attr-key");
const { renderStyleAttribute } = require("./style");

const attrsNotToRender = {
  children: true,
  dangerouslySetInnerHTML: true
};

/**
 * Render an object of key/value pairs into their HTML attribute equivalent.
 *
 * @param      {Object}  attrs   Attributes in object form.
 *
 * @return     {String}          Generated HTML attribute output.
 */
function renderAttrs (attrs) {
  const attrString = [];

  for (let attrKey in attrs) {
    if (
      hasOwn(attrs, attrKey) &&
      !attrsNotToRender[attrKey]
    ) {
      let attrVal = attrs[attrKey];

      if (!attrVal || isFunction(attrVal)) { continue; }

      attrKey = transformAttrKey(attrKey);

      if (attrVal === true) {
        attrVal = "";
      } else if (attrKey === "style" && typeof attrVal === "object") {
        attrVal = `="${renderStyleAttribute(attrVal)}"`;
      } else {
        attrVal = `="${attrVal}"`;
      }

      attrString.push(` ${attrKey}${attrVal}`);
    }
  }

  return attrString.join("");
}

module.exports = renderAttrs;

Remove old style parsing implementation


/*jshint node:true*/
/* global require, module */
var EmberAddon = require('ember-cli/lib/broccoli/ember-addon');

module.exports = function(defaults) {
  var app = new EmberAddon(defaults, {
    // Add options here
    babel: {
      includePolyfill: false
    }
  });

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  app.import('bower_components/semantic-ui/dist/semantic.css');
  app.import('bower_components/semantic-ui/dist/semantic.js');

  // Import Highlight.js
  app.import(app.bowerDirectory + "/highlightjs/highlight.pack.min.js");

  app.import(app.bowerDirectory + "/highlightjs/styles/github-gist.css");
  app.import(app.bowerDirectory + "/highlightjs/styles/hybrid.css");

  return app.toTree();
};

/*jshint node:true*/
/* global require, module */
var EmberAddon = require('ember-cli/lib/broccoli/ember-addon');

module.exports = function(defaults) {
  var app = new EmberAddon(defaults, {
    // Add options here
    babel: {
      includePolyfill: false
    },
    SemanticUI: {
      paths: {
        fonts: 'assets/themes/default/assets/fonts',
      }
    }
  });

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  // Import Highlight.js
  app.import(app.bowerDirectory + "/highlightjs/highlight.pack.min.js");

  app.import(app.bowerDirectory + "/highlightjs/styles/github-gist.css");
  app.import(app.bowerDirectory + "/highlightjs/styles/hybrid.css");

  return app.toTree();
};

Use new options for dummy/docs app


'use strict';

const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');

module.exports = function (defaults) {
  const self = defaults.project.findAddonByName('ember-a11y-testing');
  const autoImport = self.options.autoImport;

  let app = new EmberAddon(defaults, {
    autoImport,
  });

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  const { maybeEmbroider } = require('@embroider/test-setup');
  return maybeEmbroider(app, {
    packagerOptions: {
      webpackConfig: {
        node: {
          crypto: 'empty',
        },
      },
    },
    skipBabel: [
      {
        package: 'qunit',
      },
    ],
  });
};

'use strict';

const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');

module.exports = function (defaults) {
  const self = defaults.project.findAddonByName('ember-a11y-testing');
  const autoImport = self.options.autoImport;

  let app = new EmberAddon(defaults, {
    autoImport,
  });

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  const { maybeEmbroider } = require('@embroider/test-setup');
  return maybeEmbroider(app, {
    skipBabel: [
      {
        package: 'qunit',
      },
    ],
  });
};

Remove crypto config from packagerOptions options to fix CI


var fs = require("fs")
var markdown = (require("markdown-it")({html: true})).use(require("markdown-it-deflist"))
var Mold = require("mold-template")

module.exports = function loadTemplates(config) {
  var mold = new Mold(config.env || {})
  fs.readdirSync(config.dir).forEach(function(filename) {
    var match = /^(.*?)\.html$/.exec(filename)
    if (match)
      mold.bake(match[1], fs.readFileSync(config.dir + match[1] + ".html", "utf8").trim())
  })
  mold.defs.markdown = function(options) {
    if (typeof options == "string") options = {text: options}
    let text = markdown.render(config.markdownFilter ? config.markdownFilter(options.text) : options.text)
    if (options.shiftHeadings) text = text.replace(/<h(\d)\b/ig, (_, d) => "<h" + (+d + options.shiftHeadings))
    return text
  }
  mold.defs.markdownFile = function(options) {
    if (typeof options == "string") options = {file: options}
    options.text = fs.readFileSync(config.markdownDir + options.file + ".md", "utf8")
    return mold.defs.markdown(options)
  }
  return mold
}

var fs = require("fs")
var markdown = (require("markdown-it")({html: true})).use(require("markdown-it-deflist"))
var Mold = require("mold-template")

module.exports = function loadTemplates(config) {
  var mold = new Mold(config.env || {})
  fs.readdirSync(config.dir).forEach(function(filename) {
    var match = /^(.*?)\.html$/.exec(filename)
    if (match)
      mold.bake(match[1], fs.readFileSync(config.dir + match[1] + ".html", "utf8").trim())
  })
  mold.defs.markdown = function(options) {
    if (typeof options == "string") options = {text: options}
    let text = markdown.render(config.markdownFilter ? config.markdownFilter(options.text) : options.text)
    if (options.shiftHeadings) text = text.replace(/<(\/?)h(\d)\b/ig, (_, cl, d) => "<" + cl + "h" + (+d + options.shiftHeadings))
    return text
  }
  mold.defs.markdownFile = function(options) {
    if (typeof options == "string") options = {file: options}
    options.text = fs.readFileSync(config.markdownDir + options.file + ".md", "utf8")
    return mold.defs.markdown(options)
  }
  return mold
}

Fix header shifting to also shift closing tags


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

exports = module.exports = {
    capture: capture,
};

function capture(action, cb) {
  var result = {
    text: '',
    errorText: ''
  }

  var processStdoutWrite = process.stdout.write
  var processStderrWrite = process.stderr.write
  var processExit = process.exit

  process.stdout.write = function(data, encoding, fd) {
    result.text += data;
  };

  process.stderr.write = function (data, encoding, fd) {
    result.errorText += data;
  };

  process.exit = function(status) {
    result.exitStatus = status;

    process.stdout.write = processStdoutWrite;
    process.stderr.write = processStderrWrite;
    process.exit = processExit;

    return cb(result);
  };

  try {
    action();
  } catch(err) {
    result.error = err;

    process.stdout.write = processStdoutWrite;
    process.stderr.write = processStderrWrite;
    process.exit = processExit;

    if (!result.exitStatus) {
        cb(result);
    }
  }
}

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

var sinon = require('sinon');

exports = module.exports = {
    capture: capture,
};

function capture(action, cb) {
  var sandbox = sinon.sandbox.create();

  var result = {
    text: '',
    errorText: ''
  }

  sandbox.stub(process.stdout, 'write', function(data, encoding, fd) {
    result.text += data;
  });

  sandbox.stub(process.stderr, 'write', function (data, encoding, fd) {
    result.errorText += data;
  });

  sandbox.stub(process, 'exit', function(status) {
    result.exitStatus = status;

    sandbox.restore();

    return cb(result);
  });

  try {
    action();
  } catch(err) {
    result.error = err;

    sandbox.restore();

    if (!result.exitStatus) {
      cb(result);
    }
  }
}

Improve CLI test mocking using sinon


const konan = require("konan");
const path = require("path");
const localRequire = lib => {
  return require(require("path").join(
    process.env.PROJECTPATH,
    "node_modules",
    lib
  ));
};

module.exports = (file, code) => {
  var extname = path.extname(file).toLowerCase();
  if (extname === ".mdx" || extname === ".md") {
    const mdxTransform = localRequire("@mdx-js/mdx").sync;
    code = mdxTransform(code);
  }

  if (extname === ".ts" || extname === ".tsx") {
    const ts = localRequire("typescript");
    var result = ts.transpileModule(code, {
      compilerOptions: {
        module: ts.ModuleKind.CommonJS,
        jsx: ts.JsxEmit.Preserve
      }
    });

    code = result.outputText;
  }

  if (extname === ".vue") {
    const vue = localRequire("@vue/component-compiler-utils");
    const vueTemplateCompiler = localRequire("vue-template-compiler");
    var p = vue.parse({
      source: code,
      needMap: false,
      compiler: vueTemplateCompiler
    });
    code = p && p.script ? p.script.content : "";
  }

  return konan(code);
};

const konan = require("konan");
const path = require("path");
const localRequire = lib => {
  return require(require("path").join(
    process.env.PROJECTPATH,
    "node_modules",
    lib
  ));
};

module.exports = (file, code) => {
  const extname = path.extname(file).toLowerCase();
  if (extname === ".mdx" || extname === ".md") {
    const mdxTransform = localRequire("@mdx-js/mdx").sync;
    code = mdxTransform(code);
  }

  if (extname === ".ts" || extname === ".tsx") {
    const ts = localRequire("typescript");
    const config = {
      compilerOptions: {
        module: ts.ModuleKind.CommonJS
      }
    };

    if (extname === ".tsx") {
      config.compilerOptions.jsx = ts.JsxEmit.Preserve;
    }
    const result = ts.transpileModule(code, config);

    code = result.outputText;
  }

  if (extname === ".vue") {
    const vue = localRequire("@vue/component-compiler-utils");
    const vueTemplateCompiler = localRequire("vue-template-compiler");
    const p = vue.parse({
      source: code,
      needMap: false,
      compiler: vueTemplateCompiler
    });
    code = p && p.script ? p.script.content : "";
  }

  return konan(code);
};

Fix TS to not be parsed as TSX


import React, { Component } from 'react';
import bugsnag, { Client } from 'bugsnag-react-native';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

class examples extends Component {

  constructor(opts) {
    super(opts);
    this.client = new Client('f35a2472bd230ac0ab0f52715bbdc65d');
    this.client.handleUncaughtErrors();
  }

  render() {
    this.client.leaveBreadcrumb('load main view',
        {type: 'navigation', firstLaunch: 'no'});
    this.client.setUser('123', 'John Jones');
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to the Sample Project!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.ios.js
        </Text>
        <Text style={styles.instructions}>
          Press Cmd+R to reload,{'\n'}
          Cmd+D or shake for dev menu
        </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('examples', () => examples);

import React, { Component } from 'react';
import { Client } from 'bugsnag-react-native';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

const client = new Client('API key');

class examples extends Component {

  render() {
    client.leaveBreadcrumb('load main view',
        {type: 'navigation', firstLaunch: 'no'});
    client.setUser('123', 'John Jones');
    client.notify(new Error('foo'));

    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to the Sample Project!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.ios.js
        </Text>
        <Text style={styles.instructions}>
          Press Cmd+R to reload,{'\n'}
          Cmd+D or shake for dev menu
        </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('examples', () => examples);

Add an example of sending a handled error


function KeyPressEmulation(keyboardEventUtil, sinon) {
  this._keyDownListeners = [];
  this._keyUpListeners = [];
  var self = this;
  sinon.stub(keyboardEventUtil, 'addKeyDownListener', function(fn) {
    self._keyDownListeners.push(fn);
  });
  sinon.stub(keyboardEventUtil, 'addKeyUpListener', function(fn) {
    self._keyUpListeners.push(fn);
  });
}
KeyPressEmulation.prototype = {
  keyDownByKeyName: function(keyName) {
    this._keyDownListeners[0](keyName);
  },

  keyUpByKeyName: function(keyName) {
    this._keyUpListeners[0](keyName);
  },

  keyDownByKeyNames: function(keyNames) {
    keyNames.forEach(this.keyDownByKeyName.bind(this));
  },

  keyUpByKeyNames: function(keyNames) {
    keyNames.forEach(this.keyUpByKeyName.bind(this));
  },

  pressByKeyNames: function(keyNames) {
    // The first key is (normally) the Meta key, don't fire keyUp yet,
    // fire it only at the end of it all.
    var firstKeyName = keyNames[0];
    this._keyDownListeners[0](firstKeyName);

    // Fire all keyDowns and keyUps.
    var self = this;
    keyNames.slice(1).forEach(function(key) {
      self._keyDownListeners[0](key);
      self._keyUpListeners[0](key);
    });

    this.keyUpByKeyName(firstKeyName);
  }

};

module.exports = {
  KeyPressEmulation: KeyPressEmulation
};

export class KeyPressEmulation {
  constructor(keyboardEventUtil, sinon) {
    this._keyDownListeners = [];
    this._keyUpListeners = [];
    sinon.stub(keyboardEventUtil, 'addKeyDownListener', (fn) => this._keyDownListeners.push(fn));
    sinon.stub(keyboardEventUtil, 'addKeyUpListener', (fn) => this._keyUpListeners.push(fn));
  }

  keyDownByKeyName(keyName) {
    this._keyDownListeners[0](keyName);
  }

  keyUpByKeyName(keyName) {
    this._keyUpListeners[0](keyName);
  }

  keyDownByKeyNames(keyNames) {
    keyNames.forEach((...args) => { this.keyDownByKeyName(...args)});
  }

  keyUpByKeyNames(keyNames) {
    keyNames.forEach((...args) => { this.keyUpByKeyName(...args)});
  }

  pressByKeyNames(keyNames) {
    // The first key is (normally) the Meta key, don't fire keyUp yet,
    // fire it only at the end of it all.
    var firstKeyName = keyNames[0];
    this._keyDownListeners[0](firstKeyName);

    // Fire all keyDowns and keyUps.
    keyNames.slice(1).forEach((key) => {
      this._keyDownListeners[0](key);
      this._keyUpListeners[0](key);
    });

    this.keyUpByKeyName(firstKeyName);
  }

}

Make it an ES6 class and remove usage of self.


/*
 Copyright 2018 Carmilla Mina Jankovic

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

const ViewWrapper = require('../ViewWrapper');
const ForumList = require('../lists/ForumList');
const ForumPage = require('./ForumPage');
const UserList = require('../lists/UserList');

class ForumView extends ViewWrapper {
  constructor({
    classes = [],
    elementId = `fView-${Date.now()}`,
  }) {
    const forumList = new ForumList({});
    const forumPage = new ForumPage({});
    const userList = new UserList({
      title: 'Users',
    });

    super({
      elementId,
      columns: [
        {
          components: [
            { component: forumList },
            { component: userList },
          ],
          classes: ['columnList'],
        },
        { components: [{ component: forumPage }] },
      ],
      classes: classes.concat(['docFileView']),
    });
  }
}

module.exports = ForumView;

/*
 Copyright 2018 Carmilla Mina Jankovic

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

const ViewWrapper = require('../ViewWrapper');
const ForumList = require('../lists/ForumList');
const ForumPage = require('./ForumPage');
const UserList = require('../lists/UserList');

class ForumView extends ViewWrapper {
  constructor({
    classes = [],
    elementId = `fView-${Date.now()}`,
  }) {
    const forumList = new ForumList({});
    const forumPage = new ForumPage({});
    const userList = new UserList({
      title: 'Users',
    });

    super({
      elementId,
      columns: [
        {
          components: [
            { component: forumList },
            { component: userList },
          ],
          classes: ['columnList'],
        },
        { components: [{ component: forumPage }] },
      ],
      classes: classes.concat(['forumView']),
    });
  }
}

module.exports = ForumView;

Correct CSS class for forum view


$(function(){
  const GALLERY_SLICK_SELECTOR = '.gallery--slick';

  $(GALLERY_SLICK_SELECTOR).slick({
    infinite: false,
    dots: true,
    speed: 600,
    slidesToShow: 4,
    slidesToScroll: 2,
    responsive: [
      {
        breakpoint: 768,
        settings: {
          slidesToShow: 2,
          slidesToScroll: 2,
        }
      }
    ]
  });
});

$(function(){
  const GALLERY_SLICK_SELECTOR = '.gallery--slick';

  $(GALLERY_SLICK_SELECTOR).slick({
    infinite: false,
    dots: true,
    speed: 600,
    slidesToShow: 4,
    slidesToScroll: 2,
    prevArrow: '
<button type="button" class="slick-prev">Previous</button>
',
    nextArrow: '
<button type="button" class="slick-next">Next</button>
',
    responsive: [
      {
        breakpoint: 768,
        settings: {
          slidesToShow: 2,
          slidesToScroll: 2,
        }
      }
    ]
  });
});

Fix slick gallery buttons in Chrome


$(document).on('turbolinks:load', function(event) {

  //Merge all editor components.
  $.extend(
      CodeOceanEditor,
      CodeOceanEditorAJAX,
      CodeOceanEditorEvaluation,
      CodeOceanEditorFlowr,
      CodeOceanEditorSubmissions,
      CodeOceanEditorTurtle,
      CodeOceanEditorWebsocket,
      CodeOceanEditorPrompt,
      CodeOceanEditorCodePilot,
      CodeOceanEditorRequestForComments
  );

  if ($('#editor').isPresent() && CodeOceanEditor && event.originalEvent.data.url.endsWith("/implement")) {
    if (CodeOceanEditor.isBrowserSupported()) {
      $('#alert').hide();
      // This call will (amon other things) initializeEditors and load the content except for the last line
      // It must not be called during page navigation. Otherwise, content will be duplicated!
      // Search for insertLines and Turbolinks reload / cache control
      CodeOceanEditor.initializeEverything();
    }
  }
});

$(document).on('turbolinks:load', function(event) {

  //Merge all editor components.
  $.extend(
      CodeOceanEditor,
      CodeOceanEditorAJAX,
      CodeOceanEditorEvaluation,
      CodeOceanEditorFlowr,
      CodeOceanEditorSubmissions,
      CodeOceanEditorTurtle,
      CodeOceanEditorWebsocket,
      CodeOceanEditorPrompt,
      CodeOceanEditorCodePilot,
      CodeOceanEditorRequestForComments
  );

  if ($('#editor').isPresent() && CodeOceanEditor && event.originalEvent.data.url.includes("/implement")) {
    if (CodeOceanEditor.isBrowserSupported()) {
      $('#alert').hide();
      // This call will (amon other things) initializeEditors and load the content except for the last line
      // It must not be called during page navigation. Otherwise, content will be duplicated!
      // Search for insertLines and Turbolinks reload / cache control
      CodeOceanEditor.initializeEverything();
    }
  }
});

Use includes instead of endsWith (due to query parameters)


'use strict';

var _ = require( '../utils' );
var Object3D = require( '../object3d' );

function Mesh( geometry, material ) {
  Object3D.call( this );

  this.geometry = geometry;
  this.material = material;
}

_.extends( Mesh, Object3D );

module.exports = Mesh;

'use strict';

var _ = require( '../utils' );
var Object3D = require( '../object3d' );
var Filter = require( '../math/filter' );

function Mesh( geometry, material ) {
  Object3D.call( this );

  this.geometry = geometry;
  this.material = material;

  this.filter = new Filter();
}

_.extends( Mesh, Object3D );

module.exports = Mesh;

Add Mesh collision filter property.


'use strict';

var path = require('path');
var gulp = require('gulp');

var karma = require('karma');

function runTests(singleRun, done) {
  karma.server.start({
    configFile: path.join(__dirname, '/../karma.conf.js'),
    singleRun: singleRun,
    autoWatch: !singleRun
  }, function(failCount) {
    done(failCount ? new Error('Failed ' + failCount + ' tests.') : null);
  });
}

gulp.task('test', ['scripts:test'], function(done) {
  runTests(true, done);
});

gulp.task('test:auto', ['scripts:test-watch'], function(done) {
  runTests(false, done);
});

'use strict';

var path = require('path');
var gulp = require('gulp');

var karma = require('karma');

function runTests(singleRun, done) {
  var server = new karma.Server({
    configFile: path.join(__dirname, '/../karma.conf.js'),
    singleRun: singleRun,
    autoWatch: !singleRun
  }, function(failCount) {
    done(failCount ? new Error('Failed ' + failCount + ' tests.') : null);
  });
  server.start();
}

gulp.task('test', ['scripts:test'], function(done) {
  runTests(true, done);
});

gulp.task('test:auto', ['scripts:test-watch'], function(done) {
  runTests(false, done);
});

Use karma.Server instead of karma.server


/**
 * Array with fixed max length and displacing first element on oversize.
 *
 * @author Serhii Maksymchuk from Ubrainians for imCode
 * 10.05.18
 */
Imcms.define('imcms-displacing-array', [], function () {

    var DisplacingArray = function (size) {
        if (typeof size !== 'number') throw new Error("Size should be integer!");
        if (size < 1) throw new Error("Size should be >= 1");

        this.size = size;
        this.elements = [];
    };

    DisplacingArray.prototype = {
        push: function (content) {
            if (this.elements.length > this.size) {
                this.elements.splice(0, 1); // removes first element
            }

            this.elements.push(content);
            this.length = this.elements.length;
        },
        forEach: function (doForEach) {
            this.elements.forEach(doForEach);
        }
    };

    return DisplacingArray;
});

/**
 * List with fixed max length and displacing first element on oversize.
 *
 * @author Serhii Maksymchuk from Ubrainians for imCode
 * 10.05.18
 */
Imcms.define('imcms-displacing-array', [], function () { // todo: rename "array"->"list" in module name and file

    var DisplacingList = function (size) {
        if (typeof size !== 'number') throw new Error("Size should be integer!");
        if (size < 1) throw new Error("Size should be >= 1");

        this.size = size;
        this.elements = [];
        this.length = 0;
    };

    DisplacingList.prototype = {
        push: function (content) {
            if (this.elements.length > this.size) {
                this.elements.splice(0, 1); // removes first element
            }

            this.elements.push(content);
            this.length = this.elements.length;
        },
        forEach: function (doForEach) {
            this.elements.forEach(doForEach);
        },
        get: function (index) {
            return this.elements[index];
        }
    };

    return DisplacingList;
});

Add a "pin" icon to imCMS's panel: - Refactored displacing array.


module.exports = (client) => {
  var regex = require("./regexp");
  var galeguinhos = 0;
  client.on('message', message => {
    if (regex.regexSiNo.test(message.content)) {
      let response = Math.random() < 0.5 ? -1 : 1;
      if (response > 0) {
        response = "SI"
      } else {
        response = "NO"
      }
      message.reply(`PUES OBVIAMENTE, ${response}`).catch(console.log)
    }
    if (regex.regexCuantos.test(message.content)) {
      if (message.guild.members.array().filter(each => regex.regexGale.test(each.user.username)).length > 0) {
          galeguinhos = message.guild.members.array().filter(each => regex.regexGale.test(each.user.username)).length
      }
      let response = message.guild.memberCount - 1 + " DE LOS CUALES " + galeguinhos + " SON GALEGUINHO95 PORQUE ES PUTO TONTO. AH! Y YO, EL BOT, SOY EL BOT, YO ESTUVE, SÍ."
      message.reply(response).then(() => galeguinhos = 0).catch(console.log)
    }
  })
}

module.exports = (client) => {
  var regex = require("./regexp");
  var galeguinhos = 0;
  client.on('message', message => {
    if (regex.regexSiNo.test(message.content)) {
      let response = Math.random() < 0.5 ? -1 : 1;
      if (response > 0) {
        response = "SI"
      } else {
        response = "NO"
      }
      message.reply(`PUES OBVIAMENTE, ${response}`).catch(console.log)
    }
    if (regex.regexCuantos.test(message.content)) {
      if (message.guild.members.array().filter(each => regex.regexGale.test(each.user.username)).length > 0) {
          galeguinhos = message.guild.members.array().filter(each => regex.regexGale.test(each.user.displayName)).length
      }
      let response = message.guild.memberCount - 1 + " DE LOS CUALES " + galeguinhos + " SON GALEGUINHO95 PORQUE ES PUTO TONTO. AH! Y YO, EL BOT, SOY EL BOT, YO ESTUVE, SÍ."
      message.reply(response).then(() => galeguinhos = 0).catch(console.log)
    }
  })
}

Fix galeginho si todo va bien


/* global requirejs */
/* global require */

function registerComponents(container) {
  var seen = requirejs._eak_seen;
  var templates = seen, match;
  if (!templates) { return; }

  for (var prop in templates) {
    if (match = prop.match(/components\/(.*)$/)) {
      require(prop, null, null, true);
      registerComponent(container, match[1]);
    }
  }
}

function registerComponent(container, name) {
  Ember.assert("You provided a template named 'components/" + name + "', but custom components must include a '-'", name.match(/-/));

  var fullName         = 'component:' + name,
      templateFullName = 'template:components/' + name;

  container.injection(fullName, 'layout', templateFullName);

  var Component = container.lookupFactory(fullName);

  if (!Component) {
    container.register(fullName, Ember.Component);
    Component = container.lookupFactory(fullName);
  }

  Ember.Handlebars.helper(name, Component);
}

export default registerComponents;

Fix JSHint issue with requirejs & require.