import React, {Component} from 'react';
import Style from 'styled-components';

class Progress extends Component {
  state = {progress: 0};

  componentDidMount() {
    this.props.emitter.on(({progress}) => {
      if (this.state.progress !== progress) {
        this.setState({progress: progress});
      }
    });
  }
  Bar = Style.div`
    position:absolute;
    left: 0;
    top: 0;
    height: 2px;
    background-color: #337ab7;
    transition: all 0.4s ease-in-out;
  `;
  render() {
    return <this.Bar style={{width: `${this.state.progress}%`}} />;
  }
}

export default Progress;

import React, {Component} from 'react';
import Style from 'styled-components';

class Progress extends Component {
  state = {progress: 0};

  componentDidMount() {
    this.props.emitter.on(({progress}) => {
      if (this.state.progress !== progress) {
        this.setState({progress: progress});
      }
    });
  }
  Bar = Style.div`
    position:absolute;
    left: 0;
    top: 0;
    height: 2px;
    background-color: #337ab7;
  `;
  render() {
    return <this.Bar style={{width: `${this.state.progress}%`}} />;
  }
}

export default Progress;

Remove css transition from progress bar


/*
 * Raven.js @VERSION
 * https://github.com/getsentry/raven-js
 *
 * Includes TraceKit
 * https://github.com/getsentry/TraceKit
 *
 * Copyright 2013 Matt Robenolt and other contributors
 * Released under the BSD license
 * https://github.com/getsentry/raven-js/blob/master/LICENSE
 *
 */

/*! Raven.js @VERSION | github.com/getsentry/raven-js */

/*! Raven.js @VERSION | github.com/getsentry/raven-js */

/*
 * Includes TraceKit
 * https://github.com/getsentry/TraceKit
 *
 * Copyright 2013 Matt Robenolt and other contributors
 * Released under the BSD license
 * https://github.com/getsentry/raven-js/blob/master/LICENSE
 *
 */

Build the copyright header slightly less dumb


import { MJMLElement } from 'mjml-core'
import React, { Component } from 'react'

const tagName = 'mj-spacer'
const parentTag = ['mj-column', 'mj-hero-content']
const selfClosingTag = true
const defaultMJMLDefinition = {
  attributes: {
    'align': null,
    'container-background-color': null,
    'height': '20px',
    'padding-bottom': null,
    'padding-left': null,
    'padding-right': null,
    'padding-top': null,
    'vertical-align': null
  }
}

@MJMLElement
class Spacer extends Component {

  styles = this.getStyles()

  getStyles () {
    const { mjAttribute, defaultUnit } = this.props

    return {
      div: {
        fontSize: '1px',
        lineHeight: defaultUnit(mjAttribute('height'))
      }
    }
  }

  render () {
    return (
      <div
        dangerouslySetInnerHTML={{ __html: ' ' }}
        style={this.styles.div} />
    )
  }

}

Spacer.tagName = tagName
Spacer.parentTag = parentTag
Spacer.selfClosingTag = selfClosingTag
Spacer.defaultMJMLDefinition = defaultMJMLDefinition

export default Spacer

import { MJMLElement } from 'mjml-core'
import React, { Component } from 'react'

const tagName = 'mj-spacer'
const parentTag = ['mj-column', 'mj-hero-content']
const selfClosingTag = true
const defaultMJMLDefinition = {
  attributes: {
    'align': null,
    'container-background-color': null,
    'height': '20px',
    'padding-bottom': null,
    'padding-left': null,
    'padding-right': null,
    'padding-top': null,
    'vertical-align': null
  }
}

@MJMLElement
class Spacer extends Component {

  styles = this.getStyles()

  getStyles () {
    const { mjAttribute, defaultUnit } = this.props

    return {
      div: {
        fontSize: '1px',
        lineHeight: defaultUnit(mjAttribute('height')),
        whiteSpace: 'nowrap'
      }
    }
  }

  render () {
    return (
      <div
        dangerouslySetInnerHTML={{ __html: ' ' }}
        style={this.styles.div} />
    )
  }

}

Spacer.tagName = tagName
Spacer.parentTag = parentTag
Spacer.selfClosingTag = selfClosingTag
Spacer.defaultMJMLDefinition = defaultMJMLDefinition

export default Spacer

Fix escaping servers which replace the ` ` with a space


"use strict";

var GitHubAPI = function(accessToken, org, repo) {

  var API_URL = 'https://api.github.com/repos/' + org + '/' + repo;

  return {
    getBranch: function(branchName) {
      return $.get(API_URL + '/branches/' + branchName);
    },

    getTree: function(sha) {
      return $.get(API_URL + '/git/trees/' + sha + '?recursive=1');
    },

  };
}

var Vidius = function(github) {
  return {
    getFileListing: function() {
      return github.getBranch('master').then(function(data) {
        return github.getTree(data.commit.sha);
      }).then(function(data) {
        return data.tree;
      });
    },

    getMarkdownFiles: function() {
      return this.getFileListing().then(function(files) {
        return files.filter(function(file) {
          return file.path.endsWith('.md');
        });
      });
    }
  };
};

"use strict";

var GitHubAPI = function(accessToken, org, repo) {

  var API_URL = 'https://api.github.com/repos/' + org + '/' + repo;

  return {
    getBranch: function(branchName) {
      return $.get(API_URL + '/branches/' + branchName);
    },

    getTree: function(sha) {
      return $.get(API_URL + '/git/trees/' + sha + '?recursive=1');
    },

    getFileContents: function(path, ref) {
      return $.get(API_URL + '/contents/' + path + '?ref=' + ref);
    }
  };
}

var Vidius = function(github) {
  return {
    getFileListing: function() {
      return github.getBranch('master').then(function(data) {
        return github.getTree(data.commit.sha);
      }).then(function(data) {
        return data.tree;
      });
    },

    getMarkdownFiles: function() {
      return this.getFileListing().then(function(files) {
        return files.filter(function(file) {
          return file.path.endsWith('.md');
        });
      });
    },

    getTextFileContents: function(file) {
      // TODO don't hardcode the ref
      return github.getFileContents(file.path, 'master').then(function(contents) {
        // TODO check type is file and encoding is base64, otherwise fail
        return atob(contents.content.replace(/\s/g, ''));
      });
    }
  };
};

Add an API call for file contents


var ready;

beforeEach(function() {
	storage = TEST_STORAGE;

	storage.clear(function() {
		ready = true;
	});

	waitsFor(function() {
		return ready;
	}, "the storage to be set up for testing", 500);
});

afterEach(function() {
	storage = DEFAULT_STORAGE;
});

var ready;

beforeEach(function() {
	ready = false;
	storage = TEST_STORAGE;

	storage.clear(function() {
		ready = true;
	});

	waitsFor(function() {
		return ready;
	}, "the storage to be set up for testing", 500);
});

afterEach(function() {
	storage = DEFAULT_STORAGE;
});

Set ready var to false before each test so it doesn't run prematurely.


/**
 * WidgetNull component.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * External dependencies
 */
import PropTypes from 'prop-types';

/**
 * Internal dependencies
 */
import useWidgetStateEffect from '../hooks/useWidgetStateEffect';
import Null from '../../../components/Null';

// The supported props must match `Null` (except `widgetSlug`).
export default function WidgetNull( { widgetSlug } ) {
	useWidgetStateEffect( widgetSlug, Null );

	return <Null />;
}

WidgetNull.propTypes = {
	widgetSlug: PropTypes.string.isRequired,
	...Null.propTypes,
};

/**
 * WidgetNull component.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * External dependencies
 */
import PropTypes from 'prop-types';

/**
 * Internal dependencies
 */
import useWidgetStateEffect from '../hooks/useWidgetStateEffect';
import Null from '../../../components/Null';

// The supported props must match `Null` (except `widgetSlug`).
export default function WidgetNull( { widgetSlug } ) {
	useWidgetStateEffect( widgetSlug, Null, null );

	return <Null />;
}

WidgetNull.propTypes = {
	widgetSlug: PropTypes.string.isRequired,
	...Null.propTypes,
};

Update fn call for unset to work.


'use strict';

require('../stanza/dataforms');

module.exports = function (client) {
    client.disco.addFeature('jabber:x:data');
    client.disco.addFeature('urn:xmpp:media-element');
    client.disco.addFeature('http://jabber.org/protocol/xdata-validate');

    client.on('message', function (msg) {
        if (msg.form) {
            client.emit('dataform', msg);
        }
    });
};

'use strict';

require('../stanza/dataforms');

module.exports = function (client) {
    client.disco.addFeature('jabber:x:data');
    client.disco.addFeature('urn:xmpp:media-element');
    client.disco.addFeature('http://jabber.org/protocol/xdata-validate');
    client.disco.addFeature('http://jabber.org/protocol/xdata-layout');

    client.on('message', function (msg) {
        if (msg.form) {
            client.emit('dataform', msg);
        }
    });
};

Add disco feature for forms layout


import {type} from 'ramda';

export const sanitizeOptions = options => {
    if (type(options) === 'Object') {
        return Object.entries(options).map(([value, label]) => ({
            label: String(label),
            value,
        }));
    }

    if (type(options) === 'Array') {
        if (
            options.length > 0 &&
            ['String', 'Number', 'Bool'].includes(type(options[0]))
        ) {
            return options.map(option => ({
                label: String(option),
                value: option,
            }));
        }
        return options;
    }

    return options;
};

import React from 'react';
import {type} from 'ramda';

export const sanitizeOptions = options => {
    if (type(options) === 'Object') {
        return Object.entries(options).map(([value, label]) => ({
            label: React.isValidElement(label) ? label : String(label),
            value,
        }));
    }

    if (type(options) === 'Array') {
        if (
            options.length > 0 &&
            ['String', 'Number', 'Bool'].includes(type(options[0]))
        ) {
            return options.map(option => ({
                label: String(option),
                value: option,
            }));
        }
        return options;
    }

    return options;
};

Fix objects options with component label.


/* global require, describe, it */

import assert from 'assert';
var urlPrefix = 'http://katas.tddbin.com/katas/es6/language/';
var katasUrl = urlPrefix + '__grouped__.json';

var GroupedKata = require('../src/grouped-kata.js');

describe('load ES6 kata data', function() {
  it('loaded data are as expected', function(done) {
    function onSuccess(groupedKatas) {
      assert.ok(groupedKatas);
      done();
    }

    new GroupedKata(katasUrl).load(function() {}, onSuccess);
  });
  describe('on error, call error callback and the error passed', function() {
    it('invalid JSON', function(done) {
      function onError(err) {
        assert.ok(err);
        done();
      }

      var invalidUrl = urlPrefix;
      new GroupedKata(invalidUrl).load(onError);
    });
    it('for invalid data', function(done) {
      function onError(err) {
        assert.ok(err);
        done();
      }

      var invalidData = urlPrefix + '__all__.json';
      new GroupedKata(invalidData).load(onError);
    });
  });
});

/* global describe, it */

import assert from 'assert';
const urlPrefix = 'http://katas.tddbin.com/katas/es6/language';
const katasUrl = `${urlPrefix}/__grouped__.json`;

import GroupedKata from '../src/grouped-kata.js';

describe('load ES6 kata data', function() {
  it('loaded data are as expected', function(done) {
    function onSuccess(groupedKatas) {
      assert.ok(groupedKatas);
      done();
    }

    new GroupedKata(katasUrl).load(() => {}, onSuccess);
  });
  describe('on error, call error callback and the error passed', function() {
    it('invalid JSON', function(done) {
      function onError(err) {
        assert.ok(err);
        done();
      }

      var invalidUrl = urlPrefix;
      new GroupedKata(invalidUrl).load(onError);
    });
    it('for invalid data', function(done) {
      function onError(err) {
        assert.ok(err);
        done();
      }

      var invalidData = `${urlPrefix}/__all__.json`;
      new GroupedKata(invalidData).load(onError);
    });
  });
});

Use ES6 in the tests.


import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

Router.map(function() {
  this.route('lists', function() {
    this.route('show', {path: 'list/:id'});
  });

  this.route('top50');

  this.route('movies', {path: '/'}, function() {
    this.route('show', {path: '/movie/:id'});
  });
});

export default Router;

import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

Router.map(function() {
  this.route('lists', function() {
    this.route('show', {path: ':id'});
  });

  this.route('top50');

  this.route('movies', {path: '/'}, function() {
    this.route('show', {path: '/movie/:id'});
  });
});

export default Router;

Fix up route for single list


/*
 * grunt-util-options
 * https://github.com/mikaelkaron/grunt-util-process
 *
 * Copyright (c) 2013 Mikael Karon
 * Licensed under the MIT license.
 */

module.exports = function(grunt) {
	"use strict";

	var _ = grunt.util._;
	var _property = require("grunt-util-property")(grunt);

	return function (properties) {
		var me = this;
		var name = me.name;
		var target = me.target;

		_.each(_.rest(arguments), function (key) {
			_property.call(properties, key, _.find([
				grunt.option([ name, target, key ].join(".")),
				grunt.option([ name, key ].join(".")),
				grunt.option(key),
				properties[key]
			], function (value) {
				return !_.isUndefined(value);
			}));
		});

		return properties;
	};
}

/*
 * grunt-util-options
 * https://github.com/mikaelkaron/grunt-util-process
 *
 * Copyright (c) 2013 Mikael Karon
 * Licensed under the MIT license.
 */

module.exports = function(grunt) {
	"use strict";

	var _ = grunt.util._;
	var _property = require("grunt-util-property")(grunt);

	return function (properties) {
		var me = this;
		var name = me.name;
		var target = me.target;

		_.each(_.tail(arguments), function (key) {
			_property.call(properties, key, _.find([
				grunt.option([ name, target, key ].join(".")),
				grunt.option([ name, key ].join(".")),
				grunt.option(key),
				properties[key]
			], function (value) {
				return !_.isUndefined(value);
			}));
		});

		return properties;
	};
}

Add support for lodash 4.x (Found in Grunt 1.x) * Changed lodash `rest` usage to tail. * Note this still supports lodash 3.x as tail was an alias for the original rest. Both 3.x and 4.x tail do the same thing.


import ExamplePluginComponent from "./components/ExamplePluginComponent";

var PluginHelper = global.MarathonUIPluginAPI.PluginHelper;

PluginHelper.registerMe("examplePlugin-0.0.1");

PluginHelper.injectComponent(ExamplePluginComponent, "SIDEBAR_BOTTOM");

import ExamplePluginComponent from "./components/ExamplePluginComponent";

var MarathonUIPluginAPI = global.MarathonUIPluginAPI;
var PluginHelper = MarathonUIPluginAPI.PluginHelper;
var PluginMountPoints = MarathonUIPluginAPI.PluginMountPoints;

PluginHelper.registerMe("examplePlugin-0.0.1");

PluginHelper.injectComponent(ExamplePluginComponent,
  PluginMountPoints.SIDEBAR_BOTTOM);

Introduce read-only but extensible mount points file


document.addEventListener('DOMContentLoaded', function () {
  display('Searching...');
});

function display(msg) {
  var el = document.body;
  el.innerHTML = msg;
}

chrome.runtime.getBackgroundPage(displayMessages);

function displayMessages(backgroundPage) {
  var html = '
';
  html += backgroundPage.services.map(function (service) {
    return '
'
            + service.name
            + ''
            + service.host + ':' + service.port
            + ''
           '
';
  }).join('');
  html += '
';
  display(html);

  var items = Array.prototype.slice.call(document.getElementsByTagName('li')),
      uiPage = chrome.extension.getURL("ui.html");

  items.forEach(function(li) {
    li.addEventListener('click', function() {
      chrome.tabs.create({url: uiPage});
    });
  });
}

document.addEventListener('DOMContentLoaded', function () {
  display('Searching...');
});

function display(msg) {
  var el = document.body;
  el.innerHTML = msg;
}

chrome.runtime.getBackgroundPage(displayMessages);

function displayMessages(backgroundPage) {
  var html = '
';
  html += backgroundPage.services.map(function (service) {
    return '
'
            + service.host
            + ''
            + service.address + ':' + service.port
            + ''
           '
';
  }).join('');
  html += '
';
  display(html);

  var items = Array.prototype.slice.call(document.getElementsByTagName('li')),
      uiPage = chrome.extension.getURL("ui.html");

  items.forEach(function(li) {
    li.addEventListener('click', function() {
      chrome.tabs.create({url: uiPage});
    });
  });
}

Change name to match new service instance object


'use strict';

const _ = require('lodash');

const tests = {
  db: (value) => {
    const keys = ['query', 'connect', 'begin'];

    return keys.every((key) => _.has(value, key));
  },
};

const ok = require('ok')(tests);

const previous = [];

module.exports = (obj) => {
  const result = obj ? previous.find((item) => _.isEqual(item, obj)) : _.last(previous);

  if (result) {
    return result;
  } else {
    const errors = ok(obj);

    if (errors.length) {
      throw new Error(`Configuration is invalid: ${errors.join(', ')}`);
    }

    if (obj) {
      previous.push(obj);
    }

    return obj;
  }
};

'use strict';

const _ = require('lodash');

const tests = {
  db: (value) => {
    const keys = ['query', 'connect', 'begin'];

    return keys.every((key) => _.has(value, key));
  },
};

const ok = require('ok')(tests);

const previous = [];

module.exports = (obj) => {
  let result;

  if (obj) {
    result = previous.find((item) => _.isEqual(item, obj));
  }

  if (result) {
    return result;
  } else {
    const errors = ok(obj);

    if (errors.length) {
      throw new Error(`Configuration is invalid: ${errors.join(', ')}`);
    }

    if (obj) {
      previous.push(obj);
    }

    return obj;
  }
};

Remove ability to get last memoize result by passing falsy argument


(function() {
  'use strict';

  angular.module('app.states')
    .run(appRun);

  /** @ngInject */
  function appRun(routerHelper, navigationHelper) {
    routerHelper.configureStates(getStates());
    navigationHelper.navItems(navItems());
    navigationHelper.sidebarItems(sidebarItems());
  }

  function getStates() {
    return {
      'manage.cms': {
        url: '/cms',
        redirectTo: 'manage.cms.list',
        template: '<ui-view></ui-view>'
      }
    };
  }

  function navItems() {
    return {};
  }

  function sidebarItems() {
    return {
      'manage.cms': {
        type: 'state',
        state: 'manage.cms',
        label: 'CMS',
        order: 10
      }
    };
  }
})();

(function() {
  'use strict';

  angular.module('app.states')
    .run(appRun);

  /** @ngInject */
  function appRun(routerHelper, navigationHelper) {
    routerHelper.configureStates(getStates());
    navigationHelper.navItems(navItems());
    navigationHelper.sidebarItems(sidebarItems());
  }

  function getStates() {
    return {
      'manage.cms': {
        url: '/cms',
        redirectTo: 'manage.cms.list',
        template: '<ui-view></ui-view>'
      }
    };
  }

  function navItems() {
    return {};
  }

  function sidebarItems() {
    return {
      'manage.cms': {
        type: 'state',
        state: 'manage.cms',
        label: 'Pages',
        order: 10
      }
    };
  }
})();

Rename CMS label to Pages


import { createStore, applyMiddleware } from 'redux'
import logger from 'redux-logger'
import thunk from 'redux-thunk'
import oaaChat from './reducers'

const configureStore = () => {
	const store = createStore(
		oaaChat, applyMiddleware(thunk, logger()))

	return store
}

export default configureStore

import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import oaaChat from './reducers'

const configureStore = () => {
	const store = createStore(
		oaaChat,
		window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
		applyMiddleware(thunk))

	return store
}

export default configureStore

Remove redux-logger and setup redux devtools


export async function up(knex) {
  await knex.schema.createTable('Resource', (table) => {
    table.uuid('id').notNullable().primary()
    table.string('name', 32).notNullable()
    table.string('mime', 32)
    table.string('md5')
    table.integer('status').notNullable()
    table.bigInteger('createdAt')
    table.bigInteger('updatedAt')
  })

  await knex.schema.createTable('Content', (table) => {
    table.increments()
    table.uuid('resourceId').notNullable().references('Resource.id')
    table.string('name', 32)
    table.string('title', 255)
    table.text('description')
    table.json('data')
    table.integer('status').notNullable()
    table.bigInteger('createdAt')
    table.bigInteger('updatedAt')
  })
}

export async function down(knex) {
  await knex.schema.dropTableIfExists('Content')
  await knex.schema.dropTableIfExists('Resource')
}

export async function up(knex) {
  await knex.schema.createTable('Resource', (table) => {
    table.uuid('id').notNullable().primary()
    table.string('name', 32).notNullable()
    table.string('mime', 32)
    table.string('md5')
    table.integer('status').notNullable()
    table.bigInteger('createdAt')
    table.bigInteger('updatedAt')
  })

  await knex.schema.createTable('Content', (table) => {
    table.increments()
    table.uuid('resourceId').notNullable().references('Resource.id')
    table.string('name', 32).notNullable()
    table.string('title', 255)
    table.text('description')
    table.json('data')
    table.integer('status').notNullable()
    table.bigInteger('createdAt')
    table.bigInteger('updatedAt')
  })
}

export async function down(knex) {
  await knex.schema.dropTableIfExists('Content')
  await knex.schema.dropTableIfExists('Resource')
}

Tweak Content name to be not nullable


'use strict';

// Load our requirements
const glob = require('glob'),
      path = require('path'),
      logger = require('../log');

// Build a list of the available locale files in a given directory
module.exports = function(dir) {

  // Variables
  let available = [];

  // Run through the installed locales and add to array to be loaded
  glob.sync(path.join(dir, '/*.json')).forEach((file) => {

    // Get the shortname for the file
    let lang = path.basename(file, '.json');

    // Add to our object
    logger.debug('Found the "%s" locale.', lang);
    available.push(lang);
  });

  return available;
};

'use strict';

// Load our requirements
const glob = require('glob'),
      path = require('path'),
      logger = require(__base + 'libs/log');

// Build a list of the available locale files in a given directory
module.exports = function(dir) {

  // Variables
  let available = ['en'];

  // Run through the installed locales and add to array to be loaded
  glob.sync(path.join(dir, '/*.json')).forEach((file) => {

    // Get the shortname for the file
    let lang = path.basename(file, '.json');

    // Ignore english
    if ( lang !== 'en' ) { available.push(lang); }
  });

  return available;
};

Update available locales to prioritise english


module.exports = {
  verbose: !!process.env.VERBOSE,
  moduleNameMapper: {
    testHelpers: '<rootDir>/testHelpers/index.js',
  },
  setupTestFrameworkScriptFile: '<rootDir>/testHelpers/setup.js',
  testResultsProcessor: './node_modules/jest-junit',
  testPathIgnorePatterns: ['/node_modules/'],
  testEnvironment: 'node',
}

module.exports = {
  verbose: !!process.env.VERBOSE,
  moduleNameMapper: {
    testHelpers: '<rootDir>/testHelpers/index.js',
  },
  setupTestFrameworkScriptFile: '<rootDir>/testHelpers/setup.js',
  testResultsProcessor: './node_modules/jest-junit',
  testPathIgnorePatterns: ['/node_modules/'],
  testEnvironment: 'node',
  bail: true,
}

Configure tests to fail fast


/*!
 * Start Bootstrap - Agnecy Bootstrap Theme (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */

// jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
    $('a.page-scroll').bind('click', function(event) {
        var $anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top
        }, 1500, 'easeInOutExpo');
        event.preventDefault();
    });
});

// Highlight the top nav as scrolling occurs
$('body').scrollspy({
    target: '.navbar-fixed-top'
})

// Closes the Responsive Menu on Menu Item Click
$('.navbar-collapse ul li a').click(function() {
    $('.navbar-toggle:visible').click();
});

/*!
 * Start Bootstrap - Agnecy Bootstrap Theme (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */

// jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
    $('a.page-scroll').bind('click', function(event) {
        var $anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top
        }, 1500, 'easeInOutExpo');
        event.preventDefault();
    });
});

// Highlight the top nav as scrolling occurs
$('body').scrollspy({
    target: '.navbar-fixed-top'
})

// Event tracking for google analytics
// inspired by http://cutroni.com/blog/2012/02/21/advanced-content-tracking-with-google-analytics-part-1/
var timer = 0;
var callBackTime = 700;
var debugTracker = false;
var startTime = new Date().getTime();
var currentItem = "";
function trackLocation() {
    var currentTime = new Date().getTime();
    var timeToScroll = Math.round((currentTime - startTime) / 1000);
    if(!debugTracker) {
	ga('send', {
	    'hitType': 'event',
	    'eventCategory': 'Navigation',
	    'eventAction': '#'+currentItem,
	    'eventValue': timeToScroll
	});
    } else {
	console.log("You have viewed: #" + currentItem + " (" + timeToScroll + " sec.)");
    }
    // determine current location
    currentItem = $(".nav li.active > a").text();
    // reset duration
    startTime = currentTime;
}
$('body').on('activate.bs.scrollspy', function () {
    // Use a buffer so we don't call track location too often (high speed scroll)
    if (timer) clearTimeout(timer);
    timer = setTimeout(trackLocation, callBackTime);
})
window.onbeforeunload = function() {
    trackLocation();
    return null;
}

// Closes the Responsive Menu on Menu Item Click
$('.navbar-collapse ul li a').click(function() {
    $('.navbar-toggle:visible').click();
});

Add event tracking to google analytics


var pkg = require(process.cwd() + '/package.json');
var intrepidjsVersion = pkg.version;

// Dummy index, only shows intrepidjs-cli version
console.log(intrepidjsVersion);

var pkg = require(__dirname + '/package.json');
var intrepidjsVersion = pkg.version;

// Dummy index, only shows intrepidjs-cli version
console.log(intrepidjsVersion);

Use __dirname instead of process.cwd


'use strict';

module.exports = {
  name: 'Ember CLI ic-ajax',

  init: function(name) {
    this.treePaths['vendor'] = 'node_modules';
  },

  included: function(app) {
    var options = this.app.options.icAjaxOptions || {enabled: true};

    if (options.enabled) {
      this.app.import('vendor/ic-ajax/dist/named-amd/main.js', {
        exports: {
          'ic-ajax': [
            'default',
            'defineFixture',
            'lookupFixture',
            'raw',
            'request',
          ]
        }
      });
    }
  }
};

'use strict';

module.exports = {
  name: 'Ember CLI ic-ajax',

  init: function(name) {
    this.treePaths['vendor'] = require.resolve('ic-ajax').replace('ic-ajax/dist/cjs/main.js', '');
  },

  included: function(app) {
    var options = this.app.options.icAjaxOptions || {enabled: true};

    if (options.enabled) {
      this.app.import('vendor/ic-ajax/dist/named-amd/main.js', {
        exports: {
          'ic-ajax': [
            'default',
            'defineFixture',
            'lookupFixture',
            'raw',
            'request',
          ]
        }
      });
    }
  }
};

Revert "Revert "resolve ala node_module resolution algorithim (NPM v3 support);""


import postcss from 'postcss';

const postcssFlexibility = postcss.plugin('postcss-flexibility', () => css => {
	css.walkRules(rule => {
		const isDisabled = rule.some(({prop, text}) =>
			prop === '-js-display' || text === 'flexibility-disable' || text === '! flexibility-disable'
		);

		if (!isDisabled) {
			rule.walkDecls('display', decl => {
				const {value} = decl;
				if (value === 'flex') {
					decl.cloneBefore({prop: '-js-display'});
				}
			});
		}
	});
});

export default postcssFlexibility;

import postcss from 'postcss';

const postcssFlexibility = postcss.plugin('postcss-flexibility', () => css => {
	css.walkRules(rule => {
		const isDisabled = rule.some(({prop, text = ''}) =>
			prop === '-js-display' || text.endsWith('flexibility-disable')
		);

		if (!isDisabled) {
			rule.walkDecls('display', decl => {
				const {value} = decl;
				if (value === 'flex') {
					decl.cloneBefore({prop: '-js-display'});
				}
			});
		}
	});
});

export default postcssFlexibility;

Change check to use endsWith for supporting loud comments


$(document).ready(function() {
    $("#trcAge").slider({
        id: "trcAge"
    });
    $("#trcAge").on("slide", function(slideEvt) {
        console.log("Age range selected", slideEvt.value);
        $("#trcAgeSelection").text(slideEvt.value.join(" - "));
    });
});

$(document).ready(function() {
    $("#trcAge").slider({
        id: "trcAge"
    });
    $("#trcAge").on("slide", function(slideEvt) {
        // console.log("Age range selected", slideEvt.value);
        $("#trcAgeSelection").text(slideEvt.value.join(" - "));
    });
});

Undo console log (was a demo of git)


#!/usr/bin/env node
const express = require('express');
const fileExists = require('file-exists');
const bodyParser = require('body-parser');
const fs = require('fs');
const { port = 8123 } = require('minimist')(process.argv.slice(2));

const app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.get('*', (req, res) => {
    const filePath = req.get('X-Requested-File-Path');

    if (!filePath) {
        return res.status(500).send('Server did not provide file path');
    }

    if (!fileExists(filePath)) {
        return res.status(500).send('Cannot find such file on the server');
    }

    try {
        require(filePath)(req, res); // eslint-disable-line global-require
    } catch (e) {
        return res.status(500).send(`<pre>${e.stack}</pre>`);
    }

    const watcher = fs.watch(filePath, (eventType) => {
        if (eventType === 'change') {
            delete require.cache[require.resolve(filePath)];
            watcher.close();
        }
    });

    return undefined;
});

app.listen(port, () => {
    console.log(`node-direct listening on port ${port}!`);
});

#!/usr/bin/env node
const express = require('express');
const fileExists = require('file-exists');
const bodyParser = require('body-parser');
const fs = require('fs');
const { port = 8123 } = require('minimist')(process.argv.slice(2));

const app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.get('*', (req, res) => {
    const filePath = req.get('X-Requested-File-Path');

    if (!filePath) {
        return res.status(500).send('Server did not provide file path');
    }

    if (!fileExists(filePath)) {
        return res.status(404).send('Cannot find such file on the server');
    }

    try {
        require(filePath)(req, res); // eslint-disable-line global-require
    } catch (e) {
        return res.status(500).send(`<pre>${e.stack}</pre>`);
    }

    const watcher = fs.watch(filePath, (eventType) => {
        if (eventType === 'change') {
            delete require.cache[require.resolve(filePath)];
            watcher.close();
        }
    });

    return undefined;
});

app.listen(port, () => {
    console.log(`node-direct listening on port ${port}!`);
});

Use 404 instead of 500 when a file is not found


module.exports = isPromise;

function isPromise(obj) {
  return obj && typeof obj.then === 'function';
}

module.exports = isPromise;

function isPromise(obj) {
  return obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
}

Make the test a bit more strict


const Discord = require('discord.js');
const client = new Discord.Client();
const config = require("./config.json");

client.on('ready', () => {
  console.log("I am ready!");
  // client.channels.get('spam').send("Soup is ready!")
});

client.on('message', (message) => {
  if (!message.content.startsWith(config.prefix) || message.author.bot) return;

  let msg = message.content.slice(config.prefix.length);

  if (msg.startsWith('ping')) {
    message.reply('pong');
  }

  if (msg.startsWith('echo')) {
    if (msg.length > 5) {
      message.channel.send(msg.slice(5));
    } else {
      message.channel.send("Please provide valid text to echo!");
    }
  }

  if (msg.startsWith('die')) {
    message.channel.send("Shutting down...");
    client.destroy((err) => {
      console.log(err);
    });
  }

});

client.on('disconnected', () => {
  console.log("Disconnected!");
  process.exit(0);
});

client.login(config.token);

const Discord = require('discord.js');
const client = new Discord.Client();
const config = require("./config.json");

client.on('ready', () => {
  console.log("I am ready!");
});

client.on('message', (message) => {
  if (!message.content.startsWith(config.prefix) || message.author.bot) return; // Ignore messages not
                                                                                // starting with your prefix

  let msg = message.content.slice(config.prefix.length);

  if (msg.startsWith('ping')) {
    message.reply('pong');
  }

  if (msg.startsWith('echo')) {
    if (msg.length > 5 && msg[4] === ' ') { // If msg starts with 'echo '
      message.channel.send(msg.slice(5));   // Echo the rest of msg.
    } else {
      message.channel.send("Please provide valid text to echo!");
    }
  }

  if (msg.startsWith('die')) {
    message.channel.send("Shutting down...");
    client.destroy((err) => {
      console.log(err);
    });
  }

});

client.on('disconnected', () => {
  console.log("Disconnected!");
  process.exit(0);
});

client.login(config.token);

Add some comments and refine echo command


var Q = require('q');

/**
 * Chai-Mugshot Plugin
 *
 * @param mugshot - Mugshot instance
 * @param testRunnerCtx - Context of the test runner where the assertions are
 *    done
 */
module.exports = function(mugshot, testRunnerCtx) {
  return function(chai) {
    var Assertion = chai.Assertion;

    function composeMessage(message) {
      var standardMessage = 'expected baseline and screenshot of #{act}';

      return {
        affirmative: standardMessage + ' to ' + message,
        negative: standardMessage + ' to not ' + message
      };
    }

    function mugshotProperty(name, message) {
      var msg = composeMessage(message);

      Assertion.addProperty(name, function() {
        var captureItem = this._obj;
        var deferred = Q.defer();
        var _this = this;

        mugshot.test(captureItem, function(error, result) {
          if (error) {
            deferred.reject(error);
          } else {
            if (testRunnerCtx !== undefined) {
              testRunnerCtx.result = result;
            }

            try {
              _this.assert(result.isEqual, msg.affirmative, msg.negative);
              deferred.resolve();
            } catch (error) {
              deferred.reject(error);
            }
          }
        });

        return deferred.promise;
      });
    }

    mugshotProperty('identical', 'be identical');
  }
};

/**
 * Chai-Mugshot Plugin
 *
 * @param mugshot - Mugshot instance
 * @param testRunnerCtx - Context of the test runner where the assertions are
 *    done
 */
module.exports = function(mugshot, testRunnerCtx) {
  return function(chai) {
    var Assertion = chai.Assertion;

    function composeMessage(message) {
      var standardMessage = 'expected baseline and screenshot of #{act}';

      return {
        affirmative: standardMessage + ' to ' + message,
        negative: standardMessage + ' to not ' + message
      };
    }

    function mugshotProperty(name, message) {
      var msg = composeMessage(message);

      Assertion.addProperty(name, function() {
        var _this = this,
            captureItem = this._obj,
            promise, resolve, reject;

        promise = new Promise(function(res, rej) {
          resolve = res;
          reject = rej;
        });

        mugshot.test(captureItem, function(error, result) {
          if (error) {
            reject(error);
          } else {
            if (testRunnerCtx !== undefined) {
              testRunnerCtx.result = result;
            }

            try {
              _this.assert(result.isEqual, msg.affirmative, msg.negative);
              resolve();
            } catch (error) {
              reject(error);
            }
          }
        });

        return promise;
      });
    }

    mugshotProperty('identical', 'be identical');
  }
};

Replace q with native Promises


"use strict";

/*!
 * Module dependencies.
 */

var dummy
  , hotplate = require('hotplate')
;

exports.getAllStores = hotplate.cachable( function( done ){

  var res = {
    stores: {},
    collections: {},
  };

  hotplate.hotEvents.emit( 'stores', function( err, results){

    results.forEach( function( element ) {
      element.result.forEach( function( Store ){

        try {
         var store = new Store();
        } catch ( e ){
          hotplate.log("AN ERROR HAPPENED WHILE INSTANCING A STORE: " );
          hotplate.log( e );
          hotplate.log( element );
          hotplate.log( Store );
        }

        // If the store was created (no exception thrown...)
        if( store ){

           // Add the module to the store registry
           res.stores[ store.storeName ] = { Store: Store, storeObject: store };

          // Add the module to the collection registry
          if( store.collectionName ){
            res.collections[ store.collectionName ] = res.collections[ store.collectionName ] || [];
            res.collections[ store.collectionName ].push( { Store: Store, storeObject: store }  );
          }

        }

      });

    });
    done( null, res );
  });

});

"use strict";

/*!
 * Module dependencies.
 */

var dummy
  , hotplate = require('hotplate')
;

exports.getAllStores = hotplate.cachable( function( done ){

  var res = {
    stores: {},
    collections: {},
  };

  hotplate.hotEvents.emit( 'stores', function( err, results){

    results.forEach( function( element ) {

      Object.keys( element.result ).forEach( function( k ){

        var Store = element.result[ k ];

        try {
         var store = new Store();
        } catch ( e ){
          hotplate.log("AN ERROR HAPPENED WHILE INSTANCING A STORE: " );
          hotplate.log( e );
          hotplate.log( element );
          hotplate.log( Store );
        }

        // If the store was created (no exception thrown...)
        if( store ){

           // Add the module to the store registry
           res.stores[ store.storeName ] = { Store: Store, storeObject: store };

          // Add the module to the collection registry
          if( store.collectionName ){
            res.collections[ store.collectionName ] = res.collections[ store.collectionName ] || [];
            res.collections[ store.collectionName ].push( { Store: Store, storeObject: store }  );
          }

        }

      });

    });
    done( null, res );
  });

});

Change way in which storeRegistry expects stores to be returned, it's now a hash


angular.module('mwUI.Menu')

  .directive('mwMenuTopEntries', function ($rootScope, $timeout) {
    return {
      scope: {
        menu: '=mwMenuTopEntries',
        right: '='
      },
      transclude: true,
      templateUrl: 'uikit/mw-menu/directives/templates/mw_menu_top_entries.html',
      controller: function ($scope) {
        var menu = $scope.menu || new mwUI.Menu.MwMenu();

        this.getMenu = function () {
          return menu;
        };
      },
      link: function (scope, el, attrs, ctrl) {
        scope.entries = ctrl.getMenu();

        scope.unCollapse = function () {
          var collapseEl = el.find('.navbar-collapse');
          if (collapseEl.hasClass('in')) {
            collapseEl.collapse('hide');
          }
        };

        $rootScope.$on('$locationChangeSuccess', function () {
          scope.unCollapse();
        });

        scope.$on('mw-menu:triggerReorder', _.throttle(function () {
          $timeout(function () {
            scope.$broadcast('mw-menu:reorder');
          });
        }));

        scope.$on('mw-menu:triggerResort', _.throttle(function () {
          $timeout(function () {
            scope.$broadcast('mw-menu:resort');
            scope.entries.sort();
          });
        }));

        scope.entries.on('add remove reset', _.throttle(function () {
          $timeout(function () {
            scope.$broadcast('mw-menu:reorder');
          });
        }));
      }
    };
  });

angular.module('mwUI.Menu')

  .directive('mwMenuTopEntries', function ($rootScope, $timeout) {
    return {
      scope: {
        menu: '=mwMenuTopEntries',
        right: '='
      },
      transclude: true,
      templateUrl: 'uikit/mw-menu/directives/templates/mw_menu_top_entries.html',
      controller: function ($scope) {
        var menu = $scope.menu || new mwUI.Menu.MwMenu();

        this.getMenu = function () {
          return menu;
        };
      },
      link: function (scope, el, attrs, ctrl) {
        scope.entries = ctrl.getMenu();

        scope.$on('mw-menu:triggerReorder', _.throttle(function () {
          $timeout(function () {
            scope.$broadcast('mw-menu:reorder');
          });
        }));

        scope.$on('mw-menu:triggerResort', _.throttle(function () {
          $timeout(function () {
            scope.$broadcast('mw-menu:resort');
            scope.entries.sort();
          });
        }));

        scope.entries.on('add remove reset', _.throttle(function () {
          $timeout(function () {
            scope.$broadcast('mw-menu:reorder');
          });
        }));
      }
    };
  });

Move close functionality on location change into mwMenuTopBar


/**
 * Copyright 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @emails react-core
*/

'use strict';

module.exports = function(context) {
  function check(node) {
    const name = node.callee.name;
    let msg = null;
    switch (name) {
      case 'Boolean':
        msg = 'To cast a value to a boolean, use double negation: !!value';
        break;
      case 'String':
        msg = 'To cast a value to a string, concat it with the empty string: \'\' + value';
        break;
    }
    if (msg) {
      context.report(node, `Do not use the ${name} constructor. ${msg}`);
    }
  }

  return {
    CallExpression: check,
    NewExpression: check,
  };
};

/**
 * Copyright 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @emails react-core
*/

'use strict';

module.exports = function(context) {
  function report(node, name, msg) {
    context.report(node, `Do not use the ${name} constructor. ${msg}`);
  }

  function check(node) {
    const name = node.callee.name;
    switch (name) {
      case 'Boolean':
        report(
          node,
          name,
          'To cast a value to a boolean, use double negation: !!value'
        );
        break;
      case 'String':
        report(
          node,
          name,
          'To cast a value to a string, concat it with the empty string ' +
          '(unless it\'s a symbol, which have different semantics): ' +
          '\'\' + value'
        );
        break;
    }
  }

  return {
    CallExpression: check,
    NewExpression: check,
  };
};

Add caveat about symbols to string error message


'use strict';

angular.module('StudentApp').config(['$routeProvider', '$locationProvider',
    function ($routeProvider, $locationProvider) {
        $routeProvider.when('/studentPage', {
            templateUrl: 'views/student/student.list.html',
            controller: 'StudentController'
        }).when('/comments/:id', {
            templateUrl: 'views/comment/comments.list.html',
            controller: 'CommentsController'
        }).when('/stockPage', {
            templateUrl: 'views/Stock/StockManagment.html',
            controller: 'StockController'
        }).when('/orderPage', {
            templateUrl: 'views/Stock/OrderManagment.html',
            controller: 'OrderController'
        }).otherwise({
            redirectTo: '/'
        });

        $locationProvider.html5Mode(true);
    }]);

'use strict';

angular.module('StudentApp').config(['$routeProvider', '$locationProvider',
    function ($routeProvider, $locationProvider) {
        $routeProvider.when('/studentPage', {
            templateUrl: 'views/student/student.list.html',
            controller: 'StudentController'
        }).when('/comments/:id', {
            templateUrl: 'views/comment/comments.list.html',
            controller: 'CommentsController'
        }).when('/stockPage', {
            templateUrl: 'views/Stock/StockManagment.html',
            controller: 'StockController'
        }).when('/orderPage', {
            templateUrl: 'views/Stock/OrderManagment.html',
            controller: 'OrderController'
        }).when('/customerPage', {
            templateUrl: 'views/Customer/Customer.html',
            controller: 'CustomerController'
        }).otherwise({
            redirectTo: '/'
        });

        $locationProvider.html5Mode(true);
    }]);

Add relevant Customer section changes to main.router.js


'use strict';

// MODULES //

var isInteger = require( '@stdlib/assert/is-integer' ).isPrimitive;

// FUNCTIONS //

/**
* Returns an array element.
*
* @private
* @param {...integer} idx - indices
* @throws {TypeError} provided indices must be integer valued
* @throws {RangeError} index exceeds array dimensions
* @returns {*} array element
*/
function get() {
	/* eslint-disable no-invalid-this */
	var len;
	var idx;
	var i;

	// TODO: support index modes

	len = arguments.length;
	idx = this._offset;
	for ( i = 0; i < len; i++ ) {
		if ( !isInteger( arguments[ i ] ) ) {
			throw new TypeError( 'invalid input argument. Indices must be integer valued. Argument: '+i+'. Value: `'+arguments[i]+'`.' );
		}
		idx += this._strides[ i ] * arguments[ i ];
	}
	return this._buffer[ idx ];
} // end FUNCTION get()

// EXPORTS //

module.exports = get;

'use strict';

// MODULES //

var isInteger = require( '@stdlib/assert/is-integer' ).isPrimitive;
var getIndex = require( './get_index.js' );

// FUNCTIONS //

/**
* Returns an array element.
*
* @private
* @param {...integer} idx - indices
* @throws {TypeError} provided indices must be integer valued
* @throws {RangeError} index exceeds array dimensions
* @returns {*} array element
*/
function get() {
	/* eslint-disable no-invalid-this */
	var len;
	var idx;
	var ind;
	var i;

	len = arguments.length;
	idx = this._offset;
	for ( i = 0; i < len; i++ ) {
		if ( !isInteger( arguments[ i ] ) ) {
			throw new TypeError( 'invalid input argument. Indices must be integer valued. Argument: '+i+'. Value: `'+arguments[i]+'`.' );
		}
		ind = getIndex( arguments[ i ], this._shape[ i ], this._mode );
		idx += this._strides[ i ] * ind;
	}
	return this._buffer[ idx ];
} // end FUNCTION get()

// EXPORTS //

module.exports = get;

Add support for an index mode


require('babel/register');
require('dotenv').load();

var startServer = require('./app');

var port = process.env['PORT'] || 3000;
startServer(port);

require('babel/register');

if (process.env.NODE_ENV !== 'production') {
  require('dotenv').load();
}

var startServer = require('./app');

var port = process.env.PORT || 3000;
startServer(port);

Handle case where dotenv is not included in production.


import Vue from "vue"

export default {
    name: 'AppPage',
    props: {
        layout: {
            type: String,
            required: true,
            validator: [].includes.bind(["standard", "empty"])
        }
    },
    created() {
        let component = components[this.layout]
        if (!Vue.options.components[component.name]) {
            Vue.component(
                component.name,
                component,
            );
        }
        this.$parent.$emit('update:layout', component);
    },
    render(h) {
        return this.$slots.default ? this.$slots.default[0] : h();
    },
}

const components = {
    "standard": () => import("./layout-standard"),
    "empty": () => import("./layout-empty")
}

import Vue from "vue"

export default {
    name: 'AppPage',
    props: {
        layout: {
            type: String,
            required: true,
            validator: [].includes.bind(["standard", "empty"])
        }
    },
    created() {
        let component = components[this.layout]
        if (!Vue.options.components[component.name]) {
            Vue.component(
                component.name,
                component,
            );
        }
        if (this.$parent.layout !== component) {
            this.$parent.$emit('update:layout', component);
        }
    },
    render(h) {
        return this.$slots.default ? this.$slots.default[0] : h();
    },
}

const components = {
    "standard": () => import("./layout-standard"),
    "empty": () => import("./layout-empty")
}

Add identity gard before firing layout change


"use strict";

var _ = require("lodash");
var HTTP_STATUS_CODES = require("http").STATUS_CODES;
var request = require("request");
var url = require("url");

function LamernewsAPI(root) {
    this.root = root;
    return this;
}

LamernewsAPI.prototype.getNews = function getNews(options, callback) {
    var defaults = {
        count: 30,
        start: 0,
        type: "latest"
    };
    var signature;

    if (!callback && typeof options === "function") {
        callback = options;
        options = {};
    }

    options = _.defaults(options || {}, defaults);
    signature = ["getnews", options.type, options.start, options.count];

    this.query(signature.join("/"), callback);

    return this;
};

LamernewsAPI.prototype.query = function query(signature, callback) {
    if (!this.root) {
        throw new Error("No API root specified");
    }

    request(url.resolve(this.root, signature), function(err, res, body) {
        var status;

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

        status = res.statusCode;

        if (status !== 200) {
            err = new Error(HTTP_STATUS_CODES[status]);
            err.code = status;

            return callback(err);
        }

        try {
            body = JSON.parse(body);
        } catch (err) {
            callback(err);
        }

        callback(null, body);
    });
};

module.exports = LamernewsAPI;

"use strict";

var _ = require("lodash");
var HTTP_STATUS_CODES = require("http").STATUS_CODES;
var request = require("request");
var url = require("url");

function LamernewsAPI(root) {
    this.root = root;
    return this;
}

LamernewsAPI.prototype = {
    getNews: function getNews(options, callback) {
        var defaults = {
            count: 30,
            start: 0,
            type: "latest"
        };
        var signature;

        if (!callback && typeof options === "function") {
            callback = options;
            options = {};
        }

        options = _.defaults(options || {}, defaults);
        signature = ["getnews", options.type, options.start, options.count];

        this.query(signature.join("/"), callback);

        return this;
    },

    query: function query(signature, callback) {
        if (!this.root) {
            throw new Error("No API root specified");
        }

        request(url.resolve(this.root, signature), function(err, res, body) {
            var status;

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

            status = res.statusCode;

            if (status !== 200) {
                err = new Error(HTTP_STATUS_CODES[status]);
                err.code = status;

                return callback(err);
            }

            try {
                body = JSON.parse(body);
            } catch (err) {
                callback(err);
            }

            callback(null, body);
        });
    }
};

module.exports = LamernewsAPI;

Refactor method definitions on prototype to be more DRY


/**
 * espower-source - Power Assert instrumentor from source to source.
 *
 * https://github.com/twada/espower-source
 *
 * Copyright (c) 2014 Takuto Wada
 * Licensed under the MIT license.
 *   https://github.com/twada/espower-source/blob/master/MIT-LICENSE.txt
 */
var espower = require('espower'),
    esprima = require('esprima'),
    escodegen = require('escodegen'),
    merge = require('lodash.merge'),
    convert = require('convert-source-map');

function espowerSourceToSource(jsCode, filepath, options) {
    'use strict';

    var jsAst, espowerOptions, modifiedAst, escodegenOutput, code, map;

    jsAst = esprima.parse(jsCode, {tolerant: true, loc: true, tokens: true, raw: true, source: filepath});
    espowerOptions = merge(merge(espower.defaultOptions(), options), {
        destructive: true,
        path: filepath
    });
    modifiedAst = espower(jsAst, espowerOptions);
    escodegenOutput = escodegen.generate(modifiedAst, {
        sourceMap: true,
        sourceMapWithCode: true
    });
    code = escodegenOutput.code; // Generated source code
    map = convert.fromJSON(escodegenOutput.map.toString());
    map.sourcemap.sourcesContent = [jsCode];
    return code + '\n' + map.toComment() + '\n';
}

module.exports = espowerSourceToSource;

/**
 * espower-source - Power Assert instrumentor from source to source.
 *
 * https://github.com/twada/espower-source
 *
 * Copyright (c) 2014 Takuto Wada
 * Licensed under the MIT license.
 *   https://github.com/twada/espower-source/blob/master/MIT-LICENSE.txt
 */
var espower = require('espower'),
    esprima = require('esprima'),
    escodegen = require('escodegen'),
    merge = require('lodash.merge'),
    convert = require('convert-source-map');

function espowerSource(jsCode, filepath, options) {
    'use strict';

    var jsAst, espowerOptions, modifiedAst, escodegenOutput, code, map;

    jsAst = esprima.parse(jsCode, {tolerant: true, loc: true, tokens: true, raw: true, source: filepath});
    espowerOptions = merge(merge(espower.defaultOptions(), options), {
        destructive: true,
        path: filepath
    });
    modifiedAst = espower(jsAst, espowerOptions);
    escodegenOutput = escodegen.generate(modifiedAst, {
        sourceMap: true,
        sourceMapWithCode: true
    });
    code = escodegenOutput.code; // Generated source code
    map = convert.fromJSON(escodegenOutput.map.toString());
    map.sourcemap.sourcesContent = [jsCode];
    return code + '\n' + map.toComment() + '\n';
}

module.exports = espowerSource;

Change exposed function name to espowerSource


'use strict'

var window = require('global/window')
var Struct = require('observ-struct')
var Observ = require('observ')
var minimumViewport = require('minimum-viewport')
var orientation = require('screen-orientation')

var MOBILE_WIDTH = 640

var device = Struct({
  mobile: Observ(false),
  orientation: Observ(null)
})

module.exports = device

if (window.addEventListener) {
  window.addEventListener('resize', onResize)
  onResize()
}

function onResize () {
  device.mobile.set(minimumViewport({x: MOBILE_WIDTH}))
  device.orientation.set(orientation().direction)
}

'use strict'

var window = require('global/window')
var Struct = require('observ-struct')
var Observ = require('observ')
var minimumViewport = require('minimum-viewport')
var orientation = require('screen-orientation')

var MOBILE_WIDTH = 840

var device = Struct({
  mobile: Observ(false),
  orientation: Observ(null)
})

module.exports = device

if (window.addEventListener) {
  window.addEventListener('resize', onResize)
  onResize()
}

function onResize () {
  device.mobile.set(minimumViewport({x: MOBILE_WIDTH}))
  device.orientation.set(orientation().direction)
}

Update mobile width to 840 px


'use strict';

var MarkdownIt = require('markdown-it');

exports.name = 'markdown-it';
exports.outputFormat = 'html';
exports.render = function (str, options) {
  var md = MarkdownIt(options);
  return md.render(str);
};

'use strict';

var MarkdownIt = require('markdown-it');

exports.name = 'markdown-it';
exports.outputFormat = 'xml';
exports.render = function (str, options) {
  var md = MarkdownIt(options);
  return md.render(str);
};

Mark output format as XML


function Fs() {}
Fs.prototype = require('fs')
var fs = new Fs()
  , Promise = require('promise')

module.exports = exports = fs
for (var key in fs)
  if (!(typeof fs[key] != 'function'
      || key.match(/Sync$/)
      || key.match(/^[A-Z]/)
      || key.match(/^create/)
      || key.match(/^(un)?watch/)
      ))
    fs[key] = Promise.denodeify(fs[key])

var fs = Object.create(require('fs'))
var Promise = require('promise')

module.exports = exports = fs
for (var key in fs)
  if (!(typeof fs[key] != 'function'
      || key.match(/Sync$/)
      || key.match(/^[A-Z]/)
      || key.match(/^create/)
      || key.match(/^(un)?watch/)
      ))
    fs[key] = Promise.denodeify(fs[key])

Use multiple var statements and `Object.create`


/* eslint-env node */
"use strict";

module.exports = {
  name: "ember-component-attributes",

  setupPreprocessorRegistry(type, registry) {
    registry.add("htmlbars-ast-plugin", {
      name: "attributes-expression",
      plugin: require("./lib/attributes-expression-transform"),
      baseDir: function() {
        return __dirname;
      }
    });
  }
};

/* eslint-env node */
"use strict";

module.exports = {
  name: "ember-component-attributes",

  setupPreprocessorRegistry(type, registry) {
    registry.add("htmlbars-ast-plugin", {
      name: "attributes-expression",
      plugin: require("./lib/attributes-expression-transform"),
      baseDir: function() {
        return __dirname;
      }
    });
  },

  included() {
    this.import('vendor/ember-component-attributes/index.js');
  },

  treeForVendor(rawVendorTree) {
    let babelAddon = this.addons.find(addon => addon.name === 'ember-cli-babel');

    let transpiledVendorTree = babelAddon.transpileTree(rawVendorTree, {
      'ember-cli-babel': {
        compileModules: false
      }
    });

    return transpiledVendorTree;
  },
};

Add `treeForVendor` and `included` hook implementations.


/**
 * @jsx React.DOM
 */

var React = require('react');

var Pdf = React.createClass({
  getInitialState: function() {
    return {};
  },
  componentDidMount: function() {
    var self = this;
    PDFJS.getDocument(this.props.file).then(function(pdf) {
      pdf.getPage(self.props.page).then(function(page) {
        self.setState({pdfPage: page, pdf: pdf});
      });
    });
  },
  componentWillReceiveProps: function(newProps) {
    var self = this;
    if (newProps.page) {
      self.state.pdf.getPage(newProps.page).then(function(page) {
        self.setState({pdfPage: page, pageId: newProps.page});
      });
    }
    this.setState({
      pdfPage: null
    });
  },
  render: function() {
    var self = this;
    this.state.pdfPage && setTimeout(function() {
      var canvas = self.getDOMNode(),
          context = canvas.getContext('2d'),
          scale = 1.0,
          viewport = self.state.pdfPage.getViewport(scale);
      canvas.height = viewport.height;
      canvas.width = viewport.width;
      var renderContext = {
        canvasContext: context,
        viewport: viewport
      };
      self.state.pdfPage.render(renderContext);
    });
    return this.state.pdfPage ? <canvas></canvas> :
Loading pdf..
;
  }
});

module.exports = Pdf;

/**
 * @jsx React.DOM
 */

var React = require('react');

var Pdf = React.createClass({
  getInitialState: function() {
    return {};
  },
  componentDidMount: function() {
    var self = this;
    PDFJS.getDocument(this.props.file).then(function(pdf) {
      pdf.getPage(self.props.page).then(function(page) {
        self.setState({pdfPage: page, pdf: pdf});
      });
    });
  },
  componentWillReceiveProps: function(newProps) {
    var self = this;
    if (newProps.page) {
      self.state.pdf.getPage(newProps.page).then(function(page) {
        self.setState({pdfPage: page, pageId: newProps.page});
      });
    }
    this.setState({
      pdfPage: null
    });
  },
  getDefaultProps: function() {
    return {page: 1};
  },
  render: function() {
    var self = this;
    this.state.pdfPage && setTimeout(function() {
      var canvas = self.getDOMNode(),
          context = canvas.getContext('2d'),
          scale = 1.0,
          viewport = self.state.pdfPage.getViewport(scale);
      canvas.height = viewport.height;
      canvas.width = viewport.width;
      var renderContext = {
        canvasContext: context,
        viewport: viewport
      };
      self.state.pdfPage.render(renderContext);
    });
    return this.state.pdfPage ? <canvas></canvas> :
Loading pdf..
;
  }
});

module.exports = Pdf;

Add default prop for page


angular.module('app').controller('mvUserListController', function ($scope, mvUser) {
  $scope.users = mvUser.query();

  $scope.sortOptions = [{
    value: "username",
    text: "Sort by username"
  }, {
    value: "registrationDate",
    text: "Sort by registration date"
  }, {
    value: "role",
    text: "Sort by role"
  }];

  $scope.sortOrder = {
    selected: $scope.sortOptions[0].value
  };
});

angular.module('app').controller('mvUserListController', function ($scope, mvUser) {
  $scope.users = mvUser.query();

  $scope.sortOptions = [{
    value: "username",
    text: "Sort by username"
  }, {
    value: "- registrationDate",
    text: "Sort by registration date"
  }, {
    value: "- role",
    text: "Sort by role"
  }];

  $scope.sortOrder = {
    selected: $scope.sortOptions[0].value
  };
});

Fix ordering on user list page


(function(){

  angular
       .module('app')
       .config(function(uiGmapGoogleMapApiProvider) {
            uiGmapGoogleMapApiProvider.configure({
                //    key: 'your api key',
                v: '3.20', //defaults to latest 3.X anyhow
                libraries: 'weather,geometry,visualization'
            });
        })
       .controller('MapController', [
          '$state', 'uiGmapGoogleMapApi', 'sitesService',
          MapController
       ]);

  function MapController($state, uiGmapGoogleMapApi, sitesService) {

      self = this;

      sitesService
        .loadAllItems()
        .then(function(siteData) {
            self.siteData = [].concat(siteData);
            console.log(self.siteData);
        });

      uiGmapGoogleMapApi.then(function(maps) {

          //small hack to fix issues with older lodash version. to be resolved in future
          if( typeof _.contains === 'undefined' ) {
              _.contains = _.includes;
          }
          if( typeof _.object === 'undefined' ) {
              _.object = _.zipObject;
          }

          self.mapParams = { center: { latitude: 51.48, longitude: -2.5879 }, zoom: 12 };

      });

      self.goToSite = function (shortcode) {
          $state.go('home.site', {shortcode: shortcode});
      };

   }

})();

(function(){

  angular
       .module('app')
       .config(function(uiGmapGoogleMapApiProvider) {
            uiGmapGoogleMapApiProvider.configure({
                //    key: 'your api key',
                v: '3.20', //defaults to latest 3.X anyhow
                libraries: 'weather,geometry,visualization'
            });
        })
       .controller('MapController', [
          '$state', 'uiGmapGoogleMapApi', 'sitesService',
          MapController
       ]);

  function MapController($state, uiGmapGoogleMapApi, sitesService) {

      self = this;

      sitesService
        .loadAllItems()
        .then(function(siteData) {
            self.siteData = [].concat(siteData);
            console.log(self.siteData);
        });

      uiGmapGoogleMapApi.then(function(maps) {

          //small hack to fix issues with older lodash version. to be resolved in future
          if( typeof _.contains === 'undefined' ) {
              _.contains = _.includes;
          }
          if( typeof _.object === 'undefined' ) {
              _.object = _.zipObject;
          }

          self.mapParams = { center: { latitude: 51.48, longitude: -2.53 }, zoom: 12 };

      });

      self.goToSite = function (shortcode) {
          $state.go('home.site', {shortcode: shortcode});
      };

   }

})();

Move starting location a little so Wick Sports Ground is visible


import Ember from 'ember';

var configKeys, configKeysMap, languageConfigKeys;

languageConfigKeys = {
  go: 'Go',
  php: 'PHP',
  node_js: 'Node.js',
  perl: 'Perl',
  perl6: 'Perl6',
  python: 'Python',
  scala: 'Scala',
  smalltalk: 'Smalltalk',
  ruby: 'Ruby',
  d: 'D',
  julia: 'Julia',
  csharp: 'C#',
  mono: 'Mono',
  dart: 'Dart',
  elixir: 'Elixir',
  ghc: 'GHC',
  haxe: 'Haxe',
  jdk: 'JDK',
  rvm: 'Ruby',
  otp_release: 'OTP Release',
  rust: 'Rust',
  c: 'C',
  cpp: 'C++',
  clojure: 'Clojure',
  lein: 'Lein',
  compiler: 'Compiler',
  crystal: 'Crystal',
  osx_image: 'Xcode'
};

configKeys = {
  env: 'ENV',
  gemfile: 'Gemfile',
  xcode_sdk: 'Xcode SDK',
  xcode_scheme: 'Xcode Scheme',
  compiler: 'Compiler',
  os: 'OS'
};

configKeysMap = Ember.merge(configKeys, languageConfigKeys);

export default configKeysMap;

export { languageConfigKeys, configKeys };

import Ember from 'ember';

var configKeys, configKeysMap, languageConfigKeys;

languageConfigKeys = {
  go: 'Go',
  php: 'PHP',
  node_js: 'Node.js',
  perl: 'Perl',
  perl6: 'Perl6',
  python: 'Python',
  scala: 'Scala',
  smalltalk: 'Smalltalk',
  ruby: 'Ruby',
  d: 'D',
  julia: 'Julia',
  csharp: 'C#',
  mono: 'Mono',
  dart: 'Dart',
  elixir: 'Elixir',
  ghc: 'GHC',
  haxe: 'Haxe',
  jdk: 'JDK',
  rvm: 'Ruby',
  otp_release: 'OTP Release',
  rust: 'Rust',
  c: 'C',
  cpp: 'C++',
  clojure: 'Clojure',
  lein: 'Lein',
  compiler: 'Compiler',
  crystal: 'Crystal',
  osx_image: 'Xcode',
  r: 'R'
};

configKeys = {
  env: 'ENV',
  gemfile: 'Gemfile',
  xcode_sdk: 'Xcode SDK',
  xcode_scheme: 'Xcode Scheme',
  compiler: 'Compiler',
  os: 'OS'
};

configKeysMap = Ember.merge(configKeys, languageConfigKeys);

export default configKeysMap;

export { languageConfigKeys, configKeys };

Add R language key for matrix column


/**
 * util-lang.js - The minimal language enhancement
 */

var hasOwnProperty = {}.hasOwnProperty

function hasOwn(obj, prop) {
  return hasOwnProperty.call(obj, prop)
}

function isFunction(obj) {
  return typeof obj === "function"
}

var isArray = Array.isArray || function(obj) {
  return obj instanceof Array
}

function unique(arr) {
  var obj = {}
  var ret = []

  for (var i = 0, len = arr.length; i < len; i++) {
    var item = arr[i]
    if (!obj[item]) {
      obj[item] = 1
      ret.push(item)
    }
  }

  return ret
}

/**
 * util-lang.js - The minimal language enhancement
 */

var hasOwnProperty = {}.hasOwnProperty

function hasOwn(obj, prop) {
  return hasOwnProperty.call(obj, prop)
}

function isFunction(obj) {
  return typeof obj === "function"
}

var isArray = Array.isArray || function(obj) {
  return obj instanceof Array
}

function unique(arr) {
  var obj = {}
  var ret = []

  for (var i = 0, len = arr.length; i < len; i++) {
    var item = arr[i]
    if (obj[item] !== 1) {
      obj[item] = 1
      ret.push(item)
    }
  }

  return ret
}

Fix a bug for unique


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

'use strict';

const {google} = require('googleapis');
const sampleClient = require('../sampleclient');

const plus = google.plus({
  version: 'v1',
  auth: sampleClient.oAuth2Client,
});

async function runSample() {
  const res = await plus.people.get({userId: 'me'});
  console.log(res.data);
}

const scopes = [
  'https://www.googleapis.com/auth/plus.login',
  'https://www.googleapis.com/auth/plus.me',
  'https://www.googleapis.com/auth/userinfo.email',
  'https://www.googleapis.com/auth/userinfo.profile',
];

if (module === require.main) {
  sampleClient
    .authenticate(scopes)
    .then(runSample)
    .catch(console.error);
}

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

'use strict';

const {google} = require('googleapis');
const sampleClient = require('../sampleclient');

const people = google.people({
  version: 'v1',
  auth: sampleClient.oAuth2Client,
});

async function runSample() {
  // See documentation of personFields at
  // https://developers.google.com/people/api/rest/v1/people/get
  const res = await people.people.get({
    resourceName: 'people/me',
    personFields: 'emailAddresses,names,photos',
  });
  console.log(res.data);
}

const scopes = [
  'https://www.googleapis.com/auth/userinfo.email',
  'https://www.googleapis.com/auth/userinfo.profile',
];

if (module === require.main) {
  sampleClient
    .authenticate(scopes)
    .then(runSample)
    .catch(console.error);
}

Use people API instead of plus API


var Office365ConnectorHook = require("./index.js"),
    winston = require('winston'),
    Logger = winston.Logger,
    Console = winston.transports.Console,
    hookUrl = process.env.HOOK_URL;

if (!hookUrl) {
    console.warn("No process.env.HOOK_URL set. Please set it to your Connector Webhook URL before running this test.");
    process.exit();
}

var logger = new Logger({
    transports: [
        new Console({}),
        new Office365ConnectorHook({
            "hookUrl": hookUrl,
            "colors": {
                "debug": "FFFFFF"
            }
        })
    ]
});

// will be sent to both console and channel
logger.log('debug', 'Starting tests...');
logger.info('This is a test log from Winston.');
logger.info('This text appears in card body.', { title: 'You can send card titles too!' });
logger.info('# Seriously!?\n > This is cool!', { title: 'You can use Markdown in error messages.' });
logger.warn('Warning! An error test coming up!');
try {
    throw new Error("Everything's alright, just testing error logging.");
}
catch (err) {
    logger.error(err.message, err);
}

var Office365ConnectorHook = require("./index.js"),
    winston = require('winston'),
    Logger = winston.Logger,
    Console = winston.transports.Console,
    hookUrl = process.env.HOOK_URL;

if (!hookUrl) {
    console.warn("No process.env.HOOK_URL set. Please set it to your Connector Webhook URL before running this test.");
    process.exit();
}

var logger = new Logger({
    transports: [
        new Console({}),
        new Office365ConnectorHook({
            "hookUrl": hookUrl,
            "colors": {
                "debug": "FFFFFF"
            }
        })
    ]
});

// will be sent to both console and channel
logger.log('debug', 'Starting tests...');
logger.info('This is a test log from Winston.');
logger.info('This text appears in card body.', { title: 'My puny title' });
logger.info('# Seriously!?\n > This is cool!', { title: 'You can use Markdown in messages.' });
logger.warn('Warning! An error test coming up!');
try {
    throw new Error("Everything's alright, just testing error logging.");
}
catch (err) {
    logger.error(err.message, err);
}

Change error message per readme.


var sys = require("sys"),
  stomp = require("./stomp");

var client = new stomp.Client("localhost", 61613);
client.subscribe("/queue/news", function(data){
  console.log('received: ' + data.body);
});
client.publish('/queue/news','hello');

var repl = require('repl').start( 'stomp-test> ' );
repl.context.client = client;

var sys = require("sys"),
  stomp = require("./stomp");

var client = new stomp.Client("localhost", 61613);
client.subscribe("/queue/news", function(data){
  console.log('received: ' + JSON.stringify(data));
});
client.publish('/queue/news','hello');

var repl = require('repl').start( 'stomp-test> ' );
repl.context.client = client;

Test program now emits JSON strings of messages, not just message bodies


'use strict';

import React from 'react';

require('styles//Controls.scss');

class ControlsComponent extends React.Component {

  renderStopButton() {
    if (this.props.isPlaying) {
      return <button id="stop">Stop</button>
    }

    return <button id="stop" style={{display: 'none'}}>Stop</button>

  }

  renderPlayButton() {
    if (this.props.isPlaying) {
      return <button id="play" style={{display: 'none'}}>Play</button>
    }

    return <button id="play">Play</button>
  }

  render() {
    return (
      <div className="controls-component">
          <button id="rewind">Rewind</button>
          {this.renderStopButton()}
          {this.renderPlayButton()}
          <button id="forward">Forward</button>
      </div>
    );
  }
}

ControlsComponent.displayName = 'ControlsComponent';

ControlsComponent.propTypes = {
  isPlaying : React.PropTypes.bool.isRequired
};

ControlsComponent.defaultProps = {
  isPlaying : true
};

export default ControlsComponent;

'use strict';

import React from 'react';

require('styles//Controls.scss');

class ControlsComponent extends React.Component {

  renderStopButton() {
    if (this.props.isPlaying) {
      return <button id="stop">Stop</button>
    }

    return <button id="stop" style={{display: 'none'}}>Stop</button>

  }

  renderPlayButton() {
    if (this.props.isPlaying) {
      return <button id="play" style={{display: 'none'}}>Play</button>
    }

    return <button id="play">Play</button>
  }

  render() {
    return (
      <div className="controls-component">
          <button id="previous">Previous</button>
          {this.renderStopButton()}
          {this.renderPlayButton()}
          <button id="next">Next</button>
      </div>
    );
  }
}

ControlsComponent.displayName = 'ControlsComponent';

ControlsComponent.propTypes = {
  isPlaying :  React.PropTypes.bool.isRequired,
  onPrevious : React.PropTypes.func,
  onStop :     React.PropTypes.func,
  onPlay :     React.PropTypes.func,
  onNext :     React.PropTypes.func
};

ControlsComponent.defaultProps = {
  isPlaying : true
};

export default ControlsComponent;

Add props for the action trigger


var save = (function() {
  "use strict";

  // saveAs from https://gist.github.com/MrSwitch/3552985
  var saveAs = window.saveAs || (window.navigator.msSaveBlob ? function (b, n) {
      return window.navigator.msSaveBlob(b, n);
    } : false) || window.webkitSaveAs || window.mozSaveAs || window.msSaveAs || (function () {

      // URL's
      window.URL = window.URL || window.webkitURL;

      if (!window.URL) {
        return false;
      }

      return function (blob, name) {
        var url = URL.createObjectURL(blob);

        // Test for download link support
        if ("download" in document.createElement('a')) {

          var a = document.createElement('a');
          a.setAttribute('href', url);
          a.setAttribute('download', name);

          // Create Click event
          var clickEvent = document.createEvent("MouseEvent");
          clickEvent.initMouseEvent("click", true, true, window, 0,
            event.screenX, event.screenY, event.clientX, event.clientY,
            event.ctrlKey, event.altKey, event.shiftKey, event.metaKey,
            0, null);

          // dispatch click event to simulate download
          a.dispatchEvent(clickEvent);

        } else {
          // fallover, open resource in new tab.
          window.open(url, '_blank', '');
        }
      };
    })();

  function save (text, fileName) {
    var blob = new Blob([text], {
      type: 'text/plain'
    });
    saveAs(blob, fileName || 'subtitle.srt');
  }

  return save;

})();

var save = (function() {
  "use strict";

  // saveAs from https://gist.github.com/MrSwitch/3552985
  var saveAs = window.saveAs || (window.navigator.msSaveBlob ? function (b, n) {
      return window.navigator.msSaveBlob(b, n);
    } : false) || window.webkitSaveAs || window.mozSaveAs || window.msSaveAs || (function () {

      // URL's
      window.URL = window.URL || window.webkitURL;

      if (!window.URL) {
        return false;
      }

      return function (blob, name) {
        var url = URL.createObjectURL(blob);

        // Test for download link support
        if ("download" in document.createElement('a')) {

          var a = document.createElement('a');
          a.setAttribute('href', url);
          a.setAttribute('download', name);

          // Create Click event
          var clickEvent = document.createEvent("MouseEvent");
          clickEvent.initMouseEvent("click", true, true, window, 0,
            0, 0, 0, 0, false, false, false, false, 0, null);

          // dispatch click event to simulate download
          a.dispatchEvent(clickEvent);

        } else {
          // fallover, open resource in new tab.
          window.open(url, '_blank', '');
        }
      };
    })();

  function save (text, fileName) {
    var blob = new Blob([text], {
      type: 'text/plain'
    });
    saveAs(blob, fileName || 'subtitle.srt');
  }

  return save;

})();

Fix ReferenceError in saveAs polyfill


var questions = [
  Q1 = {
    question: "What does HTML means?",
    answer: "HyperText Markup Language"
  },
  Q2 = {
    question: "What does CSS means?",
    answer: "Cascading Style Sheet"
  },
  Q3 = {
    question: "Why the \"C\" in CSS, is called Cascading?",
    answer: "When CSS rules are duplicated, the rule to be use is chosen by cascading down from more general rules to the specific rule required"
  }
];

var question = document.getElementById('question');

var questionNum = 0;

// Generate random number to display random QA set
function createNum() {
  questionNum = Math.floor(Math.random() * 3);
}

createNum();
question.innerHTML = questions[questionNum].question;

Increase indention by 2 spaces


/*
 * Copyright 2015 Vivliostyle Inc.
 *
 * This file is part of Vivliostyle UI.
 *
 * Vivliostyle UI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Vivliostyle UI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Vivliostyle UI.  If not, see <http://www.gnu.org/licenses/>.
 */

import ko from "knockout";

function MessageDialog(queue) {
    this.list = queue;
    this.visible = ko.pureComputed(function() {
        return queue().length > 0;
    });
}

MessageDialog.prototype.getDisplayMessage = function(errorInfo) {
    var msg;
    var e = errorInfo.error;
    var stack = e && (e.frameTrace || e.stack || e.toString());
    if (stack) {
        msg = stack.split("\n", 1)[0];
    }
    if (!msg) {
        msg = errorInfo.messages.join("\n");
    }
    return msg;
};

export default MessageDialog;

/*
 * Copyright 2015 Vivliostyle Inc.
 *
 * This file is part of Vivliostyle UI.
 *
 * Vivliostyle UI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Vivliostyle UI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Vivliostyle UI.  If not, see <http://www.gnu.org/licenses/>.
 */

import ko from "knockout";

function MessageDialog(queue) {
    this.list = queue;
    this.visible = ko.pureComputed(function() {
        return queue().length > 0;
    });
}

MessageDialog.prototype.getDisplayMessage = function(errorInfo) {
    var e = errorInfo.error;
    var msg = e && (e.toString() || e.frameTrace || e.stack);
    if (msg) {
        msg = msg.split("\n", 1)[0];
    }
    if (!msg) {
        msg = errorInfo.messages.join("\n");
    }
    return msg;
};

export default MessageDialog;

Use `Error.toString` for a displayed message whenever possible


/**
 * Transfer component data from .mxt to json
 */

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

var componentDataPath = './componentdata.tmp';

fs.readFile(componentDataPath, { encoding : 'utf-8' }, function (err, data) {
  if(err) return console.log(err);

  var lines = data.split('\n');

  var categories = ['groups', 'teachers', 'rooms', 'other'];
  var container = categories.map(function (item) {
    return {
      name : item,
      data : []
    }
  });

  lines.forEach(function (line) {
    if(!line.length) return;

    var data = line.split('=')[1];
    var items = data.split(';');

    container[items[2] - 1].data.push({
      code : items[0],
      name : items[1]
    });
  });

  container.forEach(function (item) {
    fs.writeFile(item.name + '.json', JSON.stringify(item.data, null, '\t'), function (err) {
      if(err) console.log(err);
    });
  });

  console.log('Files are processing');

});

/**
 * Transfer component data from .mxt to json
 */

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

var componentDataPath = './componentdata.tmp';

fs.readFile(componentDataPath, { encoding : 'utf-8' }, function (err, data) {
  if(err) return console.log(err);

  var lines = data.split('\n');

  var categories = ['groups', 'teachers', 'rooms', 'other'];
  var container = {};

  lines.forEach(function (line) {
    if(!line.length) return;

    var data = line.split('=')[1];
    var items = data.split(';');

    container[items[0]] = {
      name : items[1],
      category : categories[items[2] - 1]
    };
  });

  fs.writeFile('components.json', JSON.stringify(container, null, '\t'), function (err) {
    if(err) console.log(err);
  });

  console.log('Files are processing');

});

Use a better structure for components


var path = require("path");

var Interlock = require("..");

var ilk = new Interlock({
  srcRoot: __dirname,
  destRoot: path.join(__dirname, "dist"),

  entry: {
    "./app/entry-a.js": "entry-a.bundle.js",
    "./app/entry-b.js": { dest: "entry-b.bundle.js" }
  },
  split: {
    "./app/shared/lib-a.js": "[setHash].js"
  },

  includeComments: true,
  sourceMaps: true,
  // cacheMode: "localStorage",

  implicitBundleDest: "[setHash].js",

  plugins: []
});

ilk.watch(true).observe(function (buildEvent) {
  var patchModules = buildEvent.patchModules;
  var compilation = buildEvent.compilation;

  if (patchModules) {
    const paths = patchModules.map(function (module) { return module.path; });
    console.log("the following modules have been updated:", paths);
  }
  if (compilation) {
    console.log("a new compilation has completed");
  }
});

// ilk.build();

var path = require("path");

var Interlock = require("..");

var ilk = new Interlock({
  srcRoot: __dirname,
  destRoot: path.join(__dirname, "dist"),

  entry: {
    "./app/entry-a.js": "entry-a.bundle.js",
    "./app/entry-b.js": { dest: "entry-b.bundle.js" }
  },
  split: {
    "./app/shared/lib-a.js": "[setHash].js"
  },

  includeComments: true,
  sourceMaps: true,

  implicitBundleDest: "[setHash].js",

  plugins: []
});

ilk.watch(true).observe(function (buildEvent) {
  var patchModules = buildEvent.patchModules;
  var compilation = buildEvent.compilation;

  if (patchModules) {
    const paths = patchModules.map(function (module) { return module.path; });
    console.log("the following modules have been updated:", paths);
  }
  if (compilation) {
    console.log("a new compilation has completed");
  }
});

// ilk.build();

Remove `cacheMode` top-level property - this will be accomplished through plugin.


import { callController } from '../../../util/apiConnection'

export const acceptThesis = token => callController(`/invite/thesis/${token}`, 'INVITE_ACCEPT_THESIS_')
export const acceptRole = token => callController(`/invite/role/${token}`, 'INVITE_ACCEPT_ROLE_')

import { callController } from '../../../util/apiConnection'

const prefix = process.env.NODE_ENV === 'development' ? '' : '../..'

export const acceptThesis = token => callController(`${prefix}/invite/thesis/${token}`, 'INVITE_ACCEPT_THESIS_')
export const acceptRole = token => callController(`${prefix}/invite/role/${token}`, 'INVITE_ACCEPT_ROLE_')

Fix thesis invite on staging.


/**
 * RequireJS configuration
 * @description Pass in options for RequireJS like paths, shims or the baseUrl
 */
require.config({
	paths: { }
});

/**
 * RequireJS calls
 * @description Call the needed AMD modules.
 */
require(['Modules/Main'], function(MainFn) {
	new MainFn;
});

/**
 * RequireJS configuration
 * @description Pass in options for RequireJS like paths, shims or the baseUrl
 */
require.config({
	paths: { },

	// Append a date on each requested script to prevent caching issues.
	urlArgs: 'bust=' + (new Date()).getDate()
});

/**
 * RequireJS calls
 * @description Call the needed AMD modules.
 */
require(['Modules/Main'], function(MainFn) {
	new MainFn;
});

Append a date on each requested requireJS module to prevent caching issues


import most from "most";

import * as Pluggable from "../../pluggable";
import resolveAsset from "../modules/resolve";
import loadAst from "../modules/load-ast";

import { entries } from "../../util";

const bootstrapBundle = Pluggable.sync(function bootstrapBundle (srcPath, definition, isEntryPt) {
  const asset = this.resolveAsset(srcPath);
  const module = this.loadAst(asset);
  return {
    module: module,
    dest: definition.dest,
    entry: isEntryPt,
    includeRuntime: !!definition.entry && !definition.excludeRuntime
  };
}, { resolveAsset, loadAst });

function bootstrapBundles (entryPointDefs, splitPointDefs) {
  const entryPointBundles = most.generate(entries, entryPointDefs)
    .map(([srcPath, bundleDef]) => this.bootstrapBundle(srcPath, bundleDef, true));
  const splitPointBundles = most.generate(entries, splitPointDefs)
    .map(([srcPath, splitDef]) => this.bootstrapBundle(srcPath, splitDef, false));

  return most.merge(entryPointBundles, splitPointBundles);
}

export default Pluggable.stream(bootstrapBundles, { bootstrapBundle });

import most from "most";

import * as Pluggable from "../../pluggable";
import resolveAsset from "../modules/resolve";
import loadAst from "../modules/load-ast";

import { entries } from "../../util";

const bootstrapBundle = Pluggable.sync(function bootstrapBundle (srcPath, definition, isEntryPt) {
  const asset = this.resolveAsset(srcPath);
  const module = this.loadAst(asset);
  return {
    module: module,
    dest: definition.dest,
    entry: isEntryPt,
    includeRuntime: isEntryPt && !definition.excludeRuntime
  };
}, { resolveAsset, loadAst });

function bootstrapBundles (entryPointDefs, splitPointDefs) {
  const entryPointBundles = most.generate(entries, entryPointDefs)
    .map(([srcPath, bundleDef]) => this.bootstrapBundle(srcPath, bundleDef, true));
  const splitPointBundles = most.generate(entries, splitPointDefs)
    .map(([srcPath, splitDef]) => this.bootstrapBundle(srcPath, splitDef, false));

  return most.merge(entryPointBundles, splitPointBundles);
}

export default Pluggable.stream(bootstrapBundles, { bootstrapBundle });

Fix runtime inclusion after API changes.


"use strict";

// yamb.prototype.remove()

module.exports = function(symbl, flags, opts) {
  return function *remove() {
    if (!this[symbl].id) {
      // TODO: fix error message
      throw new Error('This is a new object');
    }

    let result = yield opts.storage.removeById(this.id);

    // TODO: remove all related posts

    return result;
  };
};

"use strict";

// yamb.prototype.remove()

module.exports = function(symbl, flags, opts) {
  return function *remove() {
    if (!this.id) {
      // TODO: fix error message
      throw new Error('This is a new object');
    }

    let oid = '' + this.id;
    yield opts.storage.update({related: oid}, {$pull: {related: oid}});

    let result = yield opts.storage.removeById(this.id);

    return result;
  };
};

Remove related link if yamb deleted


export default function getList(data, orm, inputValue) {
    let retVal = [];
    if (Array.isArray(orm.groups)) {
        orm.groups.forEach(({ key, show }) => {
            if (!(typeof show === 'function' && !show(inputValue))) {
                const list = data[key];
                retVal = retVal.concat(list);
            }
        });
    } else {
        Object.keys(data)
            .forEach((key) => {
                const list = data[key];
                retVal = retVal.concat(list);
            });
    }
    return retVal;
}

import { isFunction } from '../../utils/is';

export default function getList(data, orm, inputValue) {
    let retVal = [];
    if (Array.isArray(orm.groups)) {
        orm.groups.forEach(({ key, show }) => {
            if (!(isFunction(show) && !show(inputValue) && (!isFunction(orm.filter) || orm.filter(inputValue)))) {
                const list = data[key];
                retVal = retVal.concat(list);
            }
        });
    } else {
        Object.keys(data)
            .forEach((key) => {
                if (!isFunction(orm.filter) || orm.filter(inputValue)) {
                    const list = data[key];
                    retVal = retVal.concat(list);
                }
            });
    }
    return retVal;
}

Fix bug that personFinder used unfiltered list


'use strict';

var ect = require('ect');

exports.name = 'ect';
exports.outputFormat = 'html';
exports.compile = function(str, options) {
  if (!options) {
    options = {};
  }
  if (!options.root) {
    options.root = {
      'page': str
    };
  }
  var engine = ect(options);
  return function(locals) {
    return engine.render('page', locals);
  };
};

'use strict';

var ect = require('ect');

exports.name = 'ect';
exports.outputFormat = 'html';
exports.compile = function(str, options) {
  options = options || {};
  options.root = options.root || {};
  options.root.page = str;

  var engine = ect(options);
  return function(locals) {
    return engine.render('page', locals);
  };
};

Fix the if statement syntax


/* jshint node: true */
'use strict';

var path = require('path');
var Funnel = require('broccoli-funnel');

module.exports = {
  name: 'ember-cli-bourbon',
  blueprintsPath: function() {
    return path.join(__dirname, 'blueprints');
  },
  treeForStyles: function() {
    var bourbonPath = path.join(this.app.bowerDirectory, 'bourbon', 'app');
    var bourbonTree = new Funnel(this.treeGenerator(bourbonPath), {
      srcDir: '/assets/stylesheets',
      destDir: '/app/styles'
    });
    return bourbonTree;
  }
};

/* jshint node: true */
'use strict';

var path = require('path');
var Funnel = require('broccoli-funnel');

module.exports = {
  name: 'ember-cli-bourbon',
  blueprintsPath: function() {
    return path.join(__dirname, 'blueprints');
  },

  treeForStyles: function() {
    var bourbonPath = path.join(this.project.bowerDirectory, 'bourbon', 'app');
    var bourbonTree = new Funnel(this.treeGenerator(bourbonPath), {
      srcDir: '/assets/stylesheets',
      destDir: '/app/styles'
    });
    return bourbonTree;
  }
};

Allow add-on to be nested.


var globalOffset = require("global-offset");

module.exports = function(element) {
  var offset = globalOffset(element),
    scrollbar = document.createElement("div"),
    inner = document.createElement("div");

  element.style.overflowX = "scroll";

  element.parentNode.insertBefore(scrollbar, element);

  scrollbar.style.backgroundColor = "transparent";
  scrollbar.style.position = "fixed";
  scrollbar.style.bottom = 0;
  scrollbar.style.left = offset.left + "px";
  scrollbar.style.height = "20px";
  scrollbar.style.width = element.getBoundingClientRect().width + "px";
  scrollbar.style.overflowX = "scroll";
  scrollbar.style.overflowY = "hidden";

  scrollbar.appendChild(inner);

  inner.style.width = element.children[0].getBoundingClientRect().width + "px";
  inner.style.height = "1px";

  scrollbar.onscroll = function() {
    element.scrollLeft = scrollbar.scrollLeft;
  };
  element.onscroll = function() {
    scrollbar.scrollLeft = element.scrollLeft;
  };

  window.onscroll = function() {
    scrollbar.style.display = element.getBoundingClientRect().height + offset.top < window.scrollY + window.innerHeight ? "none" : "block";
    scrollbar.scrollLeft = element.scrollLeft;
  };
};

var globalOffset = require("global-offset");

module.exports = function(element) {
  var offset = globalOffset(element),
    scrollbar = document.createElement("div"),
    inner = document.createElement("div");

  element.style.overflowX = "scroll";

  element.parentNode.insertBefore(scrollbar, element);

  scrollbar.style.backgroundColor = "transparent";
  scrollbar.style.position = "fixed";
  scrollbar.style.bottom = 0;
  scrollbar.style.left = offset.left + "px";
  scrollbar.style.height = "20px";
  scrollbar.style.width = element.getBoundingClientRect().width + "px";
  scrollbar.style.overflowX = "scroll";
  scrollbar.style.overflowY = "hidden";

  scrollbar.appendChild(inner);

  inner.style.width = element.children[0].getBoundingClientRect().width + "px";
  inner.style.height = "1px";

  scrollbar.onscroll = function() {
    element.scrollLeft = scrollbar.scrollLeft;
  };
  element.onscroll = function() {
    scrollbar.scrollLeft = element.scrollLeft;
  };

  window.onscroll = function() {
    scrollbar.style.display = element.getBoundingClientRect().height + offset.top <= window.scrollY + window.innerHeight ? "none" : "block";
    scrollbar.scrollLeft = element.scrollLeft;
  };
};

Hide scrollbar when scroll reaches the bottom of the page