<commit_before>define('reporter', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		_ = require('lodash'),
		$ = require('$');

	module.exports = defaultDir.extend({
		initDir : function () {
			var rows = '',
				tpl = _.template($('#tbl-row').html()),
				self = this;

			$.ajax({
				url : './output.json',
				type : 'GET',
				dataType : 'json'
			}).success(function (data) {
				//debugger;
				_.forEach(data, function (file) {
					rows += tpl({
						filename : file.file,
						errors : file.error,
						warns : file.warn,
						infos : file.info
					});
				});
				self.$el.find('.js-tbody').append(rows);
			}).error(function () {
				//debugger;
			});
		}
	});
});

define('reporter-warn', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		_ = require('lodash'),
		$ = require('$');

	module.exports = defaultDir.extend({

	});
});

define('reporter-error', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		_ = require('lodash'),
		$ = require('$');

	module.exports = defaultDir.extend({

	});
});

define('reporter-info', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		_ = require('lodash'),
		$ = require('$');

	module.exports = defaultDir.extend({

	});
});

define('projects', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		_ = require('lodash'),
		$ = require('$');

	module.exports = defaultDir.extend({
		initDir : function () {
			$.ajax({
				url : './projects.json',
				type : 'GET',
				dataType : 'json'
			}).success(function (data) {
				//debugger;
			}).error(function () {
				//debugger;
			});
		}
	});
});

define('project', function (require, exports, module) {
	var $ = require('$');

	module.exports = require('base.dir').extend({
		initDir : function () {
			console.log(3);
		},
		events : function () {
			this.on('click', 'button', 'saveProject');
		},
		saveProject : function () {
			var vals = this.callChilds('getInput');
			$.ajax({
				type : 'POST',
				url : '/project',
				data : JSON.stringify(vals),
				contentType : 'application/json; charset=utf-8',
				dataType : 'json'
			});
		}
	});
});

define('config-dir', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		dirs = require('dirs'),
		_ = require('lodash'),
		$ = require('$'),
			configDir = defaultDir.extend({
			initDir : function () {
			},
			events : function () {
				if (this._super) {
					this._super();
				}
				this.on('click', '.js-config', 'showConfig');
				this.on('click', '.js-addnew', 'addNew');
			},
			addNew : function () {
				var tpl = _.template($('#t-project').html()),
					list = this.$el.find('.js-projectlist');

				dirs.detachEl(list);
				list.html(tpl({projectName: '', projectID : '', paths: ''}));
				list.find('.js-pr-name').removeAttr('disabled');
				dirs.attachEl(list);
				console.log(999);
			},
			showConfig : function () {
				var tpl = _.template($('#t-project').html()),
					pList = '',
					list = this.$el.find('.js-projectlist');

				$.ajax({
					url : './projects.json',
					type : 'GET',
					dataType : 'json'
				}).success(function (data) {
					dirs.detachEl(list);
					_.each(data, function (prj) {
						pList += tpl(prj);
					});
					list.show();
					pList += '<button class="btn js-addnew">Add new</button>';
					list.html(pList);
					dirs.attachEl(list);
				}).error(function () {
					list.html('error happend!');
				});
			}
		});
	module.exports = configDir;
});

define('projects-tab', function (require, exports, module) {
	var $ = require('$'),
		gevent = require('ebus');

	module.exports = require('base.dir').extend({
		events : function () {
			this.on('click', '.js-tab', 'onTabClick');
		},
		onTabClick : function (event) {
			gevent.trigger('project.tab.click', event);
		},
		initDir : function () {
			var self = this,
				tpl = _.template($('#t-project-tab').html());

			$.ajax({
				url : './projects.json',
				type : 'GET',
				dataType : 'json'
			}).success(function (data) {
				$.each(data, function (index, prj) {
					self.$el.append(tpl(prj));
				});
			});
		}
	});
});

define('project-view', function (require, exports, module) {
	var $ = require("$"),
		progress = require('progress-bar');

	module.exports = require('base.dir').extend({
		events : function () {
			this.ong('project.tab.click', 'onProjectClick');
		},
		onProjectClick : function (event) {
			var $target = $(event.target),
				self = this;
			//debugger;
			progress.show();
			$.ajax({
				url : '/output/' + $target.data('id'),
				type : 'GET',
				dataType : 'json'
			}).success(function (data) {
				var tpl = _.template($('#totals').html()),
					tplFiles = _.template($('#file-container').html()),
					file = _.template($('#file').html()),
					html = '',
					fileHtml = '';

				if (data.success) {
					html += tpl(data.data.total);
					delete data.data.total;
					$.each(data.data, function(index, value) {
						value.filename = index;
						fileHtml += file(value);
					});
					html += tplFiles({files : fileHtml});
					self.$el.html(html);
					//debugger;
				} else {
					require('log').error(data);
				}
			}).always(function () {
				progress.hide();
			});
		}
	});
});

define('progress-bar', function(require, exports) {
	var count = 0,
		spin = require('spin'),

	opts = {
		lines: 12, // The number of lines to draw
		length: 30, // The length of each line
		width: 4, // The line thickness
		radius: 20, // The radius of the inner circle
		corners: 0.2, // Corner roundness (0..1)
		rotate: 0, // The rotation offset
		direction: 1, // 1: clockwise, -1: counterclockwise
		color: '#476172', // #rgb or #rrggbb or array of colors
		speed: 1.6, // Rounds per second
		trail: 53, // Afterglow percentage
		shadow: false, // Whether to render a shadow
		hwaccel: true, // Whether to use hardware acceleration
		className: 'spinner', // The CSS class to assign to the spinner
		zIndex: 2e9, // The z-index (defaults to 2000000000)
		position: "fixed",
		top: '50%', // Top position relative to parent
		left: '50%' // Left position relative to parent
	},
	spinner = new spin(opts);

	exports.show = function() {
		if (count < 1) {
			spinner.spin(require('document').body);
		}
		count++;
	}
	exports.hide = function() {
		count--;
		if (count < 1) {
			spinner.stop();
			count = 0;
		}
	}
});
<commit_msg>sorting<commit_after>/* global define */
define('reporter', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		_ = require('lodash'),
		$ = require('$');

	module.exports = defaultDir.extend({
		initDir : function () {
			var rows = '',
				tpl = _.template($('#tbl-row').html()),
				self = this;

			$.ajax({
				url : './output.json',
				type : 'GET',
				dataType : 'json'
			}).success(function (data) {
				//debugger;
				_.forEach(data, function (file) {
					rows += tpl({
						filename : file.file,
						errors : file.error,
						warns : file.warn,
						infos : file.info
					});
				});
				self.$el.find('.js-tbody').append(rows);
			}).error(function () {
				//debugger;
			});
		}
	});
});

define('reporter-warn', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		_ = require('lodash'),
		$ = require('$');

	module.exports = defaultDir.extend({

	});
});

define('reporter-error', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		_ = require('lodash'),
		$ = require('$');

	module.exports = defaultDir.extend({

	});
});

define('reporter-info', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		_ = require('lodash'),
		$ = require('$');

	module.exports = defaultDir.extend({

	});
});

define('projects', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		_ = require('lodash'),
		$ = require('$');

	module.exports = defaultDir.extend({
		initDir : function () {
			$.ajax({
				url : './projects.json',
				type : 'GET',
				dataType : 'json'
			}).success(function () {
				//debugger;
			}).error(function () {
				//debugger;
			});
		}
	});
});

define('project', function (require, exports, module) {
	var $ = require('$');

	module.exports = require('base.dir').extend({
		initDir : function () {
			console.log(3);
		},
		events : function () {
			this.on('click', 'button', 'saveProject');
		},
		saveProject : function () {
			var vals = this.callChilds('getInput');
			$.ajax({
				type : 'POST',
				url : '/project',
				data : JSON.stringify(vals),
				contentType : 'application/json; charset=utf-8',
				dataType : 'json'
			});
		}
	});
});

define('config-dir', function (require, exports, module) {
	var defaultDir = require('base.dir'),
		dirs = require('dirs'),
		_ = require('lodash'),
		$ = require('$'),
			configDir = defaultDir.extend({
			initDir : function () {
			},
			events : function () {
				if (this._super) {
					this._super();
				}
				this.on('click', '.js-config', 'showConfig');
				this.on('click', '.js-addnew', 'addNew');
			},
			addNew : function () {
				var tpl = _.template($('#t-project').html()),
					list = this.$el.find('.js-projectlist');

				dirs.detachEl(list);
				list.html(tpl({projectName: '', projectID : '', paths: ''}));
				list.find('.js-pr-name').removeAttr('disabled');
				dirs.attachEl(list);
				console.log(999);
			},
			showConfig : function () {
				var tpl = _.template($('#t-project').html()),
					pList = '',
					list = this.$el.find('.js-projectlist');

				$.ajax({
					url : './projects.json',
					type : 'GET',
					dataType : 'json'
				}).success(function (data) {
					dirs.detachEl(list);
					_.each(data, function (prj) {
						pList += tpl(prj);
					});
					list.show();
					pList += '<button class="btn js-addnew">Add new</button>';
					list.html(pList);
					dirs.attachEl(list);
				}).error(function () {
					list.html('error happend!');
				});
			}
		});
	module.exports = configDir;
});

define('projects-tab', function (require, exports, module) {
	var $ = require('$'),
		gevent = require('ebus'),
		_ = require('lodash');

	module.exports = require('base.dir').extend({
		events : function () {
			this.on('click', '.js-tab', 'onTabClick');
		},
		onTabClick : function (event) {
			gevent.trigger('project.tab.click', event);
		},
		initDir : function () {
			var self = this,
				tpl = _.template($('#t-project-tab').html());

			$.ajax({
				url : './projects.json',
				type : 'GET',
				dataType : 'json'
			}).success(function (data) {
				$.each(data, function (index, prj) {
					self.$el.append(tpl(prj));
				});
			});
		}
	});
});

define('project-view', function (require, exports, module) {
	var $ = require('$'),
		_ = require('lodash'),
		progress = require('progress-bar'),
		records = [],
		sortBy = '',
		totals,
		tpl = _.template($('#totals').html()),
		tplFiles = _.template($('#file-container').html()),
		file = _.template($('#file').html());

	module.exports = require('base.dir').extend({
		events : function () {
			this.ong('project.tab.click', 'onProjectClick');
			this.on('click', '.js-sortby .btn', 'onSortBy');
		},
		onSortBy : function (event) {
			var sortedArr;

			sortBy = $(event.target).data('sortby');
			sortedArr = _.sortBy(records, function (value) {
				switch (sortBy) {
					case 'errors':
						return -value.error.length;
					case 'warns':
						return -value.warn.length;
					case 'infos':
						return -value.info.length;
					case 'functs':
						return -value.functionCount;
					case 'sumcomp' :
						return -value.complexity.sum;
					case 'avgcomp' :
						return -value.complexity.avg;
					case 'medcomp' :
						return -value.complexity.mediana;
					case 'maxcomp' :
						return -value.complexity.max;
					case 'mincomp' :
						return -value.complexity.min;
					case 'sumstat' :
						return -value.statements.sum;
					case 'avgstat' :
						return -value.statements.avg;
					case 'medstat' :
						return -value.statements.mediana;
					case 'maxstat' :
						return -value.statements.max;
					case 'minstat' :
						return -value.statements.min;
					case 'sloc' :
						return -value.sloc.source;
					case 'loc' :
						return -value.sloc.total;
					case 'comments' :
						return -value.sloc.comment;
					case 'empty' :
						return -value.sloc.empty;
					default:
						return 0;
				}
			});

			//debugger;
			this.drawView(sortedArr);
		},
		drawView : function (elements) {
			var html = '',
				fileHtml = '';
			elements = elements || records;
			$.each(elements, function (index, value) {
				fileHtml += file(value);
			});
			html += tplFiles({files : fileHtml, totals : tpl(totals)});
			this.$el.html(html);
		},
		onProjectClick : function (event) {
			var $target = $(event.target),
				self = this;
			//debugger;
			progress.show();
			$.ajax({
				url : '/output/' + $target.data('id'),
				type : 'GET',
				dataType : 'json'
			}).success(function (data) {
				if (data.success) {
					totals = data.data.total;
					delete data.data.total;
					$.each(data.data, function (index, value) {
						value.filename = index;
						records.push(value);
					});
					self.drawView();
				} else {
					require('log').error(data);
				}
			}).always(function () {
				progress.hide();
			});
		}
	});
});

define('progress-bar', function (require, exports) {
	var count = 0,
		Spin = require('spin'),

	opts = {
		lines: 12, // The number of lines to draw
		length: 30, // The length of each line
		width: 4, // The line thickness
		radius: 20, // The radius of the inner circle
		corners: 0.2, // Corner roundness (0..1)
		rotate: 0, // The rotation offset
		direction: 1, // 1: clockwise, -1: counterclockwise
		color: '#476172', // #rgb or #rrggbb or array of colors
		speed: 1.6, // Rounds per second
		trail: 53, // Afterglow percentage
		shadow: false, // Whether to render a shadow
		hwaccel: true, // Whether to use hardware acceleration
		className: 'spinner', // The CSS class to assign to the spinner
		zIndex: 2e9, // The z-index (defaults to 2000000000)
		position: 'fixed',
		top: '50%', // Top position relative to parent
		left: '50%' // Left position relative to parent
	},
	spinner = new Spin(opts);

	exports.show = function () {
		if (count < 1) {
			spinner.spin(require('document').body);
		}
		count++;
	};
	exports.hide = function () {
		count--;
		if (count < 1) {
			spinner.stop();
			count = 0;
		}
	};
});
<|endoftext|>


<commit_before>module.exports = (frame, assert, browserWidth, helper) => {
    describe('Teaser external', () => {
        let label;
        let content;

        beforeEach(() => {
            label = frame.getAll('#teaser-external .sc-teaser__label').at(0).toDomElement();
            content = frame.getAll('#teaser-external .sc-teaser__content').at(0);
        });

        afterEach(done => {
            helper.reload(frame, done)
        });

        if(browserWidth < 768) {
          it('opens on click', () => {
              content.assert({
                  rendered: false
              });

              //helper.click(label);
              label.click();

              content.assert({
                  rendered: true
              })
          });
        }
    });
};
<commit_msg>teaser-external tests<commit_after>module.exports = (frame, assert, browserWidth, helper) => {
    describe('Teaser external', () => {
        let label;
        let content;

        beforeEach(() => {
            label = frame.getAll('#teaser-external .sc-teaser__label').at(0).toDomElement();
            content = frame.getAll('#teaser-external .sc-teaser__content').at(0);
        });

        afterEach(done => {
            helper.reload(frame, done)
        });

        if(browserWidth < 768) {
          it('opens on click', () => {
              content.assert({
                  rendered: false
              });

              label.click();

              content.assert({
                  rendered: true
              })
          });
        }
    });
};
<|endoftext|>


<commit_before>
// Add notifications options to user profile settings
Users.addField([
  {
    fieldName: 'telescope.notifications_users',
    fieldSchema: {
      label: 'New users',
      type: Boolean,
      optional: true,
      defaultValue: false,
      control: "checkbox",
      insertableIf: Users.is.admin,
      editableIf: Users.is.admin
    }
  },
  {
    fieldName: 'telescope.notifications_posts',
    fieldSchema: {
      label: 'New posts',
      type: Boolean,
      optional: true,
      defaultValue: false,
      control: "checkbox",
      insertableIf: Users.is.memberOrAdmin,
      editableIf: Users.is.ownerOrAdmin
    }
  },
  {
    fieldName: 'telescope.notifications_comments',
    fieldSchema: {
      label: 'Comments on my posts',
      type: Boolean,
      optional: true,
      defaultValue: true,
      control: "checkbox",
      insertableIf: Users.is.memberOrAdmin,
      editableIf: Users.is.ownerOrAdmin
    }
  },
  {
    fieldName: 'telescope.notifications_replies',
    fieldSchema: {
      label: 'Replies to my comments',
      type: Boolean,
      optional: true,
      defaultValue: true,
      control: "checkbox",
      insertableIf: Users.is.memberOrAdmin,
      editableIf: Users.is.ownerOrAdmin
    }
  }
]);
<commit_msg>split user notification prefs<commit_after>
// Add notifications options to user profile settings
Users.addField([
  {
    fieldName: 'telescope.notifications_users',
    fieldSchema: {
      label: 'New users',
      type: Boolean,
      optional: true,
      defaultValue: false,
      control: "checkbox",
      insertableIf: Users.is.admin,
      editableIf: Users.is.admin
    }
  },
  {
    fieldName: 'telescope.notifications_posts',
    fieldSchema: {
      label: 'New posts',
      type: Boolean,
      optional: true,
      defaultValue: false,
      control: "checkbox",
      insertableIf: Users.is.memberOrAdmin,
      editableIf: Users.is.ownerOrAdmin
    }
  }
]);

if (typeof Comments !== "undefined") {
  Users.addField([
    {
      fieldName: 'telescope.notifications_comments',
      fieldSchema: {
        label: 'Comments on my posts',
        type: Boolean,
        optional: true,
        defaultValue: true,
        control: "checkbox",
        insertableIf: Users.is.memberOrAdmin,
        editableIf: Users.is.ownerOrAdmin
      }
    },
    {
      fieldName: 'telescope.notifications_replies',
      fieldSchema: {
        label: 'Replies to my comments',
        type: Boolean,
        optional: true,
        defaultValue: true,
        control: "checkbox",
        insertableIf: Users.is.memberOrAdmin,
        editableIf: Users.is.ownerOrAdmin
      }
    }
  ]);
}
<|endoftext|>


<commit_before>/***
 *
 * Basic Publish/Subscribe library for Named WebSockets
 * ------------------------------------------------------------------------
 * ------------------------------------------------------------------------
 * https://github.com/richtr/namedwebsockets/tree/master/examples/pubsub
 * ------------------------------------------------------------------------
 *
 * For an example of usage, please see `pubsub.html`.
 *
 */
var NamedWebSockets_Basic_PubSub = function(namedWebSocketObj) {
	this.ws = namedWebSocketObj;
	this.ws.addEventListener("open", function() {
		for(var msg in this.sendQueue) {
			this.ws.send(this.sendQueue[msg]);
			this.sendQueue = [];
		}
	}.bind(this));

	this.nodeId = Math.floor( Math.random() * 1e16);

	this.topicSubscriptions = [];

	this.sendQueue = [];

	this.ws.onmessage = function(messageEvent) {
		// Distribute received message to subscriber
		try {
			var msg = JSON.parse(messageEvent.data);

			if (msg.action && msg.action == "publish") {
				var subscriptions = this.topicSubscriptions[msg.topicURI];
				for (var nodeId in subscriptions) {
					var nodeSubscriptions = subscriptions[nodeId];
					for (var callback in nodeSubscriptions) {
						(nodeSubscriptions[callback]).call(this, msg.payload);
					}
				}
			}
		} catch (e) {
			console.error("Could not process publish message");
		}
	}.bind(this);
};

NamedWebSockets_Basic_PubSub.prototype.constructor = NamedWebSockets_Basic_PubSub;

NamedWebSockets_Basic_PubSub.prototype.subscribe = function(topicURI, successCallback)	{
	var subscriptions = this.topicSubscriptions[topicURI] || {};
	var nodeSubscriptions = subscriptions[this.nodeId] || [];

	nodeSubscriptions.push(successCallback);

	subscriptions[this.nodeId] = nodeSubscriptions;
	this.topicSubscriptions[topicURI] = subscriptions;
};

NamedWebSockets_Basic_PubSub.prototype.unsubscribe = function(topicURI, successCallback)	{
	var subscriptions = this.topicSubscriptions[topicURI] || {};
	var nodeSubscriptions = subscriptions[this.nodeId] || [];

	for (var i in nodeSubscriptions) {
		if (successCallbackBack == nodeSubscriptions[i]) {
			nodeSubscriptions.splice(i, 1);
			break;
		}
	}

	subscriptions[this.nodeId] = nodeSubscriptions;
	this.topicSubscriptions[topicURI] = subscriptions;
}

NamedWebSockets_Basic_PubSub.prototype.publish = function(topicURI, payload, successCallback, advancedOptions)	{
	// Send over websocket
	var publishMsg = {
		action: "publish",
		topicURI: topicURI || "",
		payload: payload || {}
	};

	this.send(publishMsg);
};

NamedWebSockets_Basic_PubSub.prototype.send = function(json) {
	var msg = JSON.stringify(json)

	if (this.ws.readyState != 1) {
		this.sendQueue.push(msg);
	} else {
		this.ws.send(msg);
	}
};
<commit_msg>Clean up PubSub lib demo<commit_after>/***
 *
 * Basic Publish/Subscribe library for Named WebSockets
 * ------------------------------------------------------------------------
 * ------------------------------------------------------------------------
 * https://github.com/richtr/namedwebsockets/tree/master/examples/pubsub
 * ------------------------------------------------------------------------
 *
 * For an example of usage, please see `pubsub.html`.
 *
 */
var NamedWebSockets_Basic_PubSub = function(namedWebSocketObj) {
	this.ws = namedWebSocketObj;
	this.ws.addEventListener("open", function() {
		for(var msg in this.sendQueue) {
			this.ws.send(this.sendQueue[msg]);
			this.sendQueue = [];
		}
	}.bind(this));

	this.nodeId = Math.floor(Math.random() * 1e16);

	this.topicSubscriptions = [];

	this.sendQueue = [];

	this.ws.onmessage = function(messageEvent) {
		// Distribute received message to subscriber
		try {
			var msg = JSON.parse(messageEvent.data);

			if (msg.action && msg.action == "publish") {
				var subscriptions = this.topicSubscriptions[msg.topicURI];
				for (var nodeId in subscriptions) {
					var nodeSubscriptions = subscriptions[nodeId];
					for (var callback in nodeSubscriptions) {
						(nodeSubscriptions[callback]).call(this, msg.payload);
					}
				}
			}
		} catch (e) {
			console.error("Could not process publish message");
		}
	}.bind(this);
};

NamedWebSockets_Basic_PubSub.prototype.constructor = NamedWebSockets_Basic_PubSub;

NamedWebSockets_Basic_PubSub.prototype.subscribe = function(topicURI, successCallback)	{
	var subscriptions = this.topicSubscriptions[topicURI] || {};
	var nodeSubscriptions = subscriptions[this.nodeId] || [];

	nodeSubscriptions.push(successCallback);

	subscriptions[this.nodeId] = nodeSubscriptions;
	this.topicSubscriptions[topicURI] = subscriptions;
};

NamedWebSockets_Basic_PubSub.prototype.unsubscribe = function(topicURI, successCallback)	{
	var subscriptions = this.topicSubscriptions[topicURI] || {};
	var nodeSubscriptions = subscriptions[this.nodeId] || [];

	for (var i in nodeSubscriptions) {
		if (successCallbackBack == nodeSubscriptions[i]) {
			nodeSubscriptions.splice(i, 1);
			break;
		}
	}

	subscriptions[this.nodeId] = nodeSubscriptions;
	this.topicSubscriptions[topicURI] = subscriptions;
}

NamedWebSockets_Basic_PubSub.prototype.publish = function(topicURI, payload, successCallback)	{
	// Send over websocket
	var publishMsg = {
		action: "publish",
		topicURI: topicURI || "",
		payload: payload || {}
	};

	var msg = JSON.stringify(publishMsg)

	if (this.ws.readyState != 1) {
		this.sendQueue.push(msg);
	} else {
		this.ws.send(msg);
	}

	if (successCallback) {
		successCallback.call(this);
	}
};
<|endoftext|>


<commit_before>/**
 * @file reputation command
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

let recentUsers = [];
const COOLDOWN = 12;

exports.exec = async (Bastion, message, args) => {
  try {
    if (/^tay(?:lor)?(?: alison)?(?: swift)?$/i.test(args.length && args.join(' '))) {
      let reputationLyrics = [
        'Big **reputation**, big **reputation**\nOoh, you and me, we got big **reputations**, ah\nAnd you heard about me, ooh',
        'Big **reputation**, big **reputation**\nOoh, you and me would be a big conversation, ah\nAnd I heard about you, ooh',
        'I got a **reputation**, girl, that don\'t precede me\nI\'m one call away whenever you need me',
        'I got issues and chips on both of my shoulders\n**Reputation** precedes me, in rumors, I\'m knee-deep'
      ];
      return message.channel.send({
        embed: {
          description: reputationLyrics[Math.floor(Math.random() * reputationLyrics.length)]
        }
      }).catch(() => {});
    }

    if (!recentUsers.includes(message.author.id)) {
      let user = message.mentions.users.first();
      if (!user) return;
      if (user.id === message.author.id) {
        /**
        * Error condition is encountered.
        * @fires error
        */
        return Bastion.emit('error', Bastion.strings.error(message.guild.language, 'forbidden'), 'You can\'t give reputation to yourself!', message.channel);
      }

      let [ guildMemberModel, initialized ] = await message.client.database.models.guildMember.findOrBuild({
        where: {
          userID: message.author.id
        },
        defaults: {
          guildID: message.guild.id,
          experiencePoints: 1,
          reputations: 1
        }
      });
      if (initialized) {
        await guildMemberModel.save();
      }
      else {
        await message.client.database.models.guildMember.update({
          reputations: parseInt(guildMemberModel.dataValues.reputations) + 1
        },
        {
          where: {
            userID: message.author.id
          },
          fields: [ 'reputations' ]
        });
      }

      recentUsers.push(message.author.id);
      setTimeout(() => {
        recentUsers.splice(recentUsers.indexOf(message.author.id), 1);
      }, COOLDOWN * 60 * 60 * 1000);

      message.channel.send({
        embed: {
          color: Bastion.colors.GREEN,
          description: `You have given one reputation to ${user.tag}`
        }
      }).catch(e => {
        Bastion.log.error(e);
      });
    }
    else {
      /**
      * Error condition is encountered.
      * @fires error
      */
      return Bastion.emit('error', Bastion.strings.error(message.guild.language, 'cooldown'), `You have recently given reputation to someone, please wait at least ${COOLDOWN} hours before giving reputation again.`, message.channel);
    }
  }
  catch (e) {
    Bastion.log.error(e);
  }
};

exports.config = {
  aliases: [ 'rep' ],
  enabled: true
};

exports.help = {
  name: 'reputation',
  botPermission: '',
  userTextPermission: '',
  userVoicePermission: '',
  usage: 'reputation <@USER_MENTION>',
  example: [ 'reputation @k3rn31p4nic#8383' ]
};
<commit_msg>Support for per server reputations<commit_after>/**
 * @file reputation command
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

let recentUsers = [];
const COOLDOWN = 12;

exports.exec = async (Bastion, message, args) => {
  try {
    if (/^tay(?:lor)?(?: alison)?(?: swift)?$/i.test(args.length && args.join(' '))) {
      let reputationLyrics = [
        'Big **reputation**, big **reputation**\nOoh, you and me, we got big **reputations**, ah\nAnd you heard about me, ooh',
        'Big **reputation**, big **reputation**\nOoh, you and me would be a big conversation, ah\nAnd I heard about you, ooh',
        'I got a **reputation**, girl, that don\'t precede me\nI\'m one call away whenever you need me',
        'I got issues and chips on both of my shoulders\n**Reputation** precedes me, in rumors, I\'m knee-deep'
      ];
      return message.channel.send({
        embed: {
          description: reputationLyrics[Math.floor(Math.random() * reputationLyrics.length)]
        }
      }).catch(() => {});
    }

    if (!recentUsers.includes(message.author.id)) {
      let user = message.mentions.users.first();
      if (!user) return;
      if (user.id === message.author.id) {
        /**
        * Error condition is encountered.
        * @fires error
        */
        return Bastion.emit('error', Bastion.strings.error(message.guild.language, 'forbidden'), 'You can\'t give reputation to yourself!', message.channel);
      }

      let [ guildMemberModel, initialized ] = await message.client.database.models.guildMember.findOrBuild({
        where: {
          userID: message.author.id,
          guildID: message.guild.id
        },
        defaults: {
          experiencePoints: 1,
          reputations: 1
        }
      });
      if (initialized) {
        await guildMemberModel.save();
      }
      else {
        await message.client.database.models.guildMember.update({
          reputations: parseInt(guildMemberModel.dataValues.reputations) + 1
        },
        {
          where: {
            userID: message.author.id,
            guildID: message.guild.id
          },
          fields: [ 'reputations' ]
        });
      }

      recentUsers.push(message.author.id);
      setTimeout(() => {
        recentUsers.splice(recentUsers.indexOf(message.author.id), 1);
      }, COOLDOWN * 60 * 60 * 1000);

      message.channel.send({
        embed: {
          color: Bastion.colors.GREEN,
          description: `You have given one reputation to ${user.tag}`
        }
      }).catch(e => {
        Bastion.log.error(e);
      });
    }
    else {
      /**
      * Error condition is encountered.
      * @fires error
      */
      return Bastion.emit('error', Bastion.strings.error(message.guild.language, 'cooldown'), `You have recently given reputation to someone, please wait at least ${COOLDOWN} hours before giving reputation again.`, message.channel);
    }
  }
  catch (e) {
    Bastion.log.error(e);
  }
};

exports.config = {
  aliases: [ 'rep' ],
  enabled: true
};

exports.help = {
  name: 'reputation',
  botPermission: '',
  userTextPermission: '',
  userVoicePermission: '',
  usage: 'reputation <@USER_MENTION>',
  example: [ 'reputation @k3rn31p4nic#8383' ]
};
<|endoftext|>


<commit_before>var parser = require('./parser');
// Predicts the path of the code
// TODO this requires some serious refactoring... really.

// 1000 : keep direction
// -1000 : reverse direction

var DirectionMap = {
  'up': {
    x: 0,
    y: -1
  },
  'left': {
    x: -1,
    y: 0
  },
  'right': {
    x: 1,
    y: 0
  },
  'down': {
    x: 0,
    y: 1
  },
  'skip-up': {
    x: 0,
    y: -2
  },
  'skip-left': {
    x: -2,
    y: 0
  },
  'skip-right': {
    x: 2,
    y: 0
  },
  'skip-down': {
    x: 0,
    y: 2
  },
  'horizontal': {
    x: 1000,
    y: -1000
  },
  'vertical': {
    x: -1000,
    y: 1000
  },
  'reverse': {
    x: -1000,
    y: -1000
  },
  'none': {
    x: 1000,
    y: 1000
  }
};

var UP = 1;
var DOWN = 2;
var LEFT = 4;
var RIGHT = 8;

var DirectionBitMap = {
  'up': UP,
  'down': DOWN,
  'left': LEFT,
  'right': RIGHT,
  'horizontal': LEFT|RIGHT,
  'vertical': UP|DOWN,
  'up-left': UP|LEFT,
  'down-left': DOWN|LEFT,
  'up-right': UP|RIGHT,
  'down-right': DOWN|RIGHT
};

var DirectionBitRevMap = {};
Object.keys(DirectionBitMap).forEach(function(k) {
  DirectionBitRevMap[DirectionBitMap[k]] = k;
});

var ReversibleMap = {
  'condition': true,
  'pop': true,
  'add': true,
  'multiply': true,
  'subtract': true,
  'divide': true,
  'mod': true,
  'pop': true,
  'pop-unicode': true,
  'pop-number': true,
  'copy': true,
  'flip': true,
  'move': true,
  'compare': true
};

var UnlikelyMap = {
  'add': true,
  'multiply': true,
  'subtract': true,
  'divide': true,
  'mod': true,
  'pop': true,
  'pop-unicode': true,
  'pop-number': true,
  'copy': true,
  'flip': true,
  'move': true,
  'compare': true
};

function Predictor(code) {
  if(typeof code == 'string') {
    this.map = parser.parse(code);
  } else {
    this.map = code;
  }
  this.segmentId = 0;
  this.segments = {};
  this.stack = [{
    x: 0,
    y: 0,
    direction: {
      x: 0,
      y: 1
    },
    register: {
      x: 0,
      y: 0,
      preDir: 0
    }
  }];
  this.updated = [];
}

Predictor.prototype.next = function() {
  if(this.stack.length == 0) return false;
  var state = this.stack[this.stack.length-1];
  if(state.register) {
    // Assign segment
    state.segment = this.segmentId++;
    this.segments[state.segment] = [];
    // Update the tile
    if(state.register.preDir) {
      processDir({
          x: state.register.x,
          y: state.register.y
        }, this.map, state.direction, state.register.preDir,
        this.updated, state.segment, state.unlikely);
    }
    delete state.register;
  }
  var segment = this.segments[state.segment];
  var direction = state.direction;
  direction.x = sign(direction.x);
  direction.y = sign(direction.y);
  var preDir = convertDir(-direction.x, -direction.y);
  var tile = this.map.get(state.x, state.y);
  var removal = false;
  if(segment) segment.push(tile);
  if(tile != null) {
    if(!tile.segments) {
      tile.segments = {};
    }
    // Set the direction
    var tileDir = DirectionMap[tile.direction];
    direction.x = calculateDir(direction.x, tileDir.x);
    direction.y = calculateDir(direction.y, tileDir.y);
    if(tile.command == 'end') removal = true;
    if(tile.segments[convertDir(direction.x, direction.y)]) {
      removal = true;
    } else {
      tile.segments[convertDir(direction.x, direction.y)] = {
        segment: state.segment,
        position: segment? segment.length - 1 : 0
      }
    }
    if(ReversibleMap[tile.command]) {
      var flipDir = {
        x: -direction.x,
        y: -direction.y
      };
      var flipState = {
        x: movePos(state.x, flipDir.x, this.map.width),
        y: movePos(state.y, flipDir.y, this.map.height),
        direction: flipDir,
        unlikely: state.unlikely,
        register: {
          x: state.x,
          y: state.y,
          preDir: preDir
        }
      };
      var flipTile = this.map.get(flipState.x, flipState.y);
      var skip = false;
      if(flipTile) {
        var flipTileDir = DirectionMap[flipTile.direction];
        if(flipTileDir.x == direction.x && flipTileDir.y == direction.y) {
          // It's useless; skipping
          skip = true;
        }
      }
      if(!skip && (!flipTile || !flipTile.segments ||
        !flipTile.segments[convertDir(flipDir.x, flipDir.y)])) {
        if(UnlikelyMap[tile.command]) {
          flipState.unlikely = true;
          this.stack.unshift(flipState);
        } else {
          this.stack.push(flipState);
        }
      }
    }
  }
  processDir(state, this.map, direction, preDir, this.updated, state.segment,
    state.unlikely);
  state.x = movePos(state.x, direction.x, this.map.width);
  state.y = movePos(state.y, direction.y, this.map.height);
  if(removal) {
    this.stack.splice(this.stack.indexOf(state), 1);
    if(segment && segment.length <= 1) {
      delete this.segments[state.segment];
    }
  }
  return this.stack.length > 0;
}

function processDir(state, map, direction, preDir, updated, segment, unlikely) {
  var tile = map.get(state.x, state.y);
  // Add 'skip' direction to skipping tile
  if(isSkipping(direction.x, direction.y)) {
    var skipX = movePos(state.x, sign(direction.x), map.width);
    var skipY = movePos(state.y, sign(direction.y), map.height);
    var skipTile = map.get(skipX, skipY);
    updated.push({
      x: skipX,
      y: skipY
    });
    if(direction.x) {
      writeDir(skipTile, 'skip-horizontal', segment, unlikely);
    } else {
      writeDir(skipTile, 'skip-vertical', segment, unlikely);
    }
  }
  // Move to tile
  updated.push({
    x: state.x,
    y: state.y
  });
  var bitDir = preDir | convertDir(direction.x, direction.y);
  writeDir(tile, DirectionBitRevMap[bitDir], segment, unlikely);
}

function calculateDir(current, target) {
  if(target == 1000) return current;
  else if(target == -1000) return -current;
  return target;
}

function isSkipping(x, y) {
  return Math.abs(x) >= 2 || Math.abs(y) >= 2;
}

function convertDir(x, y) {
  var val = 0;
  if(y <= -1) val |= UP;
  if(y >= 1) val |= DOWN;
  if(x <= -1) val |= LEFT;
  if(x >= 1) val |= RIGHT;
  return val;
}

function movePos(pos, dir, size) {
  pos += dir;
  if(pos < 0) pos = size + pos;
  if(pos >= size) pos = pos - size;
  return pos;
}

function sign(a) {
  if(a>0) return 1;
  else if(a<0) return -1;
  else return 0;
}

function writeDir(tile, direction, segment, unlikely) {
  if(tile == null) return;
  if(tile.directions == null) {
    tile.directions = {};
  }
  if(tile.directions[direction] == null) {
    tile.directions[direction] = {
      segment: segment,
      unlikely: unlikely
    };
  }
}

module.exports = Predictor;
<commit_msg>Fix infinite loop in predictor<commit_after>var parser = require('./parser');
// Predicts the path of the code
// TODO this requires some serious refactoring... really.

// 1000 : keep direction
// -1000 : reverse direction

var DirectionMap = {
  'up': {
    x: 0,
    y: -1
  },
  'left': {
    x: -1,
    y: 0
  },
  'right': {
    x: 1,
    y: 0
  },
  'down': {
    x: 0,
    y: 1
  },
  'skip-up': {
    x: 0,
    y: -2
  },
  'skip-left': {
    x: -2,
    y: 0
  },
  'skip-right': {
    x: 2,
    y: 0
  },
  'skip-down': {
    x: 0,
    y: 2
  },
  'horizontal': {
    x: 1000,
    y: -1000
  },
  'vertical': {
    x: -1000,
    y: 1000
  },
  'reverse': {
    x: -1000,
    y: -1000
  },
  'none': {
    x: 1000,
    y: 1000
  }
};

var UP = 1;
var DOWN = 2;
var LEFT = 4;
var RIGHT = 8;

var DirectionBitMap = {
  'up': UP,
  'down': DOWN,
  'left': LEFT,
  'right': RIGHT,
  'horizontal': LEFT|RIGHT,
  'vertical': UP|DOWN,
  'up-left': UP|LEFT,
  'down-left': DOWN|LEFT,
  'up-right': UP|RIGHT,
  'down-right': DOWN|RIGHT
};

var DirectionBitRevMap = {};
Object.keys(DirectionBitMap).forEach(function(k) {
  DirectionBitRevMap[DirectionBitMap[k]] = k;
});

var ReversibleMap = {
  'condition': true,
  'pop': true,
  'add': true,
  'multiply': true,
  'subtract': true,
  'divide': true,
  'mod': true,
  'pop': true,
  'pop-unicode': true,
  'pop-number': true,
  'copy': true,
  'flip': true,
  'move': true,
  'compare': true
};

var UnlikelyMap = {
  'add': true,
  'multiply': true,
  'subtract': true,
  'divide': true,
  'mod': true,
  'pop': true,
  'pop-unicode': true,
  'pop-number': true,
  'copy': true,
  'flip': true,
  'move': true,
  'compare': true
};

function Predictor(code) {
  if(typeof code == 'string') {
    this.map = parser.parse(code);
  } else {
    this.map = code;
  }
  this.segmentId = 0;
  this.segments = {};
  this.stack = [{
    x: 0,
    y: 0,
    direction: {
      x: 0,
      y: 1
    },
    register: {
      x: 0,
      y: 0,
      preDir: 0
    }
  }];
  this.updated = [];
}

Predictor.prototype.next = function() {
  if(this.stack.length == 0) return false;
  var state = this.stack[this.stack.length-1];
  if(state.register) {
    // Assign segment
    state.segment = this.segmentId++;
    this.segments[state.segment] = [];
    // Update the tile
    if(state.register.preDir) {
      processDir({
          x: state.register.x,
          y: state.register.y
        }, this.map, state.direction, state.register.preDir,
        this.updated, state.segment, state.unlikely);
    }
    delete state.register;
  }
  var segment = this.segments[state.segment];
  var direction = state.direction;
  direction.x = sign(direction.x);
  direction.y = sign(direction.y);
  var preDir = convertDir(-direction.x, -direction.y);
  var tile = this.map.get(state.x, state.y);
  var removal = false;
  if(segment) segment.push(tile);
  if(tile != null) {
    if(!tile.heat) {
      tile.heat = 0;
    }
    tile.heat ++;
    if(!tile.segments) {
      tile.segments = {};
    }
    // Set the direction
    var tileDir = DirectionMap[tile.direction];
    direction.x = calculateDir(direction.x, tileDir.x);
    direction.y = calculateDir(direction.y, tileDir.y);
    if(tile.command == 'end') removal = true;
    if(tile.segments[convertDir(direction.x, direction.y)]) {
      removal = true;
    } else {
      tile.segments[convertDir(direction.x, direction.y)] = {
        segment: state.segment,
        position: segment? segment.length - 1 : 0
      }
    }
    if(!removal && ReversibleMap[tile.command]) {
      var flipDir = {
        x: -direction.x,
        y: -direction.y
      };
      var flipState = {
        x: movePos(state.x, flipDir.x, this.map.width),
        y: movePos(state.y, flipDir.y, this.map.height),
        direction: flipDir,
        unlikely: state.unlikely,
        register: {
          x: state.x,
          y: state.y,
          preDir: preDir
        }
      };
      var flipTile = this.map.get(flipState.x, flipState.y);
      var skip = false;
      if(flipTile) {
        var flipTileDir = DirectionMap[flipTile.direction];
        if(flipTileDir.x == direction.x && flipTileDir.y == direction.y) {
          // It's useless; skipping
          skip = true;
        }
      }
      if(!skip && (!flipTile || !flipTile.segments ||
        !flipTile.segments[convertDir(flipDir.x, flipDir.y)])) {
        if(UnlikelyMap[tile.command]) {
          flipState.unlikely = true;
          this.stack.unshift(flipState);
        } else {
          this.stack.push(flipState);
        }
      }
    }
  }
  processDir(state, this.map, direction, preDir, this.updated, state.segment,
    state.unlikely);
  state.x = movePos(state.x, direction.x, this.map.width);
  state.y = movePos(state.y, direction.y, this.map.height);
  if(removal) {
    this.stack.splice(this.stack.indexOf(state), 1);
    if(segment && segment.length <= 1) {
      delete this.segments[state.segment];
    }
  }
  return this.stack.length > 0;
}

function processDir(state, map, direction, preDir, updated, segment, unlikely) {
  var tile = map.get(state.x, state.y);
  // Add 'skip' direction to skipping tile
  if(isSkipping(direction.x, direction.y)) {
    var skipX = movePos(state.x, sign(direction.x), map.width);
    var skipY = movePos(state.y, sign(direction.y), map.height);
    var skipTile = map.get(skipX, skipY);
    updated.push({
      x: skipX,
      y: skipY
    });
    if(direction.x) {
      writeDir(skipTile, 'skip-horizontal', segment, unlikely);
    } else {
      writeDir(skipTile, 'skip-vertical', segment, unlikely);
    }
  }
  // Move to tile
  updated.push({
    x: state.x,
    y: state.y
  });
  var bitDir = preDir | convertDir(direction.x, direction.y);
  writeDir(tile, DirectionBitRevMap[bitDir], segment, unlikely);
}

function calculateDir(current, target) {
  if(target == 1000) return current;
  else if(target == -1000) return -current;
  return target;
}

function isSkipping(x, y) {
  return Math.abs(x) >= 2 || Math.abs(y) >= 2;
}

function convertDir(x, y) {
  var val = 0;
  if(y <= -1) val |= UP;
  if(y >= 1) val |= DOWN;
  if(x <= -1) val |= LEFT;
  if(x >= 1) val |= RIGHT;
  return val;
}

function movePos(pos, dir, size) {
  pos += dir;
  if(pos < 0) pos = size + pos;
  if(pos >= size) pos = pos - size;
  return pos;
}

function sign(a) {
  if(a>0) return 1;
  else if(a<0) return -1;
  else return 0;
}

function writeDir(tile, direction, segment, unlikely) {
  if(tile == null) return;
  if(tile.directions == null) {
    tile.directions = {};
  }
  if(tile.directions[direction] == null) {
    tile.directions[direction] = {
      segment: segment,
      unlikely: unlikely
    };
  }
}

module.exports = Predictor;
<|endoftext|>


<commit_before>import { createRequire } from 'node:module'
import process, { env, exit } from 'node:process'
import { log } from '@serverless/utils/log.js'
import chalk from 'chalk'
import semver from 'semver'
import updateNotifier from 'update-notifier'
import { satisfiesVersionRange } from './utils/index.js'
import {
  commandOptions,
  CUSTOM_OPTION,
  defaultOptions,
  SERVER_SHUTDOWN_TIMEOUT,
} from './config/index.js'

const require = createRequire(import.meta.url)
const pkg = require('../package.json')

export default class ServerlessOffline {
  #cliOptions = null

  #http = null

  #lambda = null

  #options = null

  #schedule = null

  #serverless = null

  #webSocket = null

  constructor(serverless, cliOptions) {
    this.#cliOptions = cliOptions
    this.#serverless = serverless

    this.commands = {
      offline: {
        // add start nested options
        commands: {
          functionsUpdated: {
            lifecycleEvents: ['cleanup'],
            type: 'entrypoint',
          },
          start: {
            lifecycleEvents: ['init', 'ready', 'end'],
            options: commandOptions,
            usage:
              'Simulates API Gateway to call your lambda functions offline using backward compatible initialization.',
          },
        },
        lifecycleEvents: ['start'],
        options: commandOptions,
        usage: 'Simulates API Gateway to call your lambda functions offline.',
      },
    }

    this.hooks = {
      'offline:functionsUpdated:cleanup': this.cleanupFunctions.bind(this),
      'offline:start': this.#startWithExplicitEnd.bind(this),
      'offline:start:end': this.end.bind(this),
      'offline:start:init': this.start.bind(this),
      'offline:start:ready': this.ready.bind(this),
    }
  }

  // Entry point for the plugin (sls offline) when running 'sls offline start'
  async start() {
    // Put here so available everywhere, not just in handlers
    env.IS_OFFLINE = true

    // check if update is available
    updateNotifier({ pkg }).notify()

    this.#verifyServerlessVersionCompatibility()

    this._mergeOptions()

    const { httpEvents, lambdas, scheduleEvents, webSocketEvents } =
      this._getEvents()

    // if (lambdas.length > 0) {
    await this._createLambda(lambdas)
    // }

    const eventModules = []

    if (httpEvents.length > 0) {
      eventModules.push(this._createHttp(httpEvents))
    }

    if (!this.#options.disableScheduledEvents && scheduleEvents.length > 0) {
      eventModules.push(this.#createSchedule(scheduleEvents))
    }

    if (webSocketEvents.length > 0) {
      eventModules.push(this.#createWebSocket(webSocketEvents))
    }

    await Promise.all(eventModules)
  }

  async ready() {
    if (env.NODE_ENV !== 'test') {
      await this.#listenForTermination()
    }
  }

  async end(skipExit) {
    // TEMP FIXME
    if (env.NODE_ENV === 'test' && skipExit === undefined) {
      return
    }

    log.info('Halting offline server')

    const eventModules = []

    if (this.#lambda) {
      eventModules.push(this.#lambda.cleanup())
      eventModules.push(this.#lambda.stop(SERVER_SHUTDOWN_TIMEOUT))
    }

    if (this.#http) {
      eventModules.push(this.#http.stop(SERVER_SHUTDOWN_TIMEOUT))
    }

    // if (this.#schedule) {
    //   eventModules.push(this.#schedule.stop())
    // }

    if (this.#webSocket) {
      eventModules.push(this.#webSocket.stop(SERVER_SHUTDOWN_TIMEOUT))
    }

    await Promise.all(eventModules)

    if (!skipExit) {
      exit(0)
    }
  }

  async cleanupFunctions() {
    if (this.#lambda) {
      log.debug('Forcing cleanup of Lambda functions')
      await this.#lambda.cleanup()
    }
  }

  /**
   * Entry point for the plugin (sls offline) when running 'sls offline'
   * The call to this.end() would terminate the process before 'offline:start:end' could be consumed
   * by downstream plugins. When running sls offline that can be expected, but docs say that
   * 'sls offline start' will provide the init and end hooks for other plugins to consume
   * */
  async #startWithExplicitEnd() {
    await this.start()
    await this.ready()
    this.end()
  }

  async #listenForTermination() {
    const command = await new Promise((resolve) => {
      process
        // SIGINT will be usually sent when user presses ctrl+c
        .on('SIGINT', () => resolve('SIGINT'))
        // SIGTERM is a default termination signal in many cases,
        // for example when "killing" a subprocess spawned in node
        // with child_process methods
        .on('SIGTERM', () => resolve('SIGTERM'))
    })

    log.info(`Got ${command} signal. Offline Halting...`)
  }

  async _createLambda(lambdas, skipStart) {
    const { default: Lambda } = await import('./lambda/index.js')

    this.#lambda = new Lambda(this.#serverless, this.#options)

    this.#lambda.create(lambdas)

    if (!skipStart) {
      await this.#lambda.start()
    }
  }

  async _createHttp(events, skipStart) {
    const { default: Http } = await import('./events/http/index.js')

    this.#http = new Http(this.#serverless, this.#options, this.#lambda)

    await this.#http.registerPlugins()

    this.#http.create(events)

    // HTTP Proxy defined in Resource
    this.#http.createResourceRoutes()

    // Not found handling
    // we have to create the 404 routes last, otherwise we could have
    // collisions with catch all routes, e.g. any (proxy+}
    this.#http.create404Route()

    if (!skipStart) {
      await this.#http.start()
    }
  }

  async #createSchedule(events) {
    const { default: Schedule } = await import('./events/schedule/index.js')

    this.#schedule = new Schedule(
      this.#lambda,
      this.#serverless.service.provider.region,
    )

    this.#schedule.create(events)
  }

  async #createWebSocket(events) {
    const { default: WebSocket } = await import('./events/websocket/index.js')

    this.#webSocket = new WebSocket(
      this.#serverless,
      this.#options,
      this.#lambda,
    )

    this.#webSocket.create(events)

    return this.#webSocket.start()
  }

  _mergeOptions() {
    const {
      service: { custom = {}, provider },
    } = this.#serverless

    const customOptions = custom[CUSTOM_OPTION]

    // merge options
    // order of Precedence: command line options, custom options, defaults.
    this.#options = {
      ...defaultOptions,
      ...customOptions,
      ...this.#cliOptions,
    }

    // Parse CORS options
    this.#options.corsAllowHeaders = this.#options.corsAllowHeaders
      .replace(/\s/g, '')
      .split(',')
    this.#options.corsAllowOrigin = this.#options.corsAllowOrigin
      .replace(/\s/g, '')
      .split(',')
    this.#options.corsExposedHeaders = this.#options.corsExposedHeaders
      .replace(/\s/g, '')
      .split(',')

    if (this.#options.corsDisallowCredentials) {
      this.#options.corsAllowCredentials = false
    }

    this.#options.corsConfig = {
      credentials: this.#options.corsAllowCredentials,
      exposedHeaders: this.#options.corsExposedHeaders,
      headers: this.#options.corsAllowHeaders,
      origin: this.#options.corsAllowOrigin,
    }

    log.notice()
    log.notice(
      `Starting Offline at stage ${provider.stage} ${chalk.gray(
        `(${provider.region})`,
      )}`,
    )
    log.notice()
    log.debug('options:', this.#options)
  }

  _getEvents() {
    const { service } = this.#serverless

    const httpEvents = []
    const lambdas = []
    const scheduleEvents = []
    const webSocketEvents = []

    const functionKeys = service.getAllFunctions()

    let hasPrivateHttpEvent = false

    functionKeys.forEach((functionKey) => {
      const functionDefinition = service.getFunction(functionKey)

      lambdas.push({ functionDefinition, functionKey })

      const events = service.getAllEventsInFunction(functionKey) || []

      events.forEach((event) => {
        const { http, httpApi, schedule, websocket } = event

        if ((http || httpApi) && functionDefinition.handler) {
          const httpEvent = {
            functionKey,
            handler: functionDefinition.handler,
            http: http || httpApi,
          }

          if (httpApi) {
            // Ensure definitions for 'httpApi' events are objects so that they can be marked
            // with an 'isHttpApi' property (they are handled differently to 'http' events)
            if (typeof httpEvent.http === 'string') {
              httpEvent.http = {
                routeKey: httpEvent.http === '*' ? '$default' : httpEvent.http,
              }
            } else if (typeof httpEvent.http === 'object') {
              if (!httpEvent.http.method) {
                log.warning(
                  `Event definition is missing a method for function "${functionKey}"`,
                )
                httpEvent.http.method = ''
              }
              if (
                httpEvent.http.method === '*' &&
                httpEvent.http.path === '*'
              ) {
                httpEvent.http.routeKey = '$default'
              } else {
                const resolvedMethod =
                  httpEvent.http.method === '*'
                    ? 'ANY'
                    : httpEvent.http.method.toUpperCase()
                httpEvent.http.routeKey = `${resolvedMethod} ${httpEvent.http.path}`
              }
              // Clear these properties to avoid confusion (they will be derived from the routeKey
              // when needed later)
              delete httpEvent.http.method
              delete httpEvent.http.path
            } else {
              log.warning(
                `Event definition must be a string or object but received ${typeof httpEvent.http} for function "${functionKey}"`,
              )
              httpEvent.http.routeKey = ''
            }

            httpEvent.http.isHttpApi = true
            if (
              functionDefinition.httpApi &&
              functionDefinition.httpApi.payload
            ) {
              httpEvent.http.payload = functionDefinition.httpApi.payload
            } else {
              httpEvent.http.payload =
                service.provider.httpApi && service.provider.httpApi.payload
                  ? service.provider.httpApi.payload
                  : '2.0'
            }
          }

          if (http && http.private) {
            hasPrivateHttpEvent = true
          }

          httpEvents.push(httpEvent)
        }

        if (schedule) {
          scheduleEvents.push({
            functionKey,
            schedule,
          })
        }

        if (websocket) {
          webSocketEvents.push({
            functionKey,
            websocket,
          })
        }
      })
    })

    // for simple API Key authentication model
    if (hasPrivateHttpEvent) {
      log.notice(`Key with token: ${this.#options.apiKey}`)

      if (this.#options.noAuth) {
        log.notice(
          'Authorizers are turned off. You do not need to use x-api-key header.',
        )
      } else {
        log.notice('Remember to use x-api-key on the request headers')
      }
    }

    return {
      httpEvents,
      lambdas,
      scheduleEvents,
      webSocketEvents,
    }
  }

  // TEMP FIXME quick fix to expose gateway server for testing, look for better solution
  getApiGatewayServer() {
    return this.#http.getServer()
  }

  // TODO: missing tests
  #verifyServerlessVersionCompatibility() {
    const currentVersion = this.#serverless.version
    const requiredVersionRange = pkg.peerDependencies.serverless

    if (semver.parse(currentVersion).prerelease.length) {
      // Do not validate, if run against serverless pre-release
      return
    }

    const versionIsSatisfied = satisfiesVersionRange(
      currentVersion,
      requiredVersionRange,
    )

    if (!versionIsSatisfied) {
      log.warning(
        `'serverless-offline' requires 'serverless' version '${requiredVersionRange}' but found version '${currentVersion}'.
         Be aware that functionality might be limited or contains bugs.
         To avoid any issues update 'serverless' to a later version.
        `,
      )
    }
  }
}
<commit_msg>refactor: make cleanupFunctions private<commit_after>import { createRequire } from 'node:module'
import process, { env, exit } from 'node:process'
import { log } from '@serverless/utils/log.js'
import chalk from 'chalk'
import semver from 'semver'
import updateNotifier from 'update-notifier'
import { satisfiesVersionRange } from './utils/index.js'
import {
  commandOptions,
  CUSTOM_OPTION,
  defaultOptions,
  SERVER_SHUTDOWN_TIMEOUT,
} from './config/index.js'

const require = createRequire(import.meta.url)
const pkg = require('../package.json')

export default class ServerlessOffline {
  #cliOptions = null

  #http = null

  #lambda = null

  #options = null

  #schedule = null

  #serverless = null

  #webSocket = null

  constructor(serverless, cliOptions) {
    this.#cliOptions = cliOptions
    this.#serverless = serverless

    this.commands = {
      offline: {
        // add start nested options
        commands: {
          functionsUpdated: {
            lifecycleEvents: ['cleanup'],
            type: 'entrypoint',
          },
          start: {
            lifecycleEvents: ['init', 'ready', 'end'],
            options: commandOptions,
            usage:
              'Simulates API Gateway to call your lambda functions offline using backward compatible initialization.',
          },
        },
        lifecycleEvents: ['start'],
        options: commandOptions,
        usage: 'Simulates API Gateway to call your lambda functions offline.',
      },
    }

    this.hooks = {
      'offline:functionsUpdated:cleanup': this.#cleanupFunctions.bind(this),
      'offline:start': this.#startWithExplicitEnd.bind(this),
      'offline:start:end': this.end.bind(this),
      'offline:start:init': this.start.bind(this),
      'offline:start:ready': this.ready.bind(this),
    }
  }

  // Entry point for the plugin (sls offline) when running 'sls offline start'
  async start() {
    // Put here so available everywhere, not just in handlers
    env.IS_OFFLINE = true

    // check if update is available
    updateNotifier({ pkg }).notify()

    this.#verifyServerlessVersionCompatibility()

    this._mergeOptions()

    const { httpEvents, lambdas, scheduleEvents, webSocketEvents } =
      this._getEvents()

    // if (lambdas.length > 0) {
    await this._createLambda(lambdas)
    // }

    const eventModules = []

    if (httpEvents.length > 0) {
      eventModules.push(this._createHttp(httpEvents))
    }

    if (!this.#options.disableScheduledEvents && scheduleEvents.length > 0) {
      eventModules.push(this.#createSchedule(scheduleEvents))
    }

    if (webSocketEvents.length > 0) {
      eventModules.push(this.#createWebSocket(webSocketEvents))
    }

    await Promise.all(eventModules)
  }

  async ready() {
    if (env.NODE_ENV !== 'test') {
      await this.#listenForTermination()
    }
  }

  async end(skipExit) {
    // TEMP FIXME
    if (env.NODE_ENV === 'test' && skipExit === undefined) {
      return
    }

    log.info('Halting offline server')

    const eventModules = []

    if (this.#lambda) {
      eventModules.push(this.#lambda.cleanup())
      eventModules.push(this.#lambda.stop(SERVER_SHUTDOWN_TIMEOUT))
    }

    if (this.#http) {
      eventModules.push(this.#http.stop(SERVER_SHUTDOWN_TIMEOUT))
    }

    // if (this.#schedule) {
    //   eventModules.push(this.#schedule.stop())
    // }

    if (this.#webSocket) {
      eventModules.push(this.#webSocket.stop(SERVER_SHUTDOWN_TIMEOUT))
    }

    await Promise.all(eventModules)

    if (!skipExit) {
      exit(0)
    }
  }

  async #cleanupFunctions() {
    if (this.#lambda) {
      log.debug('Forcing cleanup of Lambda functions')
      await this.#lambda.cleanup()
    }
  }

  /**
   * Entry point for the plugin (sls offline) when running 'sls offline'
   * The call to this.end() would terminate the process before 'offline:start:end' could be consumed
   * by downstream plugins. When running sls offline that can be expected, but docs say that
   * 'sls offline start' will provide the init and end hooks for other plugins to consume
   * */
  async #startWithExplicitEnd() {
    await this.start()
    await this.ready()
    this.end()
  }

  async #listenForTermination() {
    const command = await new Promise((resolve) => {
      process
        // SIGINT will be usually sent when user presses ctrl+c
        .on('SIGINT', () => resolve('SIGINT'))
        // SIGTERM is a default termination signal in many cases,
        // for example when "killing" a subprocess spawned in node
        // with child_process methods
        .on('SIGTERM', () => resolve('SIGTERM'))
    })

    log.info(`Got ${command} signal. Offline Halting...`)
  }

  async _createLambda(lambdas, skipStart) {
    const { default: Lambda } = await import('./lambda/index.js')

    this.#lambda = new Lambda(this.#serverless, this.#options)

    this.#lambda.create(lambdas)

    if (!skipStart) {
      await this.#lambda.start()
    }
  }

  async _createHttp(events, skipStart) {
    const { default: Http } = await import('./events/http/index.js')

    this.#http = new Http(this.#serverless, this.#options, this.#lambda)

    await this.#http.registerPlugins()

    this.#http.create(events)

    // HTTP Proxy defined in Resource
    this.#http.createResourceRoutes()

    // Not found handling
    // we have to create the 404 routes last, otherwise we could have
    // collisions with catch all routes, e.g. any (proxy+}
    this.#http.create404Route()

    if (!skipStart) {
      await this.#http.start()
    }
  }

  async #createSchedule(events) {
    const { default: Schedule } = await import('./events/schedule/index.js')

    this.#schedule = new Schedule(
      this.#lambda,
      this.#serverless.service.provider.region,
    )

    this.#schedule.create(events)
  }

  async #createWebSocket(events) {
    const { default: WebSocket } = await import('./events/websocket/index.js')

    this.#webSocket = new WebSocket(
      this.#serverless,
      this.#options,
      this.#lambda,
    )

    this.#webSocket.create(events)

    return this.#webSocket.start()
  }

  _mergeOptions() {
    const {
      service: { custom = {}, provider },
    } = this.#serverless

    const customOptions = custom[CUSTOM_OPTION]

    // merge options
    // order of Precedence: command line options, custom options, defaults.
    this.#options = {
      ...defaultOptions,
      ...customOptions,
      ...this.#cliOptions,
    }

    // Parse CORS options
    this.#options.corsAllowHeaders = this.#options.corsAllowHeaders
      .replace(/\s/g, '')
      .split(',')
    this.#options.corsAllowOrigin = this.#options.corsAllowOrigin
      .replace(/\s/g, '')
      .split(',')
    this.#options.corsExposedHeaders = this.#options.corsExposedHeaders
      .replace(/\s/g, '')
      .split(',')

    if (this.#options.corsDisallowCredentials) {
      this.#options.corsAllowCredentials = false
    }

    this.#options.corsConfig = {
      credentials: this.#options.corsAllowCredentials,
      exposedHeaders: this.#options.corsExposedHeaders,
      headers: this.#options.corsAllowHeaders,
      origin: this.#options.corsAllowOrigin,
    }

    log.notice()
    log.notice(
      `Starting Offline at stage ${provider.stage} ${chalk.gray(
        `(${provider.region})`,
      )}`,
    )
    log.notice()
    log.debug('options:', this.#options)
  }

  _getEvents() {
    const { service } = this.#serverless

    const httpEvents = []
    const lambdas = []
    const scheduleEvents = []
    const webSocketEvents = []

    const functionKeys = service.getAllFunctions()

    let hasPrivateHttpEvent = false

    functionKeys.forEach((functionKey) => {
      const functionDefinition = service.getFunction(functionKey)

      lambdas.push({ functionDefinition, functionKey })

      const events = service.getAllEventsInFunction(functionKey) || []

      events.forEach((event) => {
        const { http, httpApi, schedule, websocket } = event

        if ((http || httpApi) && functionDefinition.handler) {
          const httpEvent = {
            functionKey,
            handler: functionDefinition.handler,
            http: http || httpApi,
          }

          if (httpApi) {
            // Ensure definitions for 'httpApi' events are objects so that they can be marked
            // with an 'isHttpApi' property (they are handled differently to 'http' events)
            if (typeof httpEvent.http === 'string') {
              httpEvent.http = {
                routeKey: httpEvent.http === '*' ? '$default' : httpEvent.http,
              }
            } else if (typeof httpEvent.http === 'object') {
              if (!httpEvent.http.method) {
                log.warning(
                  `Event definition is missing a method for function "${functionKey}"`,
                )
                httpEvent.http.method = ''
              }
              if (
                httpEvent.http.method === '*' &&
                httpEvent.http.path === '*'
              ) {
                httpEvent.http.routeKey = '$default'
              } else {
                const resolvedMethod =
                  httpEvent.http.method === '*'
                    ? 'ANY'
                    : httpEvent.http.method.toUpperCase()
                httpEvent.http.routeKey = `${resolvedMethod} ${httpEvent.http.path}`
              }
              // Clear these properties to avoid confusion (they will be derived from the routeKey
              // when needed later)
              delete httpEvent.http.method
              delete httpEvent.http.path
            } else {
              log.warning(
                `Event definition must be a string or object but received ${typeof httpEvent.http} for function "${functionKey}"`,
              )
              httpEvent.http.routeKey = ''
            }

            httpEvent.http.isHttpApi = true
            if (
              functionDefinition.httpApi &&
              functionDefinition.httpApi.payload
            ) {
              httpEvent.http.payload = functionDefinition.httpApi.payload
            } else {
              httpEvent.http.payload =
                service.provider.httpApi && service.provider.httpApi.payload
                  ? service.provider.httpApi.payload
                  : '2.0'
            }
          }

          if (http && http.private) {
            hasPrivateHttpEvent = true
          }

          httpEvents.push(httpEvent)
        }

        if (schedule) {
          scheduleEvents.push({
            functionKey,
            schedule,
          })
        }

        if (websocket) {
          webSocketEvents.push({
            functionKey,
            websocket,
          })
        }
      })
    })

    // for simple API Key authentication model
    if (hasPrivateHttpEvent) {
      log.notice(`Key with token: ${this.#options.apiKey}`)

      if (this.#options.noAuth) {
        log.notice(
          'Authorizers are turned off. You do not need to use x-api-key header.',
        )
      } else {
        log.notice('Remember to use x-api-key on the request headers')
      }
    }

    return {
      httpEvents,
      lambdas,
      scheduleEvents,
      webSocketEvents,
    }
  }

  // TEMP FIXME quick fix to expose gateway server for testing, look for better solution
  getApiGatewayServer() {
    return this.#http.getServer()
  }

  // TODO: missing tests
  #verifyServerlessVersionCompatibility() {
    const currentVersion = this.#serverless.version
    const requiredVersionRange = pkg.peerDependencies.serverless

    if (semver.parse(currentVersion).prerelease.length) {
      // Do not validate, if run against serverless pre-release
      return
    }

    const versionIsSatisfied = satisfiesVersionRange(
      currentVersion,
      requiredVersionRange,
    )

    if (!versionIsSatisfied) {
      log.warning(
        `'serverless-offline' requires 'serverless' version '${requiredVersionRange}' but found version '${currentVersion}'.
         Be aware that functionality might be limited or contains bugs.
         To avoid any issues update 'serverless' to a later version.
        `,
      )
    }
  }
}
<|endoftext|>


<commit_before>;(function(Agent){

  var patchViewChanges = _.debounce(function(view, prop, action, difference, oldValue) {
    Agent.lazyWorker.push({
      context: Agent,
      args: [view],
      callback: function(view) {
        Agent.sendAppComponentReport('view:change', {
          cid: view.cid,
          data: Agent.serializeView(view)
        });
      }
    });
  }, 200);

  // @private
  Agent.patchBackboneView = function(BackboneView) {
    debug.log('Backbone.View detected');

    Agent.patchBackboneComponent(BackboneView, function(view) { // on new instance
      Agent.lazyWorker.push({
        context: Agent,
        args: [view],
        callback: function(view) {
          // registra il nuovo componente dell'app
          var data = Agent.serializeView(view)
          Agent.registerAppComponent('View', view, data);
          Agent.sendAppComponentReport('view:change', {
            data: data,
            cid: view.cid
          });
        }
      });

      // set class name if we can
      if (view._requirePath) {
        view._className = _.last(view._requirePath.split('/'));
      }

      // Patcha i metodi del componente dell'app
      Agent.patchAppComponentTrigger(view, 'view');

      Agent.onDefined(view, 'ui', function() {
        Agent.onChange(view.ui, _.partial(patchViewChanges, view));
        patchViewChanges(view);
      });

      Agent.onDefined(view, '_events', function() {
        Agent.onChange(view._events, _.partial(patchViewChanges, view));
        patchViewChanges(view);
      });

      Agent.onDefined(view, '_listeningTo', function() {
        Agent.onChange(view._events, _.partial(patchViewChanges, view));
        patchViewChanges(view);
      });
    });
  };

}(Agent));
<commit_msg>Fix watching view _listeningTo property<commit_after>;(function(Agent){

  var patchViewChanges = _.debounce(function(view, prop, action, difference, oldValue) {
    Agent.lazyWorker.push({
      context: Agent,
      args: [view],
      callback: function(view) {
        Agent.sendAppComponentReport('view:change', {
          cid: view.cid,
          data: Agent.serializeView(view)
        });
      }
    });
  }, 200);

  // @private
  Agent.patchBackboneView = function(BackboneView) {
    debug.log('Backbone.View detected');

    Agent.patchBackboneComponent(BackboneView, function(view) { // on new instance
      Agent.lazyWorker.push({
        context: Agent,
        args: [view],
        callback: function(view) {
          // registra il nuovo componente dell'app
          var data = Agent.serializeView(view)
          Agent.registerAppComponent('View', view, data);
          Agent.sendAppComponentReport('view:change', {
            data: data,
            cid: view.cid
          });
        }
      });

      // set class name if we can
      if (view._requirePath) {
        view._className = _.last(view._requirePath.split('/'));
      }

      // Patcha i metodi del componente dell'app
      Agent.patchAppComponentTrigger(view, 'view');

      Agent.onDefined(view, 'ui', function() {
        Agent.onChange(view.ui, _.partial(patchViewChanges, view));
        patchViewChanges(view);
      });

      Agent.onDefined(view, '_events', function() {
        Agent.onChange(view._events, _.partial(patchViewChanges, view));
        patchViewChanges(view);
      });

      Agent.onDefined(view, '_listeningTo', function() {
        Agent.onChange(view._listeningTo, _.partial(patchViewChanges, view));
        patchViewChanges(view);
      });
    });
  };

}(Agent));
<|endoftext|>


<commit_before>/**
 * Templates holder class
 * @param object config
 */
var Template = function (config) {
    var _templates = {};
    var _config = {
        'template_class': '.template',
        'template_alias': 'template'
    };
    _.merge(_config, config);

    /**
     * register a template
     *
     * @param string name
     * @param string content
     */
    var register = function(name, content) {
        _templates[name] = _.template(_.unescape(content));
    };

    /**
     * render template under "name" alias, with given data
     *
     * @param string name
     * @param object data
     * @return string
     */
    var render = function(name, data) {
        if (!_templates[name]) {
            throw "Unregistered template " + name;
        }

        return _templates[name](data);
    };

    if (_config.container) {
        $(_config.container)
            .find(_config.template_class + '[data-' + _config.template_alias + ']')
            .each(function(index, element) {
                var element = $(element);
                register(
                    element.data(_config.template_alias),
                    element.html()
                );
            })
        ;
    }

    return {
        render: render,
        templates: _templates
    };
};
<commit_msg>update template.js<commit_after>'use strict';
/**
 * Templates holder class
 * @param object config
 */
function Template(config) {
    var _templates = {};
    var templatesHtml;
    var _config = {
        'template_alias': 'template'
    };
    _.merge(_config, config);

    if (_config.container) {
        templatesHtml = $(_config.container).html();
        $(templatesHtml).filter('[data-' + _config.template_alias + ']')
            .each(function(index, element) {
                register(
                    element.dataset[_config.template_alias],
                    _.unescape(element.innerHTML)
                );
            });
    }

    /**
     * register a template
     *
     * @param string name
     * @param string content
     */
    function register(name, content) {
        _.set(_templates, name, _.template(content));
    }

    /**
     * render template under "name" alias, with given data
     *
     * @param string name
     * @param object data
     * @return string
     */
    function render(name, data) {
        var template = _.get(_templates, name);
        if (!template) {
            throw "Unregistered template " + name;
        }
        return template(data);
    }

    return {
        render: render,
        templates: _templates
    };
}
<|endoftext|>


<commit_before>'use strict';

var Vinyl = require('vinyl');
var through = require('through2');
var plugin = require('./');

var list = new Vinyl({
  path: 'list.hbs',
  content: 'this is a list'
});
var item = new Vinyl({
  path: 'item.hbs',
  content: 'this is an item'
});

var stream = through.obj();

stream
  .pipe(through.obj(function(file, enc, next) {
    // console.log(file.path);
    // console.log(file.data);
    next(null, file);
  }))
  .pipe(plugin(':tags/:tag/page/:idx/index.html', {
    list: list,
    item: item
  }))
  .pipe(plugin(':categories/:category/page/:idx/index.html', {
    list: list,
    item: item
  }))
  .on('data', function(file) {
    console.log(file.path);
    console.log(file.data);
    console.log();
  })
  .on('error', console.error)
  .on('end', function() {
    console.log('done');
    process.exit();
  });

var tags = ['foo', 'bar', 'baz', 'bang', 'beep', 'boop', 'bop'];
var categories = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
var maxPages = 100;
var maxTags = 5;
var maxCategories = 5;

function pickTag() {
  return tags[Math.floor(Math.random() * (tags.length))];
}

function pickTags() {
  var picked = [];
  var max = Math.floor(Math.random() * maxTags);
  while(picked.length < max) {
    var tag = pickTag();
    if (picked.indexOf(tag) === -1) {
      picked.push(tag);
    }
  }
  return picked;
}

function pickCategory() {
  return categories[Math.floor(Math.random() * (categories.length))];
}

function pickCategories() {
  var picked = [];
  var max = Math.floor(Math.random() * maxCategories);
  while(picked.length < max) {
    var category = pickCategory();
    if (picked.indexOf(category) === -1) {
      picked.push(category);
    }
  }
  return picked;
}

function makeFile(idx) {
  var file = new Vinyl({
    path: `source-file-${idx}.hbs`,
    contents: new Buffer(`this is source-file-${idx}`)
  });
  file.data = {
    categories: pickCategories(),
    tags: pickTags()
  };
  return file;
}

process.nextTick(function() {
  for(var i = 0; i < maxPages; i++) {
    stream.write(makeFile(i));
  }
  stream.end();
});
<commit_msg>udpate example with pagination options cleanup and comment code<commit_after>'use strict';

var Vinyl = require('vinyl');
var through = require('through2');
var collection = require('./');

// files to use for creating list and item pages
// these can be Vinyl files
var list = {path: 'list.hbs', content: 'this is a list'};
var item = {path: 'item.hbs', content: 'this is an item'};
var stream = through.obj();

// options to pass to the collection plugin
var options = {
  list: list,
  item: item,
  paginate: {limit: 5}
};

// stream that source files will be piped into
stream
  // use the collection plugin to create files for that tags found in the source files
  .pipe(collection(':tags/:tag/page/:idx/index.html', options))
  // use the collection plugin to create files for the categories found in the source files
  .pipe(collection(':categories/:category/page/:idx/index.html', options))
  .on('data', function(file) {
    console.log(file.path);
  })
  .on('error', console.error)
  .on('end', function() {
    console.log('done');
    process.exit();
  });

/**
 * Below is code for creating a lot of random fake files.
 * Change `maxFiles` to change how many files are created.
 */

var maxFiles = 500;
var maxTags = 5;
var maxCategories = 5;
var tags = ['foo', 'bar', 'baz', 'bang', 'beep', 'boop', 'bop'];
var categories = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];

// make fake files and write the to the stream to begin piping
process.nextTick(function() {
  for(var i = 0; i < maxFiles; i++) {
    stream.write(makeFile(i));
  }
  stream.end();
});

// make a new file with randomly selected categories and tags
function makeFile(idx) {
  var file = new Vinyl({
    path: `source-file-${idx}.hbs`,
    contents: new Buffer(`this is source-file-${idx}`)
  });
  file.data = {
    categories: pickCategories(),
    tags: pickTags()
  };
  return file;
}

// pick a random tag from the possible tags in the tags array
function pickTag() {
  return tags[Math.floor(Math.random() * (tags.length))];
}

// pick random tags up to the `maxTags`
function pickTags() {
  var picked = [];
  var max = Math.floor(Math.random() * maxTags);
  while(picked.length < max) {
    var tag = pickTag();
    if (picked.indexOf(tag) === -1) {
      picked.push(tag);
    }
  }
  return picked;
}

// pick a random category from the possible categories in the categories array
function pickCategory() {
  return categories[Math.floor(Math.random() * (categories.length))];
}

// pick random categories up to the `maxCategories`
function pickCategories() {
  var picked = [];
  var max = Math.floor(Math.random() * maxCategories);
  while(picked.length < max) {
    var category = pickCategory();
    if (picked.indexOf(category) === -1) {
      picked.push(category);
    }
  }
  return picked;
}
<|endoftext|>


<commit_before>import { INCREMENT, ADD_CHILD, REMOVE_CHILD, CREATE_NODE, DELETE_NODE } from '../actions'

function childIds(state, action) {
  switch (action.type) {
    case ADD_CHILD:
      return [ ...state, action.childId ]
    case REMOVE_CHILD:
      const index = state.indexOf(action.childId)
      return [
        ...state.slice(0, index),
        ...state.slice(index + 1)
      ]
    default:
      return state
  }
}

function node(state, action) {
  switch (action.type) {
    case CREATE_NODE:
      return {
        id: action.nodeId,
        counter: 0,
        childIds: []
      }
    case INCREMENT:
      return Object.assign({}, state, {
        counter: state.counter + 1
      })
    case ADD_CHILD:
    case REMOVE_CHILD:
      return Object.assign({}, state, {
        childIds: childIds(state.childIds, action)
      })
    default:
      return state
  }
}

function getAllDescendantIds(state, nodeId) {
  return state[nodeId].childIds.reduce((acc, childId) => (
    [ ...acc, childId, ...getAllDescendantIds(state, childId) ]
  ), [])
}

function deleteMany(state, ids) {
  state = Object.assign({}, state)
  ids.forEach(id => delete state[id])
  return state
}

export default function (state = {}, action) {
  const { nodeId } = action
  if (typeof nodeId === 'undefined') {
    return state
  }

  if (action.type === DELETE_NODE) {
    const descendantIds = getAllDescendantIds(state, nodeId)
    return deleteMany(state, [ nodeId, ...descendantIds ])
  }

  return Object.assign({}, state, {
    [nodeId]: node(state[nodeId], action)
  })
}
<commit_msg>tree-view: simplify reducer function<commit_after>import { INCREMENT, ADD_CHILD, REMOVE_CHILD, CREATE_NODE, DELETE_NODE } from '../actions'

function childIds(state, action) {
  switch (action.type) {
    case ADD_CHILD:
      return [ ...state, action.childId ]
    case REMOVE_CHILD:
      return state.filter(id => id !== action.childId)
    default:
      return state
  }
}

function node(state, action) {
  switch (action.type) {
    case CREATE_NODE:
      return {
        id: action.nodeId,
        counter: 0,
        childIds: []
      }
    case INCREMENT:
      return Object.assign({}, state, {
        counter: state.counter + 1
      })
    case ADD_CHILD:
    case REMOVE_CHILD:
      return Object.assign({}, state, {
        childIds: childIds(state.childIds, action)
      })
    default:
      return state
  }
}

function getAllDescendantIds(state, nodeId) {
  return state[nodeId].childIds.reduce((acc, childId) => (
    [ ...acc, childId, ...getAllDescendantIds(state, childId) ]
  ), [])
}

function deleteMany(state, ids) {
  state = Object.assign({}, state)
  ids.forEach(id => delete state[id])
  return state
}

export default function (state = {}, action) {
  const { nodeId } = action
  if (typeof nodeId === 'undefined') {
    return state
  }

  if (action.type === DELETE_NODE) {
    const descendantIds = getAllDescendantIds(state, nodeId)
    return deleteMany(state, [ nodeId, ...descendantIds ])
  }

  return Object.assign({}, state, {
    [nodeId]: node(state[nodeId], action)
  })
}
<|endoftext|>


<commit_before>// this file patches playemjs' Youtube player, so that it streams tracks from an
// iframe hosted on a different domain name.
//
// it will load YoutubePlayerIframe.html or YoutubePlayerIframeLocal.html,
// based on the domain name where openwhyd is running (local or production),
// which will load whydRemotePlayer.js so that openwhyd can control the playback.
//
function YoutubeIframePlayer(){
	return YoutubeIframePlayer.super_.apply(this, arguments);
}

(function() {

	var isLocal = window.location.href.indexOf("http://localhost:") == 0
		|| /^https?\:\/\/(\w+)\.openwhyd\.(\w+)(\:8080)?\//.test(window.location.href);

	var
		IFRAME_HOST = isLocal
			? window.location.href.substr(0, window.location.href.indexOf("/", 10))
			: (window.location.protocol + "//d3qdgup1c3urcq.cloudfront.net"), // CDN cached of Openwhyd's static resources (html and js files), available through a different domain name.
		IFRAME_PATH = isLocal
			? "/html/YoutubePlayerIframeLocal.html"
			: "/html/YoutubePlayerIframe.html"; // same file, except it explicitly loads playem-all.js and whydRemotePlayer.js from the openwhyd.org domain

	function Player(eventHandlers, embedVars) {
		var that = this;
		this.iframeReady = false;
		this.eventHandlers = eventHandlers || {};
		this.embedVars = embedVars || {};
		this.label = "Youtube";
		window.addEventListener('message', function(e) {
			if (e.origin === IFRAME_HOST) {
				var message, param;
				try {
					message = JSON.parse(e.data);
					param = message.data[0];
				} catch (err) {
					console.warn('skipping invalid message:', message);
					return;
				}
				that.iframeReady = true;
		        //for (var i in message.data)
		        //	if (message.data[i] == "(object)")
		        //    message.data[i] = that;
		        if (param == "(player)")
		        	param = that;
				//console.log("[youtube-iframe-player] iframe says:", message.code, param);
				if (message.code == "onApiReady")
					that.safeCall("play", that.embedVars.videoId);
				else
					that.safeClientCall(message.code, param);
			}
		});
		this.isReady = true;
		this.safeClientCall("onApiReady", this);
	}

	Player.prototype.safeCall = function(fctName, param) {
		if (!this.iframeReady)
			return console.warn("YT-iframe not ready => ignoring call to", fctName);
		try {
			var args = Array.apply(null, arguments).slice(1); // exclude first arg (fctName)
			this.iframe.contentWindow.postMessage(
				JSON.stringify({code: fctName, data: args}), IFRAME_HOST + IFRAME_PATH
			);
		}
		catch(e) {
			console.error("YT safecall error", e, e.stack);
		}
	}

	Player.prototype.safeClientCall = function(fctName, param) {
		try {
			if (this.eventHandlers[fctName])
				this.eventHandlers[fctName](param);
		}
		catch(e) {
			console.error("YT safeclientcall error", e.stack);
		}
	}

	Player.prototype.getEid = function(url) {
		if (
			/(youtube\.com\/(v\/|embed\/|(?:.*)?[\?\&]v=)|youtu\.be\/)([a-zA-Z0-9_\-]+)/.test(url)
			|| /\/yt\/([a-zA-Z0-9_\-]+)/.test(url)
			|| /youtube\.com\/attribution_link\?.*v\%3D([^ \%]+)/.test(url)
		)
			return RegExp.lastParen;
	}

	Player.prototype.play = function(id) {
		var that = this;
		this.iframeReady = false;
		this.embedVars.videoId = id;
		this.embedVars.playerId = this.embedVars.playerId || 'ytplayer';
		this.iframe = document.createElement('iframe');
		this.iframe.id = this.embedVars.playerId;
		var settings = {
			width: this.embedVars.width || '200',
			height: this.embedVars.height || '200',
			//origin: this.embedVars.origin
		};
		this.iframe.style.border = "0";
		this.iframe.style.width = "100%";
		this.iframe.style.height = "100%";
		this.iframe.onload = function(){
			that.iframeReady = true;
		};
		this.iframe.setAttribute("src", IFRAME_HOST + IFRAME_PATH + "?" + Object.keys(settings).map(function(p){
			return p + "=" + encodeURIComponent(settings[p]);
		}).join("&"));
		this.embedVars.playerContainer.appendChild(this.iframe);
	}

	Player.prototype.pause = function() {
		this.safeCall('pause');
	}

	Player.prototype.resume = function() {
		this.safeCall('resume');
	}

	Player.prototype.stop = function() {
		this.iframeReady = false;
		this.safeCall("stop");
		try {
			this.iframe.setAttribute("src", "");
			this.embedVars.playerContainer.removeChild(this.iframe);
		}
		catch(e){
			console.log("youtube iframe stop:");
		}
	}

	Player.prototype.getTrackPosition = function(callback) {
		this.safeCall('getTrackPosition'); // -> will call onTrackInfo()
	};

	Player.prototype.setTrackPosition = function(pos) {
		this.safeCall("setTrackPosition", pos);
	};

	Player.prototype.setVolume = function(vol) {
		this.safeCall('setVolume', vol);
	};

	//return Player;
	//inherits(YoutubeIframePlayer, Player);
	Player.prototype.fetchMetadata = YoutubePlayer.prototype.fetchMetadata;
	Player.prototype.searchTracks = YoutubePlayer.prototype.searchTracks;
	YoutubeIframePlayer.prototype = Player.prototype;
	YoutubeIframePlayer.super_ = Player;
})();
<commit_msg>fix: log message object if data is invalid<commit_after>// this file patches playemjs' Youtube player, so that it streams tracks from an
// iframe hosted on a different domain name.
//
// it will load YoutubePlayerIframe.html or YoutubePlayerIframeLocal.html,
// based on the domain name where openwhyd is running (local or production),
// which will load whydRemotePlayer.js so that openwhyd can control the playback.
//
function YoutubeIframePlayer(){
	return YoutubeIframePlayer.super_.apply(this, arguments);
}

(function() {

	var isLocal = window.location.href.indexOf("http://localhost:") == 0
		|| /^https?\:\/\/(\w+)\.openwhyd\.(\w+)(\:8080)?\//.test(window.location.href);

	var
		IFRAME_HOST = isLocal
			? window.location.href.substr(0, window.location.href.indexOf("/", 10))
			: (window.location.protocol + "//d3qdgup1c3urcq.cloudfront.net"), // CDN cached of Openwhyd's static resources (html and js files), available through a different domain name.
		IFRAME_PATH = isLocal
			? "/html/YoutubePlayerIframeLocal.html"
			: "/html/YoutubePlayerIframe.html"; // same file, except it explicitly loads playem-all.js and whydRemotePlayer.js from the openwhyd.org domain

	function Player(eventHandlers, embedVars) {
		var that = this;
		this.iframeReady = false;
		this.eventHandlers = eventHandlers || {};
		this.embedVars = embedVars || {};
		this.label = "Youtube";
		window.addEventListener('message', function(e) {
			if (e.origin === IFRAME_HOST) {
				var message, param;
				try {
					message = JSON.parse(e.data);
					param = message.data[0];
				} catch (err) {
					console.warn('skipping message with invalid data:', e);
					return;
				}
				that.iframeReady = true;
		        //for (var i in message.data)
		        //	if (message.data[i] == "(object)")
		        //    message.data[i] = that;
		        if (param == "(player)")
		        	param = that;
				//console.log("[youtube-iframe-player] iframe says:", message.code, param);
				if (message.code == "onApiReady")
					that.safeCall("play", that.embedVars.videoId);
				else
					that.safeClientCall(message.code, param);
			}
		});
		this.isReady = true;
		this.safeClientCall("onApiReady", this);
	}

	Player.prototype.safeCall = function(fctName, param) {
		if (!this.iframeReady)
			return console.warn("YT-iframe not ready => ignoring call to", fctName);
		try {
			var args = Array.apply(null, arguments).slice(1); // exclude first arg (fctName)
			this.iframe.contentWindow.postMessage(
				JSON.stringify({code: fctName, data: args}), IFRAME_HOST + IFRAME_PATH
			);
		}
		catch(e) {
			console.error("YT safecall error", e, e.stack);
		}
	}

	Player.prototype.safeClientCall = function(fctName, param) {
		try {
			if (this.eventHandlers[fctName])
				this.eventHandlers[fctName](param);
		}
		catch(e) {
			console.error("YT safeclientcall error", e.stack);
		}
	}

	Player.prototype.getEid = function(url) {
		if (
			/(youtube\.com\/(v\/|embed\/|(?:.*)?[\?\&]v=)|youtu\.be\/)([a-zA-Z0-9_\-]+)/.test(url)
			|| /\/yt\/([a-zA-Z0-9_\-]+)/.test(url)
			|| /youtube\.com\/attribution_link\?.*v\%3D([^ \%]+)/.test(url)
		)
			return RegExp.lastParen;
	}

	Player.prototype.play = function(id) {
		var that = this;
		this.iframeReady = false;
		this.embedVars.videoId = id;
		this.embedVars.playerId = this.embedVars.playerId || 'ytplayer';
		this.iframe = document.createElement('iframe');
		this.iframe.id = this.embedVars.playerId;
		var settings = {
			width: this.embedVars.width || '200',
			height: this.embedVars.height || '200',
			//origin: this.embedVars.origin
		};
		this.iframe.style.border = "0";
		this.iframe.style.width = "100%";
		this.iframe.style.height = "100%";
		this.iframe.onload = function(){
			that.iframeReady = true;
		};
		this.iframe.setAttribute("src", IFRAME_HOST + IFRAME_PATH + "?" + Object.keys(settings).map(function(p){
			return p + "=" + encodeURIComponent(settings[p]);
		}).join("&"));
		this.embedVars.playerContainer.appendChild(this.iframe);
	}

	Player.prototype.pause = function() {
		this.safeCall('pause');
	}

	Player.prototype.resume = function() {
		this.safeCall('resume');
	}

	Player.prototype.stop = function() {
		this.iframeReady = false;
		this.safeCall("stop");
		try {
			this.iframe.setAttribute("src", "");
			this.embedVars.playerContainer.removeChild(this.iframe);
		}
		catch(e){
			console.log("youtube iframe stop:");
		}
	}

	Player.prototype.getTrackPosition = function(callback) {
		this.safeCall('getTrackPosition'); // -> will call onTrackInfo()
	};

	Player.prototype.setTrackPosition = function(pos) {
		this.safeCall("setTrackPosition", pos);
	};

	Player.prototype.setVolume = function(vol) {
		this.safeCall('setVolume', vol);
	};

	//return Player;
	//inherits(YoutubeIframePlayer, Player);
	Player.prototype.fetchMetadata = YoutubePlayer.prototype.fetchMetadata;
	Player.prototype.searchTracks = YoutubePlayer.prototype.searchTracks;
	YoutubeIframePlayer.prototype = Player.prototype;
	YoutubeIframePlayer.super_ = Player;
})();
<|endoftext|>