<commit_before>'use strict';

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

var async = require('async');
var glob = require('glob');
var chalk = require('chalk');

module.exports = exports = checkLocales;

var templateKeyPattern = /\{@pre\s+type="content"\s+key="([a-zA-Z0-9.\[\]]+)"(?:\s+mode="([^"]+)")?\s*\/\}/gm;
var templatesExt = '.dust';

var bundleKeyPattern = /^\s*([a-zA-Z0-9.\[\]]+)\s*=.*$/gm;
var bundlesExt = '.properties';

function checkLocales(root, options, callback) {
	if (typeof options === 'function') {
		callback = options;
		options = {};

	} else if (!(options instanceof Object)) {
		options = {};
	}

	var templatesPath = path.join(root, 'public', 'templates');
	var bundlesPath = path.join(root, 'locales');

	var globOptions = {
		ignore: options.ignore || []
	};

	var templates = {};
	var locales = [];
	var badBundles = [];

	glob(path.join(templatesPath, '**', '*' + templatesExt), globOptions, loadTemplates);

	function loadTemplates(error, filenames) {
		if (error) {
			callback(error);
			return;
		}

		async.each(filenames, loadTemplate, onTemplatesLoaded);
	}

	function loadTemplate(filename, callback) {
		fs.readFile(filename, 'utf8', parseTemplate);

		function parseTemplate(error, file) {
			if (error) {
				callback(error);
				return;
			}

			var name = path.relative(templatesPath, filename).slice(0, -templatesExt.length);

			templates[name] = {
				name: name,
				keys: getTemplateKeys(file),
				locales: {}
			};

			callback(null);
		}
	}

	function onTemplatesLoaded(error) {
		if (error) {
			callback(error);
			return;
		}

		glob(path.join(bundlesPath, '*', '*'), globOptions, loadLocales);
	}

	function loadLocales(error, dirnames) {
		if (error) {
			callback(error);
			return;
		}

		async.each(dirnames, loadLocale, onLocalesLoaded);
	}

	function loadLocale(dirname, callback) {
		var locale = path.relative(bundlesPath, dirname);
		locales.push(locale);

		glob(path.join(dirname, '**', '*' + bundlesExt), globOptions, loadBundles);

		function loadBundles(error, filenames) {
			if (error) {
				callback(error);
				return;
			}

			async.each(filenames, loadBundle, callback);
		}

		function loadBundle(filename, callback) {
			fs.readFile(filename, 'utf8', parseBundle);

			function parseBundle(error, file) {
				if (error) {
					callback(error);
					return;
				}

				var name = path.relative(dirname, filename).slice(0, -bundlesExt.length);

				if (!templates.hasOwnProperty(name)) {
					onBadBundle('unused', path.relative(bundlesPath, filename));
				} else {
					templates[name].locales[locale] = getBundleKeys(file);
				}

				callback(null);
			}
		}
	}

	function onLocalesLoaded(error) {
		if (error) {
			callback(error);
			return;
		}

		Object.keys(templates).forEach(checkTemplate);

		callback(null, badBundles);
	}

	function checkTemplate(name) {
		var template = templates[name];

		locales.forEach(checkLocale);

		function checkLocale(locale) {
			if (!template.locales.hasOwnProperty(locale)) {
				if (template.keys.length > 0) {
					onBadBundle('missing', path.join(locale, template.name + bundlesExt));
				}
				return;
			}

			var requiredKeys = buildHash(template.keys.raw);
			var pairedKeys = template.keys.paired;
			var unusedKeys = [];

			template.locales[locale].forEach(checkKey);

			var missingKeys = Object.keys(requiredKeys);

			if ((missingKeys.length > 0) || (unusedKeys.length > 0)) {
				onBadBundle('invalid', path.join(locale, template.name + bundlesExt), {
					unusedKeys: unusedKeys,
					missingKeys: missingKeys
				});
			}

			function checkKey(key) {
				if (requiredKeys.hasOwnProperty(key)) {
					delete requiredKeys[key];
				} else if (!isPaired(key)) {
					unusedKeys.push(key);
				}
			}

			function isPaired(key) {
				for (var index = 0, count = pairedKeys.length; index < count; index++) {
					if (matchesPrefix(pairedKeys[index], key)) {
						return true;
					}
				}

				return false;
			}
		}
	}

	function onBadBundle(error, bundlePath, data) {
		badBundles.push({
			bundlePath: bundlePath,
			error: error,
			data: data
		});

		switch (error) {
		case 'missing':
			console.log(chalk.red('Missing bundle: ' + bundlePath));
			break;

		case 'unused':
			console.log(chalk.yellow('Unused bundle: ' + bundlePath));
			break;

		case 'invalid':
			var unused = (data.unusedKeys.length > 0);
			var missing = (data.missingKeys.length > 0);
			var color = (missing ? chalk.red : chalk.yellow);

			console.log(color('Invalid bundle: ' + bundlePath));
			if (missing) {
				console.log('\tMissing keys: ' + data.missingKeys.join(', '));
			}
			if (unused) {
				console.log('\tUnused keys: ' + data.unusedKeys.join(', '));
			}
			break;

		default:
			console.error(chalk.red('Invalid bundle (unknown error: ' + error + '): ' + bundlePath));
		}
	}
}

function getTemplateKeys(file) {
	var raw = {};
	var paired = {};

	var match;
	while ((match = templateKeyPattern.exec(file))) {
		((match[2] === 'paired') ? paired : raw)[match[1]] = true;
	}

	return {
		raw: Object.keys(raw),
		paired: Object.keys(paired)
	};
}

function getBundleKeys(file) {
	var keys = {};

	var match;
	while ((match = bundleKeyPattern.exec(file))) {
		keys[match[1]] = true;
	}

	return Object.keys(keys);
}

function buildHash(keys) {
	return keys.reduce(addKey, {});
}

function addKey(hash, key) {
	hash[key] = true;
	return hash;
}

function matchesPrefix(prefix, key) {
	var length = prefix.length;

	if (key.substr(0, length) !== prefix) {
		return false;
	}

	var nextChar = key.charAt(length);
	return (nextChar === '.') || (nextChar === '[') || (nextChar === '');
}
<commit_msg>Minor cleanup<commit_after>'use strict';

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

var async = require('async');
var glob = require('glob');
var chalk = require('chalk');

module.exports = exports = checkLocales;

var templateKeyPattern = /\{@pre\s+type="content"\s+key="([a-zA-Z0-9.\[\]]+)"(?:\s+mode="([^"]+)")?\s*\/\}/gm;
var templateExt = '.dust';

var bundleKeyPattern = /^\s*([a-zA-Z0-9.\[\]]+)\s*=.*$/gm;
var bundleExt = '.properties';

function checkLocales(root, options, callback) {
	if (typeof options === 'function') {
		callback = options;
		options = {};

	} else if (!(options instanceof Object)) {
		options = {};
	}

	var templatesPath = path.join(root, 'public', 'templates');
	var bundlesPath = path.join(root, 'locales');

	var globOptions = {
		ignore: options.ignore || []
	};

	var templates = {};
	var locales = [];
	var badBundles = [];

	glob(path.join(templatesPath, '**', '*' + templateExt), globOptions, loadTemplates);

	function loadTemplates(error, filenames) {
		if (error) {
			callback(error);
			return;
		}

		async.each(filenames, loadTemplate, onTemplatesLoaded);
	}

	function loadTemplate(filename, callback) {
		fs.readFile(filename, 'utf8', parseTemplate);

		function parseTemplate(error, file) {
			if (error) {
				callback(error);
				return;
			}

			var name = path.relative(templatesPath, filename).slice(0, -templateExt.length);

			templates[name] = {
				name: name,
				keys: getTemplateKeys(file),
				locales: {}
			};

			callback(null);
		}
	}

	function onTemplatesLoaded(error) {
		if (error) {
			callback(error);
			return;
		}

		glob(path.join(bundlesPath, '*', '*'), globOptions, loadLocales);
	}

	function loadLocales(error, dirnames) {
		if (error) {
			callback(error);
			return;
		}

		async.each(dirnames, loadLocale, onLocalesLoaded);
	}

	function loadLocale(dirname, callback) {
		var locale = path.relative(bundlesPath, dirname);
		locales.push(locale);

		glob(path.join(dirname, '**', '*' + bundleExt), globOptions, loadBundles);

		function loadBundles(error, filenames) {
			if (error) {
				callback(error);
				return;
			}

			async.each(filenames, loadBundle, callback);
		}

		function loadBundle(filename, callback) {
			fs.readFile(filename, 'utf8', parseBundle);

			function parseBundle(error, file) {
				if (error) {
					callback(error);
					return;
				}

				var name = path.relative(dirname, filename).slice(0, -bundleExt.length);

				if (!templates.hasOwnProperty(name)) {
					onBadBundle('unused', path.relative(bundlesPath, filename));
				} else {
					templates[name].locales[locale] = getBundleKeys(file);
				}

				callback(null);
			}
		}
	}

	function onLocalesLoaded(error) {
		if (error) {
			callback(error);
			return;
		}

		Object.keys(templates).forEach(checkTemplate);

		callback(null, badBundles);
	}

	function checkTemplate(name) {
		var template = templates[name];

		locales.forEach(checkLocale);

		function checkLocale(locale) {
			if (!template.locales.hasOwnProperty(locale)) {
				if (template.keys.length > 0) {
					onBadBundle('missing', path.join(locale, template.name + bundleExt));
				}
				return;
			}

			var requiredKeys = buildHash(template.keys.raw);
			var pairedKeys = template.keys.paired;
			var unusedKeys = [];

			template.locales[locale].forEach(checkKey);

			var missingKeys = Object.keys(requiredKeys);

			if ((missingKeys.length > 0) || (unusedKeys.length > 0)) {
				onBadBundle('invalid', path.join(locale, template.name + bundleExt), {
					unusedKeys: unusedKeys,
					missingKeys: missingKeys
				});
			}

			function checkKey(key) {
				if (requiredKeys.hasOwnProperty(key)) {
					delete requiredKeys[key];
				} else if (!isPaired(key)) {
					unusedKeys.push(key);
				}
			}

			function isPaired(key) {
				for (var index = 0, count = pairedKeys.length; index < count; index++) {
					if (matchesPrefix(pairedKeys[index], key)) {
						return true;
					}
				}

				return false;
			}
		}
	}

	function onBadBundle(error, bundlePath, data) {
		badBundles.push({
			bundlePath: bundlePath,
			error: error,
			data: data
		});

		switch (error) {
		case 'missing':
			console.log(chalk.red('Missing bundle: ' + bundlePath));
			break;

		case 'unused':
			console.log(chalk.yellow('Unused bundle: ' + bundlePath));
			break;

		case 'invalid':
			var unused = (data.unusedKeys.length > 0);
			var missing = (data.missingKeys.length > 0);
			var color = (missing ? chalk.red : chalk.yellow);

			console.log(color('Invalid bundle: ' + bundlePath));
			if (missing) {
				console.log('\tMissing keys: ' + data.missingKeys.join(', '));
			}
			if (unused) {
				console.log('\tUnused keys: ' + data.unusedKeys.join(', '));
			}
			break;

		default:
			console.log(chalk.red('Invalid bundle (unknown error: ' + error + '): ' + bundlePath));
		}
	}
}

function getTemplateKeys(file) {
	var raw = {};
	var paired = {};

	var match;
	while ((match = templateKeyPattern.exec(file))) {
		((match[2] === 'paired') ? paired : raw)[match[1]] = true;
	}

	return {
		raw: Object.keys(raw),
		paired: Object.keys(paired)
	};
}

function getBundleKeys(file) {
	var keys = {};

	var match;
	while ((match = bundleKeyPattern.exec(file))) {
		keys[match[1]] = true;
	}

	return Object.keys(keys);
}

function buildHash(keys) {
	return keys.reduce(addKey, {});
}

function addKey(hash, key) {
	hash[key] = true;
	return hash;
}

function matchesPrefix(prefix, key) {
	var length = prefix.length;

	if (key.substr(0, length) !== prefix) {
		return false;
	}

	var nextChar = key.charAt(length);
	return (nextChar === '.') || (nextChar === '[') || (nextChar === '');
}
<|endoftext|>


<commit_before>/*
---
name: Behavior
description: Auto-instantiates widgets/classes based on parsed, declarative HTML.
requires: [Core/Class.Extras, Core/Element, Core/Selectors, /ART.Window, /Element.Data, Table/Table, /DashSelectors]
provides: [Behavior]
...
*/

(function(){

	this.Behavior = new Class({

		Implements: [Options, Events],

		options: {
			//default error behavior when a filter cannot be applied
			onError: function(){
				if (window.console && console.warn) console.warn.apply(console, arguments);
			}
			//Components that have a Behavior instance (like an ART.Window)
			//call these events to tell filters that need to know that the state
			//has changed:
			// onResize: $empty, //the element's dimensions have changed
			// onShow: $empty, //the element is displayed
			// onHide: $empty //the element is hidden
		},

		initialize: function(options){
			this.setOptions(options);
			this.passMethods({
				addEvent: this.addEvent.bind(this),
				removeEvent: this.removeEvent.bind(this),
				addEvents: this.addEvents.bind(this),
				removeEvents: this.removeEvents.bind(this),
				//this doesn't really stand up; the container is variable - one behavior instance
				//can handle numerous containers... TODO: revisit
				getContainerSize: function() { return this.currentSize; }.bind(this),
				error: function(){ this.fireEvent('error', arguments); }.bind(this)
			});
		},

		//pass a method pointer through to a filter
		//by default the methods for add/remove events are passed to the filter
		//pointed to this instance of behavior. you could use this to pass along
		//other methods to your filters. For example, a method to close a popup
		//for filters presented inside popups.
		_passedMethods: {},
		passMethod: function(method, fn){
			var self = this;
			this._passedMethods[method] = function(){
				return fn.apply(this, arguments);
			};
		},

		passMethods: function(methods){
			for (method in methods) {
				this.passMethod(method, methods[method]);
			}
		},

		//These methods don't change the element's state but rather are used
		//to tell filters that need to adapt to the new element state that
		//it has changed.
		show: function(){
			return this.fireEvent('show');
		},

		//the element is hidden
		hide: function(){
			return this.fireEvent('hide');
		},

		//the element's dimensions are now the specified width and height
		resize: function(x, y){
			this.currentSize = {x: x, y: y};
			return this.fireEvent('resize', [x, y]);
		},

		//Applies all the behavior filters for an element.
		//container - (element) an element to apply the filters registered with this Behavior instance to.
		//force - (boolean; optional) passed through to applyBehavior (see it for docs)
		apply: function(container, force){
			document.id(container).getElements('[data-filters]').each(function(element){
				element.get('data', 'filters').split(',').each(function(name){
					var behavior = this.getBehavior(name.trim());
					if (!behavior) this.fireEvent('error', ['There is no behavior registered with this name: ', name, element]);
					else this.applyBehavior(element, behavior, force);
				}, this);
			}, this);
			return this;
		},

		//Applies a specific behavior to a specific element.
		//element - the element to which to apply the behavior
		//behavior - (object) a specific behavior filter, typically one registered with this instance or registered globally.
		//force - (boolean; optional) apply the behavior to each element it matches, even if it was previously applied. Defaults to *false*.
		applyBehavior: function(element, behavior, force){
			element = document.id(element);
			//get the filters already applied to this element
			var applied = getApplied(element);
			//if this filter is not yet applied to the element, or we are forcing the filter
			if (!applied[behavior.name] || force) {
				//if it was previously applied, garbage collect it
				if (applied[behavior.name]) applied[behavior.name].cleanup(element);
				//apply the filter
				behavior.attach(element, this._passedMethods);
				//and mark it as having been previously applied
				applied[behavior.name] = behavior;
				//apply all the plugins for this filter
				var plugins = this.getPlugins(behavior.name);
				if (plugins) {
					for (name in plugins) {
						this.applyBehavior(element, plugins[name], force);
					}
				}
			}
			return this;
		},

		//given a name, returns a registered behavior
		getBehavior: function(name){
			return this._registered[name] || Behavior._registered[name];
		},

		getPlugins: function(name){
			return this._plugins[name] || Behavior._plugins[name];
		},

		//Garbage collects all applied filters for an element and its children.
		//element - (*element*) container to cleanup
		//ignoreChildren - (*boolean*; optional) if *true* only the element will be cleaned, otherwise the element and all the
		//	  children with filters applied will be cleaned. Defaults to *false*.
		cleanup: function(element, ignoreChildren){
			element = document.id(element);
			var applied = getApplied(element);
			for (behavior in applied) {
				applied[behavior].cleanup(element);
				delete applied[behavior];
			}
			if (!ignoreChildren) element.getElements(':hasBehaviors').each(this.cleanup, this);
			return this;
		}

	});

	//Returns the applied behaviors for an element.
	var getApplied = function(el){
		return el.retrieve('_appliedBehaviors', {});
	};

	//Registers a behavior filter.
	//name - the name of the filter
	//fn - a function that applies the filter to the given element
	//overwrite - (boolean) if true, will overwrite existing filter if one exists; defaults to false.
	var addFilter = function(name, fn, overwrite){
		if (!this._registered[name] || overwrite) this._registered[name] = new Behavior.Filter(name, fn);
	};

	var addFilters = function(obj, overwrite) {
		for (var name in obj) {
			addFilter.apply(this, [name, obj[name], overwrite]);
		}
	};

	//Registers a behavior plugin
	//filterName - (*string*) the filter (or plugin) this is a plugin for
	//name - (*string*) the name of this plugin
	//attacher - a function that applies the filter to the given element
	var addPlugin = function(filterName, name, attacher, overwrite) {
		if (!this._plugins[filterName]) this._plugins[filterName] = {};
		if (!this._plugins[filterName][name] || overwrite) this._plugins[filterName][name] = new Behavior.Filter(name, attacher);
	};

	var addPlugins = function(obj, overwrite) {
		for (name in obj) {
			addPlugin.apply(this, [obj[name].fitlerName, obj[name].name, obj[name].attacher], overwrite);
		}
	};

	//Add methods to the Behavior namespace for global registration.
	$extend(Behavior, {
		_registered: {},
		_plugins: {},
		addGlobalFilter: addFilter,
		addGlobalFilters: addFilters,
		addGlobalPlugin: addPlugin,
		addGlobalPlugins: addPlugins
	});
	//Add methods to the Behavior class for instance registration.
	Behavior.implement({
		_registered: {},
		_plugins: {},
		addFilter: addFilter,
		addFilters: addFilters,
		addPlugin: addPlugin,
		addPlugins: addPlugins
	});

	//This class is an actual filter that, given an element, alters it with specific behaviors.
	Behavior.Filter = new Class({

		//Filter implements window tools for filters that integrate with ART.Window.
		Implements: [ART.WindowTools],

		//Pass in an object with the following properties:
		//name - the name of this filter
		//attacher - a function that applies the filter to the given element
		initialize: function(name, attacher){
			this.name = name;
			this.attach = attacher;
			this._marks = new Table();
		},

		//Stores a garbage collection pointer for a specific element.
		//Example: if your filter enhances all the inputs in the container
		//you might have a function that removes that enhancement for garbage collection.
		//You would mark each input matched with its own cleanup function.
		//NOTE: this MUST be the element passed to the filter - the element with this filters
		//      name in its data-filter property. I.E.:
		//<form data-filter="FormValidator">
		//  <input type="text" name="email"/>
		//</form>
		//If this filter is FormValidator, you can mark the form for cleanup, but not, for example
		//the input. Only elements that match this filter can be marked.
		markForCleanup: function(element, fn){
			var marks = this._marks.get(element);
			if (!marks) marks = [];
			marks.include(fn);
			this._marks.set(element, marks);
			return this;
		},

		//Garbage collect a specific element.
		//NOTE: this should be an element that has a data-filter property that matches this filter.
		cleanup: function(element){
			var marks = this._marks.get(element);
			if (marks) {
				marks.each(function(fn){ fn(); });
				this._marks.erase(element);
			}
			return this;
		}

	});

})();

//a selector to find all elements that have behaviors applied to them.
Selectors.Pseudo.hasBehaviors = function(){
	return !!Element.retrieve(this,'_appliedBehaviors');
};

Element.implement({

	addDataFilter: function(name){
		return this.set('data', 'filters', this.getDataFilters().include(name).join(','));
	},

	removeDataFilter: function(name){
		return this.set('data', 'filters', this.getDataFilters().erase(name).join(','));
	},

	getDataFilters: function(){
		var filters = this.get('data', 'filters');
		if (!filters) return [];
		return filters.split(',').map(String.trim);
	},

	hasDataFilter: function(name){
		return this.getDataFilters().contains(name);
	}

});
<commit_msg>console.warn is not a function in IE.  Only use console.warn.apply when it exists.<commit_after>/*
---
name: Behavior
description: Auto-instantiates widgets/classes based on parsed, declarative HTML.
requires: [Core/Class.Extras, Core/Element, Core/Selectors, /ART.Window, /Element.Data, Table/Table, /DashSelectors]
provides: [Behavior]
...
*/

(function(){

	this.Behavior = new Class({

		Implements: [Options, Events],

		options: {
			//default error behavior when a filter cannot be applied
			onError: function(){
				if (window.console && console.warn){
                                        if(console.warn.apply) {
                                                 console.warn.apply(console, arguments);
                                        } else {
                                                console.warn($A(arguments).join(' '));
                                        }
                                }
                        }
			//Components that have a Behavior instance (like an ART.Window)
			//call these events to tell filters that need to know that the state
			//has changed:
			// onResize: $empty, //the element's dimensions have changed
			// onShow: $empty, //the element is displayed
			// onHide: $empty //the element is hidden
		},

		initialize: function(options){
			this.setOptions(options);
			this.passMethods({
				addEvent: this.addEvent.bind(this),
				removeEvent: this.removeEvent.bind(this),
				addEvents: this.addEvents.bind(this),
				removeEvents: this.removeEvents.bind(this),
				//this doesn't really stand up; the container is variable - one behavior instance
				//can handle numerous containers... TODO: revisit
				getContainerSize: function() { return this.currentSize; }.bind(this),
				error: function(){ this.fireEvent('error', arguments); }.bind(this)
			});
		},

		//pass a method pointer through to a filter
		//by default the methods for add/remove events are passed to the filter
		//pointed to this instance of behavior. you could use this to pass along
		//other methods to your filters. For example, a method to close a popup
		//for filters presented inside popups.
		_passedMethods: {},
		passMethod: function(method, fn){
			var self = this;
			this._passedMethods[method] = function(){
				return fn.apply(this, arguments);
			};
		},

		passMethods: function(methods){
			for (method in methods) {
				this.passMethod(method, methods[method]);
			}
		},

		//These methods don't change the element's state but rather are used
		//to tell filters that need to adapt to the new element state that
		//it has changed.
		show: function(){
			return this.fireEvent('show');
		},

		//the element is hidden
		hide: function(){
			return this.fireEvent('hide');
		},

		//the element's dimensions are now the specified width and height
		resize: function(x, y){
			this.currentSize = {x: x, y: y};
			return this.fireEvent('resize', [x, y]);
		},

		//Applies all the behavior filters for an element.
		//container - (element) an element to apply the filters registered with this Behavior instance to.
		//force - (boolean; optional) passed through to applyBehavior (see it for docs)
		apply: function(container, force){
			document.id(container).getElements('[data-filters]').each(function(element){
				element.get('data', 'filters').split(',').each(function(name){
					var behavior = this.getBehavior(name.trim());
					if (!behavior) this.fireEvent('error', ['There is no behavior registered with this name: ', name, element]);
					else this.applyBehavior(element, behavior, force);
				}, this);
			}, this);
			return this;
		},

		//Applies a specific behavior to a specific element.
		//element - the element to which to apply the behavior
		//behavior - (object) a specific behavior filter, typically one registered with this instance or registered globally.
		//force - (boolean; optional) apply the behavior to each element it matches, even if it was previously applied. Defaults to *false*.
		applyBehavior: function(element, behavior, force){
			element = document.id(element);
			//get the filters already applied to this element
			var applied = getApplied(element);
			//if this filter is not yet applied to the element, or we are forcing the filter
			if (!applied[behavior.name] || force) {
				//if it was previously applied, garbage collect it
				if (applied[behavior.name]) applied[behavior.name].cleanup(element);
				//apply the filter
				behavior.attach(element, this._passedMethods);
				//and mark it as having been previously applied
				applied[behavior.name] = behavior;
				//apply all the plugins for this filter
				var plugins = this.getPlugins(behavior.name);
				if (plugins) {
					for (name in plugins) {
						this.applyBehavior(element, plugins[name], force);
					}
				}
			}
			return this;
		},

		//given a name, returns a registered behavior
		getBehavior: function(name){
			return this._registered[name] || Behavior._registered[name];
		},

		getPlugins: function(name){
			return this._plugins[name] || Behavior._plugins[name];
		},

		//Garbage collects all applied filters for an element and its children.
		//element - (*element*) container to cleanup
		//ignoreChildren - (*boolean*; optional) if *true* only the element will be cleaned, otherwise the element and all the
		//	  children with filters applied will be cleaned. Defaults to *false*.
		cleanup: function(element, ignoreChildren){
			element = document.id(element);
			var applied = getApplied(element);
			for (behavior in applied) {
				applied[behavior].cleanup(element);
				delete applied[behavior];
			}
			if (!ignoreChildren) element.getElements(':hasBehaviors').each(this.cleanup, this);
			return this;
		}

	});

	//Returns the applied behaviors for an element.
	var getApplied = function(el){
		return el.retrieve('_appliedBehaviors', {});
	};

	//Registers a behavior filter.
	//name - the name of the filter
	//fn - a function that applies the filter to the given element
	//overwrite - (boolean) if true, will overwrite existing filter if one exists; defaults to false.
	var addFilter = function(name, fn, overwrite){
		if (!this._registered[name] || overwrite) this._registered[name] = new Behavior.Filter(name, fn);
	};

	var addFilters = function(obj, overwrite) {
		for (var name in obj) {
			addFilter.apply(this, [name, obj[name], overwrite]);
		}
	};

	//Registers a behavior plugin
	//filterName - (*string*) the filter (or plugin) this is a plugin for
	//name - (*string*) the name of this plugin
	//attacher - a function that applies the filter to the given element
	var addPlugin = function(filterName, name, attacher, overwrite) {
		if (!this._plugins[filterName]) this._plugins[filterName] = {};
		if (!this._plugins[filterName][name] || overwrite) this._plugins[filterName][name] = new Behavior.Filter(name, attacher);
	};

	var addPlugins = function(obj, overwrite) {
		for (name in obj) {
			addPlugin.apply(this, [obj[name].fitlerName, obj[name].name, obj[name].attacher], overwrite);
		}
	};

	//Add methods to the Behavior namespace for global registration.
	$extend(Behavior, {
		_registered: {},
		_plugins: {},
		addGlobalFilter: addFilter,
		addGlobalFilters: addFilters,
		addGlobalPlugin: addPlugin,
		addGlobalPlugins: addPlugins
	});
	//Add methods to the Behavior class for instance registration.
	Behavior.implement({
		_registered: {},
		_plugins: {},
		addFilter: addFilter,
		addFilters: addFilters,
		addPlugin: addPlugin,
		addPlugins: addPlugins
	});

	//This class is an actual filter that, given an element, alters it with specific behaviors.
	Behavior.Filter = new Class({

		//Filter implements window tools for filters that integrate with ART.Window.
		Implements: [ART.WindowTools],

		//Pass in an object with the following properties:
		//name - the name of this filter
		//attacher - a function that applies the filter to the given element
		initialize: function(name, attacher){
			this.name = name;
			this.attach = attacher;
			this._marks = new Table();
		},

		//Stores a garbage collection pointer for a specific element.
		//Example: if your filter enhances all the inputs in the container
		//you might have a function that removes that enhancement for garbage collection.
		//You would mark each input matched with its own cleanup function.
		//NOTE: this MUST be the element passed to the filter - the element with this filters
		//      name in its data-filter property. I.E.:
		//<form data-filter="FormValidator">
		//  <input type="text" name="email"/>
		//</form>
		//If this filter is FormValidator, you can mark the form for cleanup, but not, for example
		//the input. Only elements that match this filter can be marked.
		markForCleanup: function(element, fn){
			var marks = this._marks.get(element);
			if (!marks) marks = [];
			marks.include(fn);
			this._marks.set(element, marks);
			return this;
		},

		//Garbage collect a specific element.
		//NOTE: this should be an element that has a data-filter property that matches this filter.
		cleanup: function(element){
			var marks = this._marks.get(element);
			if (marks) {
				marks.each(function(fn){ fn(); });
				this._marks.erase(element);
			}
			return this;
		}

	});

})();

//a selector to find all elements that have behaviors applied to them.
Selectors.Pseudo.hasBehaviors = function(){
	return !!Element.retrieve(this,'_appliedBehaviors');
};

Element.implement({

	addDataFilter: function(name){
		return this.set('data', 'filters', this.getDataFilters().include(name).join(','));
	},

	removeDataFilter: function(name){
		return this.set('data', 'filters', this.getDataFilters().erase(name).join(','));
	},

	getDataFilters: function(){
		var filters = this.get('data', 'filters');
		if (!filters) return [];
		return filters.split(',').map(String.trim);
	},

	hasDataFilter: function(name){
		return this.getDataFilters().contains(name);
	}

});
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from "react";
import {Text, View, Animated} from "react-native";
import { getColor } from './helpers';

export default class IconToggle extends Component {

    constructor(props) {
        super(props);
        this.state = {
            scaleValue: new Animated.Value(0.01),
            opacityValue: new Animated.Value(0.1),
            maxOpacity: props.opacity,
            size: null
        };
        this._responder = {
            onStartShouldSetResponder: (e) => true,
            onResponderGrant: this._highlight,
            onResponderRelease: this._handleResponderEnd,
            onResponderTerminate: this._unHighlight
        };
    }

    componentDidUpdate(prevProps) {
        if (this.props && this.props.badge) {
            if (prevProps.badge && this.props.badge.value !== prevProps.badge.value) {
                this._animateBadgeCounter();
            }
        }
    };

    static propTypes = {
        color: PropTypes.string.isRequired,
        opacity: PropTypes.number,
        disabled: PropTypes.bool,
        onPress: PropTypes.func,
        percent: PropTypes.number,
        children: PropTypes.element.isRequired,
        badge: PropTypes.shape({
            value: PropTypes.number,
            animate: PropTypes.bool,
            backgroundColor: PropTypes.string,
            textColor: PropTypes.string
        }),
        onLayout: PropTypes.func
    };

    static defaultProps = {
        opacity: .1,
        disabled: false,
        percent: 90
    };

    setSize = (event) => {
        const { width, height } = event.nativeEvent.layout;

        this.setState({
            size: width > height ? width : height
        });
    };

    render() {
        const { scaleValue, opacityValue, size } = this.state;
        const { color, onLayout, children } = this.props;

        let { badge } = this.props;
        let { percent } = this.props;

        if (percent < 0) {
            percent = 0;
        }
        if (percent > 100) {
            percent = 100;
        }

        percent = percent / 100;

        if (badge && typeof badge.value === 'number') {
            badge = Object.assign({},
                {value: badge.value},
                badge.backgroundColor ? {backgroundColor: badge.backgroundColor} : {backgroundColor: 'paperRed'},
                badge.textColor ? {textColor: badge.textColor} : {textColor: '#ffffff'}
            );
        }

        this.badgeAnim = this.badgeAnim || new Animated.Value(0);

        return (
            <View {...this._responder} onLayout={onLayout}>
                <View>
                    {size &&
                        <Animated.View
                            style={[{
                                position: 'absolute',
                                left: ((1 - percent) * size) / 2,
                                top: ((1 - percent) * size) / 2,
                                width: percent * size,
                                height: percent * size,
                                borderRadius: percent * size / 2,
                                transform: [{ scale: scaleValue }],
                                opacity: opacityValue,
                                backgroundColor: getColor(color)
                            }]}
                        />
                    }
                    <View style={{ backgroundColor: 'transparent' }} onLayout={(event) => { this.setSize(event) }}>
                        {children}
                    </View>
                    {size && badge && typeof badge.value === 'number' &&
                        <Animated.View style={[
                            styles.badgeContainer, {
                            backgroundColor: getColor(badge.backgroundColor),
                            top: size / 10,
                            right: size / 10,
                            transform: [   // Array order matters
                                {scale: this.badgeAnim.interpolate({
                                  inputRange: [0, 1],
                                  outputRange: [1, 1.25]
                                })},
                                {translateX: this.badgeAnim.interpolate({
                                  inputRange: [0, 1],
                                  outputRange: [0, -6]
                                })},
                                {translateY: this.badgeAnim.interpolate({
                                  inputRange: [0, 1],
                                  outputRange: [0, 5]
                                })},
                                {rotate: this.badgeAnim.interpolate({
                                  inputRange: [0, 1],
                                  outputRange: [
                                    '0deg', '45deg' // 'deg' or 'rad'
                                  ]
                                })}
                            ]}]}
                        >
                            <View style={{ flex: 1, justifyContent: 'center' }}>
                                <Text style={[styles.badgeText, { color: getColor(badge.textColor) }, badge.value > 99 ? { fontSize: 8 } : { fontSize: 10 }]}>
                                    {badge.value}
                                </Text>
                            </View>
                        </Animated.View>
                    }
                </View>
            </View>
        );
    };

    /**
     *
     * @private
     */
    _highlight = () => {
        if (!this.props.disabled) {
            Animated.timing(this.state.scaleValue, {
                toValue: 1,
                duration: 150
            }).start();
            Animated.timing(this.state.opacityValue, {
                toValue: this.state.maxOpacity,
                duration: 100
            }).start();
        }
    };

    /**
     *
     * @private
     */
    _unHighlight = () => {
        if (!this.props.disabled) {
            Animated.timing(this.state.scaleValue, {
                toValue: 0.01,
                duration: 1500
            }).start();
            Animated.timing(this.state.opacityValue, {
                toValue: 0
            }).start();
        }
    };

    /**
     *
     * @private
     */
    _animateBadgeCounter = () => {
        if (this.badgeAnim && this.props.badge && this.props.badge.animate !== false) {
            Animated.spring(this.badgeAnim, {
                toValue: 0,   // Returns to the start
                velocity: 8,  // Velocity makes it move
                tension: -5, // Slow
                friction: 1,  // Oscillate a lot
                duration: 300
            }).start();
        }
    };

    /**
     *
     * @private
     */
    _handleResponderEnd = () => {
        const { disabled, onPress } = this.props;

        if (!disabled) {
            this._unHighlight();
            onPress && onPress();
        }
    };
}

const styles = {
    badgeContainer: {
        position: 'absolute',
        borderRadius: 7.5,
        width: 15,
        height: 15
    },
    badgeText: {
        textAlign: 'center'
    }
};
<commit_msg>Have IconToggle proxy the native measurement methods for the main View<commit_after>import React, {Component, PropTypes} from "react";
import {Text, View, Animated} from "react-native";
import { getColor } from './helpers';

export default class IconToggle extends Component {

    constructor(props) {
        super(props);
        this.state = {
            scaleValue: new Animated.Value(0.01),
            opacityValue: new Animated.Value(0.1),
            maxOpacity: props.opacity,
            size: null
        };
        this._responder = {
            onStartShouldSetResponder: (e) => true,
            onResponderGrant: this._highlight,
            onResponderRelease: this._handleResponderEnd,
            onResponderTerminate: this._unHighlight
        };
    }

    componentDidUpdate(prevProps) {
        if (this.props && this.props.badge) {
            if (prevProps.badge && this.props.badge.value !== prevProps.badge.value) {
                this._animateBadgeCounter();
            }
        }
    };

    static propTypes = {
        color: PropTypes.string.isRequired,
        opacity: PropTypes.number,
        disabled: PropTypes.bool,
        onPress: PropTypes.func,
        percent: PropTypes.number,
        children: PropTypes.element.isRequired,
        badge: PropTypes.shape({
            value: PropTypes.number,
            animate: PropTypes.bool,
            backgroundColor: PropTypes.string,
            textColor: PropTypes.string
        }),
        onLayout: PropTypes.func
    };

    static defaultProps = {
        opacity: .1,
        disabled: false,
        percent: 90
    };

    setSize = (event) => {
        const { width, height } = event.nativeEvent.layout;

        this.setState({
            size: width > height ? width : height
        });
    };

    render() {
        const { scaleValue, opacityValue, size } = this.state;
        const { color, onLayout, children } = this.props;

        let { badge } = this.props;
        let { percent } = this.props;

        if (percent < 0) {
            percent = 0;
        }
        if (percent > 100) {
            percent = 100;
        }

        percent = percent / 100;

        if (badge && typeof badge.value === 'number') {
            badge = Object.assign({},
                {value: badge.value},
                badge.backgroundColor ? {backgroundColor: badge.backgroundColor} : {backgroundColor: 'paperRed'},
                badge.textColor ? {textColor: badge.textColor} : {textColor: '#ffffff'}
            );
        }

        this.badgeAnim = this.badgeAnim || new Animated.Value(0);

        return (
            <View {...this._responder} onLayout={onLayout}>
                <View>
                    {size &&
                        <Animated.View
                            style={[{
                                position: 'absolute',
                                left: ((1 - percent) * size) / 2,
                                top: ((1 - percent) * size) / 2,
                                width: percent * size,
                                height: percent * size,
                                borderRadius: percent * size / 2,
                                transform: [{ scale: scaleValue }],
                                opacity: opacityValue,
                                backgroundColor: getColor(color)
                            }]}
                        />
                    }
                    <View style={{ backgroundColor: 'transparent' }} ref={this._setMainRef} onLayout={(event) => { this.setSize(event) }}>
                        {children}
                    </View>
                    {size && badge && typeof badge.value === 'number' &&
                        <Animated.View style={[
                            styles.badgeContainer, {
                            backgroundColor: getColor(badge.backgroundColor),
                            top: size / 10,
                            right: size / 10,
                            transform: [   // Array order matters
                                {scale: this.badgeAnim.interpolate({
                                  inputRange: [0, 1],
                                  outputRange: [1, 1.25]
                                })},
                                {translateX: this.badgeAnim.interpolate({
                                  inputRange: [0, 1],
                                  outputRange: [0, -6]
                                })},
                                {translateY: this.badgeAnim.interpolate({
                                  inputRange: [0, 1],
                                  outputRange: [0, 5]
                                })},
                                {rotate: this.badgeAnim.interpolate({
                                  inputRange: [0, 1],
                                  outputRange: [
                                    '0deg', '45deg' // 'deg' or 'rad'
                                  ]
                                })}
                            ]}]}
                        >
                            <View style={{ flex: 1, justifyContent: 'center' }}>
                                <Text style={[styles.badgeText, { color: getColor(badge.textColor) }, badge.value > 99 ? { fontSize: 8 } : { fontSize: 10 }]}>
                                    {badge.value}
                                </Text>
                            </View>
                        </Animated.View>
                    }
                </View>
            </View>
        );
    };

    /**
     *
     * @private
     */
    _highlight = () => {
        if (!this.props.disabled) {
            Animated.timing(this.state.scaleValue, {
                toValue: 1,
                duration: 150
            }).start();
            Animated.timing(this.state.opacityValue, {
                toValue: this.state.maxOpacity,
                duration: 100
            }).start();
        }
    };

    /**
     *
     * @private
     */
    _unHighlight = () => {
        if (!this.props.disabled) {
            Animated.timing(this.state.scaleValue, {
                toValue: 0.01,
                duration: 1500
            }).start();
            Animated.timing(this.state.opacityValue, {
                toValue: 0
            }).start();
        }
    };

    /**
     *
     * @private
     */
    _animateBadgeCounter = () => {
        if (this.badgeAnim && this.props.badge && this.props.badge.animate !== false) {
            Animated.spring(this.badgeAnim, {
                toValue: 0,   // Returns to the start
                velocity: 8,  // Velocity makes it move
                tension: -5, // Slow
                friction: 1,  // Oscillate a lot
                duration: 300
            }).start();
        }
    };

    /**
     *
     * @private
     */
    _setMainRef = (ref) => {
        this.main = ref;
    };

    /**
     *
     * @private
     */
    _handleResponderEnd = () => {
        const { disabled, onPress } = this.props;

        if (!disabled) {
            this._unHighlight();
            onPress && onPress();
        }
    };

    // Proxy the measurement methods from the main view
    measure = (...args) => this.main.measure(...args);
    measureInWindow = (...args) => this.main.measureInWindow(...args);
    measureLayout = (...args) => this.main.measureLayout(...args);
}

const styles = {
    badgeContainer: {
        position: 'absolute',
        borderRadius: 7.5,
        width: 15,
        height: 15
    },
    badgeText: {
        textAlign: 'center'
    }
};
<|endoftext|>


<commit_before>var request = require('superagent');
var q = require('q');
var baseUrl = 'https://maps.googleapis.com/maps/api/geocode/json?';

function geocode(options){
  var deffered = q.defer();

  var query = {};

  if(!options){
    throw new Error('Must supply an options object');
  }

  if(options.address){
    query.address = options.address;
  }

  if(options.key){
    query.key = options.key;
  }

  if(options.region){
    query.region = options.region;
  }

  if(options.bounds){
    var bounds = options.bounds;
    var northeast = [bounds.northeast.lat, bounds.northeast.lng].join(',');
    var southwest = [bounds.southwest.lat, bounds.southwest.lng].join(',');
    query.bounds = northeast + '|' + southwest;
  }

  if(options.components || options.result_type){
    if(options.result_type){
      options.components = options.result_type
    }
    query.components = [];
    for(var i in options.components){
      query.components.push([i, options.components[i]].join(':'))
    }
    query.components = query.components.join('|')
  }

  if(options.latlng){
    if(options.place_id){
      throw new Error('Cannot supply latlng and place_id in a single query')
    }
    query.latlng = options.latlng
  }

  if(options.place_id){
    if(options.latlng){
      throw new Error('Cannot supply latlng and place_id in a single query')
    }
    query.place_id = options.place_id
  }

  request.get(baseUrl).query(query).end(function(err, response){
    if(err){
      deffered.reject(err);
    } else {
      if(response.body.results.length > 0){
        deffered.resolve(response.body.results)
      } else {
        deffered.reject(new Error('No results'))
      }
    }
  })
  return deffered.promise;
}

module.exports = geocode;
<commit_msg>Add reverse geocode functionality<commit_after>var request = require('superagent');
var q = require('q');
var baseUrl = 'https://maps.googleapis.com/maps/api/geocode/json?';

function geocode(options){
  var deffered = q.defer();

  var query = {};

  if(!options){
    throw new Error('Must supply an options object');
  }

  if(options.address){
    query.address = options.address;
  }

  if(options.key){
    query.key = options.key;
  }

  if(options.region){
    query.region = options.region;
  }

  if(options.bounds){
    var bounds = options.bounds;
    var northeast = [bounds.northeast.lat, bounds.northeast.lng].join(',');
    var southwest = [bounds.southwest.lat, bounds.southwest.lng].join(',');
    query.bounds = northeast + '|' + southwest;
  }

  if(options.components ){
    query.components = [];
    for(var i in options.components){
      query.components.push([i, options.components[i]].join(':'))
    }
    query.components = query.components.join('|')
  }

  if(options.latlng){
    if(options.place_id){
      return deffered.reject(new Error('Cannot supply latlng and place_id in a single query'));
    }
    query.latlng = options.latlng.join(',')
  }

  if(options.place_id){
    if(options.latlng){
      return deffered.reject(new Error('Cannot supply latlng and place_id in a single query'));
    }
    query.place_id = options.place_id
  }

  if(options.result_type){
    query.result_type = options.result_type.join('|')
  }

  request.get(baseUrl).query(query).end(function(err, response){
    if(err){
      deffered.reject(err);
    } else {
      if(response.body.results.length > 0){
        deffered.resolve(response.body.results)
      } else {
        if(response.body.error_message){
          deffered.reject(new Error(response.body.error_message))
        } else {
          deffered.reject(new Error('No results'))
        }
      }
    }
  })
  return deffered.promise;
}

module.exports = geocode;
<|endoftext|>


<commit_before>var multilevel = require("multilevel/msgpack")
var net = require("net")
var level = require("level")
var path = require("path")

var location = path.resolve(__dirname, "data.db")
var db = level(location, { valueEncoding: "json" })

var server = net.createServer(function (con) {
  con.pipe(multilevel.server(db)).pipe(con)
}).listen(process.env.LEVEL_PORT || process.env.PORT || 3333)

module.exports = server
<commit_msg>don't use PORT<commit_after>var multilevel = require("multilevel/msgpack")
var net = require("net")
var level = require("level")
var path = require("path")

var location = path.resolve(__dirname, "data.db")
var db = level(location, { valueEncoding: "json" })

var server = net.createServer(function (con) {
  con.pipe(multilevel.server(db)).pipe(con)
}).listen(process.env.LEVEL_PORT || 3333)

module.exports = server
<|endoftext|>


<commit_before>/*
---
name: Behavior
description: Auto-instantiates widgets/classes based on parsed, declarative HTML.
requires: [Core/Class.Extras, Core/Element, Core/Selectors, /ART.Window, /Element.Data, Table/Table, /DashSelectors]
provides: [Behavior]
...
*/

(function(){

	this.Behavior = new Class({

		Implements: [Options, Events],

		options: {
			//apply behaviors on startup?
			applyNow: true,
			//default error behavior when a filter cannot be applied
			onError: function(){
				if (window.console && console.warn) console.warn.apply(console, arguments);
			}
			//components that have a Behavior instance (like an ART.Window)
			//call these events to tell filters that need to know that the state
			//has changed:
			// onResize: $empty, //the element's dimensions have changed
			// onShow: $empty, //the element is displayed
			// onHide: $empty //the element is hidden
		},

		initialize: function(element, options){
			this.element = $(element);
			this.setOptions(options);
			if (this.options.applyNow) this.apply();
		},

		toElement: function(){
			return this.element;
		},

		//these methods don't change the element's state but rather are used
		//to tell filters that need to adapt to the new element state that
		//it has changed

		//the element is now visible
		show: function(){
			this.element.fireEvent('show');
			this.fireEvent('show');
		},

		//the element is hidden
		hide: function(){
			this.element.fireEvent('hide');
			this.fireEvent('hide');
		},

		//the element's dimensions are now the specified width and height
		resize: function(w, h){
			this.element.fireEvent('resize', [w, h]);
			this.fireEvent('resize', [w, h]);
		},

		//applies all the behavior filters for an element
		//force is passed through to _applyBehavior (see it for docs)
		apply: function(force){
			this.element.getElements('[data-filters]').each(function(element){
				element.get('data', 'filters').split(',').each(function(name){
					var behavior = this.getBehavior(name.trim());
					if (!behavior) this.fireEvent('error', ['There is no behavior registered with this name: ', name, element]);
					else this._applyBehavior(element, behavior, force);
				}, this);
			}, this);
			return this;
		},

		//applies a specific behavior to a specific element
		//element - the element to which to apply the behavior
		//behavior - a specific behavior filter, typically one registered with this instance or registered globally
		//force - apply the behavior to each element it matches, even if it was previously applied
		_applyBehavior: function(element, behavior, force){
			//get the filters already applied to this element
			var applied = getApplied(element);
			//if this filter is not yet applied to the element, or we are forcing the filter
			if (!applied[behavior.name] || force) {
				//if it was previously applied, garbage collect it
				if (applied[behavior.name]) applied[behavior.name].sweep(element);
				//apply the filter
				behavior.attach(element, this.element);
				//and mark it as having been previously applied
				applied[behavior.name] = behavior;
			}
		},

		//given a name, returns a registered behavior
		getBehavior: function(name){
			return this._registered[name] || Behavior._registered[name];
		},

		//garbage collects all applied filters for this element and its children
		sweep:function(element, ignoreChildren){
			var applied = getApplied(element);
			for (behavior in applied) {
				applied[behavior].sweep(element);
				delete applied[behavior];
			}
			if (!ignoreChildren) element.getElements(':hasBehaviors').each(this.sweep, this);
		}

	});

	//returns the applied behaviors for an element
	var getApplied = function(el){
		return el.retrieve('_appliedBehaviors', {});
	};

	//registers a behavior filter
	//name - the name of the filter
	//behavior - an instance of Behavior.Filter
	//overwrite - (boolean) if true, will overwrite existing filter if one exists; defaults to false
	var register = function(name, behavior, overwrite){
		if (!this._registered[name] || overwrite) this._registered[name] = behavior;
		return this;
	};
	//overwrites a filter
	var overwrite = function(name, behavior){
		return register(name, behavior, true);
	};
	//add methods to the Behavior namespace for global registration
	$extend(Behavior, {
		_registered: {},
		registerGlobal: register,
		overwriteGlobal: overwrite
	});
	//add methods to the Behavior class for instance registration
	Behavior.implement({
		_registered: {},
		register: register,
		overwrite: overwrite
	});

	//this class is an actual filter that, given an element, alters it with specific behaviors
	Behavior.Filter = new Class({

		//implements window tools for filters that integrate with ART.Window
		Implements: [ART.WindowTools],

		//pass in an object with the following properties:
		//name - the name of this filter
		//attacher - a function that applies the filter to the given element
		initialize: function(name, attacher){
			this.name = name;
			this.attach = attacher;
			this._marks = new Table();
		},

		//stores a garbage collection pointer for a specific element
		//example: if your filter enhances all the inputs in the container
		//you might have a function that removes that enhancement for garbage collection
		//you would mark each input matched with its own cleanup function
		//NOTE: this MUST be an element returned by the select method above (it is passed
		//      to the filter)
		mark: function(element, fn){
			var marks = this._marks.get(element);
			if (!marks) marks = [];
			marks.include(fn);
			this._marks.set(element, marks);
			return this;
		},

		//garbage collect a specific element
		sweep: function(element){
			var marks = this._marks.get(element);
			if (marks) {
				marks.each(function(fn){ fn(); });
				this._marks.erase(element);
			}
			return this;
		},

		//register this filter with a specific behavior
		//behavior - an instance of Behavior
		//overwrite - (boolean) force this filter to register even if one with the same name exists
		register: function(behavior, overwrite){
			behavior.register(this.name, this, overwrite);
			return this;
		},

		//globally registers this filter on the Behavior namespace
		//overwrite - (boolean) force this filter to register even if one with the same name exists
		global: function(overwrite){
			Behavior.registerGlobal(this.name, this, overwrite);
			return this;
		},

		//for use in the filter's attach method
		//returns the parent widget, if there is one
		getWidget: function(){
			var parent = this.getParent(':widget');
			return parent ? parent.get('widget') : null;
		}

	});

})();

//a selector to find all elements that have behaviors applied to them.
Selectors.Pseudo.hasBehaviors = function(){
	return !!this.retrieve('_appliedBehaviors');
};

//allows for selectors like $$('[data-foo-bar]'); TODO: Note that it'll be in Moo 1.3; remove then.
Selectors.RegExps.combined = (/\.([\w-]+)|\[([\w-]+)(?:([!*^$~|]?=)(["']?)([^\4]*?)\4)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g);<commit_msg>making my docs a little more clear renaming sweep > cleanup and mark > markForCleanup<commit_after>/*
---
name: Behavior
description: Auto-instantiates widgets/classes based on parsed, declarative HTML.
requires: [Core/Class.Extras, Core/Element, Core/Selectors, /ART.Window, /Element.Data, Table/Table, /DashSelectors]
provides: [Behavior]
...
*/

(function(){

	this.Behavior = new Class({

		Implements: [Options, Events],

		options: {
			//apply behaviors on instantiation?
			applyNow: true,
			//default error behavior when a filter cannot be applied
			onError: function(){
				if (window.console && console.warn) console.warn.apply(console, arguments);
			}
			//Components that have a Behavior instance (like an ART.Window)
			//call these events to tell filters that need to know that the state
			//has changed:
			// onResize: $empty, //the element's dimensions have changed
			// onShow: $empty, //the element is displayed
			// onHide: $empty //the element is hidden
		},

		initialize: function(element, options){
			this.element = $(element);
			this.setOptions(options);
			if (this.options.applyNow) this.apply();
		},

		toElement: function(){
			return this.element;
		},

		//These methods don't change the element's state but rather are used
		//to tell filters that need to adapt to the new element state that
		//it has changed.

		//the element is now visible
		show: function(){
			this.element.fireEvent('show');
			this.fireEvent('show');
		},

		//the element is hidden
		hide: function(){
			this.element.fireEvent('hide');
			this.fireEvent('hide');
		},

		//the element's dimensions are now the specified width and height
		resize: function(w, h){
			this.element.fireEvent('resize', [w, h]);
			this.fireEvent('resize', [w, h]);
		},

		//Applies all the behavior filters for an element.
		//force is passed through to _applyBehavior (see it for docs)
		apply: function(force){
			this.element.getElements('[data-filters]').each(function(element){
				element.get('data', 'filters').split(',').each(function(name){
					var behavior = this.getBehavior(name.trim());
					if (!behavior) this.fireEvent('error', ['There is no behavior registered with this name: ', name, element]);
					else this._applyBehavior(element, behavior, force);
				}, this);
			}, this);
			return this;
		},

		//Applies a specific behavior to a specific element.
		//element - the element to which to apply the behavior
		//behavior - a specific behavior filter, typically one registered with this instance or registered globally
		//force - apply the behavior to each element it matches, even if it was previously applied
		_applyBehavior: function(element, behavior, force){
			//get the filters already applied to this element
			var applied = getApplied(element);
			//if this filter is not yet applied to the element, or we are forcing the filter
			if (!applied[behavior.name] || force) {
				//if it was previously applied, garbage collect it
				if (applied[behavior.name]) applied[behavior.name].cleanup(element);
				//apply the filter
				behavior.attach(element, this.element);
				//and mark it as having been previously applied
				applied[behavior.name] = behavior;
			}
		},

		//given a name, returns a registered behavior
		getBehavior: function(name){
			return this._registered[name] || Behavior._registered[name];
		},

		//Garbage collects all applied filters for this element and its children.
		cleanup:function(element, ignoreChildren){
			var applied = getApplied(element);
			for (behavior in applied) {
				applied[behavior].cleanup(element);
				delete applied[behavior];
			}
			if (!ignoreChildren) element.getElements(':hasBehaviors').each(this.cleanup, this);
		}

	});

	//Returns the applied behaviors for an element.
	var getApplied = function(el){
		return el.retrieve('_appliedBehaviors', {});
	};

	//Registers a behavior filter.
	//name - the name of the filter
	//behavior - an instance of Behavior.Filter
	//overwrite - (boolean) if true, will overwrite existing filter if one exists; defaults to false
	var register = function(name, behavior, overwrite){
		if (!this._registered[name] || overwrite) this._registered[name] = behavior;
		return this;
	};
	//Overwrites a filter.
	var overwrite = function(name, behavior){
		return register(name, behavior, true);
	};
	//Add methods to the Behavior namespace for global registration.
	$extend(Behavior, {
		_registered: {},
		registerGlobal: register,
		overwriteGlobal: overwrite
	});
	//Add methods to the Behavior class for instance registration.
	Behavior.implement({
		_registered: {},
		register: register,
		overwrite: overwrite
	});

	//This class is an actual filter that, given an element, alters it with specific behaviors.
	Behavior.Filter = new Class({

		//Filter implements window tools for filters that integrate with ART.Window.
		Implements: [ART.WindowTools],

		//Pass in an object with the following properties:
		//name - the name of this filter
		//attacher - a function that applies the filter to the given element
		initialize: function(name, attacher){
			this.name = name;
			this.attach = attacher;
			this._marks = new Table();
		},

		//Stores a garbage collection pointer for a specific element.
		//Example: if your filter enhances all the inputs in the container
		//you might have a function that removes that enhancement for garbage collection.
		//You would mark each input matched with its own cleanup function.
		//NOTE: this MUST be the element passed to the filter - the element with this filters
		//      name in its data-filter property. I.E.:
		//<form data-filter="FormValidator">
		//  <input type="text" name="email"/>
		//</form>
		//If this filter is FormValidator, you can mark the form for cleanup, but not, for example
		//the input. Only elements that match this filter can be marked.
		markForCleanup: function(element, fn){
			var marks = this._marks.get(element);
			if (!marks) marks = [];
			marks.include(fn);
			this._marks.set(element, marks);
			return this;
		},

		//Garbage collect a specific element.
		//NOTE: this should be an element that has a data-filter property that matches this filter.
		cleanup: function(element){
			var marks = this._marks.get(element);
			if (marks) {
				marks.each(function(fn){ fn(); });
				this._marks.erase(element);
			}
			return this;
		},

		//Register this filter with a specific behavior.
		//behavior - an instance of Behavior
		//overwrite - (boolean) force this filter to register even if one with the same name exists
		register: function(behavior, overwrite){
			behavior.register(this.name, this, overwrite);
			return this;
		},

		//Globally registers this filter on the Behavior namespace.
		//overwrite - (boolean) force this filter to register even if one with the same name exists
		global: function(overwrite){
			Behavior.registerGlobal(this.name, this, overwrite);
			return this;
		}

	});

})();

//a selector to find all elements that have behaviors applied to them.
Selectors.Pseudo.hasBehaviors = function(){
	return !!this.retrieve('_appliedBehaviors');
};<|endoftext|>


<commit_before>module.exports = {
  name: 'Store YouTube Channel Info',
  section: 'YouTube Tools',
  meta: {
    version: '2.1.5',
    preciseCheck: false,
    author: 'DBM Mods',
    authorUrl: 'https://github.com/dbm-network/mods',
    downloadURL: 'https://github.com/dbm-network/mods/blob/master/actions/store_youtube_channel_info_MOD.js',
  },

  subtitle() {
    return 'Store information about a YouTube channel.';
  },

  variableStorage(data, varType) {
    const type = parseInt(data.storage, 10);
    if (type !== varType) return;
    const dataType = 'YouTube Channel Info';
    return [data.varName, dataType];
  },

  fields: ['query', 'info', 'storage', 'varName'],

  html(_isEvent, data) {
    return `

  YouTube Channel ID:

  <input id="query" class="round" type="text">

  Options:
  <select id="info" class="round">
    <option value="0" selected>Channel URL</option>
    <option value="1">Channel Name</option>
    <option value="2">Channel Description</option>
    <option value="3">Subscriber Count</option>
    <option value="4">Related Channels</option>
    <option value="5">Is Family Friendly?</option>
    <option value="6">Channel Banners</option>
    <option value="7">Author Thumbnails</option>
    <option value="8">Channel is Verified?</option>
    <option value="9">Channel Allowed Regions</option>
  </select>

    Store In:

    <select id="storage" class="round">
      ${data.variables[1]}
    </select>

    Variable Name:

    <input id="varName" class="round" type="text">

`;
  },

  init() {},

  async action(cache) {
    const data = cache.actions[cache.index];
    const storage = parseInt(data.storage, 10);
    const varName = this.evalMessage(data.varName, cache);
    const channelId = this.evalMessage(data.query, cache);
    const info = parseInt(data.info, 10);
    const Mods = this.getMods();
    const ytch = Mods.require('yt-channel-info');
    let result;

    const channel = await ytch.getChannelInfo(channelId);

    switch (info) {
      case 0:
        result = channel.authorUrl;
        break;
      case 1:
        result = channel.author;
        break;
      case 2:
        result = channel.description;
        break;
      case 3:
        result = channel.subscriberCount;
        break;
      case 4:
        result = channel.relatedChannels;
        break;
      case 5:
        result = channel.isFamilyFriendly;
        break;
      case 6:
        result = channel.authorBanners;
        break;
      case 7:
        result = channel.authorThumbnails;
        break;
      case 8:
        result = channel.isVerified;
        break;
      case 9:
        result = channel.allowedRegions;
        break;
    }

    this.storeValue(result, storage, varName, cache);
    this.callNextAction(cache);
  },

  mod() {},
};
<commit_msg>Fix Store YouTube Channel Info (#890)<commit_after>module.exports = {
  name: 'Store YouTube Channel Info',
  section: 'YouTube Tools',
  meta: {
    version: '2.1.5',
    preciseCheck: false,
    author: 'DBM Mods',
    authorUrl: 'https://github.com/dbm-network/mods',
    downloadURL: 'https://github.com/dbm-network/mods/blob/master/actions/store_youtube_channel_info_MOD.js',
  },

  subtitle() {
    return 'Store information about a YouTube channel.';
  },

  variableStorage(data, varType) {
    const type = parseInt(data.storage, 10);
    if (type !== varType) return;
    const dataType = 'YouTube Channel Info';
    return [data.varName, dataType];
  },

  fields: ['query', 'info', 'storage', 'varName'],

  html(_isEvent, data) {
    return `

  YouTube Channel ID:

  <input id="query" class="round" type="text">

  Options:
  <select id="info" class="round">
    <option value="0" selected>Channel URL</option>
    <option value="1">Channel Name</option>
    <option value="2">Channel Description</option>
    <option value="3">Subscriber Count</option>
    <option value="4">Related Channels</option>
    <option value="5">Is Family Friendly?</option>
    <option value="6">Channel Banners</option>
    <option value="7">Author Thumbnails</option>
    <option value="8">Channel is Verified?</option>
    <option value="9">Channel Allowed Regions</option>
  </select>

    Store In:

    <select id="storage" class="round">
      ${data.variables[1]}
    </select>

    Variable Name:

    <input id="varName" class="round" type="text">

`;
  },

  init() {},

  async action(cache) {
    const data = cache.actions[cache.index];
    const storage = parseInt(data.storage, 10);
    const varName = this.evalMessage(data.varName, cache);
    const channelId = this.evalMessage(data.query, cache);
    const info = parseInt(data.info, 10);
    const Mods = this.getMods();
    const ytch = Mods.require('yt-channel-info');
    let result;

    const channel = await ytch.getChannelInfo({ channelId });

    switch (info) {
      case 0:
        result = channel.authorUrl;
        break;
      case 1:
        result = channel.author;
        break;
      case 2:
        result = channel.description;
        break;
      case 3:
        result = channel.subscriberCount;
        break;
      case 4:
        result = channel.relatedChannels;
        break;
      case 5:
        result = channel.isFamilyFriendly;
        break;
      case 6:
        result = channel.authorBanners;
        break;
      case 7:
        result = channel.authorThumbnails;
        break;
      case 8:
        result = channel.isVerified;
        break;
      case 9:
        result = channel.allowedRegions;
        break;
    }

    this.storeValue(result, storage, varName, cache);
    this.callNextAction(cache);
  },

  mod() {},
};
<|endoftext|>


<commit_before>module.exports = IoCBinding;

var getArguments = require('./getArguments.js');

/**
 * Will be created during {@link Container#register} calls, and should not be
 * instantiated directly.
 * @param {string} name Tag of the dependency
 * @param {object} source Source function/object
 * @param {function(name:string): object} factory Builder
 * @class
 * A binding object used to handle configuring IoC bindings.
 */
function IoCBinding(name, source, factory)
{
  this._name        = name;
  this._source      = source;
  this._factory     = factory;
  this._cached      = typeof source !== 'function' ?  source : null;

  // Resolved on first build
  this._deps        = null;

  this._weak        = false;
  this._singleton   = false;
}

/**
 * Allow a binding to be overridden at a later time.
 *
 * Marking a binding as weak will let it get overridden but a subsequent
 * binding without throwing an error.
 * @return {IoCBinding} This binding.
 * @example
 * container.register('config', MemoryStoreConfig);
 *   .asWeak();
 *
 * ...
 *
 * // Would normally throw an error, but is okay since it was registered as
 * // weak above. Notice that since this new dependency was not registered as
 * // weak, if it overridden again it WILL throw an error this time.
 * container.register('config', LocalStorageConfig);
 */
IoCBinding.prototype.asWeak = function()
{
  this._weak = true;
  return this;
};

/**
 * Determine if a binding is currently set as weak
 * @return {boolean}
 */
IoCBinding.prototype.isWeak = function()
{
  return this._weak;
};

/**
 * Get a list of all the names of dependencies needed to resolve this binding.
 *
 * If the source is a class constructor or closure, it'll be the named
 * parameters. Otherwise it'll be an empty array.
 * @return {array.<string>}
 */
IoCBinding.prototype.getDependencyNames = function()
{
  if (this._deps)
    return this._deps;

  if (typeof this._source === 'function') {
    this._deps = getArguments(this._source);
  } else {
    this._deps = [];
  }

  return this._deps;
};

/**
 * Mark this dependency to be instantiated only once.
 *
 * This will allow a dependency to only actually be resolved and created a
 * single time, after which that instance is cached and re-used for all
 * subsequent requests.
 *
 * This is how you would implement a "global singleton" pattern without the
 * consumer of the dependency necessarily knowing that.
 * @return {IoCBinding} This binding.
 * @example
 * container.register('http', MyHttpServer)
 *   .asSingleton();
 *
 * var s1 = container.make('http');
 * var s2 = container.make('http');
 *
 * s1 === s2; // true
 */
IoCBinding.prototype.asSingleton = function()
{
  this._singleton = true;
  return this;
};

/**
 * Use the source object directly as the dependency.
 *
 * This is used to signal that we should simply recall the dependency directly
 * that we've registered with a container.
 *
 * This is typically used either to register plain objects to the container, or
 * to register instantiated classes that require a little extra setup at run
 * time.
 * @return {IoCBinding} This binding.
 * @example
 * container.register('configs', { ... })
 *   .asInstance();
 *
 * ...
 *
 * var configs = container.make('configs');
 */
IoCBinding.prototype.asInstance = function()
{
  // Fill the cache with our source
  this._cached = this._source;
  return this;
};

/**
 * Create the dependency.
 * @return {object}
 */
IoCBinding.prototype.build = function()
{
  if (this._cached)
    return this._cached;

  // Build and stash it if it's a singleton
  var thing = this._factory(this);
  if (this._singleton)
    this._cached = thing;

  return thing;
};

<commit_msg>Dem spaces<commit_after>module.exports = IoCBinding;

var getArguments = require('./getArguments.js');

/**
 * Will be created during {@link Container#register} calls, and should not be
 * instantiated directly.
 * @param {string} name Tag of the dependency
 * @param {object} source Source function/object
 * @param {function(name:string): object} factory Builder
 * @class
 * A binding object used to handle configuring IoC bindings.
 */
function IoCBinding(name, source, factory)
{
  this._name        = name;
  this._source      = source;
  this._factory     = factory;
  this._cached      = typeof source !== 'function' ? source : null;

  // Resolved on first build
  this._deps        = null;

  this._weak        = false;
  this._singleton   = false;
}

/**
 * Allow a binding to be overridden at a later time.
 *
 * Marking a binding as weak will let it get overridden but a subsequent
 * binding without throwing an error.
 * @return {IoCBinding} This binding.
 * @example
 * container.register('config', MemoryStoreConfig);
 *   .asWeak();
 *
 * ...
 *
 * // Would normally throw an error, but is okay since it was registered as
 * // weak above. Notice that since this new dependency was not registered as
 * // weak, if it overridden again it WILL throw an error this time.
 * container.register('config', LocalStorageConfig);
 */
IoCBinding.prototype.asWeak = function()
{
  this._weak = true;
  return this;
};

/**
 * Determine if a binding is currently set as weak
 * @return {boolean}
 */
IoCBinding.prototype.isWeak = function()
{
  return this._weak;
};

/**
 * Get a list of all the names of dependencies needed to resolve this binding.
 *
 * If the source is a class constructor or closure, it'll be the named
 * parameters. Otherwise it'll be an empty array.
 * @return {array.<string>}
 */
IoCBinding.prototype.getDependencyNames = function()
{
  if (this._deps)
    return this._deps;

  if (typeof this._source === 'function') {
    this._deps = getArguments(this._source);
  } else {
    this._deps = [];
  }

  return this._deps;
};

/**
 * Mark this dependency to be instantiated only once.
 *
 * This will allow a dependency to only actually be resolved and created a
 * single time, after which that instance is cached and re-used for all
 * subsequent requests.
 *
 * This is how you would implement a "global singleton" pattern without the
 * consumer of the dependency necessarily knowing that.
 * @return {IoCBinding} This binding.
 * @example
 * container.register('http', MyHttpServer)
 *   .asSingleton();
 *
 * var s1 = container.make('http');
 * var s2 = container.make('http');
 *
 * s1 === s2; // true
 */
IoCBinding.prototype.asSingleton = function()
{
  this._singleton = true;
  return this;
};

/**
 * Use the source object directly as the dependency.
 *
 * This is used to signal that we should simply recall the dependency directly
 * that we've registered with a container.
 *
 * This is typically used either to register plain objects to the container, or
 * to register instantiated classes that require a little extra setup at run
 * time.
 * @return {IoCBinding} This binding.
 * @example
 * container.register('configs', { ... })
 *   .asInstance();
 *
 * ...
 *
 * var configs = container.make('configs');
 */
IoCBinding.prototype.asInstance = function()
{
  // Fill the cache with our source
  this._cached = this._source;
  return this;
};

/**
 * Create the dependency.
 * @return {object}
 */
IoCBinding.prototype.build = function()
{
  if (this._cached)
    return this._cached;

  // Build and stash it if it's a singleton
  var thing = this._factory(this);
  if (this._singleton)
    this._cached = thing;

  return thing;
};

<|endoftext|>


<commit_before>/**
 * Created by donmclean on 6/10/16.
 */
"use strict";
module.exports = (gulp, $, config, funcs) => {
    gulp.task('js-deps', () => {

        return gulp.src(config.js.deps.src)
            .pipe($.plumber({errorHandler: funcs.gulpGlobalErrorHandler}))
            .pipe($.if(!!funcs.customBuild.sourcemaps || !!funcs.isProd, $.sourcemaps.init()))
            .pipe($.debug({title: 'copying and minifying js deps:'}))
            .pipe($.concat(config.js.deps.mainFileName))
            .pipe($.rev())
            .pipe($.if(!!funcs.customBuild.sourcemaps && !funcs.customBuild.minifyJS, $.sourcemaps.write()))
            .pipe($.if(!!funcs.isCustom && !funcs.customBuild.minifyJS, gulp.dest(config.js.deps.destDir)))
            .pipe($.size({showFiles:true}))
            .pipe($.if(!!funcs.customBuild.minifyJS || !!funcs.isProd, $.rename({suffix: '.min'})))
            .pipe($.if(!!funcs.customBuild.minifyJS || !!funcs.isProd, $.uglify()))
            .pipe($.if(!!funcs.customBuild.minifyJS && !!funcs.customBuild.sourcemaps || !!funcs.isProd, $.sourcemaps.write()))
            .pipe($.if(!!funcs.customBuild.minifyJS || !!funcs.isProd, $.size({showFiles:true})))
            .pipe(gulp.dest(config.js.deps.destDir));

    });
};<commit_msg>update js deps to cater for vendor files<commit_after>/**
 * Created by donmclean on 6/10/16.
 */
"use strict";
module.exports = (gulp, $, config, funcs) => {
    gulp.task('js-deps', () => {

        return gulp.src(config.vars._.concat(config.js.deps.src, config.vendor.js.src))
            .pipe($.plumber({errorHandler: funcs.gulpGlobalErrorHandler}))
            .pipe($.if(!!funcs.customBuild.sourcemaps || !!funcs.isProd, $.sourcemaps.init()))
            .pipe($.debug({title: 'copying and minifying js deps:'}))
            .pipe($.concat(config.js.deps.mainFileName))
            .pipe($.rev())
            .pipe($.if(!!funcs.customBuild.sourcemaps && !funcs.customBuild.minifyJS, $.sourcemaps.write()))
            .pipe($.if(!!funcs.isCustom && !funcs.customBuild.minifyJS, gulp.dest(config.js.deps.destDir)))
            .pipe($.size({showFiles:true}))
            .pipe($.if(!!funcs.customBuild.minifyJS || !!funcs.isProd, $.rename({suffix: '.min'})))
            .pipe($.if(!!funcs.customBuild.minifyJS || !!funcs.isProd, $.uglify()))
            .pipe($.if(!!funcs.customBuild.minifyJS && !!funcs.customBuild.sourcemaps || !!funcs.isProd, $.sourcemaps.write()))
            .pipe($.if(!!funcs.customBuild.minifyJS || !!funcs.isProd, $.size({showFiles:true})))
            .pipe(gulp.dest(config.js.deps.destDir));

    });
};
<|endoftext|>


<commit_before>// dependencies
var env = require('node-env-file');
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var _ = require('lomath');
var portfinder = require('portfinder');

// export the setEnv for convenient usage in dev
module.exports = setEnv;

// set env if not already set externally
// .env must exist if setting env vars externally
function setEnv(defaultKey) {
  // optionally set defaultKey
  process.env.DEPLOY = process.env.DEPLOY || defaultKey;

  try {
    env(__dirname + '/.env', { overwrite: false });
    // reset port for dev
    if (process.env.NODE_ENV == 'development') { process.env.PORT = 1000 + parseInt(process.env.PORT) };
    // then set env keys for the deployed bot
    console.log("Deploying using", process.env.DEPLOY)
    env(__dirname + '/bin/' + process.env.DEPLOY);
  } catch (e) {
    console.log(e)
    console.log('index.js quitting.')
    process.exit(1)
  }
}

// if this file is run directly by `node index.js`
/* istanbul ignore next */
if (require.main === module) {
  // call setEnv with a default key
  setEnv();

  // child processes by spawn
  var children = [];

  // so that hubot is killed when forever exits.
  process.on('exit', function() {
    children.forEach(function(child) {
      child.kill();
    });
    // kill the neo4j brain server too
    exec('neo4j stop')
    console.log("Shutting down")
  });

  // start and kill neo4j brain server
  exec('neo4j start');

  // set baseport to start scanning
  portfinder.basePort = parseInt(process.env.PORT)

  var botname = process.env.DEPLOY.split("-").pop()
  // detect all adapters, spawn a hubot for each
  var adapters = process.env.ADAPTERS.split(/\s*,\s*/g)
  _.each(adapters, function(adapter){
    portfinder.getPort(function(e, port) {
      // copy env for child (separate PORT)
      var envCopy = _.clone(process.env)
      envCopy['PORT'] = port
      // spawn hubot with the copied env for childprocess
      var hb = spawn('./bin/hubot', ['-a', adapter, '--name', botname], { stdio: 'inherit', env: envCopy })
      children.push(hb);
      console.log("Deployed", botname, "with", adapter, "at port", port)
      // update basePort for next search
      portfinder.basePort += 1
    })
  })

  var cleanExit = function() { process.exit() };
  process.on('SIGINT', cleanExit); // catch ctrl-c
  process.on('SIGTERM', cleanExit); // catch kill
};
<commit_msg>do not kill stop neo4j when bot dies; for performance purpose<commit_after>// dependencies
var env = require('node-env-file');
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var _ = require('lomath');
var portfinder = require('portfinder');

// export the setEnv for convenient usage in dev
module.exports = setEnv;

// set env if not already set externally
// .env must exist if setting env vars externally
function setEnv(defaultKey) {
  // optionally set defaultKey
  process.env.DEPLOY = process.env.DEPLOY || defaultKey;

  try {
    env(__dirname + '/.env', { overwrite: false });
    // reset port for dev
    if (process.env.NODE_ENV == 'development') { process.env.PORT = 1000 + parseInt(process.env.PORT) };
    // then set env keys for the deployed bot
    console.log("Deploying using", process.env.DEPLOY)
    env(__dirname + '/bin/' + process.env.DEPLOY);
  } catch (e) {
    console.log(e)
    console.log('index.js quitting.')
    process.exit(1)
  }
}

// if this file is run directly by `node index.js`
/* istanbul ignore next */
if (require.main === module) {
  // call setEnv with a default key
  setEnv();

  // child processes by spawn
  var children = [];

  // so that hubot is killed when forever exits.
  process.on('exit', function() {
    children.forEach(function(child) {
      child.kill();
    });
    // kill the neo4j brain server too
    // exec('neo4j stop')
    console.log("Shutting down")
  });

  // start and kill neo4j brain server
  exec('neo4j start');

  // set baseport to start scanning
  portfinder.basePort = parseInt(process.env.PORT)

  var botname = process.env.DEPLOY.split("-").pop()
  // detect all adapters, spawn a hubot for each
  var adapters = process.env.ADAPTERS.split(/\s*,\s*/g)
  _.each(adapters, function(adapter){
    portfinder.getPort(function(e, port) {
      // copy env for child (separate PORT)
      var envCopy = _.clone(process.env)
      envCopy['PORT'] = port
      // spawn hubot with the copied env for childprocess
      var hb = spawn('./bin/hubot', ['-a', adapter, '--name', botname], { stdio: 'inherit', env: envCopy })
      children.push(hb);
      console.log("Deployed", botname, "with", adapter, "at port", port)
      // update basePort for next search
      portfinder.basePort += 1
    })
  })

  var cleanExit = function() { process.exit() };
  process.on('SIGINT', cleanExit); // catch ctrl-c
  process.on('SIGTERM', cleanExit); // catch kill
};
<|endoftext|>


<commit_before>var Web3 = require('web3');
var web3;

exports.version = 'version 0.2';

exports.setProvider = function (host = "http://localhost:8545"){
  web3 = new Web3(new Web3.providers.HttpProvider(host));
  web3.eth.defaultAccount = web3.eth.accounts[0];
}

exports.setDefaultAccount = function (account){
  web3.eth.defaultAccount = account;
}

exports.getAddress = function(contrato) {
    let address;
    if (address == undefined || /0x([a-z0-9]{40,})$/.test(address)){
      console.log('ERROR: contract address not found');
    } else {
      address = truffleBuild.networks[web3.version.network].address;
    }
}

exports.getContractInstance = function (abi, address, web3Instance){
  if(web3Instance != undefined){
    web3 = web3Instance;
  }else{
    checkWeb3Instance();
  }
  var contract = web3.eth.contract(abi);
  contractInstance = contract.at(address);
  return contractInstance;
}

exports.blkListenAllEventsWithFilter = function(contractInstance, callback, filterParam, filterValue){
  var events = contractInstance.allEvents([{filterParam: filterValue}]);
  events.watch(function(error, event){
      if (error) {
        callback(error, null);
      } else {
         var eventRet = event;
        callback(null, eventRet);
      }
  });
}

exports.blkListenAllEventsContinuously = function(contractInstance, callback){
  var events = contractInstance.allEvents();
  events.watch(function(error, event){
      if (error) {
        callback(error, null);
      } else {
         var eventRet = event;
        callback(null, eventRet);
      }
  });
}

exports.blkListenAllEventsOnce = function(contractInstance, callback){
  var events = contractInstance.allEvents();
  events.watch(function(error, event){
    if (error) {
      callback(error, null);
    } else {
       var eventRet = event;
      callback(null, eventRet);
      events.stopWatching();
      }
  });
}

exports.printEventLog = function(instanceEvent){
    var myEvent = instanceEvent({},{fromBlock: 0, toBlock: "latest"});
    var eventLog = '';
    myEvent.get(function(error, logs){
      if(error) {
        console.log(error);
      } else {
        logs.forEach(function(element){
          console.log(element.args);
        });
      }
    });
  }

var checkWeb3Instance = function (){
  if(web3 == undefined){
    console.log('EASYWEB3 WARNING: Web3 instance is undefined, please specify it with the correct function or add it as a parameter in this one');
  }
  else {
    console.log('Everything ok');
  }
}

var JsethContract = function(abi, address, contract, instance){
  this.abi = abi;
  this.address = address;
  this.instance = instance;
  this.contract = contract;
  var listFunctions = function(){
    let index = 0;
    var list = [];
    abi.forEach((foo)=>{
      let item = {};
      item.name = foo.name;
      item.index = index;
      list[index] = item;
      index ++;
    });
    return list;
  }
  this.listFunctions = listFunctions();
}

exports.JsethContractFromTruffle = function(truffleBuild, callback){
  if (truffleBuild.networks[web3.version.network] == undefined){
    console.log('******************\nERROR: contract address not found, contract maybe not deployed\n******************');
    var error = 'error truffle object'
    callback(error, null);
  } else {
    if(!/0x([a-z0-9]{40,})$/.test(truffleBuild.networks[web3.version.network].address)){
      console.log('ERROR: Invalid address ' + truffleBuild.networks[web3.version.network].address);
      var error = 'error address';
      callback(error, null);
    } else {
      let address = truffleBuild.networks[web3.version.network].address;
      let abi = truffleBuild.abi;
      let contract = web3.eth.contract(abi);
      let instance = contract.at(address);
      callback(null, new JsethContract(abi, address, contract, instance));
    }
  }
}

exports.encodePayload = function(abiFoo, args, callback){
  if(abiFoo.inputs.length != args.length){
    callback('error: mismatch inputs', null);
  } else {
    let encodedPayload = '';
    let fooSign = abiFoo.name + '(';
    abiFoo.inputs.forEach((input) => {
      fooSign = fooSign + input.type +',';
    });
    fooSign = fooSign.slice(0,fooSign.length - 1) + ')';
    fooSign = web3.sha3(fooSign).slice(0,10);
    if(abiFoo.inputs.length == 0){
      encodedPayload = fooSign +'0'.repeat(56);
    } else {
      encodedPayload = fooSign;
      args.forEach((arg)=>{
        encodedPayload = encodedPayload + '0'.repeat(66 - web3.toHex(arg).length) + web3.toHex(arg).slice(2, web3.toHex(arg).length);
      });
    }
    callback(null, encodedPayload);
  }
}
<commit_msg>encodePayload fixed<commit_after>var fs = require('fs');
var Web3 = require('web3');
var web3;

exports.version = 'version 0.2';

exports.setProvider = function (host = "http://localhost:8545"){
  web3 = new Web3(new Web3.providers.HttpProvider(host));
  web3.eth.defaultAccount = web3.eth.accounts[0];
}

exports.setDefaultAccount = function (account){
  web3.eth.defaultAccount = account;
}

exports.getWeb3Instance = function (){
  return web3;
}

exports.getAddress = function(contrato) {
    let address;
    if (address == undefined || /0x([a-z0-9]{40,})$/.test(address)){
      console.log('ERROR: contract address not found');
    } else {
      address = truffleBuild.networks[web3.version.network].address;
    }
}

exports.getContractInstance = function (abi, address, web3Instance){
  if(web3Instance != undefined){
    web3 = web3Instance;
  }else{
    checkWeb3Instance();
  }
  var contract = web3.eth.contract(abi);
  contractInstance = contract.at(address);
  return contractInstance;
}

exports.blkListenAllEventsWithFilter = function(contractInstance, callback, filterParam, filterValue){
  var events = contractInstance.allEvents([{filterParam: filterValue}]);
  events.watch(function(error, event){
      if (error) {
        callback(error, null);
      } else {
         var eventRet = event;
        callback(null, eventRet);
      }
  });
}

exports.blkListenAllEventsContinuously = function(contractInstance, callback){
  var events = contractInstance.allEvents();
  events.watch(function(error, event){
      if (error) {
        callback(error, null);
      } else {
         var eventRet = event;
        callback(null, eventRet);
      }
  });
}

exports.blkListenAllEventsOnce = function(contractInstance, callback){
  var events = contractInstance.allEvents();
  events.watch(function(error, event){
    if (error) {
      callback(error, null);
    } else {
       var eventRet = event;
      callback(null, eventRet);
      events.stopWatching();
      }
  });
}

exports.printEventLog = function(instanceEvent){
    var myEvent = instanceEvent({},{fromBlock: 0, toBlock: "latest"});
    var eventLog = '';
    myEvent.get(function(error, logs){
      if(error) {
        console.log(error);
      } else {
        logs.forEach(function(element){
          console.log(element.args);
        });
      }
    });
  }

var checkWeb3Instance = function (){
  if(web3 == undefined){
    console.log('EASYWEB3 WARNING: Web3 instance is undefined, please specify it with the correct function or add it as a parameter in this one');
  }
  else {
    console.log('Everything ok');
  }
}

var JsethContract = function(abi, address, contract, instance){
  this.abi = abi;
  this.address = address;
  this.instance = instance;
  this.contract = contract;
  var listFunctions = function(){
    let index = 0;
    var list = [];
    abi.forEach((foo)=>{
      let item = {};
      item.name = foo.name;
      item.index = index;
      list[index] = item;
      index ++;
    });
    return list;
  }
  this.listFunctions = listFunctions();
}

exports.jsethContractFromTruffle = function(_truffleBuild, callback){
  var version = web3.version.network;
  if (typeof _truffleBuild == 'string'){
    truffleBuild = JSON.parse(fs.readFileSync(_truffleBuild, 'utf8'));
  } else if (typeof _truffleBuild == 'object'){
    truffleBuild = _truffleBuild;
  } else {
    callback(new Error('Error: Unknown truffle source'), null);
  }
  if (truffleBuild.networks[web3.version.network] == undefined){
    callback(new Error('Error: contract address not found, contract maybe not deployed'), null);
  } else {
    if(!/0x([a-z0-9]{40,})$/.test(truffleBuild.networks[version].address)){
      callback(new Error('Error: Invalid address ' + truffleBuild.networks[version].addres), null);
    } else {
      let address = truffleBuild.networks[version].address;
      let abi = truffleBuild.abi;
      let contract = web3.eth.contract(abi);
      let instance = contract.at(address);
      callback(null, new JsethContract(abi, address, contract, instance));
    }
  }
}

exports.encodePayload = function(abiFoo, args, callback){
  if(abiFoo.inputs.length != args.length){
    callback(new Error('Error: mismatch inputs'), null);
  } else {
    let encodedPayload = '';
    let fooSign = abiFoo.name + '(';
    if (abiFoo.inputs.length != 0) {
      abiFoo.inputs.forEach((input) => {
        fooSign = fooSign + input.type +',';
      });
      fooSign = fooSign.slice(0,fooSign.length - 1);
    }
    fooSign = fooSign + ')';
    fooSign = web3.sha3(fooSign).slice(0,10);
    if(abiFoo.inputs.length == 0){
      encodedPayload = fooSign +'0'.repeat(56);
    } else {
      encodedPayload = fooSign;
      args.forEach((arg)=>{
        encodedPayload = encodedPayload + '0'.repeat(66 - web3.toHex(arg).length) + web3.toHex(arg).slice(2, web3.toHex(arg).length);
      });
    }
    callback(null, encodedPayload);
  }
}
<|endoftext|>


<commit_before>'use strict';

import gulp         from 'gulp';
import gulpif       from 'gulp-if';
import gutil        from 'gulp-util';
import source       from 'vinyl-source-stream';
import sourcemaps   from 'gulp-sourcemaps';
import buffer       from 'vinyl-buffer';
import streamify    from 'gulp-streamify';
import watchify     from 'watchify';
import browserify   from 'browserify';
import babelify     from 'babelify';
import uglify       from 'gulp-uglify';
import browserSync  from 'browser-sync';
import debowerify   from 'debowerify';
import ngAnnotate   from 'browserify-ngannotate';
import handleErrors from '../util/handleErrors';
import config       from '../config';

// Based on: http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/
function buildScript(file) {

  const shouldCreateSourcemap = !global.isProd || config.browserify.prodSourcemap;

  let bundler = browserify({
    entries: [config.sourceDir + 'js/' + file],
    debug: shouldCreateSourcemap,
    cache: {},
    packageCache: {},
    fullPaths: !global.isProd
  });

  if ( !global.isProd ) {
    bundler = watchify(bundler);

    bundler.on('update', function() {
      rebundle();
      gutil.log('Rebundle...');
    });
  }

  const transforms = [
    { 'name':babelify, 'options': {}},
    { 'name':debowerify, 'options': {}},
    { 'name':ngAnnotate, 'options': {}},
    { 'name':'brfs', 'options': {}},
    { 'name':'bulkify', 'options': {}}
  ];

  transforms.forEach(function(transform) {
    bundler.transform(transform.name, transform.options);
  });

  function rebundle() {
    const stream = bundler.bundle();
    const sourceMapLocation = global.isProd ? './' : '';

    return stream.on('error', handleErrors)
      .pipe(source(file))
      .pipe(gulpif(shouldCreateSourcemap, buffer()))
      .pipe(gulpif(shouldCreateSourcemap, sourcemaps.init({ loadMaps: true })))
      .pipe(gulpif(global.isProd, streamify(uglify({
        compress: { drop_console: true } // eslint-disable-line camelcase
      }))))
      .pipe(gulpif(shouldCreateSourcemap, sourcemaps.write(sourceMapLocation)))
      .pipe(gulp.dest(config.scripts.dest))
      .pipe(browserSync.stream());
  }

  return rebundle();

}

gulp.task('browserify', function() {

  return buildScript('main.js');

});
<commit_msg>use bundleLogger<commit_after>'use strict';

import gulp         from 'gulp';
import gulpif       from 'gulp-if';
import source       from 'vinyl-source-stream';
import sourcemaps   from 'gulp-sourcemaps';
import buffer       from 'vinyl-buffer';
import streamify    from 'gulp-streamify';
import watchify     from 'watchify';
import browserify   from 'browserify';
import babelify     from 'babelify';
import uglify       from 'gulp-uglify';
import browserSync  from 'browser-sync';
import debowerify   from 'debowerify';
import ngAnnotate   from 'browserify-ngannotate';
import handleErrors from '../util/handleErrors';
import bundleLogger from '../util/bundleLogger';
import config       from '../config';

// Based on: http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/
function buildScript(file) {

  const shouldCreateSourcemap = !global.isProd || config.browserify.prodSourcemap;

  let bundler = browserify({
    entries: [config.sourceDir + 'js/' + file],
    debug: shouldCreateSourcemap,
    cache: {},
    packageCache: {},
    fullPaths: !global.isProd
  });

  if ( !global.isProd ) {
    bundler = watchify(bundler);

    bundler.on('update', rebundle);
  }

  const transforms = [
    { 'name':babelify, 'options': {}},
    { 'name':debowerify, 'options': {}},
    { 'name':ngAnnotate, 'options': {}},
    { 'name':'brfs', 'options': {}},
    { 'name':'bulkify', 'options': {}}
  ];

  transforms.forEach(function(transform) {
    bundler.transform(transform.name, transform.options);
  });

  function rebundle() {
    bundleLogger.start();

    const stream = bundler.bundle();
    const sourceMapLocation = global.isProd ? './' : '';

    return stream
      .on('error', handleErrors)
      .on('end', bundleLogger.end)
      .pipe(source(file))
      .pipe(gulpif(shouldCreateSourcemap, buffer()))
      .pipe(gulpif(shouldCreateSourcemap, sourcemaps.init({ loadMaps: true })))
      .pipe(gulpif(global.isProd, streamify(uglify({
        compress: { drop_console: true } // eslint-disable-line camelcase
      }))))
      .pipe(gulpif(shouldCreateSourcemap, sourcemaps.write(sourceMapLocation)))
      .pipe(gulp.dest(config.scripts.dest))
      .pipe(browserSync.stream());
  }

  return rebundle();

}

gulp.task('browserify', function() {

  return buildScript('main.js');

});
<|endoftext|>