export default `
  id
  title
  search_title
  social_title
  description
  search_description
  social_description
  thumbnail_image
  thumbnail_title
  social_image
  published_at
  slug
  layout
  featured
  channel_id
  partner_channel_id
  indexable
  keywords
  published
  postscript
  is_super_article
  is_super_sub_article
  super_article {
    partner_link
    partner_link_title
    partner_logo
    partner_logo_link
    partner_fullscreen_header_logo
    secondary_partner_logo
    secondary_logo_text
    secondary_logo_link
    footer_blurb
    footer_title
    related_articles
  }
  email_metadata {
    headline
    author
    credit_line
    credit_url
    image_url
  }
  authors {
    image_url
    twitter_handle
    name
    id
    bio
  }
  vertical {
    name
    id
  }
  hero_section {
    ...Image
    ...Video
    ...on FeatureHeader {
      type
      title
      url
    }
  }
  sections {
    ... on Text {
      type
      body
    }
    ... on Embed {
      type
      url
      height
      mobile_height
      layout
    }
    ...Video
    ... on Callout {
      type
    }
    ... on ImageCollection {
      type
      layout
      images {
        ...Artwork
        ...Image
      }
    }
    ... on ImageSet {
      type
      title
      layout
      images {
        ...Image
        ...Artwork
      }
    }
  }
`

export default `
  id
  title
  search_title
  social_title
  description
  search_description
  social_description
  thumbnail_image
  thumbnail_title
  social_image
  published_at
  slug
  layout
  featured
  channel_id
  partner_channel_id
  indexable
  keywords
  published
  postscript
  is_super_article
  is_super_sub_article
  super_article {
    partner_link
    partner_link_title
    partner_logo
    partner_logo_link
    partner_fullscreen_header_logo
    secondary_partner_logo
    secondary_logo_text
    secondary_logo_link
    footer_blurb
    footer_title
    related_articles
  }
  email_metadata {
    headline
    author
    credit_line
    credit_url
    image_url
  }
  authors {
    image_url
    twitter_handle
    name
    id
    bio
  }
  contributing_authors {
    name
  }
  vertical {
    name
    id
  }
  hero_section {
    ...Image
    ...Video
    ...on FeatureHeader {
      type
      title
      url
    }
  }
  sections {
    ... on Text {
      type
      body
    }
    ... on Embed {
      type
      url
      height
      mobile_height
      layout
    }
    ...Video
    ... on Callout {
      type
    }
    ... on ImageCollection {
      type
      layout
      images {
        ...Artwork
        ...Image
      }
    }
    ... on ImageSet {
      type
      title
      layout
      images {
        ...Image
        ...Artwork
      }
    }
  }
`

Add contributing author to article query


msngr.extend((function () {
	"use strict";

	return {
		utils: {
			getType: function (obj) {
				return Object.prototype.toString.call(obj);
			},
			isNullOrUndefined: function (obj) {
				return (obj === undefined || obj === null);
			},
			exists: function (obj) {
				return !this.isNullOrUndefined(obj);
			},
			isString: function (str) {
	            return (this.getType(str) === "[object String]");
	        },
	        isDate: function (obj) {
	            return (this.getType(obj) === "[object Date]");
	        },
	        isArray: function (obj) {
	            return (this.getType(obj) === "[object Array]");
	        },
	        isNumber: function (obj) {
	            return (this.getType(obj) === "[object Number]");
	        },
	        isObject: function (obj) {
	            return (this.getType(obj) === "[object Object]");
	        },
	        isFunction: function (func) {
	            return (this.getType(func) === "[object Function]");
	        },
	        isEmptyString: function (str) {
	            var isStr = this.isString(str);
	            if (str === undefined || str === null || (isStr && str.toString().trim().length === 0)) {
	                return true;
	            }
	            return false;
	        },
			hasWildCard: function (str) {
				return (str.indexOf("*") !== -1);
			}
	    }
	};
}()));

msngr.extend((function () {
	"use strict";

	return {
		utils: {
			getType: function (obj) {
				if (!msngr.utils.exists(obj)) {
					return "" + obj;
				}
				return Object.prototype.toString.call(obj);
			},
			isNullOrUndefined: function (obj) {
				return (obj === undefined || obj === null);
			},
			exists: function (obj) {
				return !this.isNullOrUndefined(obj);
			},
			isString: function (str) {
	            return (this.getType(str) === "[object String]");
	        },
	        isDate: function (obj) {
	            return (this.getType(obj) === "[object Date]");
	        },
	        isArray: function (obj) {
	            return (this.getType(obj) === "[object Array]");
	        },
	        isNumber: function (obj) {
	            return (this.getType(obj) === "[object Number]");
	        },
	        isObject: function (obj) {
	            return (this.getType(obj) === "[object Object]");
	        },
	        isFunction: function (func) {
	            return (this.getType(func) === "[object Function]");
	        },
	        isEmptyString: function (str) {
	            var isStr = this.isString(str);
	            if (str === undefined || str === null || (isStr && str.toString().trim().length === 0)) {
	                return true;
	            }
	            return false;
	        },
			hasWildCard: function (str) {
				return (str.indexOf("*") !== -1);
			}
	    }
	};
}()));

Fix for browser type checking when undefined or null


pref("browser.dom.window.dump.enabled", true);
pref("browser.sessionstore.resume_from_crash", false);
pref("layout.debug.enable_data_xbl", true);
pref("dom.max_chrome_script_run_time", 0);
pref("dom.max_script_run_time", 0);
pref("dom.disable_window_status_change", false);
pref("dom.disable_window_move_resize", true);
pref("browser.tabs.warnOnClose", false);
pref("browser.shell.checkDefaultBrowser", false);
pref("general.warnOnAboutConfig", false);

Allow fast access to about:config


'use strict';

var path = require('path');
var existsSync = require('exists-sync');
var chalk = require('chalk');

function buildDefaultConfig(ui) {
  ui.log(chalk.yellow('\nember-cli-template-lint requires a configuration file to enable rules. Please generate one with `ember generate ember-cli-template-lint`.'));

  return {};
}

module.exports = function(console, templatercPath) {
  var defaultConfigPath = templatercPath || path.join(process.cwd(), '.template-lintrc');
  var overrideConfigPath = process.env['TEMPLATE_LINTRC'];
  var configPath = overrideConfigPath || defaultConfigPath;

  if(existsSync(configPath + '.js') || existsSync(configPath + '.json')) {
    return require(configPath);
  } else {
    return buildDefaultConfig(console);
  }
};

'use strict';

/*eslint no-console: [0] */

var path = require('path');
var existsSync = require('exists-sync');
var chalk = require('chalk');

function buildDefaultConfig(console) {
  console.log(chalk.yellow('\nember-cli-template-lint requires a configuration file to enable rules. Please generate one with `ember generate ember-cli-template-lint`.'));

  return {};
}

module.exports = function(console, templatercPath) {
  var defaultConfigPath = templatercPath || path.join(process.cwd(), '.template-lintrc');
  var overrideConfigPath = process.env['TEMPLATE_LINTRC'];
  var configPath = overrideConfigPath || defaultConfigPath;

  if(existsSync(configPath + '.js') || existsSync(configPath + '.json')) {
    return require(configPath);
  } else {
    return buildDefaultConfig(console);
  }
};

Tweak argument names for getConfig.


//Require Module
var log4js = require('log4js');
var logger = log4js.getLogger('Logging');

function excuteMySQLQuery (db,query,callback){

    /**
     * Receive the database connection, query and callback function,
     * Then show the query which will be test at first.
     * After that, excute the query.
     * If the result have error, return the error,
     * Else if the result have affectedRows, save it in r return it.
     * Else,it will return null.
     * */

    logger.debug('Testing Query:', query);

    db.query(query,function(err,result){

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

        var r = {affectedRows :0};

        if(result.affectedRows){

            r['affectedRows'] = result['affectedRows'];

        }

        callback(null,r);

    });
}

module.exports = {

    excuteMySQLQuery:excuteMySQLQuery
}

//Require Module
var log4js = require('log4js');
var logger = log4js.getLogger('Logging');

/**
 * Excute mysql query and return the result.
 *
 * @Param {Object} db
 * @Param {String} query
 * @Param {function} callback
 * @Return {Object['affectedRows']} r
 * @Return {Object} err
 */

function excuteMySQLQuery (db,query,callback){

    logger.debug('Testing Query:', query);

    db.query(query,function(err,result){

        //If the result have error, return the error

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

        var r = {affectedRows :0};
        //If the result have affectedRows, save it in r return to be a result.
        if(result.affectedRows){

            r['affectedRows'] = result['affectedRows'];

        }

        callback(null,r);

    });
}

module.exports = {

    excuteMySQLQuery:excuteMySQLQuery
}

Make the comment be concise


var main = document.getElementById("main");

main.addEventListener("click", function(event) {
  console.log("event triggered on: ", event.target);
}, false);

var main = document.getElementById("main");

main.addEventListener("click", function(event) {
  console.log("event triggered on: ", event.target);
});

Remove last argument to addEventListener


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

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

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

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

Configure webpack to use root folder for static path


// These tests are run with two different test runners which work a bit
// differently. Runners are Testem and Karma. Read more about them in
// CONTRIBUTING.md
// Supporting both has lead to some compromises.

var expect = require('expect.js');

var utils = require('./utils');
var ProgressBar = require("../progressbar");

describe('ProgressBar', function() {
    it('animate should change SVG path stroke-dashoffset property', function(done) {
        // Append progress bar to body since adding a custom HTML and div
        // with Karma was not that trivial compared to Testem
        var line = new ProgressBar.Line('body');
        var offset = utils.getComputedStyle(line.path, 'stroke-dashoffset');
        line.animate(1, {duration: 1000});

        setTimeout(function checkOffsetHasChanged() {
            var offsetMiddleOfAnimation = utils.getComputedStyle(
                line.path,
                'stroke-dashoffset'
            );

            expect(offset).not.to.be(offsetMiddleOfAnimation);
            done();
        }, 100);
    });

});

// These tests are run with two different test runners which work a bit
// differently. Runners are Testem and Karma. Read more about them in
// CONTRIBUTING.md
// Supporting both has lead to some compromises.

var expect = require('expect.js');

var utils = require('./utils');
var ProgressBar = require("../progressbar");

describe('ProgressBar', function() {
    it('animate should change SVG path stroke-dashoffset property', function(done) {
        // Append progress bar to body since adding a custom HTML and div
        // with Karma was not that trivial compared to Testem
        var line = new ProgressBar.Line('body');
        var offset = utils.getComputedStyle(line.path, 'stroke-dashoffset');
        line.animate(1, {duration: 1000});

        setTimeout(function checkOffsetHasChanged() {
            var offsetMiddleOfAnimation = utils.getComputedStyle(
                line.path,
                'stroke-dashoffset'
            );

            expect(offset).not.to.be(offsetMiddleOfAnimation);
            done();
        }, 100);
    });

    it('set should change value', function() {
        var line = new ProgressBar.Line('body');
        var offset = utils.getComputedStyle(line.path, 'stroke-dashoffset');
        expect(line.value()).to.be(0);

        line.set(1);
        expect(line.value()).to.be(1);
    });
});

Add test for value() method


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

module.exports = function(environment) {
  let ENV = {
    modulePrefix: 'dummy',
    podModulePrefix: 'dummy/pods',
    environment,
    rootURL: '/',
    locationType: 'auto',
    EmberENV: {
      FEATURES: {
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      },
      EXTEND_PROTOTYPES: {
        // Prevent Ember Data from overriding Date.parse.
        Date: false
      }
    },

    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
    },

    'ember-cli-mirage': {
      enabled: true
    }
  };

  if (environment === 'development') {
    // ENV.APP.LOG_RESOLVER = true;
    // ENV.APP.LOG_ACTIVE_GENERATION = true;
    // ENV.APP.LOG_TRANSITIONS = true;
    // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
    // ENV.APP.LOG_VIEW_LOOKUPS = true;
  }

  if (environment === 'test') {
    // Testem prefers this...
    ENV.locationType = 'none';

    // keep test console output quieter
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    ENV.APP.rootElement = '#ember-testing';
  }

  if (environment === 'production') {

  }

  return ENV;
};

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

module.exports = function(environment) {
  let ENV = {
    modulePrefix: 'dummy',
    podModulePrefix: 'dummy/pods',
    environment,
    rootURL: '/',
    locationType: 'auto',
    EmberENV: {
      FEATURES: {
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      },
      EXTEND_PROTOTYPES: {
        // Prevent Ember Data from overriding Date.parse.
        Date: false
      }
    },

    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
    }
  };

  if (environment === 'development') {
    // ENV.APP.LOG_RESOLVER = true;
    // ENV.APP.LOG_ACTIVE_GENERATION = true;
    // ENV.APP.LOG_TRANSITIONS = true;
    // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
    // ENV.APP.LOG_VIEW_LOOKUPS = true;
  }

  if (environment === 'test') {
    // Testem prefers this...
    ENV.locationType = 'none';

    // keep test console output quieter
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    ENV.APP.rootElement = '#ember-testing';
  }

  if (environment === 'production') {

  }

  return ENV;
};

Remove enabled flag in production


module.exports = function (app) {
  var ACL = app.models.ACL
	var accessControls = [
		{
			model: 'AccessToken',
			accessType: '*',
			principalType: 'ROLE',
			principalId: '$everyone',
			permission: 'DENY'
		},
		{
			model: 'AccessToken',
			accessType: '*',
			principalType: 'ROLE',
			principalId: 'admin',
			permission: 'ALLOW'
		},
		{
			model: 'AccessToken',
			accessType: '*',
			principalType: 'ROLE',
			principalId: 'founder',
			permission: 'ALLOW'
		}
	]
  ACL.create(accessControls, function (err, acls) {
    console.log('ACL entry created: %j', acls)
  })
}

module.exports = function (app) {
  var ACL = app.models.ACL
	var accessControls = [
		{
			model: 'AccessToken',
			accessType: '*',
			principalType: 'ROLE',
			principalId: '$everyone',
			permission: 'DENY'
		},
		{
			model: 'AccessToken',
			accessType: '*',
			principalType: 'ROLE',
			principalId: 'admin',
			permission: 'ALLOW'
		},
		{
			model: 'AccessToken',
			accessType: '*',
			principalType: 'ROLE',
			principalId: 'founder',
			permission: 'ALLOW'
		}
	]
  ACL.create(accessControls, function (err, acls) {
    if (err)
			throw err
  })
}

Remove Useless Logs and Add Error Handler


'use strict';

angular.module('homepageApp')
  .controller('MainCtrl', function ($scope, $http, xmlFilter, Storage, Google, Gmail) {
    $scope.calendars = [
      {src:'thibault.david@gmail.com', color: '#2952A3'},
      {src:'2g5hhq1d0nk373earfrnlb37k8@group.calendar.google.com', color: '#B1365F'},
      {src:'david.thibault@sigmund.ca', color: '#8C500B'}
    ];

    $scope.addGoogleAccount = Google.newAccount;
    $scope.resetGoogleAccounts = function() {
      Storage.set("google_accounts", {});
    }

    $scope.inboxes = [];

    var accounts = Google.getAccounts();
    for (var id in accounts) {
      var a = accounts[id];

      if (new Date() > a.expires) {
        Google.refreshAccount(a);
      } else {
        Gmail.getUnreadInboxDetails(a)
          .then(function(details) {
            $scope.inboxes.push(details);
          });
      }
    }
  });

'use strict';

angular.module('homepageApp')
  .controller('MainCtrl', function ($scope, $http, xmlFilter, Storage, Google, Gmail) {
    $scope.calendars = [
      {src:'thibault.david@gmail.com', color: '#2952A3'},
      {src:'2g5hhq1d0nk373earfrnlb37k8@group.calendar.google.com', color: '#B1365F'},
      {src:'david.thibault@sigmund.ca', color: '#8C500B'}
    ];

    $scope.addGoogleAccount = Google.newAccount;
    $scope.resetGoogleAccounts = function() {
      Storage.set("google_accounts", {});
    }

    $scope.inboxes = [];

    var accounts = Google.getAccounts();
    for (var id in accounts) {
      var a = accounts[id];

      if (new Date() > new Date(a.expires)) {
        Google.refreshAccount(a);
      } else {
        Gmail.getUnreadInboxDetails(a)
          .then(function(details) {
            $scope.inboxes.push(details);
          });
      }
    }
  });

Fix bug with google account refresh


'use strict';

angular.module('noCAPTCHA', [])
  .provider('noCAPTCHA', function NoCaptchaProvider() {
    var siteKey,
        theme;

    this.setSiteKey = function(_siteKey){
      siteKey = _siteKey;
    };

    this.setTheme = function(_theme){
      theme = _theme;
    };

    this.$get = [function NoCaptchaFactory() {
      return {
        theme: theme,
        siteKey: siteKey
      }
    }];
  })
  .directive('noCaptcha', ['noCAPTCHA', function(noCaptcha){
    return {
      restrict:'EA',
      scope: {
        gRecaptchaResponse:'=',
        siteKey:'@',
        theme:'@'
      },
      replace: true,
      link: function(scope, element){
        var widgetId,
            grecaptchaCreateParameters;

        grecaptchaCreateParameters = {
          sitekey: scope.siteKey || noCaptcha.siteKey,
          theme: scope.theme || noCaptcha.theme,
          callback: function(r){
            scope.$apply(function(){
              scope.gRecaptchaResponse = r;
            });
          }
        };

        grecaptcha.render(
          element[0],
          grecaptchaCreateParameters
        );

        scope.$on('$destroy', function(){
          grecaptcha.reset(widgetId);
        });
      }
    };
  }]);

'use strict';

angular.module('noCAPTCHA', [])
  .provider('noCAPTCHA', function NoCaptchaProvider() {
    var siteKey,
        theme;

    this.setSiteKey = function(_siteKey){
      siteKey = _siteKey;
    };

    this.setTheme = function(_theme){
      theme = _theme;
    };

    this.$get = [function NoCaptchaFactory() {
      return {
        theme: theme,
        siteKey: siteKey
      }
    }];
  })
  .directive('noCaptcha', ['noCAPTCHA', function(noCaptcha){
    return {
      restrict:'EA',
      scope: {
        gRecaptchaResponse:'=',
        siteKey:'@',
        theme:'@'
      },
      replace: true,
      link: function(scope, element){
        var widgetId,
            grecaptchaCreateParameters;

        grecaptchaCreateParameters = {
          sitekey: scope.siteKey || noCaptcha.siteKey,
          theme: scope.theme || noCaptcha.theme,
          callback: function(r){
            scope.$apply(function(){
              scope.gRecaptchaResponse = r;
            });
          }
        };
        if(!grecaptchaCreateParameters.siteKey){
          return throw 'Site Key is required';
        }
        grecaptcha.render(
          element[0],
          grecaptchaCreateParameters
        );

        scope.$on('$destroy', function(){
          grecaptcha.reset(widgetId);
        });
      }
    };
  }]);

Throw error when site key is not defined


/*globals define */
'use strict';

var root = this; // jshint ignore:line

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        define(['es6-promise'], function (es6Promise) {
            return (root.httppleasepromises = factory(es6Promise));
        });
    } else if (typeof exports === 'object') {
        module.exports = factory(require('es6-promise'));
    } else {
        root.httppleasepromises = factory(root.Promise);
    }
}(function (es6Promise) {
    var Promise = es6Promise.Promise;
    return {
        processRequest: function (req) {
            var resolve, reject,
                oldOnload = req.onload,
                oldOnerror = req.onerror,
                promise = new Promise(function (a, b) {
                    resolve = a;
                    reject = b;
                });
            req.onload = function (res) {
                var result;
                if (oldOnload) {
                    result = oldOnload.apply(this, arguments);
                }
                resolve(res);
                return result;
            };
            req.onerror = function (err) {
                var result;
                if (oldOnerror) {
                    result = oldOnerror.apply(this, arguments);
                }
                reject(err);
                return result;
            };
            req.then = function () {
                return promise.then.apply(promise, arguments);
            };
            req['catch'] = function () {
                return promise['catch'].apply(promise, arguments);
            };
        }
    };
}));

/*globals define */
'use strict';

var root = this; // jshint ignore:line

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        define(['es6-promise'], function (es6Promise) {
            return (root.httppleasepromises = factory(es6Promise.Promise));
        });
    } else if (typeof exports === 'object') {
        module.exports = factory(require('es6-promise').Promise);
    } else {
        root.httppleasepromises = factory(root.Promise);
    }
}(function (Promise) {
    return {
        processRequest: function (req) {
            var resolve, reject,
                oldOnload = req.onload,
                oldOnerror = req.onerror,
                promise = new Promise(function (a, b) {
                    resolve = a;
                    reject = b;
                });
            req.onload = function (res) {
                var result;
                if (oldOnload) {
                    result = oldOnload.apply(this, arguments);
                }
                resolve(res);
                return result;
            };
            req.onerror = function (err) {
                var result;
                if (oldOnerror) {
                    result = oldOnerror.apply(this, arguments);
                }
                reject(err);
                return result;
            };
            req.then = function () {
                return promise.then.apply(promise, arguments);
            };
            req['catch'] = function () {
                return promise['catch'].apply(promise, arguments);
            };
        }
    };
}));

Fix globals case in UMD


function rebuildTOC() {
	var ToC =
		"
" +
		"
On this page:
" +
		"
";
	var newLine, el, title, link;
	$("#content h1").each(function() {
		el = $(this);
		title = el.text();
		link = "#" + el.attr("id");
		newLine =
			"
" +
			"" +
			title +
			"" +
			"
";
		ToC += newLine;
	});
	ToC +=
		"
" +
		"
";
	return ToC;
}

$(function() {
	$('#home').click(function() {
		$('#content').load('content/introduction.html');
	});
	$('#install').click(function() {
		$('#content').load('content/installmono.html', function() {
			ToC = rebuildTOC();
			$('#content').prepend(ToC);
		});
	});
	$('#contact').click(function() {
		window.alert("Contact details not yet available");
	});
	$('#license').click(function() {
		window.alert("License details not yet available");
	});
});

/* run after the page has loaded */
$(document).ready(function(){
	$('#home').trigger('click');
});

Set the home page as default


'use strict'

Room.prototype.getPlayerHostiles = function () {
  if (!this.__playerHostiles) {
    const hostiles = this.find(FIND_HOSTILE_CREEPS)
    this.__playerHostiles = _.filter(hostiles, Room.isPlayerHazard)
  }
  return this.__playerHostiles
}

Room.prototype.getHostilesByPlayer = function () {
  if (!this.__hostilesByPlayer) {
    const hostiles = this.getPlayerHostiles()
    this.__hostilesByPlayer = {}
    for (const hostile of hostiles) {
      const owner = hostile.owner.username
      if (!this.__hostilesByPlayer[owner]) {
        this.__hostilesByPlayer[owner] = []
      }
      this.__hostilesByPlayer[owner].push(hostile)
    }
  }
  return this.__hostilesByPlayer
}

Room.isPlayerHazard = function (creep) {
  if (creep.owner.username === 'Invader' || creep.owner.username === 'Screeps') {
    return false
  }
  return this.isPotentialHazard(creep)
}

Room.isPotentialHazard = function (creep) {
  const hazardTypes = [ATTACK, RANGED_ATTACK, HEAL, WORK, CLAIM]
  return _.some(creep.body, b => _.include(hazardTypes, b.type))
}

'use strict'

Room.prototype.getPlayerHostiles = function () {
  if (!this.__playerHostiles) {
    const hostiles = this.find(FIND_HOSTILE_CREEPS)
    this.__playerHostiles = _.filter(hostiles, Room.isPlayerHazard)
  }
  return this.__playerHostiles
}

Room.prototype.getHostilesByPlayer = function () {
  if (!this.__hostilesByPlayer) {
    const hostiles = this.getPlayerHostiles()
    this.__hostilesByPlayer = {}
    for (const hostile of hostiles) {
      const owner = hostile.owner.username
      if (!this.__hostilesByPlayer[owner]) {
        this.__hostilesByPlayer[owner] = []
      }
      this.__hostilesByPlayer[owner].push(hostile)
    }
  }
  return this.__hostilesByPlayer
}

Room.isPlayerHazard = function (creep) {
  if (creep.owner.username === 'Invader' || creep.owner.username === 'Screeps') {
    return false
  }
  if (creep.my) {
    return false
  }
  return this.isPotentialHazard(creep)
}

Room.isPotentialHazard = function (creep) {
  const hazardTypes = [ATTACK, RANGED_ATTACK, HEAL, WORK, CLAIM]
  return _.some(creep.body, b => _.include(hazardTypes, b.type))
}

Add check for `creep.my` in `isPlayerHazard`


/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 *
*/

module.exports = {
    vibrate: function(milliseconds) {
        if (navigator.vibrate) {
            navigator.vibrate(milliseconds);
        }
    }
};

require("cordova/tizen/commandProxy").add("Vibration", module.exports);

Add license headers to Tizen code


var SudokuBoard = {
  defaultSetup: [
                  [0, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 0]
                ],
  create: function(initialState){
    var rawValues = SudokuBoard.defaultSetup;
    if(initialState != undefined){
      var valueArray = initialState.split("");

      for(row = 0; row < 9; row++){
        for(col = 0; col < 9; col++){
          var num = parseInt(valueArray[ row*9 + col ]);
          if( num >= 0 ){
            rawValues[row][col] = num;
          }
        }
      }
    }

    function board() {};
    board.values = function(){
      return rawValues;
    };

    return board;
  }
}

var SudokuBoard = {
  create: function(initialState){
    var rawValues = [];
    for(i = 0; i < 9; i++){
      rawValues.push([0, 0, 0, 0, 0, 0, 0, 0, 0]);
    }
    if(initialState != undefined){
      var valueArray = initialState.split("");

      for(row = 0; row < 9; row++){
        for(col = 0; col < 9; col++){
          var num = parseInt(valueArray[ row*9 + col ]);
          if( num >= 0 ){
            rawValues[row][col] = num;
          }
        }
      }
    }

    function board() {};
    board.values = function(){
      return rawValues;
    };

    return board;
  }
}

Fix my problems after realizing that arrays do not automatically get copied


/* === PLUGINS === */
const gulp = require('gulp'),
    rimraf = require('gulp-rimraf'),
    webpack = require('webpack-stream'),
    path = require('path'),
    sequence = require('run-sequence');

/* === CONFIG === */
const src = 'src/**/*',
    cfg = require('./webpack.config.js');

/* === TASKS === */
gulp.task('clean', function () {
    return gulp.src(cfg.output.path, {read: false}).pipe(rimraf());
});

gulp.task('offline', function(callback) {
    cfg.entry['beverages-mock'] = path.join(__dirname, 'src/js/mock/fake-app-server');
    callback();
});

gulp.task('webpack:build', function () {
    return gulp.src(src)
        .pipe(webpack(cfg))
        .pipe(gulp.dest(cfg.output.path));
});

gulp.task('webpack:watch', ['webpack:build'], function () {
    return gulp.watch(src, ['webpack:build']);
});

// Shortcut tasks
gulp.task('build', function (callback) {
    sequence('clean', 'webpack:build', callback);
});
gulp.task('watch', ['webpack:watch']);
gulp.task('watch-offline', ['offline', 'watch']);
gulp.task('default', ['build']);

/* === PLUGINS === */
const gulp = require('gulp'),
    rimraf = require('gulp-rimraf'),
    webpack = require('webpack-stream'),
    path = require('path'),
    sequence = require('run-sequence');

/* === CONFIG === */
const src = 'src/**/*',
    cfg = require('./webpack.config.js');

/* === TASKS === */
gulp.task('clean', function () {
    return gulp.src(cfg.output.path, {read: false}).pipe(rimraf());
});

gulp.task('_webpack:offline', function(callback) {
    cfg.entry['beverages-mock'] = path.join(__dirname, 'src/js/mock/fake-app-server');
    callback();
});

gulp.task('_webpack:build', function () {
    return gulp.src(src)
        .pipe(webpack(cfg))
        .pipe(gulp.dest(cfg.output.path));
});

gulp.task('_webpack:watch', ['_webpack:build'], function () {
    return gulp.watch(src, ['_webpack:build']);
});

// Shortcut tasks
gulp.task('build', function (callback) {
    sequence('clean', '_webpack:build', callback);
});
gulp.task('watch', ['_webpack:watch']);
gulp.task('watch-offline', ['_webpack:offline', '_webpack:watch']);
gulp.task('default', ['build']);

Mark internal/technical tasks with an _


'use strict'

const getNode = require('./getNode')
const err = require('./err')

require('setimmediate')

module.exports = (db, path) => {

  let fns = db.updates.fns[path]
  let len = fns.length

  for (let i = 0; i < len; i += 1) {

    setImmediate(() => {
      let val = getNode(db, path)
      let cacheTest = JSON.stringify(val)

      if (db.updates.cache[path][i] !== cacheTest) {
        db.updates.cache[path][i] = cacheTest

        ;(function () {
          try {
            fns[i].call(null, JSON.parse(cacheTest))
          } catch (e) {
            err(db, '/err/types/on/2', {
              path: path,
              error: e
            })
          }
        }())

      }

    })

  }

}

'use strict'

const getNode = require('./getNode')
const err = require('./err')

require('setimmediate')

module.exports = (db, path) => {

  let fns = db.updates.fns[path]

  if (!fns) {
    return
  }

  let len = fns.length

  for (let i = 0; i < len; i += 1) {

    setImmediate(() => {
      let val = getNode(db, path)
      let cacheTest = JSON.stringify(val)

      if (db.updates.cache[path][i] !== cacheTest) {
        db.updates.cache[path][i] = cacheTest

        ;(function () {
          try {
            fns[i].call(null, JSON.parse(cacheTest))
          } catch (e) {
            err(db, '/err/types/on/2', {
              path: path,
              error: e
            })
          }
        }())

      }

    })

  }

}

Add check if updates to not exist for a certain trigger


var _ = require('underscore'),
underscoreDeepExtend = require('underscore-deep-extend'),
async = require('async'),
getSamlBody = require('./online/samlBody'),
samlLogin = require('./online/samlLogin'),
samlResponse = require('./online/samlResponse'),
samlAssertionResponse = require('./online/samlAssertionResponse'),
samlTokenToCookie = require('./online/samlTokenToCookie'),
authenticatedRequestClient = require('./online/authenticatedRequestClient');

_.mixin({
  deepExtend: underscoreDeepExtend(_)
});

module.exports = function(client, httpOpts, cb) {
  var waterfall = [];

  if (!client.FedAuth || !client.rtFa){
    waterfall.push(async.apply(getSamlBody, client, httpOpts, client.federatedAuthUrl, 'urn:federation:MicrosoftOnline', null));
    waterfall.push(samlLogin);
    waterfall.push(samlAssertionResponse);
    waterfall.push(getSamlBody);
    waterfall.push(samlLogin);
    waterfall.push(samlResponse);
    waterfall.push(samlTokenToCookie);
    waterfall.push(authenticatedRequestClient);
  }else{
    waterfall.push(async.apply(authenticatedRequestClient, client, httpOpts));
  }
  return async.waterfall(waterfall, cb);
};

var _ = require('underscore'),
underscoreDeepExtend = require('underscore-deep-extend'),
async = require('async'),
getSamlBody = require('./online/samlBody'),
samlLogin = require('./online/samlLogin'),
samlResponse = require('./online/samlResponse'),
samlAssertionResponse = require('./online/samlAssertionResponse'),
samlTokenToCookie = require('./online/samlTokenToCookie'),
authenticatedRequestClient = require('./online/authenticatedRequestClient'),
assert=require('assert');

_.mixin({
  deepExtend: underscoreDeepExtend(_)
});

module.exports = function(client, httpOpts, cb) {
  var waterfall = [];

  if (!client.FedAuth || !client.rtFa){
    assert.ok(client.federatedAuthUrl, "Federated Auth URL is required when using onlinesaml");
    waterfall.push(async.apply(getSamlBody, client, httpOpts, client.federatedAuthUrl, 'urn:federation:MicrosoftOnline', null));
    waterfall.push(samlLogin);
    waterfall.push(samlAssertionResponse);
    waterfall.push(getSamlBody);
    waterfall.push(samlLogin);
    waterfall.push(samlResponse);
    waterfall.push(samlTokenToCookie);
    waterfall.push(authenticatedRequestClient);
  }else{
    waterfall.push(async.apply(authenticatedRequestClient, client, httpOpts));
  }
  return async.waterfall(waterfall, cb);
};

Add an error check to make sure we have the authentication URL parameter


"use strict";
angular.module('services.jsonp', [])
.factory('jsonp', ['$rootScope', '$q', '$http', '$parse', '$interpolate',
  function ($rootScope, $q, $http, $parse, $interpolate) {
    // We return this object to anything injecting our service
    var factory = {};
    var isConnected = false;
    var urlFn;
    var msgCallback;
    factory.isConnected = function () {
      return isConnected;
    };

    factory.register = function (method, callback) {
    };

    factory.send = function (request) {
      var defer = $q.defer();
      var request =JSON.stringify(request);
      var url = urlFn({request : request})
      $http.jsonp(url).success(function (data) {
        msgCallback(data);
      });
      return defer.promise;
    };

    factory.unregister = function (method, callback) {
    };

    factory.connect = function (partial, connectCallback, disconnectCallback) {
      urlFn = $interpolate('http://'+partial+'?request={{request}}');
      isConnected = true;
      connectCallback();
    };

    factory.subscribe = function (callback) {
      msgCallback = callback
    };

    return factory;
  }
]);

"use strict";
angular.module('services.jsonp', [])
.factory('jsonp', ['$rootScope', '$q', '$http', '$parse', '$interpolate',
  function ($rootScope, $q, $http, $parse, $interpolate) {
    // We return this object to anything injecting our service
    var factory = {};
    var isConnected = false;
    var urlFn;
    var msgCallback;
    factory.isConnected = function () {
      return isConnected;
    };

    factory.register = function (method, callback) {
    };

    factory.send = function (request) {
      var defer = $q.defer();
      var req = {
       method: 'POST',
       url: urlFn,
       headers: {
         'Content-Type': 'application/json'
       },
       data: { request: request }
      };
      $http(req).success(function (data) {
        msgCallback(data);
      });
      return defer.promise;
    };

    factory.unregister = function (method, callback) {
    };

    factory.connect = function (partial, connectCallback, disconnectCallback) {
      urlFn = 'http://'+partial;
      isConnected = true;
      connectCallback();
    };

    factory.subscribe = function (callback) {
      msgCallback = callback
    };

    return factory;
  }
]);

Use POST instead of get


module.exports = function(options) {
  var sjcl = options.sjcl;
  var base58 = require(__dirname+'/base58.js')({ sjcl: sjcl });

  function MasterKey(key){
    this.value = key;
  };

  MasterKey.fromBytes = function(bytes){
    return new MasterKey(base58.encode_base_check(33, bytes));
  };

  MasterKey.getRandom = function(){
    for (var i = 0; i < 8; i++) {
      sjcl.random.addEntropy(Math.random(), 32, "Math.random()");
    }
    var randomBytes = sjcl.codec.bytes.fromBits(sjcl.random.randomWords(4));
    return MasterKey.fromBytes(randomBytes);
  };
  return MasterKey;
}

module.exports = function(options) {
  var sjcl = options.sjcl;
  var base58 = require('./base58.js')({ sjcl: sjcl });

  function MasterKey(key) {
    this.value = key;
  }

  MasterKey.fromBytes = function(bytes) {
    return new MasterKey(base58.encode_base_check(33, bytes));
  };

  MasterKey.getRandom = function() {
    if (typeof window === 'object' && window.crypto) {
      // Browser with crypto
      var entropy = new Uint32Array(32);
      window.crypto.getRandomValues(entropy);
      sjcl.random.addEntropy(entropy, 1024, 'crypto.getRandomValues');
    } else if (typeof module === 'object' && module.exports) {
      // Node
      var entropy = require('crypto').randomBytes(128);
      entropy = new Uint32Array(new Uint8Array(entropy).buffer);
      sjcl.random.addEntropy(entropy, 1024, 'crypto.randomBytes');
    } else {
      for (var i = 0; i < 8; i++) {
        sjcl.random.addEntropy(Math.random(), 32, 'Math.random()');
      }
    }

    var randomBytes = sjcl.codec.bytes.fromBits(sjcl.random.randomWords(4));

    return MasterKey.fromBytes(randomBytes);
  };

  return MasterKey;
}

Add special entropy generators for Node and browsers with crypto


/*
 * pilot-fish
 * https://github.com/jeffminnear/pilot-fish
 *
 * Copyright (c) 2016 Jeff Minnear
 * Licensed under the MIT license.
 */

'use strict';

exports.awesome = function() {
  return 'awesome';
};

#! /usr/bin/env node

/*
 * pilot-fish
 * https://github.com/jeffminnear/pilot-fish
 *
 * Copyright (c) 2016 Jeff Minnear
 * Licensed under the MIT license.
 */

'use strict';

Set script to execute using Node


/*
HTTP Strict Transport Security (HSTS)

http://tools.ietf.org/html/rfc6797

*/

module.exports = function (maxAge, includeSubdomains) {
    if (!maxAge) maxAge = '15768000'; // Approximately 6 months
    var header = "max-age=" + maxAge;

    if (includeSubdomains) header += '; includeSubdomains';

    return function (req, res, next)  {
        if (req.secure || req.headers['x-forwarded-proto'] == 'https') {
            res.setHeader('Strict-Transport-Security', header);
        }
        next();
    };
};

/*
HTTP Strict Transport Security (HSTS)

http://tools.ietf.org/html/rfc6797

*/

module.exports = function hsts (maxAge, includeSubdomains) {

    maxAge = maxAge || '15768000'; // approximately 6 months

    var header = 'max-age=' + maxAge;
    if (includeSubdomains) {
        header += '; includeSubdomains';
    }

    return function hsts (req, res, next)  {

        var isSecure = (req.secure) ||
            (req.headers['front-end-https'] == 'on') ||
            (req.headers['x-forwarded-proto'] == 'https');

        if (isSecure) {
            res.setHeader('Strict-Transport-Security', header);
        }

        next();
    };

};

Clean up the HSTS code a little bit


import React from 'react'
import {Hits} from 'react-instantsearch'

import Pagination from '../Pagination'
import Stats from '../Stats'
import Hit from '../Hit'

function CustomHits ({hits}) {
  return (

      <Stats />

        {hits.map((hit, idx) => <Hit item={hit} key={idx} />)}
        <Pagination />

  )
}

export default Hits.connect(CustomHits)

import React from 'react'
import {Hits} from 'react-instantsearch'

import Pagination from '../Pagination'
import Stats from '../Stats'
import Hit from '../Hit'

function CustomHits ({hits, hitsPerPage}) {
  const hasPagination = hits.length > hitsPerPage
  return (

      <Stats />

        {hits.map((hit, idx) => <Hit item={hit} key={idx} />)}
        {hasPagination && <Pagination /> }

  )
}

export default Hits.connect(CustomHits)

Hide pagination when is not necessary


module.exports = (function() {
    return function(options) {
        var src, rule, syntax, getTokens, mark, rules, tokens;

        if (!options || !options.src) throw new Error('Please, pass a string to parse');

        src = typeof options === 'string' ? options : options.src;
        rule = options.rule || 'stylesheet';
        syntax = options.syntax || 'css';

        try {
            getTokens = require('./' + syntax + '/tokenizer');
            mark = require('./' + syntax + '/mark');
            rules = require('./' + syntax + '/rules');
        } catch (e) {
            return console.error('Syntax "' + syntax + '" is not supported yet, sorry');
        }

        tokens = getTokens(src);
        mark(tokens);
        return rules(tokens, rule);
    }
})();

module.exports = (function() {
    return function(options) {
        var src, rule, syntax, getTokens, mark, rules, tokens;

        if (!options || !options.src) throw new Error('Please, pass a string to parse');

        src = typeof options === 'string' ? options : options.src;
        syntax = options.syntax || 'css';
        rule = options.rule || (syntax === 'js' ? 'program' : 'stylesheet');

        try {
            getTokens = require('./' + syntax + '/tokenizer');
            mark = require('./' + syntax + '/mark');
            rules = require('./' + syntax + '/rules');
        } catch (e) {
            return console.error('Syntax "' + syntax + '" is not supported yet, sorry');
        }

        tokens = getTokens(src);
        mark(tokens);
        return rules(tokens, rule);
    }
})();

Set default rule to `program`


/**
 * WPCOM module
 */

var util = require('./util');
var assert = require('assert');

/**
 * Testing data
 */
function trueAssertion( done ) { return function() { done(); }; }
function trueCallback( callback ) { callback( null, true ); }
function falseAssertion( done ) { return function() { done( new Error('Failed!')); }; }
function falseCallback( callback ) { callback( true, null ); }

function timedCallback( delay, caller = trueCallback ) {
	return function( params, callback ) {
		setTimeout( function() { return caller.apply(null, [params, callback] ); }, delay );
	};
}

/**
 * WPCOM Promises
 */

describe('wpcom', function(){
	var wpcom = util.wpcom_public();

	describe.only('wpcom.promises', function(){
		it('should fail when slower than timeout', done => {
			wpcom.site(util.site()).postsList()
				.timeout( 10 )
				.then( falseAssertion( done ) )
				.catch( trueAssertion( done ) );
		});

		it('should still catch() with timeout()', done => {
			wpcom.site(util.site()).post(-5).get()
				.timeout( 10000 )
				.then( falseAssertion( done ) )
				.catch( trueAssertion( done ) );
		});
	});

});

/**
 * WPCOM module
 */

var util = require('./util');
var assert = require('assert');

/**
 * Testing data
 */
function trueAssertion( done ) { return function() { done(); }; }
function trueCallback( callback ) { callback( null, true ); }
function falseAssertion( done ) { return function() { done( new Error('Failed!')); }; }
function falseCallback( callback ) { callback( true, null ); }

function timedCallback( delay, caller = trueCallback ) {
	return function( params, callback ) {
		setTimeout( function() { return caller.apply(null, [params, callback] ); }, delay );
	};
}

/**
 * WPCOM Promises
 */

describe('wpcom', function(){
	var wpcom = util.wpcom_public();

	describe('wpcom.promises', function(){
		it('should fail when slower than timeout', done => {
			wpcom.site(util.site()).postsList()
				.timeout( 10 )
				.then( falseAssertion( done ) )
				.catch( trueAssertion( done ) );
		});

		it('should still catch() with timeout()', done => {
			wpcom.site(util.site()).post(-5).get()
				.timeout( 10000 )
				.then( falseAssertion( done ) )
				.catch( trueAssertion( done ) );
		});
	});

});

Remove 'only' that was hogging the test suites


var mongoose = require('mongoose');
Schema = mongoose.Schema;

//This defines each entry in the phonebook and the data
//which is required and optional for it.
var entrySchema = new Schema({
    'name':
        {type: String,
        required: true},
    'surname':
        {type: String,
        required: true},
    'phonenumber':
        {type: String,
        required: true},
    'address': String
});

mongoose.model('Entry', entrySchema);

var mongoose = require('mongoose');
Schema = mongoose.Schema;

//This defines each entry in the phonebook and the data
//which is required and optional for it.
var entrySchema = new Schema({
    'name':
    {type: String,
     required: true,
     trim: true},
    'surname':
    {type: String,
     required: true,
     trim:true},
    'phonenumber':
    {type: String,
     required: true,
     trim:true},
    'address': String
});

mongoose.model('Entry', entrySchema);

Modify schema to enforce validation, required fields cannot be just formed by whitespaces


function setCarouselSize() {
    var wWidth = $(window).width();
    var wHeight = $(window).height();

    var originalImageHeight = 1080;
    var originalImageWidth = 1920;

    if (wHeight > wWidth) {
        var containerHeight = originalImageHeight * wWidth / originalImageWidth;
        $('#carousel-example-generic').height(containerHeight);
    } else {
        $('#carousel-example-generic').height($(window).height()-$('#panel-title').height());
    }
}

$(function() {
    setCarouselSize();
});

$(window).resize(function(){
    setCarouselSize();
});

function setCarouselSize() {
    var wWidth = $(window).width();
    var wHeight = $(window).height();

    var originalImageHeight = 1080;
    var originalImageWidth = 1920;

    if (wHeight > wWidth) {
        var containerHeight = originalImageHeight * wWidth / originalImageWidth;
        $('#carousel-widget').height(containerHeight);
    } else {
        $('#carousel-widget').height($(window).height()-$('#panel-title').height());
    }
}

$(function() {
    setCarouselSize();
});

$(window).resize(function(){
    setCarouselSize();
});

Replace carousel-example-generic with carousel-widget ids


//= require foundation/foundation.abide
//= require foundation/foundation.accordion
//= require foundation/foundation.alert
//= require foundation/foundation.clearing
//= require foundation/foundation.dropdown
//= require foundation/foundation.equalizer
//= require foundation/foundation.interchange
//= require foundation/foundation.joyride
//= require foundation/foundation
//= require foundation/foundation.magellan
//= require foundation/foundation.offcanvas
//= require foundation/foundation.orbit
//= require foundation/foundation.reveal
//= require foundation/foundation.slider
//= require foundation/foundation.tab
//= require foundation/foundation.tooltip
//= require foundation/foundation.topbar

//= require foundation/foundation
//= require foundation/foundation.abide
//= require foundation/foundation.accordion
//= require foundation/foundation.alert
//= require foundation/foundation.clearing
//= require foundation/foundation.dropdown
//= require foundation/foundation.equalizer
//= require foundation/foundation.interchange
//= require foundation/foundation.joyride
//= require foundation/foundation.magellan
//= require foundation/foundation.offcanvas
//= require foundation/foundation.orbit
//= require foundation/foundation.reveal
//= require foundation/foundation.slider
//= require foundation/foundation.tab
//= require foundation/foundation.tooltip
//= require foundation/foundation.topbar

Correct JavaScript files require order.


alert("You're on an ESPN page.  Hello from MERA.");

var body = document.getElementsByTagName("body")[0];

handleChildren(body);

function handleChildren(node) {
	var children = node.childNodes;
	for (var i=0; i < children.length; i++) {
		var child = children[i];
		if (child.nodeValue && child.nodeValue.includes('Kellerman')) {
			var section = findParent(child, "section");
			var sectionParent = section.parentNode;
			sectionParent.removeChild(section);
			var span = document.createElement("section");
			var text = document.createTextNode("ESPN is so reasonable!");
			span.appendChild(text);
			sectionParent.appendChild(span);
		} else {
			handleChildren(child);
		}
	}
}

function findParent(node, tagName) {
	if (!node) {
		return null;
	}
	if (node.tagName && node.tagName.toLowerCase() == tagName) {
		return node;
	}
	return findParent(node.parentNode, tagName);
}

Remove all sections containing Kellerman


import fs from "fs-extra"
import path from "path"
import _ from "underscore"

export default class ProjectStore {
  static displayName = "ProjectStore"

  constructor() {
    this.state = {
      rootPath: "",
      contentPath: "",
      mediaPath: "",
      shortcuts: {}
    }

    const ProjectActions = this.alt.actions.ProjectActions

    this.bindListeners({
      setRoot: ProjectActions.OPEN
    })
  }

  setRoot(rootPath) {
    this.state.rootPath = rootPath
    this.state.contentPath = rootPath
    this.state.mediaPath = rootPath
    this.loadConfig()
  }

  loadConfig() {
    let configFile = path.join(this.state.rootPath, "downquark_config.json")
    let config = fs.readJSONSync(configFile, { throws: false })
    if (config) {
      this.setState({
        contentPath: path.join(this.state.rootPath, config.contentPath || ""),
        mediaPath: path.join(this.state.rootPath, config.mediaPath || ""),
        shortcuts: _.mapObject(config.shortcuts || {}, (p, alias) => {
          return path.join(this.state.rootPath, p)
        })
      })
    }
  }
}

import fs from "fs-extra"
import path from "path"
import _ from "underscore"

export default class ProjectStore {
  static displayName = "ProjectStore"

  constructor() {
    this.state = {
      rootPath: "",
      contentPath: "",
      mediaPath: "",
      shortcuts: {}
    }

    const ProjectActions = this.alt.actions.ProjectActions

    this.bindListeners({
      setRoot: ProjectActions.OPEN
    })
  }

  setRoot(rootPath) {
    this.setState({
      rootPath    : rootPath,
      contentPath : rootPath,
      mediaPath   : rootPath,
      shortcuts   : {}
    })
    this.loadConfig()
  }

  loadConfig() {
    let configFile = path.join(this.state.rootPath, "downquark_config.json")
    if (!fs.existsSync(configFile)) return
    let config = fs.readJSONSync(configFile, { throws: false })
    if (config) {
      this.setState({
        contentPath: path.join(this.state.rootPath, config.contentPath || ""),
        mediaPath: path.join(this.state.rootPath, config.mediaPath || ""),
        shortcuts: _.mapObject(config.shortcuts || {}, (p, alias) => {
          return path.join(this.state.rootPath, p)
        })
      })
    }
  }
}

Allow opening projects with no config file


const FrontMatter = require('front-matter');
const { markdown } = require('markdown');

module.exports = function load(source) {
  const frontmatter = FrontMatter(source);
  return JSON.stringify(markdown.toHTML(frontmatter.body));
};

const FrontMatter = require('front-matter');
const { markdown } = require('markdown');

module.exports = function load(source) {
  const frontmatter = FrontMatter(source);
  return markdown.toHTML(frontmatter.body);
};

Remove JSON stringify from markdown loader.


'use strict';

let gulp        = require('gulp'),
    rename      = require('gulp-rename'),
    rollup      = require('rollup').rollup;

module.exports = () => {
    gulp.task('copy-dependencies', () => {
        return gulp
            .src([
                './node_modules/three/build/three.js'
            ])
            .pipe(gulp.dest('./dist/'))
    });

    gulp.task('build', ['copy-dependencies'], (callback) => {
        return rollup({
            entry: 'src/js/main.js',
            sourceMap: true,
            external: ['three']
        }).then(function(bundle) {
            return bundle.write({
                dest:  'dist/main.js',
                format: 'iife',
                globals: {
                    three: 'THREE'
                }
            });
        });
    });
};

'use strict';

let gulp        = require('gulp'),
    rollup      = require('rollup').rollup;

let cache;

module.exports = () => {
    gulp.task('copy-dependencies', () => {
        return gulp
            .src([
                './node_modules/three/build/three.js'
            ])
            .pipe(gulp.dest('./dist/'))
    });

    gulp.task('build', ['copy-dependencies'], (callback) => {
        return rollup({
            entry: 'src/js/main.js',
            cache: cache,
            sourceMap: true,
            external: ['three']
        }).then(function(bundle) {
            return bundle.write({
                dest:  'dist/main.js',
                sourceMap: true,
                format: 'iife',
                globals: {
                    three: 'THREE'
                }
            });
        });
    });
};

Create a source map file


"use strict";

var express    = require('express'),
    serverApp  = require('./test-server-app');

serverApp.use(express.logger('dev'));

serverApp.listen(3000);
console.log('listening on http://0.0.0.0:3000');

"use strict";

var express       = require('express'),
    testServerApp = require('./test-server-app');

var server = express();
server.use(express.logger('dev'));
server.use('/', testServerApp);

server.listen(3000);
console.log('listening on http://0.0.0.0:3000');

Load the logger before the app so that the logging actually happens


var self = require("sdk/self");
var panel = require("sdk/panel");

var initToolbar = function(freedom) {
  // create toolbarbutton
  var tbb = require("pathfinder/ui/toolbarbutton").ToolbarButton({
    id: "UProxyItem",
    label: "UProxy",
    image: self.data.url("common/ui/icons/uproxy-19.png"),
    panel: initPanel(freedom.communicator)
  });

  tbb.moveTo({
    toolbarID: "nav-bar",
    forceMove: false // only move from palette
  });
};

var initPanel = function(freedomCommunicator) {
  var l10n = JSON.parse(self.data.load("l10n/en/messages.json"));
  var uproxyPanel = panel.Panel({
    contentURL: self.data.url("common/ui/popup.html"),
    width: 450,
    height: 300
  });
  freedomCommunicator.addContentContext(uproxyPanel);
  uproxyPanel.port.on("show", function() {
    uproxyPanel.port.emit("l10n", l10n);
  });
  return uproxyPanel;
};

var freedomEnvironment = require('./init_freedom').InitFreedom();

// TODO: Remove when uproxy.js no longer uses setTimeout
// and replace with the line:
// initToolbar(freedomEnvironment);
require('sdk/timers').setTimeout(initToolbar, 20, freedomEnvironment);

var self = require("sdk/self");
var panel = require("sdk/panel");

var initToolbar = function(freedom) {
  // create toolbarbutton
  var tbb = require("pathfinder/ui/toolbarbutton").ToolbarButton({
    id: "UProxyItem",
    label: "UProxy",
    image: self.data.url("common/ui/icons/uproxy-19.png"),
    panel: initPanel(freedom.communicator)
  });

  tbb.moveTo({
    toolbarID: "nav-bar",
    forceMove: false // only move from palette
  });
};

var initPanel = function(freedomCommunicator) {
  var l10n = JSON.parse(self.data.load("l10n/en/messages.json"));
  var uproxyPanel = panel.Panel({
    contentURL: self.data.url("common/ui/popup.html"),
    width: 450,
    height: 300
  });
  freedomCommunicator.addContentContext(uproxyPanel);
  uproxyPanel.port.on("show", function() {
    uproxyPanel.port.emit("l10n", l10n);
  });
  return uproxyPanel;
};

var freedomEnvironment = require('./init_freedom').InitFreedom();

// TODO: Remove when uproxy.js no longer uses setTimeout
// and replace with the line:
// initToolbar(freedomEnvironment);
require('sdk/timers').setTimeout(initToolbar, 500, freedomEnvironment);

Increase delay for loading toolbarbutton so that other components have a chance to load.


'use strict'

import keytar from 'keytar'

const SERVICE = 'gh-notifications-snoozer'
const ACCOUNT = process.env.NODE_ENV === 'test' ? 'github-test' : 'github'

class GitHubAuth {
  static isAuthenticated() {
    return this.getToken() !== null
  }

  static setToken(token) {
    if (this.isAuthenticated()) {
      this.deleteToken()
    }
    keytar.addPassword(SERVICE, ACCOUNT, token)
  }

  static deleteToken() {
    keytar.deletePassword(SERVICE, ACCOUNT)
  }

  static getToken() {
    return keytar.getPassword(SERVICE, ACCOUNT)
  }
}

module.exports = GitHubAuth

'use strict'

import keytar from 'keytar'

const SERVICE = 'gh-notifications-snoozer'
const ACCOUNT = process.env.NODE_ENV === 'test' ? 'github-test' : 'github'

class GitHubAuth {
  static isAuthenticated() {
    return this.getToken() !== null
  }

  static setToken(token) {
    console.log('setToken', token)
    if (this.isAuthenticated()) {
      this.deleteToken()
    }
    keytar.addPassword(SERVICE, ACCOUNT, token)
  }

  static deleteToken() {
    keytar.deletePassword(SERVICE, ACCOUNT)
  }

  static getToken() {
    console.log('getToken', keytar.getPassword(SERVICE, ACCOUNT))
    return keytar.getPassword(SERVICE, ACCOUNT)
  }
}

module.exports = GitHubAuth

Add a couple more logs for Travis debugging


import {Controller} from "stimulus"

export default class extends Controller {

    static targets = ["mapInfo"]

    connect() {
        const courseId = this.mapInfoTarget.dataset.courseId;
        const splitId = this.mapInfoTarget.dataset.splitId;

        Rails.ajax({
            url: "/courses/" + courseId + '.json',
            type: "GET",
            success: function (data) {
                const attributes = data.data.attributes;

                var locations = null;
                if(splitId === undefined) {
                    locations = attributes.locations;
                } else {
                    locations = attributes.locations.filter(function(e) {
                        return e.id === parseInt(splitId)
                    })
                }

                const trackPoints = attributes.trackPoints;
                gmap_show(locations, trackPoints);
            }
        })
    }
}

import {Controller} from "stimulus"

export default class extends Controller {

    static targets = ["mapInfo"]

    connect() {
        const courseId = this.mapInfoTarget.dataset.courseId;
        const splitId = this.mapInfoTarget.dataset.splitId;

        Rails.ajax({
            url: "/api/v1/courses/" + courseId,
            type: "GET",
            success: function (data) {
                const attributes = data.data.attributes;

                var locations = null;
                if(splitId === undefined) {
                    locations = attributes.locations;
                } else {
                    locations = attributes.locations.filter(function(e) {
                        return e.id === parseInt(splitId)
                    })
                }

                const trackPoints = attributes.trackPoints;
                gmap_show(locations, trackPoints);
            }
        })
    }
}

Fix ajax request in Stimulus maps controller


var React = require('react');
var Router = require('react-router');
var Fetcher = require('fetchr/libs/fetcher.client');

var App = require('../shared/App');
var Routes = require('../shared/Components/Routes');

fetcher = new Fetcher({
  xhrPath: App.xhrPath,
  requireCrumb: false
});

App.fetcher = require('bluebird').promisifyAll(fetcher);

[require('../shared/Stores/roomStore'), require('../shared/Stores/messageStore'), require('../shared/Stores/likeStore')].forEach(function (store) {
  store.rehydrate(window.state);
});

Router.run(Routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler />, window.document.getElementById('app'));
});

var React = require('react');
var Router = require('react-router');
var Fetcher = require('fetchr/libs/fetcher.client');

var App = require('../shared/App');

fetcher = new Fetcher({
  xhrPath: App.xhrPath,
  requireCrumb: false
});

App.fetcher = require('bluebird').promisifyAll(fetcher);

[require('../shared/Stores/roomStore'), require('../shared/Stores/messageStore'), require('../shared/Stores/likeStore')].forEach(function (store) {
  store.rehydrate(window.state);
});

var Routes = require('../shared/Components/Routes');

Router.run(Routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler />, window.document.getElementById('app'));
});

Reorder to require Routes last.


const databaseName = 'awstest';

module.exports = {
  development: {
    client: 'postgresql',
    connection: `postgres://localhost:5432/${databaseName}`,
    migrations: {
      directory: __dirname + '/src/server/db/migrations'
    },
    seeds: {
      directory: __dirname + '/src/server/db/seeds'
    }
  },
  test: {
    client: 'postgresql',
    connection: `postgres://localhost:5432/${databaseName}_test`,
    migrations: {
      directory: __dirname + '/src/server/db/migrations'
    },
    seeds: {
      directory: __dirname + '/src/server/db/seeds'
    }
  },
  production: {
    client: 'postgresql',
    connection: `postgres://${process.env.RDS_HOSTNAME}:${process.env.RDS_PORT}/${databaseName}`,
    migrations: {
      directory: __dirname + '/src/server/db/migrations'
    },
    seeds: {
      directory: __dirname + '/src/server/db/seeds'
    }
  }
};

const databaseName = 'awstest';

module.exports = {
  development: {
    client: 'postgresql',
    connection: `postgres://localhost:5432/${databaseName}`,
    migrations: {
      directory: __dirname + '/src/server/db/migrations'
    },
    seeds: {
      directory: __dirname + '/src/server/db/seeds'
    }
  },
  test: {
    client: 'postgresql',
    connection: `postgres://localhost:5432/${databaseName}_test`,
    migrations: {
      directory: __dirname + '/src/server/db/migrations'
    },
    seeds: {
      directory: __dirname + '/src/server/db/seeds'
    }
  },
  production: {
    client: 'postgresql',
    connection: `postgres://${process.env.RDS_USERNAME}:${process.env.RDS_PASSWORD}:${process.env.RDS_HOSTNAME}:${process.env.RDS_PORT}/${databaseName}`,
    migrations: {
      directory: __dirname + '/src/server/db/migrations'
    },
    seeds: {
      directory: __dirname + '/src/server/db/seeds'
    }
  }
};

Add credentials to psql production.


const { assert } = require('chai');
const got = require('got');

const debuglogs = require('../../js/modules/debuglogs');

describe('debuglogs', () => {
  describe('upload', () => {
    it('should upload log content', async () => {
      const nonce = Math.random().toString().slice(2);
      const url = await debuglogs.upload(nonce);

      const { body } = await got.get(url);
      assert.equal(nonce, body);
    });
  });
});

const { assert } = require('chai');
const got = require('got');

const debuglogs = require('../../js/modules/debuglogs');

describe('debuglogs', () => {
  describe('upload', () => {
    it('should upload log content', async () => {
      const nonce = Math.random().toString().slice(2);
      const url = await debuglogs.upload(nonce);

      const { body } = await got.get(url);
      assert.equal(nonce, body);
    }).timeout(3000);
  });
});

Bump timeout of `debuglogs` test


/**
 * `modules/analytics` base data store
 *
 * 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.
 */

/**
 * Internal dependencies
 */
import Modules from 'googlesitekit-modules';
import { STORE_NAME } from './constants';
import { submitChanges, validateCanSubmitChanges } from './settings';

const baseModuleStore = Modules.createModuleStore( 'analytics', {
	storeName: STORE_NAME,
	settingSlugs: [
		'anonymizeIP',
		'accountID',
		'profileID',
		'propertyID',
		'internalWebPropertyID',
		'useSnippet',
		'canUseSnippet',
		'trackingDisabled',
		'ownerID',
	],
	adminPage: 'googlesitekit-module-analytics',
	submitChanges,
	validateCanSubmitChanges,
} );

export default baseModuleStore;

/**
 * `modules/analytics` base data store
 *
 * 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.
 */

/**
 * Internal dependencies
 */
import Modules from 'googlesitekit-modules';
import { STORE_NAME } from './constants';
import { submitChanges, validateCanSubmitChanges } from './settings';

const baseModuleStore = Modules.createModuleStore( 'analytics', {
	storeName: STORE_NAME,
	settingSlugs: [
		'accountID',
		'adsID',
		'anonymizeIP',
		'canUseSnippet',
		'internalWebPropertyID',
		'ownerID',
		'profileID',
		'propertyID',
		'trackingDisabled',
		'useSnippet',
	],
	adminPage: 'googlesitekit-module-analytics',
	submitChanges,
	validateCanSubmitChanges,
} );

export default baseModuleStore;

Add adsID to settings slugs and sort.


var error         = require('./error')
var passport      = require('passport')
var LocalStrategy = require('passport-local').Strategy
var User          = require('./models/User')

passport.serializeUser(function(user, done) {
  done(null, user.id)
})

passport.deserializeUser(function(id, done) {
  User.findById(id, done)
})

/**
 * Sign in using username and password
 */
passport.use(new LocalStrategy(function(username, password, done) {
  User.findOne({ username: username }, function(err, user) {
    if(err)
      return done(err)

    if(!user)
      return done(null, false, { error: 'userNotFound', message: 'Nutzer "' + username + '" wurde nicht gefunden.' })

    user.comparePassword(password, function(err, isMatch) {
      if(err)
        return done(err)

      if(isMatch)
        return done(null, user)
      else
        return done(null, user, { error: 'wrongPassword', message: 'Falsches Passwort.' })
    })
  })
}))

/**
 * Login required middleware
 */
exports.ensureAuthenticated = function(req, res, next) {
  if(!req.isAuthenticated())
    return res.returnWith('error', 'Du musst eingeloggt sein.', '/login')

  next()
}

/**
 * Admin required middleware
 */
exports.ensureAdmin = function(req, res, next) {
  if(req.user && req.user.admin === true)
    next()
  else
    next(new error.NotFound)
}

var error         = require('./error')
var passport      = require('passport')
var LocalStrategy = require('passport-local').Strategy
var User          = require('./models/User')

passport.serializeUser(function(user, done) {
  done(null, user.id)
})

passport.deserializeUser(function(id, done) {
  User.findById(id, done)
})

/**
 * Sign in using username and password
 */
passport.use(new LocalStrategy(function(username, password, done) {
  User.findOne({ username: new RegExp('^' + username + '$', 'i') }, function(err, user) {
    if(err)
      return done(err)

    if(!user)
      return done(null, false, { error: 'userNotFound', message: 'Nutzer "' + username + '" wurde nicht gefunden.' })

    user.comparePassword(password, function(err, isMatch) {
      if(err)
        return done(err)

      if(isMatch)
        return done(null, user)
      else
        return done(null, user, { error: 'wrongPassword', message: 'Falsches Passwort.' })
    })
  })
}))

/**
 * Login required middleware
 */
exports.ensureAuthenticated = function(req, res, next) {
  if(!req.isAuthenticated())
    return res.returnWith('error', 'Du musst eingeloggt sein.', '/login')

  next()
}

/**
 * Admin required middleware
 */
exports.ensureAdmin = function(req, res, next) {
  if(req.user && req.user.admin === true)
    next()
  else
    next(new error.NotFound)
}

Make username search in login case-insensitive


const xml2js = require('xml2js');
const parser = new xml2js.Parser({explicitArray: false, attrkey: "attributes"});
const createFormList = require('openrosa-formlist');
const getFormUrls = require('../helpers/get-form-urls');

/**
 * Searches for XForm XML Files on the file system and
 * returns valid OpenRosa formList XML.
 */
module.exports = function (req, res, next) {
    var options = {
        headers: {
            'User-Agent': 'OpenMapKitServer'
        },
        baseUrl: req.protocol + '://' + req.headers.host + '/public/forms'
    };

    // Look for "json" query param
    var json = req.query.json || false;

    getFormUrls(options, function (err, formUrls) {
        if (err) return next(err);
        var formListOptions = {
            headers: options.headers
        };
        createFormList(formUrls, formListOptions, function(err, xml) {
            if (err) return next(err);

            // Default is XML, but JSON is an option
            if(json) {
                parser.parseString(xml, function (err, result) {
                    res.status(200).json(result);
                });

            } else {
                res.set('content-type', 'text/xml; charset=utf-8');
                res.status(200).send(xml);
            }
        });
    });
};

const xml2js = require('xml2js');
const parser = new xml2js.Parser({explicitArray: false, attrkey: "attributes"});
const createFormList = require('openrosa-formlist');
const getFormUrls = require('../helpers/get-form-urls');

/**
 * Searches for XForm XML Files on the file system and
 * returns valid OpenRosa formList XML.
 */
module.exports = function (req, res, next) {
    var options = {
        headers: {
            'User-Agent': 'OpenMapKitServer'
        },
        baseUrl: req.protocol + '://' + req.headers.host + '/public/forms'
    };

    // Look for "json" query param
    var json = req.query.json || false;

    getFormUrls(options, function (err, formUrls) {
        if (err) return next(err);
        var formListOptions = {
            headers: options.headers
        };
        createFormList(formUrls, formListOptions, function(err, xml) {
            if (err) return next(err);

            // Default is XML, but JSON is an option
            if(json) {
                parser.parseString(xml, function (err, result) {
                    if (result === undefined) {
                        res.status(200).json(null);
                    } else {
                        res.status(200).json(result);
                    }
                });

            } else {
                res.set('content-type', 'text/xml; charset=utf-8');
                res.status(200).send(xml);
            }
        });
    });
};

Handle case of zero forms more gracefully for JSON option.


/**
 * Enum for isolation levels
 * @readonly
 * @enum {IsolationLevel}
 */
module.exports = {
  // Makes all records visible
  READ_UNCOMMITTED: 0,

  // non-transactional and COMMITTED transactional records are visible. It returns all data
  // from offsets smaller than the current LSO (last stable offset), and enables the inclusion of
  // the list of aborted transactions in the result, which allows consumers to discard ABORTED
  // transactional records
  READ_COMMITTED: 1,
}

Add JSDoc for isolation level


/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

var CompassHeading = function(magneticHeading, trueHeading, headingAccuracy, timestamp) {
  this.magneticHeading = magneticHeading || null;
  this.trueHeading = trueHeading || null;
  this.headingAccuracy = headingAccuracy || null;
  this.timestamp = timestamp || new Date().getTime();
};

module.exports = CompassHeading;

/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

var CompassHeading = function(magneticHeading, trueHeading, headingAccuracy, timestamp) {
  this.magneticHeading = magneticHeading;
  this.trueHeading = trueHeading;
  this.headingAccuracy = headingAccuracy;
  this.timestamp = timestamp || new Date().getTime();
};

module.exports = CompassHeading;

Handle case where these values can be zero, and would be set to null


"use strict";

var path = require("path"),
    gpfPath = path.resolve(__dirname, "../.."),
    args = process.argv.slice(2),
    browser = args[0],
    version,
    errorCount,
    webDriver = require("selenium-webdriver"),
    By = require("selenium-webdriver").By,
    until = require("selenium-webdriver").until,
    driver = new webDriver.Builder()
        .forBrowser(browser)
        .build();

if ("-release" === args[1]) {
    version = "?release";
} else if ("-debug" === args[1]) {
    version = "?debug";
} else {
    version = "";
}

driver.get("file://" + gpfPath + "/test/host/web.html" + version);
driver.wait(until.titleIs("GPF Tests - done"), 5000);
driver.findElements(By.id("status"))
    .then(function (elements) {
        return elements[0].getText();
    })
    .then(function (text) {
        console.log(text);
        if (0 === text.indexOf("OK")) {
            errorCount = 0;
        } else {
            // Search for failure: <number> <timespent>
            errorCount = parseInt(text.split("failure: ")[1].split(" ")[0], 10);
        }
        return driver.quit();
    })
    .then(function () {
        process.exit(errorCount);
    });

"use strict";

var path = require("path"),
    gpfPath = path.resolve(__dirname, "../.."),
    useFileAccess = false,
    args = process.argv.slice(2),
    browser = args[0],
    version,
    errorCount,
    webDriver = require("selenium-webdriver"),
    By = require("selenium-webdriver").By,
    until = require("selenium-webdriver").until,
    driver = new webDriver.Builder()
        .forBrowser(browser)
        .build();

if ("-release" === args[1]) {
    version = "?release";
} else if ("-debug" === args[1]) {
    version = "?debug";
} else {
    version = "";
}

if ("-file" === args[2]) {
    useFileAccess = true;
}

if (useFileAccess) {
    driver.get("file://" + gpfPath + "/test/host/web.html" + version);
} else {
    driver.get("http://localhost:8000/test/host/web.html" + version);
}

driver.wait(until.titleIs("GPF Tests - done"), 5000);
driver.findElements(By.id("status"))
    .then(function (elements) {
        return elements[0].getText();
    })
    .then(function (text) {
        console.log(text);
        if (0 === text.indexOf("OK")) {
            errorCount = 0;
        } else {
            // Search for failure: <number> <timespent>
            errorCount = parseInt(text.split("failure: ")[1].split(" ")[0], 10);
        }
        return driver.quit();
    })
    .then(function () {
        process.exit(errorCount);
    });

Switch to use file access (-file) or http access (default)


/*global angular: true, appInsights: true */

(function () {
    "use strict";

    angular.module('angular-appinsights', [])

        .provider('insights', function () {

            var _appId,
                _appName;

            this.start = function (appId, appName) {

                _appId = appId;
                _appName = appName || '(Root)';

                if (appInsights && appId) {
                    appInsights.start(appId);
                }

            };

            function Insights () {

                var _logEvent = function (event, properties, property) {

                    if (appInsights && _appId) {
                        appInsights.logEvent(event, properties, property);
                    }

                },

                _logPageView = function (page) {

                    if (appInsights && _appId) {
                        appInsights.logPageView(page);
                    }

                };

                return {
                    'logEvent': _logEvent,
                    'logPageView': _logPageView,
                    'appName': _appName
                };

            }

            this.$get = function() {
                return new Insights();
            };

        })

        .run(function($rootScope, $route, $location, insights) {
            $rootScope.$on('$locationChangeSuccess', function() {

                var pagePath;
                try {
                    pagePath = $location.path().substr(1);
                    pagePath =  insights.appName + '/' + pagePath;
                }
                finally {
                    insights.logPageView(pagePath);
                }
            });
        });

}());

/*global angular: true, appInsights: true */

(function () {
    "use strict";

    angular.module('angular-appinsights', [])

        .provider('insights', function () {

            var _appId,
                _appName;

            this.start = function (appId, appName) {

                _appId = appId;
                _appName = appName || '(Application Root)';

                if (appInsights && appId) {
                    appInsights.start(appId);
                }

            };

            function Insights () {

                var _logEvent = function (event, properties, property) {

                    if (appInsights && _appId) {
                        appInsights.logEvent(event, properties, property);
                    }

                },

                _logPageView = function (page) {

                    if (appInsights && _appId) {
                        appInsights.logPageView(page);
                    }

                };

                return {
                    'logEvent': _logEvent,
                    'logPageView': _logPageView,
                    'appName': _appName
                };

            }

            this.$get = function() {
                return new Insights();
            };

        })

        .run(function($rootScope, $route, $location, insights) {
            $rootScope.$on('$locationChangeSuccess', function() {

                var pagePath;
                try {
                    pagePath = $location.path().substr(1);
                    pagePath =  insights.appName + '/' + pagePath;
                }
                finally {
                    insights.logPageView(pagePath);
                }
            });
        });

}());

Update the default application name


/**
 * @flow
 */

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
  ScrollView,
  Image,
  Alert
} from 'react-native';
import MyButton from './MyButton';

export class Game extends Component {
  static navigationOptions = {
    header: {visible: false},
  };
  constructor(props) {
    super(props)
    const {teams, game} = props.navigation.state.params;
    this.state = {
      teams: teams,
      game: game
    }
  }

  render() {
    const {players} = this.state
    const { navigate } = this.props.navigation

    return (
      <View>
        <Text>
          Game {this.state.game}: Schnick-Schnack-Schnuck
        </Text>
        <MyButton
          text={this.state.teams[0][Math.floor(Math.random()*this.state.teams[0].length)]}
          onPress={()=>console.log("blue")}
        />
        <MyButton
          text={this.state.teams[1][Math.floor(Math.random()*this.state.teams[1].length)]}
          onPress={()=>console.log("red")}
        />
      </View>
    );
  }
};

const styles = StyleSheet.create({
  title: {
    color: 'blue',
    fontSize: 22
  },
});

/**
 * @flow
 */

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
  ScrollView,
  Image,
  Alert
} from 'react-native';
import MyButton from './MyButton';

class MyText extends Component {
  render(){
    return <Text>{this.props.standing[0]} - {this.props.standing[1]}</Text>
  }
};

export class Game extends Component {
  static navigationOptions = {
    header: {visible: false},
  };
  constructor(props) {
    super(props)
    const {teams, game} = props.navigation.state.params;
    this.state = {
      teams: teams,
      game: game,
      standing: [0,0]
    }
  }

  render() {
    const {players} = this.state
    const { navigate } = this.props.navigation

    return (
      <View>
        <Text>
          Game {this.state.game}: Schnick-Schnack-Schnuck
        </Text>
        <MyText
          standing={this.state.standing}
        />
        <MyButton
          text={this.state.teams[0][Math.floor(Math.random()*this.state.teams[0].length)]}
          onPress={()=>this.setState({standing: [this.state.standing[0]+1,this.state.standing[1]]})}
        />
        <MyButton
          text={this.state.teams[1][Math.floor(Math.random()*this.state.teams[1].length)]}
          onPress={()=>this.setState({standing: [this.state.standing[0],this.state.standing[1]+1]})}
        />
      </View>
    );
  }
};

const styles = StyleSheet.create({
  title: {
    color: 'blue',
    fontSize: 22
  },
});

Update standing on button click


var express  = require('express'),
    app      = express(),
    radiodan = require('radiodan-client'),
    mdns     = require('./lib/mdns'),
    port     = process.env.PORT || 5000;

app.use('/radiodan',
  radiodan.middleware({crossOrigin: true})
);

app.listen(port);

app.use(express.static(__dirname + '/static'));

mdns.advertise(radiodan, port);

console.log('Listening on port '+port);

var express  = require('express'),
    app      = express(),
    radiodan = require('radiodan-client'),
    mdns     = require('./lib/mdns'),
    port     = process.env.PORT || 5000;

app.use('/radiodan',
  radiodan.middleware({crossOrigin: true})
);

app.listen(port);

mdns.advertise(radiodan, port);

console.log('Listening on port '+port);

Remove reference to static pages, which isn't needed any more


var graph = new Graph();

function render_part(part){ part.render();};

graph.on("add",render_part);
graph.on("change:x",render_part);
graph.on("change:y",render_part);

var menu = new GraphEdit(graph, canvas);
menu.set_edge_mode();
canvas.bind("keydown",		function() {
	var key = canvas.keyboard.getKeysDown();
		if(key == 69 ){
			 menu.set_edge_mode();
			console.log("hello");
			}
		if(key == 67 ){
			menu.set_corner_mode();
		}
		});

var graph = new Graph();

function render_part(part){ part.render();};

graph.on("add",render_part);
graph.on("change:x",render_part);
graph.on("change:y",render_part);

var menu = new GraphEdit(graph, canvas);
menu.set_corner_mode();
canvas.bind("keydown",		function() {
	var key = canvas.keyboard.getKeysDown();
		if(key == 69 ){
			 menu.set_edge_mode();
			console.log("hello");
			}
		if(key == 67 ){
			menu.set_corner_mode();
		}
		});

Set initial edit mode to corner_mode


'use strict';

import localForage from 'localforage';
import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import { persistStore } from 'redux-persist';

import routes from '../routes';

export default class Root extends Component {
  constructor() {
    super();
    this.state = { rehydrated: false };
  }

  // Moving the persistStore() call to this event handler to prevent the root
  // view from loading until after the store has been rehydrated
  componentWillMount() {
    persistStore(this.props.store, { storage: localForage }, () => {
      this.setState({ rehydrated: true });
    });
  }

  render() {
    if (!this.state.rehydrated) {
      return null;
    }

    const { history, store } = this.props;
    return (
      <Provider store={store}>
        <div>
          <Router history={history} routes={routes} />
        </div>
      </Provider>
    );
  }
}

Root.propTypes = {
  store: PropTypes.object.isRequired,
  history: PropTypes.object.isRequired
};

'use strict';

import localForage from 'localforage';
import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import { persistStore } from 'redux-persist';

import routes from '../routes';

export default class Root extends Component {
  constructor() {
    super();
    this.state = { rehydrated: false };
  }

  /* Moving the persistStore() call to this event handler to prevent the root
   * view from loading until after the store has been rehydrated
   *
   * HINT: call persistStore(...).purge() to clear all data if things get out
   * of whack
   */
  componentWillMount() {
    persistStore(this.props.store, { storage: localForage }, () => {
      this.setState({ rehydrated: true });
    });
  }

  render() {
    if (!this.state.rehydrated) {
      return null;
    }

    const { history, store } = this.props;
    return (
      <Provider store={store}>
        <div>
          <Router history={history} routes={routes} />
        </div>
      </Provider>
    );
  }
}

Root.propTypes = {
  store: PropTypes.object.isRequired,
  history: PropTypes.object.isRequired
};

Add breadcrumb comment for future debugging purposes


import RemoveModal from '~/components/RemoveModal'
import BaseModal from '~/components/BaseModal'
import { mount } from 'helper'

describe('Remove modal component', () => {
  let wrapper, baseModalWrapper
  beforeEach(() => {
    wrapper = mount(RemoveModal, {
      stubs: {
        post: true
      }
    })
    baseModalWrapper = wrapper.find(BaseModal)
  })
  describe('Emitted show event from base-modal', () => {
    beforeEach(() => {
      wrapper.setMethods({
        show: jest.fn()
      })
      const post = {}
      baseModalWrapper.vm.$emit('show', post)
    })
    test('Called show()', () => {
      expect(wrapper.vm.show).toHaveBeenCalled()
    })
    test('Shown the post', () => {
      wrapper.vm.post = {}
      expect(wrapper.find('post-stub').exists()).toBe(true)
    })
  })

  describe('Emitted hidden event from base-modal', () => {
    beforeEach(() => {
      wrapper.setMethods({
        hidden: jest.fn()
      })
      baseModalWrapper.vm.$emit('hidden')
    })

    test('Called hidden()', () => {
      expect(wrapper.vm.hidden).toHaveBeenCalled()
    })
    test('The post is hidden', () => {
      expect(wrapper.find('.list-group').exists()).toBe(false)
    })
  })
})

import RemoveModal from '~/components/RemoveModal'
import BaseModal from '~/components/BaseModal'
import { shallowMount } from 'helper'

describe('Remove modal component', () => {
  let wrapper, baseModalWrapper
  beforeEach(() => {
    wrapper = shallowMount(RemoveModal, {})
    baseModalWrapper = wrapper.find(BaseModal)
  })
  describe('Emitted show event from base-modal', () => {
    beforeEach(() => {
      wrapper.setMethods({
        show: jest.fn()
      })
      const post = {}
      baseModalWrapper.vm.$emit('show', post)
    })
    test('Called show()', () => {
      expect(wrapper.vm.show).toHaveBeenCalled()
    })
    test('Shown the post', () => {
      wrapper.vm.post = {}
      expect(wrapper.find('post-stub').exists()).toBe(true)
    })
  })

  describe('Emitted hidden event from base-modal', () => {
    beforeEach(() => {
      wrapper.setMethods({
        hidden: jest.fn()
      })
      baseModalWrapper.vm.$emit('hidden')
    })

    test('Called hidden()', () => {
      expect(wrapper.vm.hidden).toHaveBeenCalled()
    })
    test('The post is hidden', () => {
      expect(wrapper.find('.list-group').exists()).toBe(false)
    })
  })
})

Use shallowMount instead of mount


import {createStore, applyMiddleware, compose} from 'redux'
import {combineReducers} from 'redux'
import {routerReducer, routerMiddleware} from 'react-router-redux'
import thunkMiddleware from 'redux-thunk'
import makeQueryExecuter from 'src/shared/middleware/queryExecuter'
import resizeLayout from 'src/shared/middleware/resizeLayout'
import adminReducer from 'src/admin/reducers/admin'
import sharedReducers from 'src/shared/reducers'
import dataExplorerReducers from 'src/data_explorer/reducers'
import rulesReducer from 'src/kapacitor/reducers/rules'
import dashboardUI from 'src/dashboards/reducers/ui'
import persistStateEnhancer from './persistStateEnhancer'

const rootReducer = combineReducers({
  routing: routerReducer,
  ...sharedReducers,
  ...dataExplorerReducers,
  admin: adminReducer,
  rules: rulesReducer,
  dashboardUI,
})

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose

export default function configureStore(initialState, browserHistory) {
  const routingMiddleware = routerMiddleware(browserHistory)
  const createPersistentStore = composeEnhancers(
    persistStateEnhancer(),
    applyMiddleware(thunkMiddleware, routingMiddleware, makeQueryExecuter(), resizeLayout),
  )(createStore)

  // https://github.com/elgerlambert/redux-localstorage/issues/42
  // createPersistantStore should ONLY take reducer and initialState
  // any store enhancers must be added to the compose() function.
  return createPersistentStore(
    rootReducer,
    initialState,
  )
}

import {createStore, applyMiddleware, compose} from 'redux'
import {combineReducers} from 'redux'
import {routerReducer, routerMiddleware} from 'react-router-redux'
import thunkMiddleware from 'redux-thunk'
import makeQueryExecuter from 'src/shared/middleware/queryExecuter'
import resizeLayout from 'src/shared/middleware/resizeLayout'
import adminReducer from 'src/admin/reducers/admin'
import sharedReducers from 'src/shared/reducers'
import dataExplorerReducers from 'src/data_explorer/reducers'
import rulesReducer from 'src/kapacitor/reducers/rules'
import dashboardUI from 'src/dashboards/reducers/ui'
import persistStateEnhancer from './persistStateEnhancer'

const rootReducer = combineReducers({
  ...sharedReducers,
  ...dataExplorerReducers,
  admin: adminReducer,
  rules: rulesReducer,
  dashboardUI,
  routing: routerReducer,
})

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose

export default function configureStore(initialState, browserHistory) {
  const routingMiddleware = routerMiddleware(browserHistory)
  const createPersistentStore = composeEnhancers(
    persistStateEnhancer(),
    applyMiddleware(thunkMiddleware, routingMiddleware, makeQueryExecuter(), resizeLayout),
  )(createStore)

  // https://github.com/elgerlambert/redux-localstorage/issues/42
  // createPersistantStore should ONLY take reducer and initialState
  // any store enhancers must be added to the compose() function.
  return createPersistentStore(
    rootReducer,
    initialState,
  )
}

Move routing reducer last in redux store


export const getActionPayload = action =>
  action.payload === undefined ? action : action.payload;

export const isRequestAction = action => {
  const actionPayload = getActionPayload(action);
  return (
    !!actionPayload.request &&
    !actionPayload.response &&
    !(actionPayload instanceof Error)
  );
};

export const mapRequest = (request, callback) =>
  Array.isArray(request) ? request.map(callback) : callback(request);

export const getActionPayload = action =>
  action.payload === undefined ? action : action.payload;

export const isRequestAction = action => {
  const actionPayload = getActionPayload(action);
  return (
    !!actionPayload &&
    !!actionPayload.request &&
    !actionPayload.response &&
    !(actionPayload instanceof Error)
  );
};

export const mapRequest = (request, callback) =>
  Array.isArray(request) ? request.map(callback) : callback(request);

Fix fail when some action has a null payload