<commit_before>$(function() {
  var springfox = {
    "baseUrl": function() {
      var urlMatches = /(.*)\/swagger-ui.html.*/.exec(window.location.href);
      return urlMatches[1];
    },
    "securityConfig": function(cb) {
      $.getJSON(this.baseUrl() + "/configuration/security", function(data) {
        cb(data);
      });
    },
    "uiConfig": function(cb) {
      $.getJSON(this.baseUrl() + "/configuration/ui", function(data) {
        cb(data);
      });
    }
  };
  window.springfox = springfox;
  window.oAuthRedirectUrl = springfox.baseUrl() + '/webjars/springfox-swagger-ui/o2c.html';

  window.springfox.uiConfig(function(data) {
    window.swaggerUi = new SwaggerUi({
      dom_id: "swagger-ui-container",
      validatorUrl: data.validatorUrl,
      supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
      onComplete: function(swaggerApi, swaggerUi) {

        initializeSpringfox();

        if (window.SwaggerTranslator) {
          window.SwaggerTranslator.translate();
        }

        $('pre code').each(function(i, e) {
          hljs.highlightBlock(e)
        });

      },
      onFailure: function(data) {
        log("Unable to Load SwaggerUI");
      },
      docExpansion: data.docExpansion || 'none',
      jsonEditor: data.jsonEditor || false,
      apisSorter: data.apisSorter || 'alpha',
      defaultModelRendering: data.defaultModelRendering || 'schema',
      showRequestHeaders: data.showRequestHeaders || true
    });

    initializeBaseUrl();

    function addApiKeyAuthorization() {
      var key = encodeURIComponent($('#input_apiKey')[0].value);
      if (key && key.trim() != "") {
        var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization(window.apiKeyName, key, window.apiKeyVehicle);
        window.swaggerUi.api.clientAuthorizations.add(window.apiKeyName, apiKeyAuth);
        log("added key " + key);
      }
    }

    $('#input_apiKey').change(addApiKeyAuthorization);

    function log() {
      if ('console' in window) {
        console.log.apply(console, arguments);
      }
    }

    function oAuthIsDefined(security) {
      return security.clientId
          && security.clientSecret
          && security.appName
          && security.realm;
    }

    function initializeSpringfox() {
      var security = {};
      window.springfox.securityConfig(function(data) {
        security = data;
        window.apiKeyVehicle = security.apiKeyVehicle || 'query';
        window.apiKeyName = security.apiKeyName || 'api_key';
        if (security.apiKey) {
          $('#input_apiKey').val(security.apiKey);
          addApiKeyAuthorization();
        }
        if (typeof initOAuth == "function" && oAuthIsDefined(security)) {
          initOAuth(security);
        }
      });
    }
  });

  $('#select_baseUrl').change(function() {
    window.swaggerUi.headerView.trigger('update-swagger-ui', {
      url: $('#select_baseUrl').val()
    });
  });

  function maybePrefix(location, withRelativePath) {
    var pat = /^https?:\/\//i;
    if (pat.test(location)) {
      return location;
    }
    return withRelativePath + location;
  }

  function initializeBaseUrl() {
    var relativeLocation = springfox.baseUrl();

    $('#input_baseUrl').hide();

    $.getJSON(relativeLocation + "/swagger-resources", function(data) {

      var $urlDropdown = $('#select_baseUrl');
      $urlDropdown.empty();
      $.each(data, function(i, resource) {
        var option = $('<option></option>')
            .attr("value", maybePrefix(resource.location, relativeLocation))
            .text(resource.name + " (" + resource.location + ")");
        $urlDropdown.append(option);
      });
      $urlDropdown.change();
    });

  }

});

<commit_msg>Fixed the urls for security and ui configuration<commit_after>$(function() {
  var springfox = {
    "baseUrl": function() {
      var urlMatches = /(.*)\/swagger-ui.html.*/.exec(window.location.href);
      return urlMatches[1];
    },
    "securityConfig": function(cb) {
      $.getJSON(this.baseUrl() + "/swagger-resources/configuration/security", function(data) {
        cb(data);
      });
    },
    "uiConfig": function(cb) {
      $.getJSON(this.baseUrl() + "/swagger-resources/configuration/ui", function(data) {
        cb(data);
      });
    }
  };
  window.springfox = springfox;
  window.oAuthRedirectUrl = springfox.baseUrl() + '/webjars/springfox-swagger-ui/o2c.html';

  window.springfox.uiConfig(function(data) {
    window.swaggerUi = new SwaggerUi({
      dom_id: "swagger-ui-container",
      validatorUrl: data.validatorUrl,
      supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
      onComplete: function(swaggerApi, swaggerUi) {

        initializeSpringfox();

        if (window.SwaggerTranslator) {
          window.SwaggerTranslator.translate();
        }

        $('pre code').each(function(i, e) {
          hljs.highlightBlock(e)
        });

      },
      onFailure: function(data) {
        log("Unable to Load SwaggerUI");
      },
      docExpansion: data.docExpansion || 'none',
      jsonEditor: data.jsonEditor || false,
      apisSorter: data.apisSorter || 'alpha',
      defaultModelRendering: data.defaultModelRendering || 'schema',
      showRequestHeaders: data.showRequestHeaders || true
    });

    initializeBaseUrl();

    function addApiKeyAuthorization() {
      var key = encodeURIComponent($('#input_apiKey')[0].value);
      if (key && key.trim() != "") {
        var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization(window.apiKeyName, key, window.apiKeyVehicle);
        window.swaggerUi.api.clientAuthorizations.add(window.apiKeyName, apiKeyAuth);
        log("added key " + key);
      }
    }

    $('#input_apiKey').change(addApiKeyAuthorization);

    function log() {
      if ('console' in window) {
        console.log.apply(console, arguments);
      }
    }

    function oAuthIsDefined(security) {
      return security.clientId
          && security.clientSecret
          && security.appName
          && security.realm;
    }

    function initializeSpringfox() {
      var security = {};
      window.springfox.securityConfig(function(data) {
        security = data;
        window.apiKeyVehicle = security.apiKeyVehicle || 'query';
        window.apiKeyName = security.apiKeyName || 'api_key';
        if (security.apiKey) {
          $('#input_apiKey').val(security.apiKey);
          addApiKeyAuthorization();
        }
        if (typeof initOAuth == "function" && oAuthIsDefined(security)) {
          initOAuth(security);
        }
      });
    }
  });

  $('#select_baseUrl').change(function() {
    window.swaggerUi.headerView.trigger('update-swagger-ui', {
      url: $('#select_baseUrl').val()
    });
  });

  function maybePrefix(location, withRelativePath) {
    var pat = /^https?:\/\//i;
    if (pat.test(location)) {
      return location;
    }
    return withRelativePath + location;
  }

  function initializeBaseUrl() {
    var relativeLocation = springfox.baseUrl();

    $('#input_baseUrl').hide();

    $.getJSON(relativeLocation + "/swagger-resources", function(data) {

      var $urlDropdown = $('#select_baseUrl');
      $urlDropdown.empty();
      $.each(data, function(i, resource) {
        var option = $('<option></option>')
            .attr("value", maybePrefix(resource.location, relativeLocation))
            .text(resource.name + " (" + resource.location + ")");
        $urlDropdown.append(option);
      });
      $urlDropdown.change();
    });

  }

});

<|endoftext|>


<commit_before>var logger = require(LIBS_DIR + '/logger');

var Command = require('./controls/command').Command;
var Action = require('./controls/action').Action;

//trim some strings
if (!String.prototype.trim) {
	String.prototype.trim = function() {
		return this.replace(/^\s+|\s+$/g, '');
	};
}

function Controls(irc, actions, commands) {
	this._irc = irc;
	this.actions = actions;
	this.commands = commands;
	this.commandDelimiter = '.';
}

Controls.prototype.add = function(ca) {
	if (ca instanceof Command) {
		if (typeof this.commands[ca.name] !== 'undefined') {
			throw new Error('Defined command \'' + ca.name + '\' already exists!');
		}
		this.commands[ca.name] = ca;
	} else if (ca instanceof Action) {
		if (typeof this.actions[ca.name] !== 'undefined') {
			throw new Error('Defined action \'' + ca.name + '\' already exists!');
		}
		this.actions[ca.name] = ca;
	} else {
		throw new Error('Unknown control type!');
	}

	return this;
};

Controls.prototype.remove = function(ca) {
	if (ca instanceof Command) {
		if (typeof this.commands[ca.name] === 'undefined') {
			throw new Error('Command \'' + ca.name + '\' does not exists!');
		}
		delete this.commands[ca.name];
	} else if (ca instanceof Action) {
		if (typeof this.actions[ca.name] === 'undefined') {
			throw new Error('Action \'' + ca.name + '\' does not exists!');
		}
		delete this.actions[ca.name];
	} else {
		throw new Error('Unknown control type!');
	}

	return this;
};

Controls.prototype.addCommand = function(name, action) {
	return this.add(new Command(name, action));
};

Controls.prototype.addAction = function(name, action, regexp) {
	return this.add(new Action(name, action, regexp));
};

Controls.prototype.removeCommand = function(name) {
	if (typeof this.commands[name] !== 'undefined') {
		this.remove(this.commands[name]);
	} else {
		throw new Error('Command \'' + name + '\' does not exists!');
	}
	return this;
};

Controls.prototype.removeAction = function(name) {
	if (typeof this.actions[name] !== 'undefined') {
		this.remove(this.actions[name]);
	} else {
		throw new Error('Action \'' + name + '\' does not exists!');
	}
	return this;
};

Controls.prototype.removeActions = function(list) {
	if (!(list instanceof Array)) {
		throw new Error('You need to pass Array as first argument!');
	}
	list.forEach(function(name) {
		this.removeAction(name);
	}, this);
	return this;
};

Controls.prototype.removeCommands = function(list) {
	if (!(list instanceof Array)) {
		throw new Error('You need to pass Array as first argument!');
	}
	list.forEach(function(name) {
		this.removeCommand(name);
	}, this);
	return this;
};

Controls.prototype.parse = function(source, text) {
	if (typeof text !== 'string' || text.length <= 0) return;

	if (!source.channel) { //itz direct message
		this.processAction(source, text.trim());
	} else if (source.channel && text.substr(0, this.commandDelimiter.length) === this.commandDelimiter) { //itz command in channel
		//remove the delimiter
		text = text.substr(this.commandDelimiter.length);

		this.processCommand(source, text.trim());
	} else if (text.substr(0, this._irc.currentNick.length + 1).search(new RegExp(this._irc.currentNick + '[ ,;:]')) !== -1) { //itz higlight in channel
		//remove the trigger
		text = text.substr(this._irc.currentNick.length + 1);

		this.processAction(source, text.trim());
	}
};

Controls.prototype.processCommand = function(source, text) {
	var args = text.match(/[^\s\"\']+|\"([^\"]*)\"|\'([^\']*)\'/g).map(function(v) {
		return v.replace(/\"|\'/g, '');
	});
	var command = args.shift();
	//execute the command
	Object.keys(this.commands).some(function(name) {
		if (command == this.commands[name].name) { //use == to not check type
			logger.debug('Processing Command \'' + name + '\'');
			this.commands[name].action(source, args, text);
			return true;
		}
		return false;
	}, this);
};

Controls.prototype.processAction = function(source, text) {
	//proces all actions that triggers rule
	Object.keys(this.actions).forEach(function(name) {
		var args = text.match(this.actions[name].rule);
		if (args !== null) {
			logger.debug('Processing Action \'' + name + '\'');
			this.actions[name].action(source, args, text);
		}
	}, this);
};

module.exports.init = function(reload) {
	if (!reload) {
		this.actions = {};
		this.commands = {};
	}

	this.controls = new Controls(this.require('irc'), this.actions, this.commands);

	if (typeof this.config.commandDelimiter === 'string') {
		this.controls.commandDelimiter = this.config.commandDelimiter;
	}

	var module = this;

	if (!reload) {
		Object.defineProperty(this, 'commandDelimiter', {
			enumerable: true,
			get: function() {
				return module.controls.commandDelimiter;
			}
		});
	}

	//export some functions from Controls
	require(LIBS_DIR + '/helpers').export(this, this.controls, ['addCommand', 'addAction', 'removeCommand', 'removeAction', 'removeCommands', 'removeActions']);

	//bind
	this.dispatcher.on('irc/PRIVMSG', this.controls.parse.bind(this.controls)).on('irc/NOTICE', this.controls.parse.bind(this.controls));
};<commit_msg>simplify this<commit_after>var logger = require(LIBS_DIR + '/logger');

var Command = require('./controls/command').Command;
var Action = require('./controls/action').Action;

//trim some strings
if (!String.prototype.trim) {
	String.prototype.trim = function() {
		return this.replace(/^\s+|\s+$/g, '');
	};
}

function Controls(irc, actions, commands) {
	this._irc = irc;
	this.actions = actions;
	this.commands = commands;
	this.commandDelimiter = '.';
}

Controls.prototype.addCommand = function(name, action, access) {
	name = name.replace(/[^a-zA-Z0-9_\-]+/g, '');
	if (typeof this.commands[name] !== 'undefined') {
		throw new Error('Defined command \'' + name + '\' already exists!');
	}
	this.commands[name] = new Command(name, action, access);
	return this;
};

Controls.prototype.addAction = function(name, action, regexp, access) {
	name = name.replace(/[^a-zA-Z0-9_\-]+/g, '');
	if (typeof this.actions[name] !== 'undefined') {
		throw new Error('Defined action \'' + name + '\' already exists!');
	}
	this.actions[name] = new Action(name, action, regexp, access);
	return this;
};

Controls.prototype.removeCommand = function(name) {
	name = name.replace(/[^a-zA-Z0-9_\-]+/g, '');
	if (typeof this.commands[name] !== 'undefined') {
		delete this.commands[name];
	} else {
		throw new Error('Command \'' + name + '\' does not exists!');
	}
	return this;
};

Controls.prototype.removeAction = function(name) {
	name = name.replace(/[^a-zA-Z0-9_\-]+/g, '');
	if (typeof this.actions[name] !== 'undefined') {
		delete this.actions[name];
	} else {
		throw new Error('Action \'' + name + '\' does not exists!');
	}
	return this;
};

Controls.prototype.removeActions = function(list) {
	if (!(list instanceof Array)) {
		throw new Error('You need to pass Array as first argument!');
	}
	list.forEach(function(name) {
		this.removeAction(name);
	}, this);
	return this;
};

Controls.prototype.removeCommands = function(list) {
	if (!(list instanceof Array)) {
		throw new Error('You need to pass Array as first argument!');
	}
	list.forEach(function(name) {
		this.removeCommand(name);
	}, this);
	return this;
};

Controls.prototype.parse = function(source, text) {
	if (typeof text !== 'string' || text.length <= 0) return;

	if (!source.channel) { //itz direct message
		this.processAction(source, text.trim());
	} else if (source.channel && text.substr(0, this.commandDelimiter.length) === this.commandDelimiter) { //itz command in channel
		//remove the delimiter
		text = text.substr(this.commandDelimiter.length);

		this.processCommand(source, text.trim());
	} else if (text.substr(0, this._irc.currentNick.length + 1).search(new RegExp(this._irc.currentNick + '[ ,;:]')) !== -1) { //itz higlight in channel
		//remove the trigger
		text = text.substr(this._irc.currentNick.length + 1);

		this.processAction(source, text.trim());
	}
};

Controls.prototype.processCommand = function(source, text) {
	var args = text.match(/[^\s\"\']+|\"([^\"]*)\"|\'([^\']*)\'/g).map(function(v) {
		return v.replace(/\"|\'/g, '');
	});
	var command = args.shift();
	//execute the command
	Object.keys(this.commands).some(function(name) {
		if (command == this.commands[name].name) { //use == to not check type
			logger.debug('Processing Command \'' + name + '\'');
			this.commands[name].action(source, args, text);
			return true;
		}
		return false;
	}, this);
};

Controls.prototype.processAction = function(source, text) {
	//proces all actions that triggers rule
	Object.keys(this.actions).forEach(function(name) {
		var args = text.match(this.actions[name].rule);
		if (args !== null) {
			logger.debug('Processing Action \'' + name + '\'');
			this.actions[name].action(source, args, text);
		}
	}, this);
};

module.exports.init = function(reload) {
	if (!reload) {
		this.actions = {};
		this.commands = {};
	}

	this.controls = new Controls(this.require('irc'), this.actions, this.commands);

	if (typeof this.config.commandDelimiter === 'string') {
		this.controls.commandDelimiter = this.config.commandDelimiter;
	}

	var module = this;

	if (!reload) {
		Object.defineProperty(this, 'commandDelimiter', {
			enumerable: true,
			get: function() {
				return module.controls.commandDelimiter;
			}
		});
	}

	//export some functions from Controls
	require(LIBS_DIR + '/helpers').export(this, this.controls, ['addCommand', 'addAction', 'removeCommand', 'removeAction', 'removeCommands', 'removeActions']);

	//bind
	this.dispatcher.on('irc/PRIVMSG', this.controls.parse.bind(this.controls)).on('irc/NOTICE', this.controls.parse.bind(this.controls));
};<|endoftext|>


<commit_before>/*******************************
          Build Task
*******************************/

var
  gulp         = require('gulp-help')(require('gulp')),

  // config
  config       = require('./config/user'),
  runSequence  = require('run-sequence'),
  install      = require('./config/project/install')
;

// add sub-tasks
if(config.rtl) {
  require('./collections/rtl')(gulp);
}
require('./collections/build')(gulp);

module.exports = function(callback) {

  console.info('Building Semantic');

  if( !install.isSetup() ) {
    console.error('Cannot find semantic.json. Run "gulp install" to set-up Semantic');
    return;
  }

  var tasks = [];

  // check for right-to-left (RTL) language
  if(config.rtl == 'both') {
    tasks.push('build-rtl');
  }
  if(config.rtl === true || config.rtl === 'Yes') {
    gulp.start('build-rtl');
    return;
  }

  tasks.push('build-javascript');
  tasks.push('build-css');
  tasks.push('build-assets');

  runSequence(tasks, callback);
};
<commit_msg>Revert "Fix callback return from build task"<commit_after>/*******************************
          Build Task
*******************************/

var
  gulp         = require('gulp-help')(require('gulp')),

  // config
  config       = require('./config/user'),
  install      = require('./config/project/install')
;

// add sub-tasks
if(config.rtl) {
  require('./collections/rtl')(gulp);
}
require('./collections/build')(gulp);

module.exports = function(callback) {

  console.info('Building Semantic');

  if( !install.isSetup() ) {
    console.error('Cannot find semantic.json. Run "gulp install" to set-up Semantic');
    return;
  }

  // check for right-to-left (RTL) language
  if(config.rtl == 'both') {
    gulp.start('build-rtl');
  }
  if(config.rtl === true || config.rtl === 'Yes') {
    gulp.start('build-rtl');
    return;
  }

  gulp.start('build-javascript');
  gulp.start('build-css');
  gulp.start('build-assets');

};
<|endoftext|>


<commit_before>'use strict';

var coveralls = require('coveralls');
var fs = require('fs');
var grunt = require('grunt');
var sinon = require('sinon');

function runGruntTask(taskName, callback) {
    var task = grunt.task._taskPlusArgs(taskName);
    task.task.fn.apply({
        nameArgs: task.nameArgs,
        name: task.task.name,
        args: task.args,
        flags: task.flags,
        async: function() { return callback; }
    }, task.args);
}

exports.coveralls = {
    setUp: function (callback) {
        sinon.stub(coveralls, 'handleInput').callsArgWith(1, null);
        sinon.spy(fs, 'readFile');
        callback();
    },

    tearDown: function (callback) {
        fs.readFile.restore();
        coveralls.handleInput.restore();
        callback();
    },

    submits_file_to_coveralls: function (test) {
        var handleStub = coveralls.handleInput;

        runGruntTask('coveralls:basic_test', function (result) {
            test.ok(result, 'Should be successful');

            test.ok(handleStub.calledOnce);
            test.equal(handleStub.getCall(0).args[0], 'lcov.info content', 'Should send lcov data');
            test.done();
        });
    },

    submits_nothing_if_the_file_is_missing: function (test) {
        runGruntTask('coveralls:missing_file_test', function (result) {
            test.ok(!result, 'Should fail');

            test.ok(!coveralls.handleInput.called);
            test.done();
        });
    },

    submits_multiple_files: function (test) {
        var handleStub = coveralls.handleInput;

        runGruntTask('coveralls:multiple_files_test', function (result) {
            test.ok(result, 'Should be successful');

            test.ok(handleStub.calledTwice);
            test.equal(handleStub.getCall(0).args[0], 'lcov.info content', 'Should send first file data');
            test.equal(handleStub.getCall(1).args[0], 'lcov2.info content', 'Should send second file data');
            test.done();
        });
    },

    submits_present_files_only_if_some_are_missing: function (test) {
        var handleStub = coveralls.handleInput;

        runGruntTask('coveralls:some_missing_files_test', function (result) {
            test.ok(result, 'Should be successful');

            test.ok(handleStub.calledOnce);
            test.equal(handleStub.getCall(0).args[0], 'lcov.info content', 'Should send first file data');
            test.done();
        });
    },

    fails_if_multiple_files_listed_and_all_files_are_missing: function (test) {
        runGruntTask('coveralls:all_missing_files_test', function (result) {
            test.ok(!result, 'Should fail');

            test.ok(!coveralls.handleInput.called);
            test.done();
        });
    },

    fails_if_file_is_not_readable: function (test) {
        fs.readFile.restore();
        var readStub = sinon.stub(fs, 'readFile').callsArgWith(2, 'Error');

        runGruntTask('coveralls:basic_test', function (result) {
            test.ok(!result, 'Should fail');

            test.ok(readStub.calledOnce);
            test.done();
        });
    },

    fails_if_any_files_fail_to_upload: function (test) {
        coveralls.handleInput.restore();
        var handleStub = sinon.stub(coveralls, 'handleInput').callsArgWith(1, 'Error');

        runGruntTask('coveralls:basic_test', function (result) {
            test.ok(!result, 'Should fail');

            test.ok(handleStub.calledOnce);
            test.done();
        });
    },

    warn_mode_doenst_print_grunt_error: function (test) {
        coveralls.handleInput.restore();
        var handleStub = sinon.stub(coveralls, 'handleInput').callsArgWith(1, 'Error');

        runGruntTask('coveralls:basic_test_warn', function (result) {
            test.ok(result, 'Should not fail when options.warn === true');

            test.ok(handleStub.calledOnce);
            test.done();
        });
    }
};
<commit_msg>Tidy up test code for clarity<commit_after>'use strict';

var coveralls = require('coveralls');
var fs = require('fs');
var grunt = require('grunt');
var sinon = require('sinon');

function runGruntTask(taskName, callback) {
    var task = grunt.task._taskPlusArgs(taskName);
    task.task.fn.apply({
        nameArgs: task.nameArgs,
        name: task.task.name,
        args: task.args,
        flags: task.flags,
        async: function() { return callback; }
    }, task.args);
}

function givenCoverallsWillFail() {
    coveralls.handleInput.restore();
    sinon.stub(coveralls, 'handleInput').callsArgWith(1, 'Error');
}

function givenFileReadsWillFail() {
    fs.readFile.restore();
    sinon.stub(fs, 'readFile').callsArgWith(2, 'Error');
}

exports.coveralls = {
    setUp: function (callback) {
        sinon.stub(coveralls, 'handleInput').callsArgWith(1, null);
        sinon.spy(fs, 'readFile');
        callback();
    },

    tearDown: function (callback) {
        fs.readFile.restore();
        coveralls.handleInput.restore();
        callback();
    },

    submits_file_to_coveralls: function (test) {
        var handleStub = coveralls.handleInput;

        runGruntTask('coveralls:basic_test', function (result) {
            test.ok(result, 'Should be successful');

            test.ok(handleStub.calledOnce);
            test.equal(handleStub.getCall(0).args[0], 'lcov.info content', 'Should send lcov data');
            test.done();
        });
    },

    submits_nothing_if_the_file_is_missing: function (test) {
        runGruntTask('coveralls:missing_file_test', function (result) {
            test.ok(!result, 'Should fail');

            test.ok(!coveralls.handleInput.called);
            test.done();
        });
    },

    submits_multiple_files: function (test) {
        runGruntTask('coveralls:multiple_files_test', function (result) {
            test.ok(result, 'Should be successful');

            test.ok(coveralls.handleInput.calledTwice);
            sinon.assert.calledWith(coveralls.handleInput, 'lcov.info content');
            sinon.assert.calledWith(coveralls.handleInput, 'lcov2.info content');
            test.done();
        });
    },

    submits_present_files_only_if_some_are_missing: function (test) {
        runGruntTask('coveralls:some_missing_files_test', function (result) {
            test.ok(result, 'Should be successful');

            test.ok(coveralls.handleInput.calledOnce);
            sinon.assert.calledWith(coveralls.handleInput, 'lcov.info content');
            test.done();
        });
    },

    fails_if_multiple_files_listed_and_all_files_are_missing: function (test) {
        runGruntTask('coveralls:all_missing_files_test', function (result) {
            test.ok(!result, 'Should fail');

            test.ok(!coveralls.handleInput.called);
            test.done();
        });
    },

    fails_if_file_is_not_readable: function (test) {
        givenFileReadsWillFail();

        runGruntTask('coveralls:basic_test', function (result) {
            test.ok(!result, 'Should fail');

            test.ok(fs.readFile.calledOnce);
            test.done();
        });
    },

    fails_if_any_files_fail_to_upload: function (test) {
        givenCoverallsWillFail();

        runGruntTask('coveralls:basic_test', function (result) {
            test.ok(!result, 'Should fail');

            test.ok(coveralls.handleInput.calledOnce);
            test.done();
        });
    },

    warn_mode_doenst_print_grunt_error: function (test) {
        coveralls.handleInput.restore();
        var handleStub = sinon.stub(coveralls, 'handleInput').callsArgWith(1, 'Error');

        runGruntTask('coveralls:basic_test_warn', function (result) {
            test.ok(result, 'Should not fail when options.warn === true');

            test.ok(handleStub.calledOnce);
            test.done();
        });
    }
};
<|endoftext|>


<commit_before>

module.exports = {
	parseInt: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
	},
	parseFloat: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
	},
	'Math.round': {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
	},
	'Math.max': {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
	},

};

<commit_msg>added infor for Math static functions<commit_after>

function standardMath() {
	return {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	};
}

function constant(val) {
	return {
		type: 'number',
		value: val,
	};
}

module.exports = {
	eval: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	uneval: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	isFinite: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	isNaN: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	parseFloat: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	parseInt: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	decodeURI: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	decodeURIComponent: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	encodeURI: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	encodeURIComponent: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	escape: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},
	unescape: {
		throwsExceptions: false,
		canReturn: ['number', 'NaN', 'Infinity'],
		synchronous: true,
		type: 'function',
	},

	'Math.abs': standardMath(),
	'Math.acos': standardMath(),
	'Math.acosh': standardMath(),
	'Math.asin': standardMath(),
	'Math.asinh': standardMath(),
	'Math.atan': standardMath(),
	'Math.atan2': standardMath(),
	'Math.atanh': standardMath(),
	'Math.cbrt': standardMath(),
	'Math.ceil': standardMath(),
	'Math.clz32': standardMath(),
	'Math.cos': standardMath(),
	'Math.exp': standardMath(),
	'Math.expm1': standardMath(),
	'Math.floor': standardMath(),
	'Math.fround': standardMath(),
	'Math.hypot': standardMath(),
	'Math.imul': standardMath(),
	'Math.log': standardMath(),
	'Math.log10': standardMath(),
	'Math.log1p': standardMath(),
	'Math.log2': standardMath(),
	'Math.max': standardMath(),
	'Math.min': standardMath(),
	'Math.pow': standardMath(),
	'Math.random': standardMath(),
	'Math.round': standardMath(),
	'Math.sign': standardMath(),
	'Math.sin': standardMath(),
	'Math.sinh': standardMath(),
	'Math.sqrt': standardMath(),
	'Math.tan': standardMath(),
	'Math.tanh': standardMath(),
	'Math.trunc': standardMath(),

	'Math.E': constant(Math.E),
	'Math.LN10': constant(Math.LN10),
	'Math.LN2': constant(Math.LN2),
	'Math.LOG10E': constant(Math.LOG10E),
	'Math.LOG2E': constant(Math.LOG2E),
	'Math.PI': constant(Math.PI),
	'Math.SQRT1_2': constant(Math.SQRT1_2),
	'Math.SQRT2': constant(Math.SQRT2),

};

<|endoftext|>


<commit_before>// @flow
import * as React from 'react'
import {StyleSheet, Platform} from 'react-native'
import Icon from 'react-native-vector-icons/Ionicons'

const styles = StyleSheet.create({
	icon: {
		fontSize: Platform.select({
			ios: 30,
			android: 24,
		}),
	},
})

type Props = {
	tintColor: string,
	focused: boolean,
}

export const TabBarIcon = (icon: string) => ({tintColor}: Props) => (
	<Icon name={`ios-${icon}`} style={[styles.icon, {color: tintColor}]} />
)
<commit_msg>navigation-tabs: Add platformPrefixIcon helper<commit_after>// @flow
import * as React from 'react'
import {StyleSheet, Platform} from 'react-native'
import Icon from 'react-native-vector-icons/Ionicons'

const styles = StyleSheet.create({
	icon: {
		fontSize: Platform.select({
			ios: 30,
			android: 24,
		}),
	},
})

type Props = {
	tintColor: string,
	focused: boolean,
}

export const platformPrefixIcon = (name: string) => {
	return Platform.OS === 'ios' ? `ios-${name}` : `md-${name}`
}

export const TabBarIcon = (icon: string) => ({tintColor}: Props) => (
	<Icon name={`ios-${icon}`} style={[styles.icon, {color: tintColor}]} />
)
<|endoftext|>


<commit_before>"use strict";

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

var async = require('async');
var chalk = require('chalk');
var filesize = require('filesize');
var Optimizer = require('./lib/optimizer');

module.exports = function (grunt) {
  grunt.registerMultiTask('image', 'Optimize PNG, JPEG, GIF images.', function() {
    var done = this.async();
    var options = this.options({
      progressive: true,
      interlace: true
    });

    async.eachLimit(this.files, 10, function (file, next) {
      var basename = path.basename(file.dest);
      var dir = file.dest.replace(basename, '');

      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir);
      }

      var optimizer = new Optimizer({
        src: file.src[0],
        dest: file.dest,
        options: options
      });

      optimizer.optimize(function (error, data) {
        if (error) {
          grunt.warn(error);
          return next(error);
        }
        grunt.log.writeln(
          chalk.green('✔ ') + file.src[0] + chalk.gray(' ->') +
          chalk.gray(' before=') + chalk.yellow(filesize(data.original)) +
          chalk.gray(' after=') + chalk.cyan(filesize(data.optimized)) +
          chalk.gray(' reduced=') + chalk.green.underline(filesize(data.diff) + '(' + data.diffPercent + '%)')
        );
        next();
      });
    }, function (error) {
      if (error) {
        grunt.warn(error);
        return done(error);
      }
      done();
    });
  });
};
<commit_msg>fix option<commit_after>"use strict";

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

var async = require('async');
var chalk = require('chalk');
var filesize = require('filesize');
var Optimizer = require('./lib/optimizer');

module.exports = function (grunt) {
  grunt.registerMultiTask('image', 'Optimize PNG, JPEG, GIF images.', function() {
    var done = this.async();
    var options = this.options({});

    async.eachLimit(this.files, 10, function (file, next) {
      var basename = path.basename(file.dest);
      var dir = file.dest.replace(basename, '');

      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir);
      }

      var optimizer = new Optimizer({
        src: file.src[0],
        dest: file.dest,
        options: options
      });

      optimizer.optimize(function (error, data) {
        if (error) {
          grunt.warn(error);
          return next(error);
        }
        grunt.log.writeln(
          chalk.green('✔ ') + file.src[0] + chalk.gray(' ->') +
          chalk.gray(' before=') + chalk.yellow(filesize(data.original)) +
          chalk.gray(' after=') + chalk.cyan(filesize(data.optimized)) +
          chalk.gray(' reduced=') + chalk.green.underline(filesize(data.diff) + '(' + data.diffPercent + '%)')
        );
        next();
      });
    }, function (error) {
      if (error) {
        grunt.warn(error);
        return done(error);
      }
      done();
    });
  });
};
<|endoftext|>


<commit_before>/**
 * This module defines the p5.Texture class
 * @module Lights, Camera
 * @submodule Material
 * @for p5
 * @requires core
 */

'use strict';

var p5 = require('../core/core');
var constants = require('../core/constants');

/**
 * Texture class for WEBGL Mode
 * @private
 * @class p5.Texture
 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that
 * will provide the GL context for this new p5.Texture
 * @param {p5.Image|p5.Graphics|p5.Element|p5.MediaElement} [obj] the
 * object containing the image data to store in the texture.
 */
p5.Texture = function(renderer, obj) {
  this._renderer = renderer;

  var gl = this._renderer.GL;

  this.src = obj;
  this.glTex = undefined;
  this.glTarget = gl.TEXTURE_2D;
  this.glFormat = gl.RGBA;
  this.mipmaps = false;
  this.glMinFilter = gl.LINEAR;
  this.glMagFilter = gl.LINEAR;
  this.glWrapS = gl.CLAMP_TO_EDGE;
  this.glWrapT = gl.CLAMP_TO_EDGE;

  // used to determine if this texture might need constant updating
  // because it is a video or gif.
  this.isSrcMediaElement =
    typeof p5.MediaElement !== 'undefined' && obj instanceof p5.MediaElement;
  this._videoPrevUpdateTime = 0;
  this.isSrcHTMLElement =
    typeof p5.Element !== 'undefined' &&
    obj instanceof p5.Element &&
    !(obj instanceof p5.Graphics);
  this.isSrcP5Image = obj instanceof p5.Image;
  this.isSrcP5Graphics = obj instanceof p5.Graphics;

  var textureData = this._getTextureDataFromSource();
  this.width = textureData.width;
  this.height = textureData.height;

  this.init(textureData);
  return this;
};

p5.Texture.prototype._getTextureDataFromSource = function() {
  var textureData;
  if (this.isSrcP5Image) {
    // param is a p5.Image
    textureData = this.src.canvas;
  } else if (
    this.isSrcMediaElement ||
    this.isSrcP5Graphics ||
    this.isSrcHTMLElement
  ) {
    // if param is a video HTML element
    textureData = this.src.elt;
  }
  return textureData;
};

/**
 * Initializes common texture parameters, creates a gl texture,
 * tries to upload the texture for the first time if data is
 * already available.
 * @private
 * @method init
 */
p5.Texture.prototype.init = function(data) {
  var gl = this._renderer.GL;
  this.glTex = gl.createTexture();
  this.bindTexture();

  //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.glWrapS);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.glWrapT);

  if (
    this.width === 0 ||
    this.height === 0 ||
    (this.isSrcMediaElement && !this.src.loadedmetadata)
  ) {
    // assign a 1x1 empty texture initially, because data is not yet ready,
    // so that no errors occur in gl console!
    var tmpdata = new Uint8Array([1, 1, 1, 1]);
    gl.texImage2D(
      this.glTarget,
      0,
      gl.RGBA,
      1,
      1,
      0,
      this.glFormat,
      gl.UNSIGNED_BYTE,
      tmpdata
    );
  } else {
    // data is ready: just push the texture!
    gl.texImage2D(
      this.glTarget,
      0,
      this.glFormat,
      this.glFormat,
      gl.UNSIGNED_BYTE,
      data
    );
  }
};

/**
 * Checks if the source data for this texture has changed (if it's
 * easy to do so) and reuploads the texture if necessary. If it's not
 * possible or to expensive to do a calculation to determine wheter or
 * not the data has occurred, this method simply re-uploads the texture.
 * @method update
 */
p5.Texture.prototype.update = function() {
  var data = this.src;
  if (data.width === 0 || data.height === 0) {
    return; // nothing to do!
  }

  var textureData = this._getTextureDataFromSource();

  var gl = this._renderer.GL;
  // pull texture from data, make sure width & height are appropriate
  if (textureData.width !== this.width || textureData.height !== this.height) {
    // make sure that if the width and height of this.src have changed
    // for some reason, we update our metadata and upload the texture again
    this.width = textureData.width;
    this.height = textureData.height;

    this.bindTexture();
    gl.texImage2D(
      this.glTarget,
      0,
      this.glFormat,
      this.glFormat,
      gl.UNSIGNED_BYTE,
      textureData
    );

    if (this.isSrcP5Image) {
      data.setModified(false);
    } else if (this.isSrcMediaElement || this.isSrcHTMLElement) {
      // on the first frame the metadata comes in, the size will be changed
      // from 0 to actual size, but pixels may not be available.
      // flag for update in a future frame.
      // if we don't do this, a paused video, for example, may not
      // send the first frame to texture memory.
      data.setModified(true);
    }
  } else if (this.isSrcP5Image) {
    // for an image, we only update if the modified field has been set,
    // for example, by a call to p5.Image.set
    if (data.isModified()) {
      this.bindTexture();
      gl.texImage2D(
        this.glTarget,
        0,
        this.glFormat,
        this.glFormat,
        gl.UNSIGNED_BYTE,
        textureData
      );
      data.setModified(false);
    }
  } else if (this.isSrcMediaElement) {
    var shouldUpdate = false;

    // for a media element (video), we'll check if the current time in
    // the video frame matches the last time. if it doesn't match, the
    // video has advanced or otherwise been taken to a new frame,
    // and we need to upload it.
    if (data.isModified()) {
      // p5.MediaElement may have also had set/updatePixels, etc. called
      // on it and should be updated, or may have been set for the first
      // time!
      shouldUpdate = true;
      data.setModified(false);
    } else if (data.loadedmetadata) {
      // if the meta data has been loaded, we can ask the video
      // what it's current position (in time) is.
      if (this._videoPrevUpdateTime !== data.time()) {
        // update the texture in gpu mem only if the current
        // video timestamp does not match the timestamp of the last
        // time we uploaded this texture (and update the time we
        // last uploaded, too)
        this._videoPrevUpdateTime = data.time();
        shouldUpdate = true;
      }
    }

    if (shouldUpdate) {
      this.bindTexture();
      gl.texImage2D(
        this.glTarget,
        0,
        this.glFormat,
        this.glFormat,
        gl.UNSIGNED_BYTE,
        textureData
      );
    }
  } else {
    /* data instanceof p5.Graphics, probably */ // there is not enough information to tell if the texture can be
    // conditionally updated; so to be safe, we just go ahead and upload it.
    gl.texImage2D(
      this.glTarget,
      0,
      this.glFormat,
      this.glFormat,
      gl.UNSIGNED_BYTE,
      textureData
    );
  }
};

/**
 * Binds the texture to the appropriate GL target.
 * @method bindTexture
 */
p5.Texture.prototype.bindTexture = function() {
  // bind texture using gl context + glTarget and
  // generated gl texture object
  var gl = this._renderer.GL;
  gl.bindTexture(this.glTarget, this.glTex);

  return this;
};

/**
 * Unbinds the texture from the appropriate GL target.
 * @method unbindTexture
 */
p5.Texture.prototype.unbindTexture = function() {
  // unbind per above, disable texturing on glTarget
  var gl = this._renderer.GL;
  gl.bindTexture(this.glTarget, null);
};

/**
 * Sets how a texture is be interpolated when upscaled or downscaled.
 * Nearest filtering uses nearest neighbor scaling when interpolating
 * Linear filtering uses WebGL's linear scaling when interpolating
 * @method setInterpolation
 * @param {String} downScale Specifies the texture filtering when
 *                           textures are shrunk. Options are LINEAR or NEAREST
 * @param {String} upScale Specifies the texture filtering when
 *                         textures are magnified. Options are LINEAR or NEAREST
 * @todo implement mipmapping filters
 */
p5.Texture.prototype.setInterpolation = function(downScale, upScale) {
  var gl = this._renderer.GL;

  if (downScale === constants.NEAREST) {
    this.glMinFilter = gl.NEAREST;
  } else {
    this.glMinFilter = gl.LINEAR;
  }

  if (upScale === constants.NEAREST) {
    this.glMagFilter = gl.NEAREST;
  } else {
    this.glMagFilter = gl.LINEAR;
  }

  this.bindTexture();
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter);
  this.unbindTexture();
};

/**
 * Sets the texture wrapping mode. This controls how textures behave
 * when their uv's go outside of the 0 - 1 range. There are three options:
 * CLAMP, REPEAT, and MIRROR. REPEAT & MIRROR are only available if the texture
 * is a power of two size (128, 256, 512, 1024, etc.).
 * @method setWrapMode
 * @param {String} wrapX Controls the horizontal texture wrapping behavior
 * @param {String} wrapY Controls the vertical texture wrapping behavior
 */
p5.Texture.prototype.setWrapMode = function(wrapX, wrapY) {
  var gl = this._renderer.GL;

  // for webgl 1 we need to check if the texture is power of two
  // if it isn't we will set the wrap mode to CLAMP
  // webgl2 will support npot REPEAT and MIRROR but we don't check for it yet
  var isPowerOfTwo = function(x) {
    return (x & (x - 1)) === 0;
  };

  var widthPowerOfTwo = isPowerOfTwo(this.width);
  var heightPowerOfTwo = isPowerOfTwo(this.width);

  if (wrapX === constants.REPEAT) {
    if (widthPowerOfTwo && heightPowerOfTwo) {
      this.glWrapS = gl.REPEAT;
    } else {
      console.warn('You tried to set the wrap mode to REPEAT but the texture size is not a power of two. Setting to CLAMP instead');
      this.glWrapS = gl.CLAMP_TO_EDGE;
    }
  } else if (wrapX === constants.MIRROR) {
    if (widthPowerOfTwo && heightPowerOfTwo) {
      this.glWrapS = gl.MIRRORED_REPEAT;
    } else {
      console.warn('You tried to set the wrap mode to MIRROR but the texture size is not a power of two. Setting to CLAMP instead');
      this.glWrapS = gl.CLAMP_TO_EDGE;
    }
  } else {
    // falling back to default if didn't get a proper mode
    this.glWrapS = gl.CLAMP_TO_EDGE;
  }

  if (wrapY === constants.REPEAT) {
    if (widthPowerOfTwo && heightPowerOfTwo) {
      this.glWrapT = gl.REPEAT;
    } else {
      console.warn('You tried to set the wrap mode to REPEAT but the texture size is not a power of two. Setting to CLAMP instead');
      this.glWrapT = gl.CLAMP_TO_EDGE;
    }
  } else if (wrapY === constants.MIRROR) {
    if (widthPowerOfTwo && heightPowerOfTwo) {
      this.glWrapT = gl.MIRRORED_REPEAT;
    } else {
      console.warn('You tried to set the wrap mode to MIRROR but the texture size is not a power of two. Setting to CLAMP instead');
      this.glWrapT = gl.CLAMP_TO_EDGE;
    }
  } else {
    // falling back to default if didn't get a proper mode
    this.glWrapT = gl.CLAMP_TO_EDGE;
  }

  this.bindTexture();
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.glWrapS);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.glWrapT);
  this.unbindTexture();
};

module.exports = p5.Texture;
<commit_msg>more prettier formatting<commit_after>/**
 * This module defines the p5.Texture class
 * @module Lights, Camera
 * @submodule Material
 * @for p5
 * @requires core
 */

'use strict';

var p5 = require('../core/core');
var constants = require('../core/constants');

/**
 * Texture class for WEBGL Mode
 * @private
 * @class p5.Texture
 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that
 * will provide the GL context for this new p5.Texture
 * @param {p5.Image|p5.Graphics|p5.Element|p5.MediaElement} [obj] the
 * object containing the image data to store in the texture.
 */
p5.Texture = function(renderer, obj) {
  this._renderer = renderer;

  var gl = this._renderer.GL;

  this.src = obj;
  this.glTex = undefined;
  this.glTarget = gl.TEXTURE_2D;
  this.glFormat = gl.RGBA;
  this.mipmaps = false;
  this.glMinFilter = gl.LINEAR;
  this.glMagFilter = gl.LINEAR;
  this.glWrapS = gl.CLAMP_TO_EDGE;
  this.glWrapT = gl.CLAMP_TO_EDGE;

  // used to determine if this texture might need constant updating
  // because it is a video or gif.
  this.isSrcMediaElement =
    typeof p5.MediaElement !== 'undefined' && obj instanceof p5.MediaElement;
  this._videoPrevUpdateTime = 0;
  this.isSrcHTMLElement =
    typeof p5.Element !== 'undefined' &&
    obj instanceof p5.Element &&
    !(obj instanceof p5.Graphics);
  this.isSrcP5Image = obj instanceof p5.Image;
  this.isSrcP5Graphics = obj instanceof p5.Graphics;

  var textureData = this._getTextureDataFromSource();
  this.width = textureData.width;
  this.height = textureData.height;

  this.init(textureData);
  return this;
};

p5.Texture.prototype._getTextureDataFromSource = function() {
  var textureData;
  if (this.isSrcP5Image) {
    // param is a p5.Image
    textureData = this.src.canvas;
  } else if (
    this.isSrcMediaElement ||
    this.isSrcP5Graphics ||
    this.isSrcHTMLElement
  ) {
    // if param is a video HTML element
    textureData = this.src.elt;
  }
  return textureData;
};

/**
 * Initializes common texture parameters, creates a gl texture,
 * tries to upload the texture for the first time if data is
 * already available.
 * @private
 * @method init
 */
p5.Texture.prototype.init = function(data) {
  var gl = this._renderer.GL;
  this.glTex = gl.createTexture();
  this.bindTexture();

  //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.glWrapS);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.glWrapT);

  if (
    this.width === 0 ||
    this.height === 0 ||
    (this.isSrcMediaElement && !this.src.loadedmetadata)
  ) {
    // assign a 1x1 empty texture initially, because data is not yet ready,
    // so that no errors occur in gl console!
    var tmpdata = new Uint8Array([1, 1, 1, 1]);
    gl.texImage2D(
      this.glTarget,
      0,
      gl.RGBA,
      1,
      1,
      0,
      this.glFormat,
      gl.UNSIGNED_BYTE,
      tmpdata
    );
  } else {
    // data is ready: just push the texture!
    gl.texImage2D(
      this.glTarget,
      0,
      this.glFormat,
      this.glFormat,
      gl.UNSIGNED_BYTE,
      data
    );
  }
};

/**
 * Checks if the source data for this texture has changed (if it's
 * easy to do so) and reuploads the texture if necessary. If it's not
 * possible or to expensive to do a calculation to determine wheter or
 * not the data has occurred, this method simply re-uploads the texture.
 * @method update
 */
p5.Texture.prototype.update = function() {
  var data = this.src;
  if (data.width === 0 || data.height === 0) {
    return; // nothing to do!
  }

  var textureData = this._getTextureDataFromSource();

  var gl = this._renderer.GL;
  // pull texture from data, make sure width & height are appropriate
  if (textureData.width !== this.width || textureData.height !== this.height) {
    // make sure that if the width and height of this.src have changed
    // for some reason, we update our metadata and upload the texture again
    this.width = textureData.width;
    this.height = textureData.height;

    this.bindTexture();
    gl.texImage2D(
      this.glTarget,
      0,
      this.glFormat,
      this.glFormat,
      gl.UNSIGNED_BYTE,
      textureData
    );

    if (this.isSrcP5Image) {
      data.setModified(false);
    } else if (this.isSrcMediaElement || this.isSrcHTMLElement) {
      // on the first frame the metadata comes in, the size will be changed
      // from 0 to actual size, but pixels may not be available.
      // flag for update in a future frame.
      // if we don't do this, a paused video, for example, may not
      // send the first frame to texture memory.
      data.setModified(true);
    }
  } else if (this.isSrcP5Image) {
    // for an image, we only update if the modified field has been set,
    // for example, by a call to p5.Image.set
    if (data.isModified()) {
      this.bindTexture();
      gl.texImage2D(
        this.glTarget,
        0,
        this.glFormat,
        this.glFormat,
        gl.UNSIGNED_BYTE,
        textureData
      );
      data.setModified(false);
    }
  } else if (this.isSrcMediaElement) {
    var shouldUpdate = false;

    // for a media element (video), we'll check if the current time in
    // the video frame matches the last time. if it doesn't match, the
    // video has advanced or otherwise been taken to a new frame,
    // and we need to upload it.
    if (data.isModified()) {
      // p5.MediaElement may have also had set/updatePixels, etc. called
      // on it and should be updated, or may have been set for the first
      // time!
      shouldUpdate = true;
      data.setModified(false);
    } else if (data.loadedmetadata) {
      // if the meta data has been loaded, we can ask the video
      // what it's current position (in time) is.
      if (this._videoPrevUpdateTime !== data.time()) {
        // update the texture in gpu mem only if the current
        // video timestamp does not match the timestamp of the last
        // time we uploaded this texture (and update the time we
        // last uploaded, too)
        this._videoPrevUpdateTime = data.time();
        shouldUpdate = true;
      }
    }

    if (shouldUpdate) {
      this.bindTexture();
      gl.texImage2D(
        this.glTarget,
        0,
        this.glFormat,
        this.glFormat,
        gl.UNSIGNED_BYTE,
        textureData
      );
    }
  } else {
    /* data instanceof p5.Graphics, probably */ // there is not enough information to tell if the texture can be
    // conditionally updated; so to be safe, we just go ahead and upload it.
    gl.texImage2D(
      this.glTarget,
      0,
      this.glFormat,
      this.glFormat,
      gl.UNSIGNED_BYTE,
      textureData
    );
  }
};

/**
 * Binds the texture to the appropriate GL target.
 * @method bindTexture
 */
p5.Texture.prototype.bindTexture = function() {
  // bind texture using gl context + glTarget and
  // generated gl texture object
  var gl = this._renderer.GL;
  gl.bindTexture(this.glTarget, this.glTex);

  return this;
};

/**
 * Unbinds the texture from the appropriate GL target.
 * @method unbindTexture
 */
p5.Texture.prototype.unbindTexture = function() {
  // unbind per above, disable texturing on glTarget
  var gl = this._renderer.GL;
  gl.bindTexture(this.glTarget, null);
};

/**
 * Sets how a texture is be interpolated when upscaled or downscaled.
 * Nearest filtering uses nearest neighbor scaling when interpolating
 * Linear filtering uses WebGL's linear scaling when interpolating
 * @method setInterpolation
 * @param {String} downScale Specifies the texture filtering when
 *                           textures are shrunk. Options are LINEAR or NEAREST
 * @param {String} upScale Specifies the texture filtering when
 *                         textures are magnified. Options are LINEAR or NEAREST
 * @todo implement mipmapping filters
 */
p5.Texture.prototype.setInterpolation = function(downScale, upScale) {
  var gl = this._renderer.GL;

  if (downScale === constants.NEAREST) {
    this.glMinFilter = gl.NEAREST;
  } else {
    this.glMinFilter = gl.LINEAR;
  }

  if (upScale === constants.NEAREST) {
    this.glMagFilter = gl.NEAREST;
  } else {
    this.glMagFilter = gl.LINEAR;
  }

  this.bindTexture();
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter);
  this.unbindTexture();
};

/**
 * Sets the texture wrapping mode. This controls how textures behave
 * when their uv's go outside of the 0 - 1 range. There are three options:
 * CLAMP, REPEAT, and MIRROR. REPEAT & MIRROR are only available if the texture
 * is a power of two size (128, 256, 512, 1024, etc.).
 * @method setWrapMode
 * @param {String} wrapX Controls the horizontal texture wrapping behavior
 * @param {String} wrapY Controls the vertical texture wrapping behavior
 */
p5.Texture.prototype.setWrapMode = function(wrapX, wrapY) {
  var gl = this._renderer.GL;

  // for webgl 1 we need to check if the texture is power of two
  // if it isn't we will set the wrap mode to CLAMP
  // webgl2 will support npot REPEAT and MIRROR but we don't check for it yet
  var isPowerOfTwo = function(x) {
    return (x & (x - 1)) === 0;
  };

  var widthPowerOfTwo = isPowerOfTwo(this.width);
  var heightPowerOfTwo = isPowerOfTwo(this.width);

  if (wrapX === constants.REPEAT) {
    if (widthPowerOfTwo && heightPowerOfTwo) {
      this.glWrapS = gl.REPEAT;
    } else {
      console.warn(
        'You tried to set the wrap mode to REPEAT but the texture size is not a power of two. Setting to CLAMP instead'
      );
      this.glWrapS = gl.CLAMP_TO_EDGE;
    }
  } else if (wrapX === constants.MIRROR) {
    if (widthPowerOfTwo && heightPowerOfTwo) {
      this.glWrapS = gl.MIRRORED_REPEAT;
    } else {
      console.warn(
        'You tried to set the wrap mode to MIRROR but the texture size is not a power of two. Setting to CLAMP instead'
      );
      this.glWrapS = gl.CLAMP_TO_EDGE;
    }
  } else {
    // falling back to default if didn't get a proper mode
    this.glWrapS = gl.CLAMP_TO_EDGE;
  }

  if (wrapY === constants.REPEAT) {
    if (widthPowerOfTwo && heightPowerOfTwo) {
      this.glWrapT = gl.REPEAT;
    } else {
      console.warn(
        'You tried to set the wrap mode to REPEAT but the texture size is not a power of two. Setting to CLAMP instead'
      );
      this.glWrapT = gl.CLAMP_TO_EDGE;
    }
  } else if (wrapY === constants.MIRROR) {
    if (widthPowerOfTwo && heightPowerOfTwo) {
      this.glWrapT = gl.MIRRORED_REPEAT;
    } else {
      console.warn(
        'You tried to set the wrap mode to MIRROR but the texture size is not a power of two. Setting to CLAMP instead'
      );
      this.glWrapT = gl.CLAMP_TO_EDGE;
    }
  } else {
    // falling back to default if didn't get a proper mode
    this.glWrapT = gl.CLAMP_TO_EDGE;
  }

  this.bindTexture();
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.glWrapS);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.glWrapT);
  this.unbindTexture();
};

module.exports = p5.Texture;
<|endoftext|>


<commit_before>import clone from 'clone';
import equal from 'deep-equal';
import extend from 'extend';
import DeltaOp from 'quill-delta/lib/op';
import Parchment from 'parchment';
import Quill from '../core/quill';
import logger from '../core/logger';
import Module from '../core/module';

let debug = logger('quill:keyboard');

const SHORTKEY = /Mac/i.test(navigator.platform) ? 'metaKey' : 'ctrlKey';

class Keyboard extends Module {
  static match(evt, binding) {
    binding = normalize(binding);
    if (!!binding.shortKey !== evt[SHORTKEY] && binding.shortKey !== null) return false;
    if (['altKey', 'ctrlKey', 'metaKey', 'shiftKey'].some(function(key) {
      return (key != SHORTKEY && !!binding[key] !== evt[key] && binding[key] !== null);
    })) {
      return false;
    }
    return binding.key === (evt.which || evt.keyCode);
  }

  constructor(quill, options) {
    super(quill, options);
    this.bindings = {};
    Object.keys(this.options.bindings).forEach((name) => {
      if (this.options.bindings[name]) {
        this.addBinding(this.options.bindings[name]);
      }
    });
    this.addBinding({ key: Keyboard.keys.ENTER, shiftKey: null }, handleEnter);
    this.addBinding({ key: Keyboard.keys.ENTER, metaKey: null, ctrlKey: null, altKey: null }, function() {});
    if (/Firefox/i.test(navigator.userAgent)) {
      // Need to handle delete and backspace for Firefox in the general case #1171
      this.addBinding({ key: Keyboard.keys.BACKSPACE }, { collapsed: true }, handleBackspace);
      this.addBinding({ key: Keyboard.keys.DELETE }, { collapsed: true }, handleDelete);
    } else {
      this.addBinding({ key: Keyboard.keys.BACKSPACE }, { collapsed: true, prefix: /^.?$/ }, handleBackspace);
      this.addBinding({ key: Keyboard.keys.DELETE }, { collapsed: true, suffix: /^.?$/ }, handleDelete);
    }
    this.addBinding({ key: Keyboard.keys.BACKSPACE }, { collapsed: false }, handleDeleteRange);
    this.addBinding({ key: Keyboard.keys.DELETE }, { collapsed: false }, handleDeleteRange);
    this.listen();
  }

  addBinding(key, context = {}, handler = {}) {
    let binding = normalize(key);
    if (binding == null || binding.key == null) {
      return debug.warn('Attempted to add invalid keyboard binding', binding);
    }
    if (typeof context === 'function') {
      context = { handler: context };
    }
    if (typeof handler === 'function') {
      handler = { handler: handler };
    }
    binding = extend(binding, context, handler);
    this.bindings[binding.key] = this.bindings[binding.key] || [];
    this.bindings[binding.key].push(binding);
  }

  listen() {
    this.quill.root.addEventListener('keydown', (evt) => {
      if (evt.defaultPrevented) return;
      let which = evt.which || evt.keyCode;
      let bindings = (this.bindings[which] || []).filter(function(binding) {
        return Keyboard.match(evt, binding);
      });
      if (bindings.length === 0) return;
      let range = this.quill.getSelection();
      if (range == null || !this.quill.hasFocus()) return;
      let [line, offset] = this.quill.scroll.line(range.index);
      let [leafStart, offsetStart] = this.quill.scroll.leaf(range.index);
      let [leafEnd, offsetEnd] = range.length === 0 ? [leafStart, offsetStart] : this.quill.scroll.leaf(range.index + range.length);
      let prefixText = leafStart instanceof Parchment.Text ? leafStart.value().slice(0, offsetStart) : '';
      let suffixText = leafEnd instanceof Parchment.Text ? leafEnd.value().slice(offsetEnd) : '';
      let curContext = {
        collapsed: range.length === 0,
        empty: range.length === 0 && line.length() <= 1,
        format: this.quill.getFormat(range),
        offset: offset,
        prefix: prefixText,
        suffix: suffixText
      };
      let prevented = bindings.some((binding) => {
        if (binding.collapsed != null && binding.collapsed !== curContext.collapsed) return false;
        if (binding.empty != null && binding.empty !== curContext.empty) return false;
        if (binding.offset != null && binding.offset !== curContext.offset) return false;
        if (Array.isArray(binding.format)) {
          // any format is present
          if (binding.format.every(function(name) {
            return curContext.format[name] == null;
          })) {
            return false;
          }
        } else if (typeof binding.format === 'object') {
          // all formats must match
          if (!Object.keys(binding.format).every(function(name) {
            if (binding.format[name] === true) return curContext.format[name] != null;
            if (binding.format[name] === false) return curContext.format[name] == null;
            return equal(binding.format[name], curContext.format[name]);
          })) {
            return false;
          }
        }
        if (binding.prefix != null && !binding.prefix.test(curContext.prefix)) return false;
        if (binding.suffix != null && !binding.suffix.test(curContext.suffix)) return false;
        return binding.handler.call(this, range, curContext) !== true;
      });
      if (prevented) {
        evt.preventDefault();
      }
    });
  }
}

Keyboard.keys = {
  BACKSPACE: 8,
  TAB: 9,
  ENTER: 13,
  ESCAPE: 27,
  LEFT: 37,
  UP: 38,
  RIGHT: 39,
  DOWN: 40,
  DELETE: 46
};

Keyboard.DEFAULTS = {
  bindings: {
    'bold'      : makeFormatHandler('bold'),
    'italic'    : makeFormatHandler('italic'),
    'underline' : makeFormatHandler('underline'),
    'indent': {
      // highlight tab or tab at beginning of list, indent or blockquote
      key: Keyboard.keys.TAB,
      format: ['blockquote', 'indent', 'list'],
      handler: function(range, context) {
        if (context.collapsed && context.offset !== 0) return true;
        this.quill.format('indent', '+1', Quill.sources.USER);
      }
    },
    'outdent': {
      key: Keyboard.keys.TAB,
      shiftKey: true,
      format: ['blockquote', 'indent', 'list'],
      // highlight tab or tab at beginning of list, indent or blockquote
      handler: function(range, context) {
        if (context.collapsed && context.offset !== 0) return true;
        this.quill.format('indent', '-1', Quill.sources.USER);
      }
    },
    'outdent backspace': {
      key: Keyboard.keys.BACKSPACE,
      collapsed: true,
      format: ['blockquote', 'indent', 'list'],
      offset: 0,
      handler: function(range, context) {
        if (context.format.indent != null) {
          this.quill.format('indent', '-1', Quill.sources.USER);
        } else if (context.format.blockquote != null) {
          this.quill.format('blockquote', false, Quill.sources.USER);
        } else if (context.format.list != null) {
          this.quill.format('list', false, Quill.sources.USER);
        }
      }
    },
    'indent code-block': makeCodeBlockHandler(true),
    'outdent code-block': makeCodeBlockHandler(false),
    'remove tab': {
      key: Keyboard.keys.TAB,
      shiftKey: true,
      collapsed: true,
      prefix: /\t$/,
      handler: function(range) {
        this.quill.deleteText(range.index - 1, 1, Quill.sources.USER);
      }
    },
    'tab': {
      key: Keyboard.keys.TAB,
      handler: function(range, context) {
        if (!context.collapsed) {
          this.quill.scroll.deleteAt(range.index, range.length);
        }
        this.quill.insertText(range.index, '\t', Quill.sources.USER);
        this.quill.setSelection(range.index + 1, Quill.sources.SILENT);
      }
    },
    'list empty enter': {
      key: Keyboard.keys.ENTER,
      collapsed: true,
      format: ['list'],
      empty: true,
      handler: function(range, context) {
        this.quill.format('list', false, Quill.sources.USER);
        if (context.format.indent) {
          this.quill.format('indent', false, Quill.sources.USER);
        }
      }
    },
    'checklist enter': {
      key: Keyboard.keys.ENTER,
      collapsed: true,
      format: { list: 'checked' },
      handler: function(range) {
        this.quill.scroll.insertAt(range.index, '\n');
        let [line, ] = this.quill.scroll.line(range.index + 1);
        line.format('list', 'unchecked');
        this.quill.update(Quill.sources.USER);
        this.quill.setSelection(range.index + 1, Quill.sources.SILENT);
        this.quill.selection.scrollIntoView();
      }
    },
    'header enter': {
      key: Keyboard.keys.ENTER,
      collapsed: true,
      format: ['header'],
      suffix: /^$/,
      handler: function(range) {
        this.quill.scroll.insertAt(range.index, '\n');
        this.quill.formatText(range.index + 1, 1, 'header', false, Quill.sources.USER);
        this.quill.setSelection(range.index + 1, Quill.sources.SILENT);
        this.quill.selection.scrollIntoView();
      }
    },
    'list autofill': {
      key: ' ',
      collapsed: true,
      format: { list: false },
      prefix: /^(1\.|-)$/,
      handler: function(range, context) {
        let length = context.prefix.length;
        this.quill.scroll.deleteAt(range.index - length, length);
        this.quill.formatLine(range.index - length, 1, 'list', length === 1 ? 'bullet' : 'ordered', Quill.sources.USER);
        this.quill.setSelection(range.index - length, Quill.sources.SILENT);
      }
    }
  }
};

function handleBackspace(range, context) {
  if (range.index === 0) return;
  let [line, ] = this.quill.scroll.line(range.index);
  let formats = {};
  if (context.offset === 0) {
    let curFormats = line.formats();
    let prevFormats = this.quill.getFormat(range.index-1, 1);
    formats = DeltaOp.attributes.diff(curFormats, prevFormats) || {};
  }
  this.quill.deleteText(range.index-1, 1, Quill.sources.USER);
  if (Object.keys(formats).length > 0) {
    this.quill.formatLine(range.index-1, 1, formats, Quill.sources.USER);
  }
  this.quill.selection.scrollIntoView();
}

function handleDelete(range) {
  if (range.index >= this.quill.getLength() - 1) return;
  this.quill.deleteText(range.index, 1, Quill.sources.USER);
}

function handleDeleteRange(range) {
  this.quill.deleteText(range, Quill.sources.USER);
  this.quill.setSelection(range.index, Quill.sources.SILENT);
  this.quill.selection.scrollIntoView();
}

function handleEnter(range, context) {
  if (range.length > 0) {
    this.quill.scroll.deleteAt(range.index, range.length);  // So we do not trigger text-change
  }
  let lineFormats = Object.keys(context.format).reduce(function(lineFormats, format) {
    if (Parchment.query(format, Parchment.Scope.BLOCK) && !Array.isArray(context.format[format])) {
      lineFormats[format] = context.format[format];
    }
    return lineFormats;
  }, {});
  this.quill.insertText(range.index, '\n', lineFormats, Quill.sources.USER);
  this.quill.selection.scrollIntoView();
  Object.keys(context.format).forEach((name) => {
    if (lineFormats[name] != null) return;
    if (Array.isArray(context.format[name])) return;
    if (name === 'link') return;
    this.quill.format(name, context.format[name], Quill.sources.USER);
  });
}

function makeCodeBlockHandler(indent) {
  return {
    key: Keyboard.keys.TAB,
    shiftKey: !indent,
    format: {'code-block': true },
    handler: function(range) {
      let CodeBlock = Parchment.query('code-block');
      let index = range.index, length = range.length;
      let [block, offset] = this.quill.scroll.descendant(CodeBlock, index);
      if (block == null) return;
      let scrollOffset = this.quill.scroll.offset(block);
      let start = block.newlineIndex(offset, true) + 1;
      let end = block.newlineIndex(scrollOffset + offset + length);
      let lines = block.domNode.textContent.slice(start, end).split('\n');
      offset = 0;
      lines.forEach((line, i) => {
        if (indent) {
          block.insertAt(start + offset, CodeBlock.TAB);
          offset += CodeBlock.TAB.length;
          if (i === 0) {
            index += CodeBlock.TAB.length;
          } else {
            length += CodeBlock.TAB.length;
          }
        } else if (line.startsWith(CodeBlock.TAB)) {
          block.deleteAt(start + offset, CodeBlock.TAB.length);
          offset -= CodeBlock.TAB.length;
          if (i === 0) {
            index -= CodeBlock.TAB.length;
          } else {
            length -= CodeBlock.TAB.length;
          }
        }
        offset += line.length + 1;
      });
      this.quill.update(Quill.sources.USER);
      this.quill.setSelection(index, length, Quill.sources.SILENT);
    }
  };
}

function makeFormatHandler(format) {
  return {
    key: format[0].toUpperCase(),
    shortKey: true,
    handler: function(range, context) {
      this.quill.format(format, !context.format[format], Quill.sources.USER);
    }
  };
}

function normalize(binding) {
  if (typeof binding === 'string' || typeof binding === 'number') {
    return normalize({ key: binding });
  }
  if (typeof binding === 'object') {
    binding = clone(binding, false);
  }
  if (typeof binding.key === 'string') {
    if (Keyboard.keys[binding.key.toUpperCase()] != null) {
      binding.key = Keyboard.keys[binding.key.toUpperCase()];
    } else if (binding.key.length === 1) {
      binding.key = binding.key.toUpperCase().charCodeAt(0);
    } else {
      return null;
    }
  }
  return binding;
}

export default Keyboard;
<commit_msg>check for astral symbols<commit_after>import clone from 'clone';
import equal from 'deep-equal';
import extend from 'extend';
import DeltaOp from 'quill-delta/lib/op';
import Parchment from 'parchment';
import Quill from '../core/quill';
import logger from '../core/logger';
import Module from '../core/module';

let debug = logger('quill:keyboard');

const SHORTKEY = /Mac/i.test(navigator.platform) ? 'metaKey' : 'ctrlKey';

class Keyboard extends Module {
  static match(evt, binding) {
    binding = normalize(binding);
    if (!!binding.shortKey !== evt[SHORTKEY] && binding.shortKey !== null) return false;
    if (['altKey', 'ctrlKey', 'metaKey', 'shiftKey'].some(function(key) {
      return (key != SHORTKEY && !!binding[key] !== evt[key] && binding[key] !== null);
    })) {
      return false;
    }
    return binding.key === (evt.which || evt.keyCode);
  }

  constructor(quill, options) {
    super(quill, options);
    this.bindings = {};
    Object.keys(this.options.bindings).forEach((name) => {
      if (this.options.bindings[name]) {
        this.addBinding(this.options.bindings[name]);
      }
    });
    this.addBinding({ key: Keyboard.keys.ENTER, shiftKey: null }, handleEnter);
    this.addBinding({ key: Keyboard.keys.ENTER, metaKey: null, ctrlKey: null, altKey: null }, function() {});
    if (/Firefox/i.test(navigator.userAgent)) {
      // Need to handle delete and backspace for Firefox in the general case #1171
      this.addBinding({ key: Keyboard.keys.BACKSPACE }, { collapsed: true }, handleBackspace);
      this.addBinding({ key: Keyboard.keys.DELETE }, { collapsed: true }, handleDelete);
    } else {
      this.addBinding({ key: Keyboard.keys.BACKSPACE }, { collapsed: true, prefix: /^.?$/ }, handleBackspace);
      this.addBinding({ key: Keyboard.keys.DELETE }, { collapsed: true, suffix: /^.?$/ }, handleDelete);
    }
    this.addBinding({ key: Keyboard.keys.BACKSPACE }, { collapsed: false }, handleDeleteRange);
    this.addBinding({ key: Keyboard.keys.DELETE }, { collapsed: false }, handleDeleteRange);
    this.listen();
  }

  addBinding(key, context = {}, handler = {}) {
    let binding = normalize(key);
    if (binding == null || binding.key == null) {
      return debug.warn('Attempted to add invalid keyboard binding', binding);
    }
    if (typeof context === 'function') {
      context = { handler: context };
    }
    if (typeof handler === 'function') {
      handler = { handler: handler };
    }
    binding = extend(binding, context, handler);
    this.bindings[binding.key] = this.bindings[binding.key] || [];
    this.bindings[binding.key].push(binding);
  }

  listen() {
    this.quill.root.addEventListener('keydown', (evt) => {
      if (evt.defaultPrevented) return;
      let which = evt.which || evt.keyCode;
      let bindings = (this.bindings[which] || []).filter(function(binding) {
        return Keyboard.match(evt, binding);
      });
      if (bindings.length === 0) return;
      let range = this.quill.getSelection();
      if (range == null || !this.quill.hasFocus()) return;
      let [line, offset] = this.quill.scroll.line(range.index);
      let [leafStart, offsetStart] = this.quill.scroll.leaf(range.index);
      let [leafEnd, offsetEnd] = range.length === 0 ? [leafStart, offsetStart] : this.quill.scroll.leaf(range.index + range.length);
      let prefixText = leafStart instanceof Parchment.Text ? leafStart.value().slice(0, offsetStart) : '';
      let suffixText = leafEnd instanceof Parchment.Text ? leafEnd.value().slice(offsetEnd) : '';
      let curContext = {
        collapsed: range.length === 0,
        empty: range.length === 0 && line.length() <= 1,
        format: this.quill.getFormat(range),
        offset: offset,
        prefix: prefixText,
        suffix: suffixText
      };
      let prevented = bindings.some((binding) => {
        if (binding.collapsed != null && binding.collapsed !== curContext.collapsed) return false;
        if (binding.empty != null && binding.empty !== curContext.empty) return false;
        if (binding.offset != null && binding.offset !== curContext.offset) return false;
        if (Array.isArray(binding.format)) {
          // any format is present
          if (binding.format.every(function(name) {
            return curContext.format[name] == null;
          })) {
            return false;
          }
        } else if (typeof binding.format === 'object') {
          // all formats must match
          if (!Object.keys(binding.format).every(function(name) {
            if (binding.format[name] === true) return curContext.format[name] != null;
            if (binding.format[name] === false) return curContext.format[name] == null;
            return equal(binding.format[name], curContext.format[name]);
          })) {
            return false;
          }
        }
        if (binding.prefix != null && !binding.prefix.test(curContext.prefix)) return false;
        if (binding.suffix != null && !binding.suffix.test(curContext.suffix)) return false;
        return binding.handler.call(this, range, curContext) !== true;
      });
      if (prevented) {
        evt.preventDefault();
      }
    });
  }
}

Keyboard.keys = {
  BACKSPACE: 8,
  TAB: 9,
  ENTER: 13,
  ESCAPE: 27,
  LEFT: 37,
  UP: 38,
  RIGHT: 39,
  DOWN: 40,
  DELETE: 46
};

Keyboard.DEFAULTS = {
  bindings: {
    'bold'      : makeFormatHandler('bold'),
    'italic'    : makeFormatHandler('italic'),
    'underline' : makeFormatHandler('underline'),
    'indent': {
      // highlight tab or tab at beginning of list, indent or blockquote
      key: Keyboard.keys.TAB,
      format: ['blockquote', 'indent', 'list'],
      handler: function(range, context) {
        if (context.collapsed && context.offset !== 0) return true;
        this.quill.format('indent', '+1', Quill.sources.USER);
      }
    },
    'outdent': {
      key: Keyboard.keys.TAB,
      shiftKey: true,
      format: ['blockquote', 'indent', 'list'],
      // highlight tab or tab at beginning of list, indent or blockquote
      handler: function(range, context) {
        if (context.collapsed && context.offset !== 0) return true;
        this.quill.format('indent', '-1', Quill.sources.USER);
      }
    },
    'outdent backspace': {
      key: Keyboard.keys.BACKSPACE,
      collapsed: true,
      format: ['blockquote', 'indent', 'list'],
      offset: 0,
      handler: function(range, context) {
        if (context.format.indent != null) {
          this.quill.format('indent', '-1', Quill.sources.USER);
        } else if (context.format.blockquote != null) {
          this.quill.format('blockquote', false, Quill.sources.USER);
        } else if (context.format.list != null) {
          this.quill.format('list', false, Quill.sources.USER);
        }
      }
    },
    'indent code-block': makeCodeBlockHandler(true),
    'outdent code-block': makeCodeBlockHandler(false),
    'remove tab': {
      key: Keyboard.keys.TAB,
      shiftKey: true,
      collapsed: true,
      prefix: /\t$/,
      handler: function(range) {
        this.quill.deleteText(range.index - 1, 1, Quill.sources.USER);
      }
    },
    'tab': {
      key: Keyboard.keys.TAB,
      handler: function(range, context) {
        if (!context.collapsed) {
          this.quill.scroll.deleteAt(range.index, range.length);
        }
        this.quill.insertText(range.index, '\t', Quill.sources.USER);
        this.quill.setSelection(range.index + 1, Quill.sources.SILENT);
      }
    },
    'list empty enter': {
      key: Keyboard.keys.ENTER,
      collapsed: true,
      format: ['list'],
      empty: true,
      handler: function(range, context) {
        this.quill.format('list', false, Quill.sources.USER);
        if (context.format.indent) {
          this.quill.format('indent', false, Quill.sources.USER);
        }
      }
    },
    'checklist enter': {
      key: Keyboard.keys.ENTER,
      collapsed: true,
      format: { list: 'checked' },
      handler: function(range) {
        this.quill.scroll.insertAt(range.index, '\n');
        let [line, ] = this.quill.scroll.line(range.index + 1);
        line.format('list', 'unchecked');
        this.quill.update(Quill.sources.USER);
        this.quill.setSelection(range.index + 1, Quill.sources.SILENT);
        this.quill.selection.scrollIntoView();
      }
    },
    'header enter': {
      key: Keyboard.keys.ENTER,
      collapsed: true,
      format: ['header'],
      suffix: /^$/,
      handler: function(range) {
        this.quill.scroll.insertAt(range.index, '\n');
        this.quill.formatText(range.index + 1, 1, 'header', false, Quill.sources.USER);
        this.quill.setSelection(range.index + 1, Quill.sources.SILENT);
        this.quill.selection.scrollIntoView();
      }
    },
    'list autofill': {
      key: ' ',
      collapsed: true,
      format: { list: false },
      prefix: /^(1\.|-)$/,
      handler: function(range, context) {
        let length = context.prefix.length;
        this.quill.scroll.deleteAt(range.index - length, length);
        this.quill.formatLine(range.index - length, 1, 'list', length === 1 ? 'bullet' : 'ordered', Quill.sources.USER);
        this.quill.setSelection(range.index - length, Quill.sources.SILENT);
      }
    }
  }
};

function handleBackspace(range, context) {
  if (range.index === 0) return;
  let [line, ] = this.quill.scroll.line(range.index);
  let formats = {};
  if (context.offset === 0) {
    let curFormats = line.formats();
    let prevFormats = this.quill.getFormat(range.index-1, 1);
    formats = DeltaOp.attributes.diff(curFormats, prevFormats) || {};
  }
  // Check for astral symbols
  let length = /[\uD800-\uDBFF][\uDC00-\uDFFF]$/.test(context.prefix) ? 2 : 1;
  this.quill.deleteText(range.index-length, length, Quill.sources.USER);
  if (Object.keys(formats).length > 0) {
    this.quill.formatLine(range.index-length, length, formats, Quill.sources.USER);
  }
  this.quill.selection.scrollIntoView();
}

function handleDelete(range, context) {
  // Check for astral symbols
  let length = /^[\uD800-\uDBFF][\uDC00-\uDFFF]/.test(context.suffix) ? 2 : 1;
  if (range.index >= this.quill.getLength() - length) return;
  this.quill.deleteText(range.index, length, Quill.sources.USER);
}

function handleDeleteRange(range) {
  this.quill.deleteText(range, Quill.sources.USER);
  this.quill.setSelection(range.index, Quill.sources.SILENT);
  this.quill.selection.scrollIntoView();
}

function handleEnter(range, context) {
  if (range.length > 0) {
    this.quill.scroll.deleteAt(range.index, range.length);  // So we do not trigger text-change
  }
  let lineFormats = Object.keys(context.format).reduce(function(lineFormats, format) {
    if (Parchment.query(format, Parchment.Scope.BLOCK) && !Array.isArray(context.format[format])) {
      lineFormats[format] = context.format[format];
    }
    return lineFormats;
  }, {});
  this.quill.insertText(range.index, '\n', lineFormats, Quill.sources.USER);
  this.quill.selection.scrollIntoView();
  Object.keys(context.format).forEach((name) => {
    if (lineFormats[name] != null) return;
    if (Array.isArray(context.format[name])) return;
    if (name === 'link') return;
    this.quill.format(name, context.format[name], Quill.sources.USER);
  });
}

function makeCodeBlockHandler(indent) {
  return {
    key: Keyboard.keys.TAB,
    shiftKey: !indent,
    format: {'code-block': true },
    handler: function(range) {
      let CodeBlock = Parchment.query('code-block');
      let index = range.index, length = range.length;
      let [block, offset] = this.quill.scroll.descendant(CodeBlock, index);
      if (block == null) return;
      let scrollOffset = this.quill.scroll.offset(block);
      let start = block.newlineIndex(offset, true) + 1;
      let end = block.newlineIndex(scrollOffset + offset + length);
      let lines = block.domNode.textContent.slice(start, end).split('\n');
      offset = 0;
      lines.forEach((line, i) => {
        if (indent) {
          block.insertAt(start + offset, CodeBlock.TAB);
          offset += CodeBlock.TAB.length;
          if (i === 0) {
            index += CodeBlock.TAB.length;
          } else {
            length += CodeBlock.TAB.length;
          }
        } else if (line.startsWith(CodeBlock.TAB)) {
          block.deleteAt(start + offset, CodeBlock.TAB.length);
          offset -= CodeBlock.TAB.length;
          if (i === 0) {
            index -= CodeBlock.TAB.length;
          } else {
            length -= CodeBlock.TAB.length;
          }
        }
        offset += line.length + 1;
      });
      this.quill.update(Quill.sources.USER);
      this.quill.setSelection(index, length, Quill.sources.SILENT);
    }
  };
}

function makeFormatHandler(format) {
  return {
    key: format[0].toUpperCase(),
    shortKey: true,
    handler: function(range, context) {
      this.quill.format(format, !context.format[format], Quill.sources.USER);
    }
  };
}

function normalize(binding) {
  if (typeof binding === 'string' || typeof binding === 'number') {
    return normalize({ key: binding });
  }
  if (typeof binding === 'object') {
    binding = clone(binding, false);
  }
  if (typeof binding.key === 'string') {
    if (Keyboard.keys[binding.key.toUpperCase()] != null) {
      binding.key = Keyboard.keys[binding.key.toUpperCase()];
    } else if (binding.key.length === 1) {
      binding.key = binding.key.toUpperCase().charCodeAt(0);
    } else {
      return null;
    }
  }
  return binding;
}

export default Keyboard;
<|endoftext|>


<commit_before>import { Mongo } from 'meteor/mongo';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';

export const Coachs = new Mongo.Collection('coachs');

Coachs.deny({
	insert() {
		return true;
	},
	update() {
		return true;
	},
	remove() {
		return true;
	}
});

export const coachSchema = new SimpleSchema({
	gameId: {
		type: String,
		label: 'Game id'
	},
	teamId: {
		type: String,
		label: 'Team id'
	},
	firstName: {
		type: String,
		label: 'Coachs first name',
		optional: true
	},
	lastName: {
		type: String,
		label: 'Coachs last name',
		optional: true
	},
	primaryCoach: {
		type: Boolean,
		label: 'Primary coach or not'
	},
	techFouls: {
		type: Number,
		label: 'Coach tech fouls',
		min: 0,
		max: 2
	}
});

Coachs.schemas = coachSchema;
<commit_msg>Add clubId property and change labels<commit_after>import { Mongo } from 'meteor/mongo';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';

export const Coachs = new Mongo.Collection('coachs');

Coachs.deny({
	insert() {
		return true;
	},
	update() {
		return true;
	},
	remove() {
		return true;
	}
});

export const coachSchema = new SimpleSchema({
	gameId: {
		type: String,
		label: 'Coach\'s game id'
	},
	teamId: {
		type: String,
		label: 'Coach\'s team id'
	},
	clubId: {
		type: String,
		label: 'Coach\'s club id',
		optional: true
	},
	firstName: {
		type: String,
		label: 'Coach\'s first name',
		optional: true
	},
	lastName: {
		type: String,
		label: 'Coach\'s last name',
		optional: true
	},
	primaryCoach: {
		type: Boolean,
		label: 'Primary coach or not'
	},
	techFouls: {
		type: Number,
		label: 'Coach\'s tech fouls',
		min: 0,
		max: 2
	}
});

Coachs.schemas = coachSchema;
<|endoftext|>


<commit_before>import LazyLoad from 'vanilla-lazyload';
import Navigo from 'navigo';

// asyncrhonously fetch the html template partial from the file directory,
// then set its contents to the html of the parent element
function loadHTML(url, id) {
    return new Promise((resolve, reject) => {
        let req = new XMLHttpRequest();
        req.open('GET', url);
        req.send();
        req.onload = () => {
            let elem = document.getElementById(id);
            elem.innerHTML = req.responseText;
            resolve();
        };
        req.onerror = (err) => {
            reject(err);
        };
    });
}

function loadControl(initFunction, data){
    let view = document.getElementById('view');
    view.className = 'transition';

    //Provide a delay to let the template load first
    setTimeout( function(){
        initFunction(data);
        view.className = 'fade';
        window.app.state.isBackNav = false;
    }, 250);
}

window.initMap = function(places, isActive){
    if(isActive){
        app.state.activeView = 'mapView';
        app.views[app.state.activeView].style.display = 'block';
        app.state.navHistory.push(app.settings.viewStates.map);
    }

    loadHTML('./map.html', 'mapView');
    loadControl(mapView.initMap, places);
    app.state.mapInitiated = true;

    loadMap();
};

window.initList = function(places, isActive){
    if(isActive){
        app.state.activeView = 'listView';
        app.views[app.state.activeView ].style.display = 'block';
        app.state.navHistory.push(app.settings.viewStates.list);
    }

    loadHTML('./list.html', 'listView');
    loadControl(listView.initList, places);
};

window.loadMap = function(){
    updateView('mapView');
};

window.loadList = function(){
    updateView('listView');
    new LazyLoad({
        container: document.getElementById('view')
    });
};

function updateView(activeView){
    let view = document.getElementById('view');
    view.className = 'transition';

    app.state.activeView = activeView;
    app.views.mapView.style.display = 'none';
    app.views.listView.style.display = 'none';
    app.views.detailView.style.display = 'none';

    app.views[activeView].style.display = 'block';

    setTimeout(() => view.className = 'fade', 150);
}

function loadDetail(place){
    app.views.mapView.style.display = 'none';
    app.views.listView.style.display = 'none';
    app.views.detailView.style.display = 'block';
    loadHTML('./detail.html', 'detailView');
    loadControl(detailView.init, place);
}

// use #! to hash
window.router = new Navigo(null, true);
router.on({
    'map': () => {
        if(app.state.mapInitiated){
            loadMap(app.state.filteredPlaces);
        }
        else{
            initMap(app.state.places, true);
        }

        app.state.mode = app.settings.viewStates.map;

        if(!app.state.isBackNav)
            app.state.navHistory.push(app.settings.viewStates.map);
    },
    'list': () => {
        loadList(app.state.filteredPlaces);
        new LazyLoad();
        app.state.mode = app.settings.viewStates.list;

        if(!app.state.isBackNav)
            app.state.navHistory.push(app.settings.viewStates.list);
    },
    'detail': () => {
        console.log('app.state.selectedPlace', app.state.selectedPlace[0]);

        loadDetail(app.state.selectedPlace[0]);
        app.state.mode = app.settings.viewStates.detail;

        if(!app.state.isBackNav)
            app.state.navHistory.push(app.settings.viewStates.detail);
    },
});

// set the default route
router.on(() => {

});

// set the 404 route
router.notFound((query) => {
    document.getElementById('view').innerHTML = '
Invalid Route
';
});

router.resolve();
<commit_msg>Properly measure template loading using promises instead of timeouts<commit_after>import LazyLoad from 'vanilla-lazyload';
import Navigo from 'navigo';

/**
 * Loads an html template from the target url and renders it inside
 * a container identified by an 'id'
 *
 * @param   {String} url Template target url
 * @param   {String} id  Container element's id
 * @returns {Promise}
 */
function loadHTML(url, id) {
    return new Promise((resolve, reject) => {
        let req = new XMLHttpRequest();
        req.open('GET', url);
        req.send();
        req.onload = () => {
            let elem = document.getElementById(id);
            elem.innerHTML = req.responseText;
            resolve();
        };
        req.onerror = (err) => {
            reject(err);
        };
    });
}

/**
 * Handles loading a controller
 *
 * @param   {Function} initFunction Controller function
 * @param   {Object} data         Initialization data for controller
 */
function loadControl(initFunction, data){
    let view = document.getElementById('view');
    view.className = 'transition';

    initFunction(data);
    view.className = 'fade';
    window.app.state.isBackNav = false;
}

/**
 * Initialize the map controller
 *
 * @param   {Object}  places   Places data
 * @param   {Boolean} isActive Wether the map is active or not
 */
window.initMap = function(places, isActive){
    if(isActive) {
        app.state.activeView = 'mapView';
        app.views[app.state.activeView].style.display = 'block';
        app.state.navHistory.push(app.settings.viewStates.map);
    }

    loadHTML('./map.html', 'mapView').then(() => {
        loadControl(mapView.initMap, places);
        app.state.mapInitiated = true;

        loadMap();
    });
};

/**
 * Initialize the list controller
 *
 * @param   {Object}  places   Places data
 * @param   {Boolean} isActive Wether the list is active or not
 */
window.initList = function(places, isActive){
    if(isActive){
        app.state.activeView = 'listView';
        app.views[app.state.activeView ].style.display = 'block';
        app.state.navHistory.push(app.settings.viewStates.list);
    }

    loadHTML('./list.html', 'listView')
        .then(() => loadControl(listView.initList, places));
};

window.loadMap = function() {
    updateView('mapView');
};

window.loadList = function(){
    updateView('listView');
    new LazyLoad({
        container: document.getElementById('view')
    });
};

function updateView(activeView){
    let view = document.getElementById('view');
    view.className = 'transition';

    app.state.activeView = activeView;
    app.views.mapView.style.display = 'none';
    app.views.listView.style.display = 'none';
    app.views.detailView.style.display = 'none';

    app.views[activeView].style.display = 'block';

    setTimeout(() => view.className = 'fade', 150);
}

function loadDetail(place){
    app.views.mapView.style.display = 'none';
    app.views.listView.style.display = 'none';
    app.views.detailView.style.display = 'block';
    loadHTML('./detail.html', 'detailView')
        .then(() => loadControl(detailView.init, place));
}

// use #! to hash
window.router = new Navigo(null, true);
router.on({
    'map': () => {
        if(app.state.mapInitiated){
            loadMap(app.state.filteredPlaces);
        }
        else{
            initMap(app.state.places, true);
        }

        app.state.mode = app.settings.viewStates.map;

        if(!app.state.isBackNav)
            app.state.navHistory.push(app.settings.viewStates.map);
    },
    'list': () => {
        loadList(app.state.filteredPlaces);
        new LazyLoad();
        app.state.mode = app.settings.viewStates.list;

        if(!app.state.isBackNav)
            app.state.navHistory.push(app.settings.viewStates.list);
    },
    'detail': () => {
        console.log('app.state.selectedPlace', app.state.selectedPlace[0]);

        loadDetail(app.state.selectedPlace[0]);
        app.state.mode = app.settings.viewStates.detail;

        if(!app.state.isBackNav)
            app.state.navHistory.push(app.settings.viewStates.detail);
    },
});

// set the default route
router.on(() => {

});

// set the 404 route
router.notFound((query) => {
    document.getElementById('view').innerHTML = '
Invalid Route
';
});

router.resolve();
<|endoftext|>


<commit_before>// @flow
import find from "lodash.find";
import React, { Component, cloneElement } from "react";
import Split, { Left, Right } from "../../blocks/split";
import Dashboard from "../../components/dashboard/";

type ILayout = {
  children?: React$Element<any>,
}

class Layout extends Component {
  props: ILayout;
  state = {
    right: {
      props: {
        background: "//s3.amazonaws.com/ns.images/newspring/christmasoffering/christmas_offering_1x1.png",
      },
    },
    subNav: [
      {
        isActive: false,
        linkUrl: "/give/home",
        onClick: () => {},
        title: "Home",
      },
      {
        isActive: false,
        linkUrl: "/give/now",
        onClick: () => {},
        title: "Give Now",
      },
      {
        isActive: false,
        linkUrl: "/give/history",
        onClick: () => {},
        title: "History",
      },
    ],
  }

  componentWillMount() {
    this.updateActive(this.props);
  }

  componentWillReceiveProps(props: Object) {
    this.updateActive(props);
  }

  updateActive = (props: Object) => {
    const { pathname } = props.location;

    this.setState((state) => state.subNav.map((x) => {
      const nav = x;
      nav.isActive = false;
      if (nav.linkUrl === pathname) {
        nav.isActive = true;
      }

      return nav;
    }));
  }

  getActive = (props: Object) => {
    const active = props.location.pathname.split("/");
    return find(props.routes, { path: active[2] });
  }

  getRightComponent = (props: Object) => {
    const { rightComponent } = this.getActive(props);
    // XXX handle function as children
    return rightComponent || null;
  }

  setRightProps = (props: Object) => {
    this.setState({ right: { props } });
  }

  render() {
    return (

        <Split>
          <Right {...this.state.right.props}>
            {this.getRightComponent(this.props)}
          </Right>
        </Split>
        <Left>
          <Dashboard
            title="Your Giving"
            subNav={this.state.subNav}
          >
            {cloneElement(this.props.children, {
              setRightProps: this.setRightProps,
            })}
          </Dashboard>
        </Left>

    );
  }
}

export default Layout;
<commit_msg>fixed flow error<commit_after>// @flow
import find from "lodash.find";
import React, { Component, cloneElement } from "react";
import Split, { Left, Right } from "../../blocks/split";
import Dashboard from "../../components/dashboard/";

type ILayout = {
  children: React$Element<any>,
}

class Layout extends Component {
  props: ILayout;
  state = {
    right: {
      props: {
        background: "//s3.amazonaws.com/ns.images/newspring/christmasoffering/christmas_offering_1x1.png",
      },
    },
    subNav: [
      {
        isActive: false,
        linkUrl: "/give/home",
        onClick: () => {},
        title: "Home",
      },
      {
        isActive: false,
        linkUrl: "/give/now",
        onClick: () => {},
        title: "Give Now",
      },
      {
        isActive: false,
        linkUrl: "/give/history",
        onClick: () => {},
        title: "History",
      },
    ],
  }

  componentWillMount() {
    this.updateActive(this.props);
  }

  componentWillReceiveProps(props: Object) {
    this.updateActive(props);
  }

  updateActive = (props: Object) => {
    const { pathname } = props.location;

    this.setState((state) => state.subNav.map((x) => {
      const nav = x;
      nav.isActive = false;
      if (nav.linkUrl === pathname) {
        nav.isActive = true;
      }

      return nav;
    }));
  }

  getActive = (props: Object) => {
    const active = props.location.pathname.split("/");
    return find(props.routes, { path: active[2] });
  }

  getRightComponent = (props: Object) => {
    const { rightComponent } = this.getActive(props);
    // XXX handle function as children
    return rightComponent || null;
  }

  setRightProps = (props: Object) => {
    this.setState({ right: { props } });
  }

  render() {
    return (

        <Split>
          <Right {...this.state.right.props}>
            {this.getRightComponent(this.props)}
          </Right>
        </Split>
        <Left>
          <Dashboard
            title="Your Giving"
            subNav={this.state.subNav}
          >
            {cloneElement(this.props.children, {
              setRightProps: this.setRightProps,
            })}
          </Dashboard>
        </Left>

    );
  }
}

export default Layout;
<|endoftext|>