<commit_before>/* Copyright 2013 William Summers, Metatribal Research
 * adapted from https://developer.mozilla.org/en-US/docs/JXON
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @author William Summers
 *
 * CSSAssist provides a minimal set of methods for working with CSS
 * Browser support is limited by the availability of
 *            querySelector (http://caniuse.com/queryselector)
 *            add/removeEventListener (ie9+, most others support)
 *
 * these are the chainable methods
 *      init, forEach, hasClass, addClass, removeClass, toggleClass
 *      setStyle, setAttr, addListener, removeListener
 *
 * additional methods supplied by plugin (chainable)
 *      unique, union, intersects, difference
 *
 * non-chainable methods
 *      makeArray, loadCSS, createCSS
 */

// create a self-invoking function
;(function () {

        // this is the main object
        // internally assigned to _ to enhance compressor performance
        var _ = CSSAssist = function (selector, context) {
                return new _.fn.init(selector);
        };

        // _ version number
        _.version = '2.0.0-alpha';

        // define the CSSAssist prototype
        _.fn = _.prototype = {

                /**
                 * CSSAssist
                 *
                 */
                init: function (selector) {
                        var context = [];
                        // if no selector, pass
                        if (!selector) context = [];
                        // got self
                        else if (selector instanceof CSSAssist) return selector;
                        else {
                                // if an array
                                if (selector instanceof Array) context = selector;
                                // wrap dom nodes.
                                else if (typeof selector === 'object') context = [selector];
                                // if its a string (CSS selector)
                                else if (typeof selector === 'string') {
                                        context = [].slice.call(document.querySelectorAll(selector));
                                }
                        }

                        // set the prototype for the context tp CSSAssist and return
                        context.__proto__ = _.fn;
                        return context;

                },

                // simple forEach loop (faster than native forEach for most cases)
                forEach: function (func, context) {
                        for (var i = 0; i < this.length; ++i) {
                                func.call(this, this[i]);
                        }
                        return this;
                },

                /**
                 * Returns true if each node in the context containes each class in values
                 * Returns false otherwise.
                 * values may be either a space delimited string or an array
                 * e.g. CSSAssist('div').hasClass('myAwesomeStyle');
                 */
                hasClass: function (values, context) {
                        if (!values) values =' ';
                        var context = (context) ? _(context) : this,
                                values = _.makeArray(values);
                        for (var i = 0; i < context.length; ++i) {
                                var className = (' ' + context[i].className + ' ').replace(rSpace, ' ');
                                for (var j = 0; j < values.length; ++j) {
                                        if ((className.indexOf(' ' + values[j] + ' ') < 0)) return false;
                                }
                        }
                        return true;

                },

                /**
                 * Adds each class in values to each node in context
                 * values may be either a space delimited string or an array
                 * e.g. CSSAssist('div').addClass('myAwesomeStyle');
                 */
                addClass: function (values, context) {
                        if (values) {
                                var context = (context) ? _(context) : this,
                                        values = _.makeArray(values);
                                context.forEach(
                                        function (item) {
                                                for (var j = 0; j < values.length; ++j) {
                                                        if (!context.hasClass(values[j], item)) item.className += ' ' + values[j];
                                                }
                                        }
                                );
                        }
                        return this;
                },

                /**
                 * Removes each class in values from each node in context
                 * values may be either a space delimited string or an array
                 * e.g. CSSAssist('div').removeClass('myAwesomeStyle');
                 */
                removeClass: function (values, context) {
                        var context = (context) ? _(context) : this;
                        if (values) values = _.makeArray(values);
                        context.forEach(
                                function (item) {
                                        if (values) {
                                                var className = (' ' + item.className + ' ').replace(rSpace, ' ');
                                                for (var j = 0; j < values.length; ++j) {
                                                        while (className.indexOf(' ' + values[j] + ' ') > -1) {
                                                                className = className.replace(' ' + values[j] + ' ', ' ');
                                                        }
                                                }
                                                item.className = className.trim();
                                        } else item.removeAttribute('class');
                                }
                        );

                        return this;
                },

                /**
                 * For each class in values for each node in context
                 *    if the class is present, remove it
                 *    if the class is not present, add it
                 * values may be either a space delimited string or an array
                 * e.g. CSSAssist('div').toggleClass('myAwesomeStyle');
                 */
                toggleClass: function (values, context) {
                        if (values) {
                                var context = (context) ? _(context) : this,
                                    values = _.makeArray(values);
                                context.forEach(
                                        function (item) {
                                                for (var j = 0; j < values.length; ++j) {
                                                        if (context.hasClass(values[j], item)) context.removeClass(values[j], item)
                                                        else context.addClass(values[j], item);
                                                }
                                        }
                                );
                        }
                        return this;
                },

                /**
                 * for each node in context
                 *      sets or clears the specified style property
                 * e.g. CSSAssist('.red').setStyle('color', '#FF0000'); // sets the style
                 * e.g. CSSAssist('.red').setStyle('color', ); // clears the style
                 */
                setStyle: function (property, value, context) {
                        if (property) {
                                var context = (context) ? _(context) : this;
                                context.forEach(
                                        function (item) {
                                                if (value) item.style[property] = value;
                                                else item.style[property] = '';
                                        }
                                );
                        }
                        return this;
                },

                /**
                 * for each node in context
                 *      sets or clears the specified style property
                 * e.g. CSSAssist('span').setAttr('data-src', 'my data source'); // sets the style
                 * e.g. CSSAssist('span').setAttr('data-src', ); // clears the style
                 */
                setAttr: function (attr, value, context) {
                        if (attr) {
                                var context = (context) ? _(context) : this;
                                context.forEach(
                                        function (item) {
                                                if (value) item.setAttribute(attr, value);
                                                else item.removeAttribute(attr);
                                        }
                                );
                        }
                        return this;
                },

                /**
                 * Set operations (as plugins)
                 */

                // unique function (returns an array not a CSSAssist object)
                unique:  function (context) {
                        var context = (context) ? _(context) : this;
                        var unique = [];
                        for (var i = 0; i < context.length; i += 1) {
                                if (unique.indexOf(context[i]) < 0) {
                                        unique.push(context[i]);
                                }
                        }
                        return _(unique);
                },

                // union (concat)
                union: function (arrayObj, context) {
                        var context = (context) ? _(context) : this;
                        if (arrayObj) {
                                return _([].concat.call(context, arrayObj)).unique();
                        }
                },

                // intersection (brute force)
                intersects: function (arrayObj, context) {
                        var context = (context) ? _(context) : this;
                        if (arrayObj) {
                                var ret = [];
                                context.forEach(
                                        function (item) {
                                                for (var i = 0; i < arrayObj.length; ++i) {
                                                        if (item == arrayObj[i]) {
                                                                ret.push(item);
                                                                break;
                                                        }
                                                }
                                        }
                                );
                                return _(ret).unique();
                        }
                        return this;
                },

                // difference
                difference: function (arrayObj, context) {
                        var context = (context) ? _(context) : this;
                        if (arrayObj) {
                                var ret = []
                                var all = context.union(arrayObj);
                                all.forEach(
                                    function (item) {
                                        //var item = all[i];
                                        if (([].indexOf.call(context, item) > -1) != ([].indexOf.call(arrayObj, item) > -1)) {
                                                ret.push(item)
                                        }
                                    }
                                );
                                return _(ret);
                        }
                        return this;
                },

                /**
                 * Add an event listener to each node in context
                 */
                addListener: function (type, listener, useCapture) {
                        if (type && listener) {
                                var capture = useCapture || false;
                                this.forEach(
                                        function (item) {
                                                item.addEventListener(type, listener, capture);
                                        }
                                );
                        }
                        return this;
                },

                /**
                 * Remove an event listener from each node in context
                 */
                removeListener: function (type, listener, useCapture) {
                        if (type && listener) {
                                var capture = useCapture || false;
                                this.forEach(
                                        function (item) {
                                                item.removeEventListener(type, listener, capture);
                                        }
                                );
                        }
                        return this;
                }

        };  // end prototype

        // regex for collapsing space, tabs, returns, and newlines to single space
        var rSpace = /[\s+\t\r\n\f]/g;

        /**
         * Utility methods outside of the prototype but in CSSAssist namespace
         * these methods do not require/accept a context
         */

        /**
         * Utility method to coerce a space delimited string into an array
         * if values is not passed, return an empty array
         * if values is already an array, simply return it
         * if values is a string clean and split it
         * oterwise, return this
         */
        _.makeArray = function (values) {
                if (!values) return []
                if (values instanceof Array) return values
                else if (typeof values === 'string') return values.replace(/^\s+|\s+$/g, '').split(/\s+/);
                else return this;
        };

        /**
         * Load an external CSS file
         * e.g. CSSAssist.loadCSSLink('http://meyerweb.com/eric/tools/css/reset/reset.css');
         */
        _.loadCSS = function (url) {
                if (url) {
                        var head = document.getElementsByTagName('head')[0],
                                link = document.createElement('link');
                        link.type = 'text/css';
                        link.rel = 'stylesheet';
                        link.href = url;
                        head.appendChild(link);
                        return this;
                }
                return this;
        }

        /**
         * Inject a programmatically created stylesheet
         * styles is a string containing css rules to be injected
         * e.g CSSAssist.loadCSS( 'body { background-color: red;} div { background-color: yellow;}' );
         */
        _.createCSS = function (styles) {
                if (styles) {
                        var head = document.getElementsByTagName('head')[0],
                                styleNode = document.createElement('style');
                        styleNode.type = 'text/css';
                        if (styleNode.styleSheet) styleNode.styleSheet.cssText = styles;
                        else styleNode.appendChild(document.createTextNode(styles));
                        head.appendChild(styleNode);
                }
                return this;
        }

        // Give the init method the CSSAssist prototype for later instantiation
        _.fn.init.prototype = _.fn;

})() // end self-invoking function
<commit_msg>removed leading semi-colon added trailing semi-colon removed 'context' from constructor as it was not used<commit_after>/* Copyright 2013 William Summers, Metatribal Research
 * adapted from https://developer.mozilla.org/en-US/docs/JXON
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @author William Summers
 *
 * CSSAssist provides a minimal set of methods for working with CSS
 * Browser support is limited by the availability of
 *            querySelector (http://caniuse.com/queryselector)
 *            add/removeEventListener (ie9+, most others support)
 *
 * these are the chainable methods
 *      init, forEach, hasClass, addClass, removeClass, toggleClass
 *      setStyle, setAttr, addListener, removeListener
 *
 * additional methods supplied by plugin (chainable)
 *      unique, union, intersects, difference
 *
 * non-chainable methods
 *      makeArray, loadCSS, createCSS
 */

// create a self-invoking function
(function () {

        // this is the main object
        // internally assigned to _ to enhance compressor performance
        var _ = CSSAssist = function (selector) {
                return new _.fn.init(selector);
        };

        // _ version number
        _.version = '2.0.0-alpha';

        // define the CSSAssist prototype
        _.fn = _.prototype = {

                /**
                 * CSSAssist
                 *
                 */
                init: function (selector) {
                        var context = [];
                        // if no selector, pass
                        if (!selector) context = [];
                        // got self
                        else if (selector instanceof CSSAssist) return selector;
                        else {
                                // if an array
                                if (selector instanceof Array) context = selector;
                                // wrap dom nodes.
                                else if (typeof selector === 'object') context = [selector];
                                // if its a string (CSS selector)
                                else if (typeof selector === 'string') {
                                        context = [].slice.call(document.querySelectorAll(selector));
                                }
                        }

                        // set the prototype for the context tp CSSAssist and return
                        context.__proto__ = _.fn;
                        return context;

                },

                // simple forEach loop (faster than native forEach for most cases)
                forEach: function (func, context) {
                        for (var i = 0; i < this.length; ++i) {
                                func.call(this, this[i]);
                        }
                        return this;
                },

                /**
                 * Returns true if each node in the context containes each class in values
                 * Returns false otherwise.
                 * values may be either a space delimited string or an array
                 * e.g. CSSAssist('div').hasClass('myAwesomeStyle');
                 */
                hasClass: function (values, context) {
                        if (!values) values =' ';
                        var context = (context) ? _(context) : this,
                                values = _.makeArray(values);
                        for (var i = 0; i < context.length; ++i) {
                                var className = (' ' + context[i].className + ' ').replace(rSpace, ' ');
                                for (var j = 0; j < values.length; ++j) {
                                        if ((className.indexOf(' ' + values[j] + ' ') < 0)) return false;
                                }
                        }
                        return true;

                },

                /**
                 * Adds each class in values to each node in context
                 * values may be either a space delimited string or an array
                 * e.g. CSSAssist('div').addClass('myAwesomeStyle');
                 */
                addClass: function (values, context) {
                        if (values) {
                                var context = (context) ? _(context) : this,
                                        values = _.makeArray(values);
                                context.forEach(
                                        function (item) {
                                                for (var j = 0; j < values.length; ++j) {
                                                        if (!context.hasClass(values[j], item)) item.className += ' ' + values[j];
                                                }
                                        }
                                );
                        }
                        return this;
                },

                /**
                 * Removes each class in values from each node in context
                 * values may be either a space delimited string or an array
                 * e.g. CSSAssist('div').removeClass('myAwesomeStyle');
                 */
                removeClass: function (values, context) {
                        var context = (context) ? _(context) : this;
                        if (values) values = _.makeArray(values);
                        context.forEach(
                                function (item) {
                                        if (values) {
                                                var className = (' ' + item.className + ' ').replace(rSpace, ' ');
                                                for (var j = 0; j < values.length; ++j) {
                                                        while (className.indexOf(' ' + values[j] + ' ') > -1) {
                                                                className = className.replace(' ' + values[j] + ' ', ' ');
                                                        }
                                                }
                                                item.className = className.trim();
                                        } else item.removeAttribute('class');
                                }
                        );

                        return this;
                },

                /**
                 * For each class in values for each node in context
                 *    if the class is present, remove it
                 *    if the class is not present, add it
                 * values may be either a space delimited string or an array
                 * e.g. CSSAssist('div').toggleClass('myAwesomeStyle');
                 */
                toggleClass: function (values, context) {
                        if (values) {
                                var context = (context) ? _(context) : this,
                                    values = _.makeArray(values);
                                context.forEach(
                                        function (item) {
                                                for (var j = 0; j < values.length; ++j) {
                                                        if (context.hasClass(values[j], item)) context.removeClass(values[j], item)
                                                        else context.addClass(values[j], item);
                                                }
                                        }
                                );
                        }
                        return this;
                },

                /**
                 * for each node in context
                 *      sets or clears the specified style property
                 * e.g. CSSAssist('.red').setStyle('color', '#FF0000'); // sets the style
                 * e.g. CSSAssist('.red').setStyle('color', ); // clears the style
                 */
                setStyle: function (property, value, context) {
                        if (property) {
                                var context = (context) ? _(context) : this;
                                context.forEach(
                                        function (item) {
                                                if (value) item.style[property] = value;
                                                else item.style[property] = '';
                                        }
                                );
                        }
                        return this;
                },

                /**
                 * for each node in context
                 *      sets or clears the specified style property
                 * e.g. CSSAssist('span').setAttr('data-src', 'my data source'); // sets the style
                 * e.g. CSSAssist('span').setAttr('data-src', ); // clears the style
                 */
                setAttr: function (attr, value, context) {
                        if (attr) {
                                var context = (context) ? _(context) : this;
                                context.forEach(
                                        function (item) {
                                                if (value) item.setAttribute(attr, value);
                                                else item.removeAttribute(attr);
                                        }
                                );
                        }
                        return this;
                },

                /**
                 * Set operations (as plugins)
                 */

                // unique function (returns an array not a CSSAssist object)
                unique:  function (context) {
                        var context = (context) ? _(context) : this;
                        var unique = [];
                        for (var i = 0; i < context.length; i += 1) {
                                if (unique.indexOf(context[i]) < 0) {
                                        unique.push(context[i]);
                                }
                        }
                        return _(unique);
                },

                // union (concat)
                union: function (arrayObj, context) {
                        var context = (context) ? _(context) : this;
                        if (arrayObj) {
                                return _([].concat.call(context, arrayObj)).unique();
                        }
                },

                // intersection (brute force)
                intersects: function (arrayObj, context) {
                        var context = (context) ? _(context) : this;
                        if (arrayObj) {
                                var ret = [];
                                context.forEach(
                                        function (item) {
                                                for (var i = 0; i < arrayObj.length; ++i) {
                                                        if (item == arrayObj[i]) {
                                                                ret.push(item);
                                                                break;
                                                        }
                                                }
                                        }
                                );
                                return _(ret).unique();
                        }
                        return this;
                },

                // difference
                difference: function (arrayObj, context) {
                        var context = (context) ? _(context) : this;
                        if (arrayObj) {
                                var ret = []
                                var all = context.union(arrayObj);
                                all.forEach(
                                    function (item) {
                                        //var item = all[i];
                                        if (([].indexOf.call(context, item) > -1) != ([].indexOf.call(arrayObj, item) > -1)) {
                                                ret.push(item)
                                        }
                                    }
                                );
                                return _(ret);
                        }
                        return this;
                },

                /**
                 * Add an event listener to each node in context
                 */
                addListener: function (type, listener, useCapture) {
                        if (type && listener) {
                                var capture = useCapture || false;
                                this.forEach(
                                        function (item) {
                                                item.addEventListener(type, listener, capture);
                                        }
                                );
                        }
                        return this;
                },

                /**
                 * Remove an event listener from each node in context
                 */
                removeListener: function (type, listener, useCapture) {
                        if (type && listener) {
                                var capture = useCapture || false;
                                this.forEach(
                                        function (item) {
                                                item.removeEventListener(type, listener, capture);
                                        }
                                );
                        }
                        return this;
                }

        };  // end prototype

        // regex for collapsing space, tabs, returns, and newlines to single space
        var rSpace = /[\s+\t\r\n\f]/g;

        /**
         * Utility methods outside of the prototype but in CSSAssist namespace
         * these methods do not require/accept a context
         */

        /**
         * Utility method to coerce a space delimited string into an array
         * if values is not passed, return an empty array
         * if values is already an array, simply return it
         * if values is a string clean and split it
         * oterwise, return this
         */
        _.makeArray = function (values) {
                if (!values) return []
                if (values instanceof Array) return values
                else if (typeof values === 'string') return values.replace(/^\s+|\s+$/g, '').split(/\s+/);
                else return this;
        };

        /**
         * Load an external CSS file
         * e.g. CSSAssist.loadCSSLink('http://meyerweb.com/eric/tools/css/reset/reset.css');
         */
        _.loadCSS = function (url) {
                if (url) {
                        var head = document.getElementsByTagName('head')[0],
                                link = document.createElement('link');
                        link.type = 'text/css';
                        link.rel = 'stylesheet';
                        link.href = url;
                        head.appendChild(link);
                        return this;
                }
                return this;
        }

        /**
         * Inject a programmatically created stylesheet
         * styles is a string containing css rules to be injected
         * e.g CSSAssist.loadCSS( 'body { background-color: red;} div { background-color: yellow;}' );
         */
        _.createCSS = function (styles) {
                if (styles) {
                        var head = document.getElementsByTagName('head')[0],
                                styleNode = document.createElement('style');
                        styleNode.type = 'text/css';
                        if (styleNode.styleSheet) styleNode.styleSheet.cssText = styles;
                        else styleNode.appendChild(document.createTextNode(styles));
                        head.appendChild(styleNode);
                }
                return this;
        }

        // Give the init method the CSSAssist prototype for later instantiation
        _.fn.init.prototype = _.fn;

})(); // end self-invoking function
<|endoftext|>


<commit_before>var	async = require('async'),
	nconf = module.parent.require('nconf'),
	Topics = module.parent.require('./topics'),
	User = module.parent.require('./user'),
	Notifications = module.parent.require('./notifications'),
	Utils = module.parent.require('../public/src/utils'),
	websockets = module.parent.require('./websockets'),
	Mentions = {
		notify: function(postData) {
			var	_self = this,
				regex = /(@\b[\w\d\-_]+\b)/g,
				matches = postData.content.match(regex);

			if (matches) {
				async.filter(matches, function(match, next) {
					var	slug = Utils.slugify(match.slice(1));
					User.exists(slug, next);
				}, function(matches) {
					async.parallel({
						title: function(next) {
							Topics.getTopicField(postData.tid, 'title', next);
						},
						author: function(next) {
							User.getUserField(postData.uid, 'username', next);
						},
						uids: function(next) {
							async.map(matches, function(match, next) {
								var	slug = Utils.slugify(match.slice(1));
								User.getUidByUserslug(slug, next);
							}, next);
						}
					}, function(err, results) {
						if (!err) {
							Notifications.create('' + results.author + ' mentioned you in "' + results.title + '"', '/topic/' + postData.tid, 'mention:' + postData.tid, function(nid) {
								Notifications.push(nid, results.uids);
							});
						}
					});
				});
			}
		},
		addMentions: function(postContent, callback) {
			var	_self = this,
				regex = /(@\b[\w\d\-_]+\b)/g,
				relativeUrl = nconf.get('relative_url') || '',
				matches = postContent.match(regex),
				uniqueMatches = [];

			if (matches) {
				// Eliminate duplicates
				matches.forEach(function(match) {
					if (uniqueMatches.indexOf(match) === -1) uniqueMatches.push(match);
				});

				// Filter out those that aren't real users
				async.filter(uniqueMatches, function(match, next) {
					var	slug = Utils.slugify(match.slice(1));
					User.exists(slug, next);
				}, function(matches) {
					if (matches) {
						async.each(matches, function(match, next) {
							var	userslug = Utils.slugify(match.slice(1));
							User.getUidByUserslug(userslug, function(err, uid) {
								postContent = postContent.replace(new RegExp(match, 'g'), ' ' + match + '');
								next();
							});
						}, function(err) {
							callback(null, postContent);
						});
					} else callback(null, postContent);
				});
			} else callback(null, postContent);
		}
	};

module.exports = Mentions;
<commit_msg>fixing mentions to work with new fontawesome lib in nodebb - closes #12<commit_after>var	async = require('async'),
	nconf = module.parent.require('nconf'),
	Topics = module.parent.require('./topics'),
	User = module.parent.require('./user'),
	Notifications = module.parent.require('./notifications'),
	Utils = module.parent.require('../public/src/utils'),
	websockets = module.parent.require('./websockets'),
	Mentions = {
		notify: function(postData) {
			var	_self = this,
				regex = /(@\b[\w\d\-_]+\b)/g,
				matches = postData.content.match(regex);

			if (matches) {
				async.filter(matches, function(match, next) {
					var	slug = Utils.slugify(match.slice(1));
					User.exists(slug, next);
				}, function(matches) {
					async.parallel({
						title: function(next) {
							Topics.getTopicField(postData.tid, 'title', next);
						},
						author: function(next) {
							User.getUserField(postData.uid, 'username', next);
						},
						uids: function(next) {
							async.map(matches, function(match, next) {
								var	slug = Utils.slugify(match.slice(1));
								User.getUidByUserslug(slug, next);
							}, next);
						}
					}, function(err, results) {
						if (!err) {
							Notifications.create('' + results.author + ' mentioned you in "' + results.title + '"', '/topic/' + postData.tid, 'mention:' + postData.tid, function(nid) {
								Notifications.push(nid, results.uids);
							});
						}
					});
				});
			}
		},
		addMentions: function(postContent, callback) {
			var	_self = this,
				regex = /(@\b[\w\d\-_]+\b)/g,
				relativeUrl = nconf.get('relative_url') || '',
				matches = postContent.match(regex),
				uniqueMatches = [];

			if (matches) {
				// Eliminate duplicates
				matches.forEach(function(match) {
					if (uniqueMatches.indexOf(match) === -1) uniqueMatches.push(match);
				});

				// Filter out those that aren't real users
				async.filter(uniqueMatches, function(match, next) {
					var	slug = Utils.slugify(match.slice(1));
					User.exists(slug, next);
				}, function(matches) {
					if (matches) {
						async.each(matches, function(match, next) {
							var	userslug = Utils.slugify(match.slice(1));
							User.getUidByUserslug(userslug, function(err, uid) {
								postContent = postContent.replace(new RegExp(match, 'g'), ' ' + match + '');
								next();
							});
						}, function(err) {
							callback(null, postContent);
						});
					} else callback(null, postContent);
				});
			} else callback(null, postContent);
		}
	};

module.exports = Mentions;
<|endoftext|>


<commit_before>(function(module) {
    "use strict";

    var iframe = {},
        embed = ' ';

    user.isAdministrator(function(err, isAdmin) {
        if(isAdmin) {
            iframe.parse = function(postContent, callback) {
                postContent = postContent.replace(/iframe=\w+/gm, embed);
                callback(null, postContent);
            };
        }
        if(!isAdmin) {
            return callback;
        }

    });

    module.exports = iframe;
}(module));<commit_msg>Forgot the user variable<commit_after>(function(module) {
    "use strict";

    var
        user = require('../user'),
        iframe = {},
        embed = ' ';

    user.isAdministrator(function(err, isAdmin) {
        if(isAdmin) {
            iframe.parse = function(postContent, callback) {
                postContent = postContent.replace(/iframe=\w+/gm, embed);
                callback(null, postContent);
            };
        }
        if(!isAdmin) {
            return callback;
        }

    });

    module.exports = iframe;
}(module));<|endoftext|>


<commit_before>"use strict";

var os = require('os'),
	gm = require('gm').subClass({ imageMagick: true }),
	fs = require('fs'),
	plugin = {};

if (os.platform() === 'linux') {
	require('child_process').exec('/usr/bin/which convert', function(err, stdout, stderr) {
		if(err || !stdout) {
			winston.warn('Couldn\'t find convert. Did you install imagemagick?');
		}
	});
}

plugin.resize = function(data, callback) {
	function done(err, stdout, stderr) {
		callback(err);
	}

	if(data.extension === '.gif') {
		gm().in(data.path)
			.in('-coalesce')
			.in('-resize')
			.in(data.width+'x'+data.height+'^')
			.write(data.target || data.path, done);
	} else {
		gm(data.path)
			.in('-resize')
			.in(data.width+'x'+data.height+'^')
			.gravity('Center')
			.crop(data.width, data.height)
			.write(data.target || data.path, done);
	}
};

plugin.size = function(data, callback) {
	gm(data.path).size(function (err, size) {
		if (err) {
			return callback(err);
		}
		var image = {
			path: data.path,
			width: size.width,
			height: size.height
		};
		callback(null, image);
	});
};

plugin.fileTypeAllowed = function(path, callback) {
	callback();
};

plugin.normalise = function(data, callback) {
	gm(data.path).toBuffer('png', function(err, buffer) {
		if (err) {
			return callback(err);
		}
		fs.writeFile(data.path + '.png', buffer, 'binary', callback);
	});
};

module.exports = plugin;
<commit_msg>fix resize if data.width or data.height is undefined<commit_after>"use strict";

var os = require('os'),
	gm = require('gm').subClass({ imageMagick: true }),
	fs = require('fs'),
	plugin = {};

if (os.platform() === 'linux') {
	require('child_process').exec('/usr/bin/which convert', function(err, stdout, stderr) {
		if(err || !stdout) {
			winston.warn('Couldn\'t find convert. Did you install imagemagick?');
		}
	});
}

plugin.resize = function(data, callback) {
	function done(err, stdout, stderr) {
		callback(err);
	}

	if(data.extension === '.gif') {
		gm().in(data.path)
			.in('-coalesce')
			.resize(data.width || null, data.height || null)
			.write(data.target || data.path, done);
	} else {
		gm(data.path)
			.resize(data.width || null, data.height || null)
			.write(data.target || data.path, done);
	}
};

plugin.size = function(data, callback) {
	gm(data.path).size(function (err, size) {
		if (err) {
			return callback(err);
		}
		var image = {
			path: data.path,
			width: size.width,
			height: size.height
		};
		callback(null, image);
	});
};

plugin.fileTypeAllowed = function(path, callback) {
	callback();
};

plugin.normalise = function(data, callback) {
	gm(data.path).toBuffer('png', function(err, buffer) {
		if (err) {
			return callback(err);
		}
		fs.writeFile(data.path + '.png', buffer, 'binary', callback);
	});
};

module.exports = plugin;
<|endoftext|>


<commit_before>(function(module) {
	"use strict";

	var SoundCloud = {},
		embed = '';

	SoundCloud.parse = function(postContent, callback) {
		postContent = postContent.replace(/.+<\/a>/g, embed);
		callback(null, postContent);
	};

	module.exports = SoundCloud;
}(module));
<commit_msg>amp<commit_after>(function(module) {
	"use strict";

	var SoundCloud = {},
		embed = '';

	SoundCloud.parse = function(postContent, callback) {
		postContent = postContent.replace(/.+<\/a>/g, embed);
		callback(null, postContent);
	};

	module.exports = SoundCloud;
}(module));
<|endoftext|>


<commit_before>/* jslint node:true */

'use strict';

exports = module.exports = {
    getAll: getAll,
    getAllLean: getAllLean,
    get: get,
    add: add,
    addFull: addFull,
    put: put,
    del: del
};

var assert = require('assert'),
    ObjectId = require('mongodb').ObjectID,
    config = require('../config.js');

var g_collections = {};

function getCollection(userId) {
    assert.strictEqual(typeof userId, 'string');

    if (!g_collections[userId]) {
        console.log('Opening collection for', userId);

        config.db.createCollection(userId + '_things');
        g_collections[userId] = config.db.collection(userId + '_things');
        g_collections[userId].createIndex({ content: 'text' }, { default_language: 'none' });
    }

    return g_collections[userId];
}

function getAll(userId, query, skip, limit, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof query, 'object');
    assert.strictEqual(typeof skip, 'number');
    assert.strictEqual(typeof limit, 'number');
    assert.strictEqual(typeof callback, 'function');

    getCollection(userId).find(query).skip(skip).limit(limit).sort({ modifiedAt: -1 }).toArray(function (error, result) {
        if (error) return callback(error);
        if (!result) return callback(null, []);

        callback(null, result);
    });
}

function getAllLean(userId, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof callback, 'function');

    getCollection(userId).find({}).toArray(function (error, result) {
        if (error) return callback(error);
        callback(null, result || []);
    });
}

function get(userId, thingId, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof thingId, 'string');
    assert.strictEqual(typeof callback, 'function');

    getCollection(userId).find({ _id: new ObjectId(thingId) }).toArray(function (error, result) {
        if (error) return callback(error);
        if (result.length === 0) return callback(new Error('not found'));

        callback(null, result[0]);
    });
}

function add(userId, content, tags, attachments, externalContent, callback) {
    addFull(userId, content, tags, attachments, externalContent, Date.now(), Date.now(), callback);
}

function addFull(userId, content, tags, attachments, externalContent, createdAt, modifiedAt, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof content, 'string');
    assert(Array.isArray(tags));
    assert(Array.isArray(attachments));
    assert(Array.isArray(externalContent));
    assert.strictEqual(typeof createdAt, 'number');
    assert.strictEqual(typeof modifiedAt, 'number');
    assert.strictEqual(typeof callback, 'function');

    var doc = {
        content: content,
        createdAt: createdAt,
        modifiedAt: modifiedAt,
        tags: tags,
        externalContent: externalContent,
        attachments: attachments
    };

    getCollection(userId).insert(doc, function (error, result) {
        if (error) return callback(error);
        if (!result) return callback(new Error('no result returned'));

        get(userId, result.ops[0]._id, callback);
    });
}

function put(userId, thingId, content, tags, attachments, externalContent, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof thingId, 'string');
    assert.strictEqual(typeof content, 'string');
    assert(Array.isArray(tags));
    assert(Array.isArray(attachments));
    assert(Array.isArray(externalContent));
    assert.strictEqual(typeof callback, 'function');

    var data = {
        content: content,
        tags: tags,
        modifiedAt: new Date(),
        externalContent: externalContent,
        attachments: attachments
    };

    getCollection(userId).update({_id: new ObjectId(thingId) }, { $set: data }, function (error) {
        if (error) return callback(error);

        get(userId, thingId, callback);
    });
}

function del(userId, thingId, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof thingId, 'string');
    assert.strictEqual(typeof callback, 'function');

    getCollection(userId).deleteOne({ _id: new ObjectId(thingId) }, function (error) {
        if (error) return callback(error);
        callback(null);
    });
}
<commit_msg>Force db id to be string<commit_after>/* jslint node:true */

'use strict';

exports = module.exports = {
    getAll: getAll,
    getAllLean: getAllLean,
    get: get,
    add: add,
    addFull: addFull,
    put: put,
    del: del
};

var assert = require('assert'),
    ObjectId = require('mongodb').ObjectID,
    config = require('../config.js');

var g_collections = {};

function getCollection(userId) {
    assert.strictEqual(typeof userId, 'string');

    if (!g_collections[userId]) {
        console.log('Opening collection for', userId);

        config.db.createCollection(userId + '_things');
        g_collections[userId] = config.db.collection(userId + '_things');
        g_collections[userId].createIndex({ content: 'text' }, { default_language: 'none' });
    }

    return g_collections[userId];
}

function getAll(userId, query, skip, limit, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof query, 'object');
    assert.strictEqual(typeof skip, 'number');
    assert.strictEqual(typeof limit, 'number');
    assert.strictEqual(typeof callback, 'function');

    getCollection(userId).find(query).skip(skip).limit(limit).sort({ modifiedAt: -1 }).toArray(function (error, result) {
        if (error) return callback(error);
        if (!result) return callback(null, []);

        callback(null, result);
    });
}

function getAllLean(userId, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof callback, 'function');

    getCollection(userId).find({}).toArray(function (error, result) {
        if (error) return callback(error);
        callback(null, result || []);
    });
}

function get(userId, thingId, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof thingId, 'string');
    assert.strictEqual(typeof callback, 'function');

    getCollection(userId).find({ _id: new ObjectId(thingId) }).toArray(function (error, result) {
        if (error) return callback(error);
        if (result.length === 0) return callback(new Error('not found'));

        callback(null, result[0]);
    });
}

function add(userId, content, tags, attachments, externalContent, callback) {
    addFull(userId, content, tags, attachments, externalContent, Date.now(), Date.now(), callback);
}

function addFull(userId, content, tags, attachments, externalContent, createdAt, modifiedAt, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof content, 'string');
    assert(Array.isArray(tags));
    assert(Array.isArray(attachments));
    assert(Array.isArray(externalContent));
    assert.strictEqual(typeof createdAt, 'number');
    assert.strictEqual(typeof modifiedAt, 'number');
    assert.strictEqual(typeof callback, 'function');

    var doc = {
        content: content,
        createdAt: createdAt,
        modifiedAt: modifiedAt,
        tags: tags,
        externalContent: externalContent,
        attachments: attachments
    };

    getCollection(userId).insert(doc, function (error, result) {
        if (error) return callback(error);
        if (!result) return callback(new Error('no result returned'));

        get(userId, String(result.ops[0]._id), callback);
    });
}

function put(userId, thingId, content, tags, attachments, externalContent, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof thingId, 'string');
    assert.strictEqual(typeof content, 'string');
    assert(Array.isArray(tags));
    assert(Array.isArray(attachments));
    assert(Array.isArray(externalContent));
    assert.strictEqual(typeof callback, 'function');

    var data = {
        content: content,
        tags: tags,
        modifiedAt: new Date(),
        externalContent: externalContent,
        attachments: attachments
    };

    getCollection(userId).update({_id: new ObjectId(thingId) }, { $set: data }, function (error) {
        if (error) return callback(error);

        get(userId, thingId, callback);
    });
}

function del(userId, thingId, callback) {
    assert.strictEqual(typeof userId, 'string');
    assert.strictEqual(typeof thingId, 'string');
    assert.strictEqual(typeof callback, 'function');

    getCollection(userId).deleteOne({ _id: new ObjectId(thingId) }, function (error) {
        if (error) return callback(error);
        callback(null);
    });
}
<|endoftext|>


<commit_before>/*!
 * lightcm
 * https://github.com/oskarbraten/lightcm
 */

(function () {

    'use strict';

    function isFunction (object) {
        return typeof object === 'function';
    }

    function render(str, data) {
        return str.replace(/{{\s*([\w]+)\s*}}/g, function (a, b) {
            let r = data[b];
            if (isFunction(r)) {
                r = r();
            }
            return typeof r === 'string' || typeof r === 'number' ? r : a;
        });
    };

    let LightCM = {
        items: null,
        element: null
    };

    LightCM.init = function (items) {
        if (items === undefined) {
            throw Error('Must provide an array of items as argument.');
        }

        this.items = items;

        // remove old context menu element.
        let _oldElement = document.getElementById('context-menu');
        if (_oldElement) {
            _oldElement.remove();
        }

        let element = document.createElement('div');
        element.classList.add('context-menu');
        element.setAttribute('id', 'context-menu');

        for (let item of this.items) {
            let button = document.createElement('a');
            button.classList.add('btn');
            button.textContent = item.label;

            for (let attribute in item.attributes) {
                let attributeValue = item.attributes[attribute];
                if (isFunction(attributeValue)) {
                    attributeValue = attributeValue();
                }
                button.setAttribute(attribute, attributeValue);
            }

            item.element = button;
            element.appendChild(button);
        }

        document.body.appendChild(element);

        this.element = element;
    };

    LightCM.open = function (event, data) {
        if (event === undefined) {
            throw Error('Missing event argument. Unable to open menu.');
        }

        event.preventDefault();

        // if user provided options, render options on elements.
        if (data !== undefined) {
            for (let item of this.items) {
                item.element.textContent = render(item.label, data);

                for (let attribute in item.attributes) {
                    let attributeValue = item.attributes[attribute];
                    if (isFunction(attributeValue)) {
                        attributeValue = attributeValue();
                    }
                    item.element.setAttribute(attribute, render(attributeValue));
                }

                if (item.handler) {
                    item.element.onclick = (clickEvent) => {
                        item.handler(data, event, clickEvent);
                    }
                }
            }
        }

        this.element.style.top = event.pageY + 'px';
        this.element.style.left = event.pageX + 'px';
        this.element.style.display = 'flex';

        let element = this.element;

        function hide(event) {
            element.style.display = 'none';
            event.target.removeEventListener('click', hide);
        }

        window.addEventListener('click', hide);
    };

    if (window.LightCM !== undefined) {
        throw Error('LightCM is already defined in the global scope!');
    }

    window.LightCM = LightCM;

}());
<commit_msg>Another bugfix.<commit_after>/*!
 * lightcm
 * https://github.com/oskarbraten/lightcm
 */

(function () {

    'use strict';

    function isFunction (object) {
        return typeof object === 'function';
    }

    function render(str, data) {
        return str.replace(/{{\s*([\w]+)\s*}}/g, function (a, b) {
            let r = data[b];
            if (isFunction(r)) {
                r = r();
            }
            return typeof r === 'string' || typeof r === 'number' ? r : a;
        });
    };

    let LightCM = {
        items: null,
        element: null
    };

    LightCM.init = function (items) {
        if (items === undefined) {
            throw Error('Must provide an array of items as argument.');
        }

        this.items = items;

        // remove old context menu element.
        let _oldElement = document.getElementById('context-menu');
        if (_oldElement) {
            _oldElement.remove();
        }

        let element = document.createElement('div');
        element.classList.add('context-menu');
        element.setAttribute('id', 'context-menu');

        for (let item of this.items) {
            let button = document.createElement('a');
            button.classList.add('btn');
            button.textContent = item.label;

            for (let attribute in item.attributes) {
                let attributeValue = item.attributes[attribute];
                if (isFunction(attributeValue)) {
                    attributeValue = attributeValue();
                }
                button.setAttribute(attribute, attributeValue);
            }

            item.element = button;
            element.appendChild(button);
        }

        document.body.appendChild(element);

        this.element = element;
    };

    LightCM.open = function (event, data) {
        if (event === undefined) {
            throw Error('Missing event argument. Unable to open menu.');
        }

        event.preventDefault();

        // if user provided options, render options on elements.
        if (data !== undefined) {
            for (let item of this.items) {
                item.element.textContent = render(item.label, data);

                for (let attribute in item.attributes) {
                    let attributeValue = item.attributes[attribute];
                    if (isFunction(attributeValue)) {
                        attributeValue = attributeValue();
                    }
                    item.element.setAttribute(attribute, render(attributeValue, data));
                }

                if (item.handler) {
                    item.element.onclick = (clickEvent) => {
                        item.handler(data, event, clickEvent);
                    }
                }
            }
        }

        this.element.style.top = event.pageY + 'px';
        this.element.style.left = event.pageX + 'px';
        this.element.style.display = 'flex';

        let element = this.element;

        function hide(event) {
            element.style.display = 'none';
            event.target.removeEventListener('click', hide);
        }

        window.addEventListener('click', hide);
    };

    if (window.LightCM !== undefined) {
        throw Error('LightCM is already defined in the global scope!');
    }

    window.LightCM = LightCM;

}());
<|endoftext|>


<commit_before>define(['app/Vector', 'app/Rect', 'app/Settings', 'app/Grid', 'app/TileMap', 'app/Layer'], function(Vector, Rect, Settings, Grid, TileMap, Layer) {
    return function() {
        var that = {};

        var layers = [];
        for(var i = 0; i < Settings.numberOfLayers; i++) {
            layers.push(Layer(document.body, Settings.canvasSize, Settings.canvasScale, Settings.drawableAreaSize));
            layers[i].setZ(i);
        }

        var layerDict = {
            bgLayer: layers[0],
            fgLayer: layers[1],
            playerLayer: layers[2],
            menuLayer: layers[3],
        };

        that.attachPlayer = function(player) {
            layerDict.playerLayer.attachDrawable(player);
        };

        var tileMap = TileMap();
        tileMap.addTile({ src: "img/SquareLightDirt1.png", solid: false });
        tileMap.addTile({ src: "img/SquareLightDirt2.png", solid: true });
        tileMap.addTile({ src: "img/SquareLightDirt4.png", solid: true });
        tileMap.addTile({ src: "img/SquareLightDirt5.png", solid: true });

        tileMap.addLayout([
            4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
            3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
            2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,
            2, 3, 2, 4, 2, 1, 1, 1, 1, 2, 4, 2, 2, 3, 4, 4,
            2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2,
            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        ], Settings.numTiles);

        layers[0].attachDrawable(tileMap);

        that.checkCollision = function(ent) {
            var rect = ent.getHitbox();

            /* check nearby cells and resolve each collision */
            var cells = tileMap.getCellsTouchingRectangle(rect);
            for(var i = 0; i < cells.length; i++) {
                if(cells[i].solid) {
                    ent.collide(rect.getOverlapOffset(Rect().buildFromVectors(cells[i].tile.position, cells[i].tile.size)));
                    rect = ent.getHitbox();
                }
            }

            /* check for absense of solid floor tiles */
            var floorCells = tileMap.getCellsBeneathRectangle(rect);
            var solid = false;
            for(i = 0; i < cells.length; i++) {
                solid = solid || cells[i].solid;
            }
            if(!solid) ent.startFalling();

        };

        that.checkBorderCollision = function(ent) {
            var rect = ent.getHitbox();
            if(rect.x + rect.width > Math.abs(layers[0].position.x) + Settings.canvasSize.x - Settings.canvasShiftMargin) {
                that.moveAll(Vector((Math.abs(layers[0].position.x) + Settings.canvasSize.x - Settings.canvasShiftMargin) - (rect.x + rect.width), 0));
            }
            if(rect.x < Math.abs(layers[0].position.x) + Settings.canvasShiftMargin) {
                that.moveAll(Vector((Math.abs(layers[0].position.x) + Settings.canvasShiftMargin) - (rect.x) , 0));
            }
            if(rect.y + rect.height > Math.abs(layers[0].position.y) + Settings.canvasSize.y - Settings.canvasShiftMargin) {
                that.moveAll(Vector(0, (Math.abs(layers[0].position.y) + Settings.canvasSize.y - Settings.canvasShiftMargin) - (rect.y + rect.height)));
            }
            if(rect.y < Math.abs(layers[0].position.x) + Settings.canvasShiftMargin) {
                that.moveAll(Vector(0, (Math.abs(layers[0].position.y) + Settings.canvasShiftMargin) - (rect.y)));
            }
        };

        that.moveAll = function(offset) {
            for(var i = 0; i < layers.length; i++) {
                layers[i].position.x = Math.min(0, Math.max(Settings.canvasSize.x - Settings.drawableAreaSize.x, layers[i].position.x + offset.x));
                layers[i].position.y = Math.min(0, Math.max(Settings.canvasSize.y - Settings.drawableAreaSize.y, layers[i].position.y + offset.y));
            }
        };

        that.draw = function(elapsedTimeSeconds) {
            for(var i = 0; i < layers.length; i++) {
                layers[i].draw(elapsedTimeSeconds);
            }
        };

        return that;
    };
});
<commit_msg>Bug fix in window movement.<commit_after>define(['app/Vector', 'app/Rect', 'app/Settings', 'app/Grid', 'app/TileMap', 'app/Layer'], function(Vector, Rect, Settings, Grid, TileMap, Layer) {
    return function() {
        var that = {};

        var layers = [];
        for(var i = 0; i < Settings.numberOfLayers; i++) {
            layers.push(Layer(document.body, Settings.canvasSize, Settings.canvasScale, Settings.drawableAreaSize));
            layers[i].setZ(i);
        }

        var layerDict = {
            bgLayer: layers[0],
            fgLayer: layers[1],
            playerLayer: layers[2],
            menuLayer: layers[3],
        };

        that.attachPlayer = function(player) {
            layerDict.playerLayer.attachDrawable(player);
        };

        var tileMap = TileMap();
        tileMap.addTile({ src: "img/SquareLightDirt1.png", solid: false });
        tileMap.addTile({ src: "img/SquareLightDirt2.png", solid: true });
        tileMap.addTile({ src: "img/SquareLightDirt4.png", solid: true });
        tileMap.addTile({ src: "img/SquareLightDirt5.png", solid: true });

        tileMap.addLayout([
            4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
            3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
            2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,
            2, 3, 2, 4, 2, 1, 1, 1, 1, 2, 4, 2, 2, 3, 4, 4,
            2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2,
            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        ], Settings.numTiles);

        layers[0].attachDrawable(tileMap);

        that.checkCollision = function(ent) {
            var rect = ent.getHitbox();

            /* check nearby cells and resolve each collision */
            var cells = tileMap.getCellsTouchingRectangle(rect);
            for(var i = 0; i < cells.length; i++) {
                if(cells[i].solid) {
                    ent.collide(rect.getOverlapOffset(Rect().buildFromVectors(cells[i].tile.position, cells[i].tile.size)));
                    rect = ent.getHitbox();
                }
            }

            /* check for absense of solid floor tiles */
            var floorCells = tileMap.getCellsBeneathRectangle(rect);
            var solid = false;
            for(i = 0; i < cells.length; i++) {
                solid = solid || cells[i].solid;
            }
            if(!solid) ent.startFalling();

        };

        that.checkBorderCollision = function(ent) {
            var rect = ent.getHitbox();
            if(rect.x + rect.width > Math.abs(layers[0].position.x) + Settings.canvasSize.x - Settings.canvasShiftMargin) {
                that.moveAll(Vector((Math.abs(layers[0].position.x) + Settings.canvasSize.x - Settings.canvasShiftMargin) - (rect.x + rect.width), 0));
            }
            if(rect.x < Math.abs(layers[0].position.x) + Settings.canvasShiftMargin) {
                that.moveAll(Vector((Math.abs(layers[0].position.x) + Settings.canvasShiftMargin) - (rect.x) , 0));
            }
            if(rect.y + rect.height > Math.abs(layers[0].position.y) + Settings.canvasSize.y - Settings.canvasShiftMargin) {
                that.moveAll(Vector(0, (Math.abs(layers[0].position.y) + Settings.canvasSize.y - Settings.canvasShiftMargin) - (rect.y + rect.height)));
            }
            if(rect.y < Math.abs(layers[0].position.y) + Settings.canvasShiftMargin) {
                that.moveAll(Vector(0, (Math.abs(layers[0].position.y) + Settings.canvasShiftMargin) - (rect.y)));
            }
        };

        that.moveAll = function(offset) {
            for(var i = 0; i < layers.length; i++) {
                layers[i].position.x = Math.min(0, Math.max(Settings.canvasSize.x - Settings.drawableAreaSize.x, layers[i].position.x + offset.x));
                layers[i].position.y = Math.min(0, Math.max(Settings.canvasSize.y - Settings.drawableAreaSize.y, layers[i].position.y + offset.y));
            }
        };

        that.draw = function(elapsedTimeSeconds) {
            for(var i = 0; i < layers.length; i++) {
                layers[i].draw(elapsedTimeSeconds);
            }
        };

        return that;
    };
});
<|endoftext|>


<commit_before>(function(define) {
    'use strict';

    define(function () {
        var native, timing;

        var cbTimeout, nextCall = Infinity, cbUpdateFn, cbMessageName = 'execQueueDelayedExecution';

        if (window) {
            window.addEventListener('message', function (e) {
                if (event.source === window && e.data === cbMessageName && cbUpdateFn) {
                    e.stopPropagation();
                    cbUpdateFn();
                }
            }, true);
        }
        var cbDelay = function (delay) {
            var ts = timing.perf() + delay;
            if (nextCall < ts) {
                return;
            }

            if (cbTimeout) {
                native.clearTimeout(cbTimeout);
                cbTimeout = undefined;
            }

            nextCall = ts;

            if (delay > 5) {
                cbTimeout = native.setTimeout(cbUpdateFn, delay);
            } else if (window) {
                window.postMessage(cbMessageName, '*');
            } else if (process) {
                process.nextTick(cbUpdateFn);
            } else {
                cbUpdateFn();
            }
        };

        return function (_native, _timing) {
            native = _native;
            timing = _timing;

            return {
                call : cbDelay,
                setCallback : function (fn, context) {
                    cbUpdateFn = function () {
                        fn.call(context);
                    };
                }
            };
        };

    });
})(typeof define === 'function' && define.amd ?
    define :
    function (factory) { 'use strict'; module.exports = factory(require); }
  );
<commit_msg>If timeout is between 20-2ms use animationFrame instead of setTimeout for smoother operation.<commit_after>(function(define) {
    'use strict';

    define(function () {
        var native, timing;

        var cbTimeout, cbFrameId, waiting,
            nextCall = Infinity,
            cbUpdateFn,
            cbMessageName = 'execQueueDelayedExecution';

        if (window) {
            window.addEventListener('message', function (e) {
                if (event.source === window && e.data === cbMessageName && cbUpdateFn) {
                    e.stopPropagation();
                    cbUpdateFn();
                }
            }, true);
        }
        var clearCallbacks = function () {
            if (cbFrameId) {
                native.cancelAnimationFrame(cbFrameId);
                cbFrameId = undefined;
            }

            if (cbTimeout) {
                native.clearTimeout(cbTimeout);
                cbTimeout = undefined;
            }

            waiting = false;
        };
        var cbDelay = function (delay) {
            var now = timing.perf(),
                ts = now + delay;

            if (waiting ||
                !((now - nextCall) >> 2) ||
                (nextCall - ts < 0) && (cbFrameId || cbTimeout)) {
                return;
            }

            clearCallbacks();

            nextCall = ts;

            if (delay > 20) {
                cbTimeout = native.setTimeout(cbUpdateFn, delay);
            } else if (delay > 2) {
                cbFrameId = native.requestAnimationFrame(cbUpdateFn);
            } else if (window) {
                waiting = true;
                window.postMessage(cbMessageName, '*');
            } else if (process) {
                waiting = true;
                process.nextTick(cbUpdateFn);
            } else {
                cbUpdateFn();
            }
        };

        return function (_native, _timing) {
            native = _native;
            timing = _timing;

            return {
                call : cbDelay,
                setCallback : function (fn, context) {
                    cbUpdateFn = function () {
                        clearCallbacks();
                        fn.call(context);
                    };
                }
            };
        };

    });
})(typeof define === 'function' && define.amd ?
    define :
    function (factory) { 'use strict'; module.exports = factory(require); }
  );
<|endoftext|>


<commit_before><commit_msg>add pie layout<commit_after>/**
 * @file pie layout
 * @author Marx
 */

import {pie, arc, scaleOrdinal, schemeCategory20, select, selectAll, sum} from 'd3';

const dataset = [
    ['小米', 60.8],
    ['大米', 90.8],
    ['小黑', 44.8],
    ['小白', 78.8],
    ['小六', 39.8]
]

// 新建pie layout
const myPie = pie()

// 将原始数据转换为我们需要的数据
const pieData =  myPie.value(d => d[1]);

// 布局数据
// svg宽度
const width = 400;

// svg高度
const height = 400;

const outerRadius = width / 3;
const innerRadius = 0;

const myArc = arc()
                .innerRadius(innerRadius)
                .outerRadius(outerRadius);

const color = scaleOrdinal(schemeCategory20);

// 在body中添加svg，并设置尺寸
const svg = select('body')
                .append('svg')
                .attr('width', width)
                .attr('height', height);

const arcs = svg.selectAll('g')
                .data(pieData(dataset))
                .enter()
                .append('g')
                .attr('transform', 'translate(' + (width / 2) + ', ' + (height / 2) + ')');

arcs.append('path')
    .attr('fill', (d, i) => color(i))
    .attr('d', d => myArc(d));

arcs.append('text')
    .attr('transform', d => {
        const x = myArc.centroid(d)[0] * 1.4;
        const y = myArc.centroid(d)[1] * 1.4;
        return 'translate(' + x + ', ' + y + ')';
    })
    .attr('text-anchor', 'middle')
    .text(d => {
        const percent = Number(d.value) / sum(dataset, d => d[1]) * 100;
        return percent.toFixed(1) + '%';
    });

arcs.append('line')
    .attr('stroke', 'black')
    .attr('x1', d => myArc.centroid(d)[0] * 2)
    .attr('y1', d => myArc.centroid(d)[1] * 2)
    .attr('x2', d => myArc.centroid(d)[0] * 2.2)
    .attr('y2', d => myArc.centroid(d)[1] * 2.2)

arcs.append('text')
    .attr('transform', d => {
        const x = myArc.centroid(d)[0] * 2.5;
        const y = myArc.centroid(d)[1] * 2.5;
        return 'translate(' + x + ', ' + y + ')';
    })
    .attr('text-anchor', 'middle')
    .text(d => d.data[0])<|endoftext|>


<commit_before>import {
  favIconFallback,
  alertCircle,
  tabList,
  searchInput,
} from './constants';
// Store all the bad favIcons so we don't get loading jank if a favIcon !exist
function badFavIconCache() {
  const badIconCache = [];
  return () => badIconCache;
}

function initializeTabs() {
  const tabs = browser.tabs.query({ currentWindow: true });
  return () => tabs;
}

const badFavIcons = badFavIconCache();
export const getAllTabs = initializeTabs();

function clearChildren(node) {
  while (node.firstChild) {
    node.removeChild(node.firstChild);
  }
}

function isChromeLink(src) {
  return /chrome:\/\//.test(src);
}

function isURL(src) {
  return /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/.test(src);
}

function getBasePath(src) {
  const { origin } = new URL(src);
  return origin;
}

export function switchActiveTab(id) {
  const numId = parseInt(id, 10);
  browser.tabs.update(numId, { active: true });
  window.close();
}

function switchTabs() {
  // this: should be the tab-object node
  const tabId = this.dataset.id;
  switchActiveTab(tabId);
}

export function clearInput(node) {
  node.value = '';
}

export function populateTabList() {
  getAllTabs().then(injectTabsInList);
}

export function tabToTag({ favIconUrl, title, id, url }) {
  const isValidFavIconUrl = favIconUrl
    && !isChromeLink(favIconUrl)
    && !badFavIcons().includes(favIconUrl);
  const favIconLink = isValidFavIconUrl
    ? favIconUrl
    : favIconFallback;
  // Just check if it's a url for now so we can shorten it
  const tabTitle = isURL(title)
    ? getBasePath(title)
    : title;

  return createTabObject({
    id,
    url,
    tabTitle,
    favIconLink,
  });
}

function createTabObject({
  id,
  url,
  tabTitle,
  favIconLink,
}) {
  // Create the parent div
  //

  const tabObjectNode = document.createElement('div');
  tabObjectNode.setAttribute('data-id', id);
  tabObjectNode.setAttribute('tabindex', '0');
  tabObjectNode.classList.add('tab-object');

  // favicon
  //
  const favIconNode = document.createElement('img');
  favIconNode.setAttribute('src', favIconLink);
  favIconNode.onerror = handleBadSvg;

  // tab-info
  //

  const tabInfoNode = document.createElement('div');
  tabInfoNode.setAttribute('class', 'tab-info');

  //      ${title}
  const titleNode = document.createElement('strong');
  titleNode.classList.add('tab-title');
  titleNode.appendChild(document.createTextNode(tabTitle));

  //
${url}

  const urlNode = document.createElement('p');
  urlNode.appendChild(document.createTextNode(url));

  // Append all block elements
  tabInfoNode.appendChild(titleNode);
  tabInfoNode.appendChild(urlNode);

  tabObjectNode.appendChild(favIconNode);
  tabObjectNode.appendChild(tabInfoNode);

  return tabObjectNode;
}

function handleBadSvg() {
  badFavIcons().push(this.src);
  this.src = favIconFallback;
}

// Get focused node's position relative to the current scrolled view
export function getNodePositions(parentNode, selectedNode) {
  return {
    parentHeight: parentNode.offsetHeight,
    selectedBottom: selectedNode.offsetHeight + (
      selectedNode.offsetTop - parentNode.offsetTop
    ) - parentNode.scrollTop,
    selectedTop: (
      selectedNode.offsetTop - parentNode.offsetTop
    ) - parentNode.scrollTop,
  };
}

export function createNoResult() {
  //

  //   <object type="image/svg+xml" data="/assets/alert-circle.svg"></object>
  //   No tabs found
  //

  const noResultNode = document.createElement('div');
  noResultNode.classList.add('no-result');

  const alertCircleNode = document.createElement('object');
  alertCircleNode.setAttribute('type', 'image/svg+xml');
  alertCircleNode.setAttribute('data', alertCircle);

  const strongMsgNode = document.createElement('strong');
  strongMsgNode.appendChild(document.createTextNode('No tabs found'));

  noResultNode.appendChild(alertCircleNode);
  noResultNode.appendChild(strongMsgNode);
  return noResultNode;
}

export function injectTabsInList(tabArray) {
  const wasNoResult = tabList.querySelectorAll('.tab-object').length ===
0;
  const showNoResult = tabArray.length === 0;
  // Don't update dom if we're going to show no results again
  if (wasNoResult && showNoResult) return;

  clearChildren(tabList);

  // Add nodes to tabList & attach event listeners
  if (showNoResult) {
    tabList.appendChild(createNoResult());
  } else {
    tabArray.map(tabToTag).forEach((tabNode) => {
      tabNode.addEventListener('click', switchTabs, true);
      tabNode.addEventListener('focus', scrollIfNeeded);
      tabList.appendChild(tabNode);
    });
  }
}

function scrollIfNeeded(event) {
  // If the selected tab isn't completely visible in the scrolled view,
  // force scroll
  const {
    parentHeight,
    selectedBottom,
    selectedTop,
  } = getNodePositions(event.target.parentNode, event.target);
  const shouldScrollDown = selectedBottom > parentHeight;
  const shouldScrollUp = selectedTop < 0;

  if (!shouldScrollDown && !shouldScrollUp) return;

  if (shouldScrollDown) {
    event.target.scrollIntoView(false);
  } else if (shouldScrollUp) {
    event.target.scrollIntoView(true);
  }
}

export function navigateResults(direction) {
  if (document.activeElement.nodeName === 'INPUT') {
    document.querySelector('.tab-object').focus();
    return;
  }

  switch (direction) {
    case 'Tab':
    case 'ArrowRight':
    case 'ArrowDown': {
      const nextSibling = document.activeElement.nextElementSibling;
      if (nextSibling) {
        nextSibling.focus();
      } else {
        // Return to top if next !exist
        tabList.querySelector('.tab-object').focus();
      }
      break;
    }
    case 'ArrowLeft':
    case 'ArrowUp': {
      const prevSibling = document.activeElement.previousElementSibling;
      if (prevSibling) {
        prevSibling.focus();
      } else {
        searchInput.focus();
      }
      break;
    }
    default: break;
  }
}

<commit_msg>Look for spaces when testing for url<commit_after>import {
  favIconFallback,
  alertCircle,
  tabList,
  searchInput,
} from './constants';
// Store all the bad favIcons so we don't get loading jank if a favIcon !exist
function badFavIconCache() {
  const badIconCache = [];
  return () => badIconCache;
}

function initializeTabs() {
  const tabs = browser.tabs.query({ currentWindow: true });
  return () => tabs;
}

const badFavIcons = badFavIconCache();
export const getAllTabs = initializeTabs();

function clearChildren(node) {
  while (node.firstChild) {
    node.removeChild(node.firstChild);
  }
}

function isChromeLink(src) {
  return /chrome:\/\//.test(src);
}

function isURL(src) {
  const urlPattern = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/;
  const spacePattern = /\s+/g;
  return urlPattern.test(src) && !spacePattern.test(src);
}

function getBasePath(src) {
  const { origin } = new URL(src);
  return origin;
}

export function switchActiveTab(id) {
  const numId = parseInt(id, 10);
  browser.tabs.update(numId, { active: true });
  window.close();
}

function switchTabs() {
  // this: should be the tab-object node
  const tabId = this.dataset.id;
  switchActiveTab(tabId);
}

export function clearInput(node) {
  node.value = '';
}

export function populateTabList() {
  getAllTabs().then(injectTabsInList);
}

export function tabToTag({ favIconUrl, title, id, url }) {
  const isValidFavIconUrl = favIconUrl
    && !isChromeLink(favIconUrl)
    && !badFavIcons().includes(favIconUrl);
  const favIconLink = isValidFavIconUrl
    ? favIconUrl
    : favIconFallback;
  // Just check if it's a url for now so we can shorten it
  const tabTitle = isURL(title)
    ? getBasePath(title)
    : title;

  return createTabObject({
    id,
    url,
    tabTitle,
    favIconLink,
  });
}

function createTabObject({
  id,
  url,
  tabTitle,
  favIconLink,
}) {
  // Create the parent div
  //

  const tabObjectNode = document.createElement('div');
  tabObjectNode.setAttribute('data-id', id);
  tabObjectNode.setAttribute('tabindex', '0');
  tabObjectNode.classList.add('tab-object');

  // favicon
  //
  const favIconNode = document.createElement('img');
  favIconNode.setAttribute('src', favIconLink);
  favIconNode.onerror = handleBadSvg;

  // tab-info
  //

  const tabInfoNode = document.createElement('div');
  tabInfoNode.setAttribute('class', 'tab-info');

  //      ${title}
  const titleNode = document.createElement('strong');
  titleNode.classList.add('tab-title');
  titleNode.appendChild(document.createTextNode(tabTitle));

  //
${url}

  const urlNode = document.createElement('p');
  urlNode.appendChild(document.createTextNode(url));

  // Append all block elements
  tabInfoNode.appendChild(titleNode);
  tabInfoNode.appendChild(urlNode);

  tabObjectNode.appendChild(favIconNode);
  tabObjectNode.appendChild(tabInfoNode);

  return tabObjectNode;
}

function handleBadSvg() {
  badFavIcons().push(this.src);
  this.src = favIconFallback;
}

// Get focused node's position relative to the current scrolled view
export function getNodePositions(parentNode, selectedNode) {
  return {
    parentHeight: parentNode.offsetHeight,
    selectedBottom: selectedNode.offsetHeight + (
      selectedNode.offsetTop - parentNode.offsetTop
    ) - parentNode.scrollTop,
    selectedTop: (
      selectedNode.offsetTop - parentNode.offsetTop
    ) - parentNode.scrollTop,
  };
}

export function createNoResult() {
  //

  //   <object type="image/svg+xml" data="/assets/alert-circle.svg"></object>
  //   No tabs found
  //

  const noResultNode = document.createElement('div');
  noResultNode.classList.add('no-result');

  const alertCircleNode = document.createElement('object');
  alertCircleNode.setAttribute('type', 'image/svg+xml');
  alertCircleNode.setAttribute('data', alertCircle);

  const strongMsgNode = document.createElement('strong');
  strongMsgNode.appendChild(document.createTextNode('No tabs found'));

  noResultNode.appendChild(alertCircleNode);
  noResultNode.appendChild(strongMsgNode);
  return noResultNode;
}

export function injectTabsInList(tabArray) {
  const wasNoResult = tabList.querySelectorAll('.tab-object').length ===
0;
  const showNoResult = tabArray.length === 0;
  // Don't update dom if we're going to show no results again
  if (wasNoResult && showNoResult) return;

  clearChildren(tabList);

  // Add nodes to tabList & attach event listeners
  if (showNoResult) {
    tabList.appendChild(createNoResult());
  } else {
    tabArray.map(tabToTag).forEach((tabNode) => {
      tabNode.addEventListener('click', switchTabs, true);
      tabNode.addEventListener('focus', scrollIfNeeded);
      tabList.appendChild(tabNode);
    });
  }
}

function scrollIfNeeded(event) {
  // If the selected tab isn't completely visible in the scrolled view,
  // force scroll
  const {
    parentHeight,
    selectedBottom,
    selectedTop,
  } = getNodePositions(event.target.parentNode, event.target);
  const shouldScrollDown = selectedBottom > parentHeight;
  const shouldScrollUp = selectedTop < 0;

  if (!shouldScrollDown && !shouldScrollUp) return;

  if (shouldScrollDown) {
    event.target.scrollIntoView(false);
  } else if (shouldScrollUp) {
    event.target.scrollIntoView(true);
  }
}

export function navigateResults(direction) {
  if (document.activeElement.nodeName === 'INPUT') {
    document.querySelector('.tab-object').focus();
    return;
  }

  switch (direction) {
    case 'Tab':
    case 'ArrowRight':
    case 'ArrowDown': {
      const nextSibling = document.activeElement.nextElementSibling;
      if (nextSibling) {
        nextSibling.focus();
      } else {
        // Return to top if next !exist
        tabList.querySelector('.tab-object').focus();
      }
      break;
    }
    case 'ArrowLeft':
    case 'ArrowUp': {
      const prevSibling = document.activeElement.previousElementSibling;
      if (prevSibling) {
        prevSibling.focus();
      } else {
        searchInput.focus();
      }
      break;
    }
    default: break;
  }
}

<|endoftext|>


<commit_before>
"use strict";

export default ['$route', '$location', 'languages', ($route, $location, languages) => {

    function found(element, path, args) {
        for (let a in args) {
            path = path.replace(':' + a, args[a]);
        }
        element.attr('href', '#' + path.replace(/^#/, ''));
    };

    return {
        restrict: 'A',
        link: (scope, element, attrs) => {
            let params = $route.current ? $route.current.params : {};
            let original = $route.current ? $route.current.originalPath : $location.path().replace(/^\/[a-z]{2}\//, '/:language/');
            let path = attrs.moPath || original;
            if (!path) {
                return;
            }
            let args = attrs['arguments'] ? scope.$eval(attrs['arguments']) : {};
            if (params.language) {
                args.language = args.language || params.language;
            } else {
                args.language = args.language || languages[0];
            }
            for (let _path in $route.routes) {
                let _pC = ($route.routes[_path].controller || '') + '';
                if (_pC.toLowerCase() == path.toLowerCase()) {
                    return found(element, _path, args);
                }
            }
            return found(element, path, args);
        }
    };
}];

<commit_msg>use language service<commit_after>
"use strict";

export default ['$route', '$location', 'moLanguage', ($route, $location, Language) => {

    function found(element, path, args) {
        for (let a in args) {
            path = path.replace(':' + a, args[a]);
        }
        element.attr('href', '#' + path.replace(/^#/, ''));
    };

    return {
        restrict: 'A',
        link: (scope, element, attrs) => {
            let params = $route.current ? $route.current.params : {};
            let original = $route.current ? $route.current.originalPath : $location.path().replace(/^\/[a-z]{2}\//, '/:language/');
            let path = attrs.moPath || original;
            if (!path) {
                return;
            }
            let args = attrs['arguments'] ? scope.$eval(attrs['arguments']) : {};
            if (params.language) {
                args.language = args.language || params.language;
            } else {
                args.language = args.language || Language.current;
            }
            for (let _path in $route.routes) {
                let _pC = ($route.routes[_path].controller || '') + '';
                if (_pC.toLowerCase() == path.toLowerCase()) {
                    return found(element, _path, args);
                }
            }
            return found(element, path, args);
        }
    };
}];

<|endoftext|>