<commit_before>/**
 * SaxParser.js
 *
 * Copyright, Moxiecode Systems AB
 * Released under LGPL License.
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

(function(tinymce) {
	/**
	 * This class parses HTML code using pure JavaScript and executes various events for each item it finds. It will
	 * always execute the events in the right order for tag soup code like

. It will also remove elements
	 * and attributes that doesn't fit the schema if the validate setting is enabled.
	 *
	 * @example
	 * var parser = new tinymce.html.SaxParser({
	 *     validate: true,
	 *
	 *     comment: function(text) {
	 *         console.log('Comment:', text);
	 *     },
	 *
	 *     cdata: function(text) {
	 *         console.log('CDATA:', text);
	 *     },
	 *
	 *     text: function(text, raw) {
	 *         console.log('Text:', text, 'Raw:', raw);
	 *     },
	 *
	 *     start: function(name, attrs, empty) {
	 *         console.log('Start:', name, attrs, empty);
	 *     },
	 *
	 *     end: function(name) {
	 *         console.log('End:', name);
	 *     },
	 *
	 *     pi: function(name, text) {
	 *         console.log('PI:', name, text);
	 *     },
	 *
	 *     doctype: function(text) {
	 *         console.log('DocType:', text);
	 *     }
	 * }, schema);
	 * @class tinymce.html.SaxParser
	 * @version 3.4
	 */

	/**
	 * Constructs a new SaxParser instance.
	 *
	 * @constructor
	 * @method SaxParser
	 * @param {Object} settings Name/value collection of settings. comment, cdata, text, start and end are callbacks.
	 * @param {tinymce.html.Schema} schema HTML Schema class to use when parsing.
	 */
	tinymce.html.SaxParser = function(settings, schema) {
		var self = this, noop = function() {};

		settings = settings || {};
		self.schema = schema = schema || new tinymce.html.Schema();

		if (settings.fix_self_closing !== false)
			settings.fix_self_closing = true;

		// Add handler functions from settings and setup default handlers
		tinymce.each('comment cdata text start end pi doctype'.split(' '), function(name) {
			if (name)
				self[name] = settings[name] || noop;
		});

		/**
		 * Parses the specified HTML string and executes the callbacks for each item it finds.
		 *
		 * @example
		 * new SaxParser({...}).parse('text');
		 * @method parse
		 * @param {String} html Html string to sax parse.
		 */
		self.parse = function(html) {
			var self = this, matches, index = 0, value, endRegExp, stack = [], attrList, i, text, name, isInternalElement, removeInternalElements,
				shortEndedElements, fillAttrsMap, isShortEnded, validate, elementRule, isValidElement, attr, attribsValue, invalidPrefixRegExp,
				validAttributesMap, validAttributePatterns, attributesRequired, attributesDefault, attributesForced, selfClosing,
				tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0, decode = tinymce.html.Entities.decode, fixSelfClosing, isIE;

			function processEndTag(name) {
				var pos, i;

				// Find position of parent of the same type
				pos = stack.length;
				while (pos--) {
					if (stack[pos].name === name)
						break;
				}

				// Found parent
				if (pos >= 0) {
					// Close all the open elements
					for (i = stack.length - 1; i >= pos; i--) {
						name = stack[i];

						if (name.valid)
							self.end(name.name);
					}

					// Remove the open elements from the stack
					stack.length = pos;
				}
			};

			function parseAttribute(match, name, value, val2, val3) {
				var attrRule, i;

				name = name.toLowerCase();
				value = name in fillAttrsMap ? name : decode(value || val2 || val3 || ''); // Handle boolean attribute than value attribute

				// Validate name and value
				if (validate && !isInternalElement && name.indexOf('data-mce-') !== 0) {
					attrRule = validAttributesMap[name];

					// Find rule by pattern matching
					if (!attrRule && validAttributePatterns) {
						i = validAttributePatterns.length;
						while (i--) {
							attrRule = validAttributePatterns[i];
							if (attrRule.pattern.test(name))
								break;
						}

						// No rule matched
						if (i === -1)
							attrRule = null;
					}

					// No attribute rule found
					if (!attrRule)
						return;

					// Validate value
					if (attrRule.validValues && !(value in attrRule.validValues))
						return;
				}

				// Add attribute to list and map
				attrList.map[name] = value;
				attrList.push({
					name: name,
					value: value
				});
			};

			// Precompile RegExps and map objects
			tokenRegExp = new RegExp('<(?:' +
				'(?:!--([\\w\\W]*?)-->)|' + // Comment
				'(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|' + // CDATA
				'(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE
				'(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI
				'(?:\\/([^>]+)>)|' + // End element
				'(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
			')', 'g');

			attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;
			specialElements = {
				'script' : /<\/script[^>]*>/gi,
				'style' : /<\/style[^>]*>/gi,
				'noscript' : /<\/noscript[^>]*>/gi
			};

			// Setup lookup tables for empty elements and boolean attributes
			shortEndedElements = schema.getShortEndedElements();
			selfClosing = settings.self_closing_elements || schema.getSelfClosingElements();
			fillAttrsMap = schema.getBoolAttrs();
			validate = settings.validate;
			removeInternalElements = settings.remove_internals;
			fixSelfClosing = settings.fix_self_closing;
			isIE = tinymce.isIE;
			invalidPrefixRegExp = /^:/;

			while (matches = tokenRegExp.exec(html)) {
				// Text
				if (index < matches.index)
					self.text(decode(html.substr(index, matches.index - index)));

				if (value = matches[6]) { // End element
					value = value.toLowerCase();

					// IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements
					if (isIE && invalidPrefixRegExp.test(value))
						value = value.substr(1);

					processEndTag(value);
				} else if (value = matches[7]) { // Start element
					value = value.toLowerCase();

					// IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements
					if (isIE && invalidPrefixRegExp.test(value))
						value = value.substr(1);

					isShortEnded = value in shortEndedElements;

					// Is self closing tag for example an
 after an open

					if (fixSelfClosing && selfClosing[value] && stack.length > 0 && stack[stack.length - 1].name === value)
						processEndTag(value);

					// Validate element
					if (!validate || (elementRule = schema.getElementRule(value))) {
						isValidElement = true;

						// Grab attributes map and patters when validation is enabled
						if (validate) {
							validAttributesMap = elementRule.attributes;
							validAttributePatterns = elementRule.attributePatterns;
						}

						// Parse attributes
						if (attribsValue = matches[8]) {
							isInternalElement = attribsValue.indexOf('data-mce-type') !== -1; // Check if the element is an internal element

							// If the element has internal attributes then remove it if we are told to do so
							if (isInternalElement && removeInternalElements)
								isValidElement = false;

							attrList = [];
							attrList.map = {};

							attribsValue.replace(attrRegExp, parseAttribute);
						} else {
							attrList = [];
							attrList.map = {};
						}

						// Process attributes if validation is enabled
						if (validate && !isInternalElement) {
							attributesRequired = elementRule.attributesRequired;
							attributesDefault = elementRule.attributesDefault;
							attributesForced = elementRule.attributesForced;

							// Handle forced attributes
							if (attributesForced) {
								i = attributesForced.length;
								while (i--) {
									attr = attributesForced[i];
									name = attr.name;
									attrValue = attr.value;

									if (attrValue === '{$uid}')
										attrValue = 'mce_' + idCount++;

									attrList.map[name] = attrValue;
									attrList.push({name: name, value: attrValue});
								}
							}

							// Handle default attributes
							if (attributesDefault) {
								i = attributesDefault.length;
								while (i--) {
									attr = attributesDefault[i];
									name = attr.name;

									if (!(name in attrList.map)) {
										attrValue = attr.value;

										if (attrValue === '{$uid}')
											attrValue = 'mce_' + idCount++;

										attrList.map[name] = attrValue;
										attrList.push({name: name, value: attrValue});
									}
								}
							}

							// Handle required attributes
							if (attributesRequired) {
								i = attributesRequired.length;
								while (i--) {
									if (attributesRequired[i] in attrList.map)
										break;
								}

								// None of the required attributes where found
								if (i === -1)
									isValidElement = false;
							}

							// Invalidate element if it's marked as bogus
							if (attrList.map['data-mce-bogus'])
								isValidElement = false;
						}

						if (isValidElement)
							self.start(value, attrList, isShortEnded);
					} else
						isValidElement = false;

					// Treat script, noscript and style a bit different since they may include code that looks like elements
					if (endRegExp = specialElements[value]) {
						endRegExp.lastIndex = index = matches.index + matches[0].length;

						if (matches = endRegExp.exec(html)) {
							if (isValidElement)
								text = html.substr(index, matches.index - index);

							index = matches.index + matches[0].length;
						} else {
							text = html.substr(index);
							index = html.length;
						}

						if (isValidElement && text.length > 0)
							self.text(text, true);

						if (isValidElement)
							self.end(value);

						tokenRegExp.lastIndex = index;
						continue;
					}

					// Push value on to stack
					if (!isShortEnded) {
						if (!attribsValue || attribsValue.indexOf('/') != attribsValue.length - 1)
							stack.push({name: value, valid: isValidElement});
						else if (isValidElement)
							self.end(value);
					}
				} else if (value = matches[1]) { // Comment
					self.comment(value);
				} else if (value = matches[2]) { // CDATA
					self.cdata(value);
				} else if (value = matches[3]) { // DOCTYPE
					self.doctype(value);
				} else if (value = matches[4]) { // PI
					self.pi(value, matches[5]);
				}

				index = matches.index + matches[0].length;
			}

			// Text
			if (index = 0; i--) {
				value = stack[i];

				if (value.valid)
					self.end(value.name);
			}
		};
	}
})(tinymce);
<commit_msg>Fixed bug where html5 data attributes where stripped from contents.<commit_after>/**
 * SaxParser.js
 *
 * Copyright, Moxiecode Systems AB
 * Released under LGPL License.
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

(function(tinymce) {
	/**
	 * This class parses HTML code using pure JavaScript and executes various events for each item it finds. It will
	 * always execute the events in the right order for tag soup code like

. It will also remove elements
	 * and attributes that doesn't fit the schema if the validate setting is enabled.
	 *
	 * @example
	 * var parser = new tinymce.html.SaxParser({
	 *     validate: true,
	 *
	 *     comment: function(text) {
	 *         console.log('Comment:', text);
	 *     },
	 *
	 *     cdata: function(text) {
	 *         console.log('CDATA:', text);
	 *     },
	 *
	 *     text: function(text, raw) {
	 *         console.log('Text:', text, 'Raw:', raw);
	 *     },
	 *
	 *     start: function(name, attrs, empty) {
	 *         console.log('Start:', name, attrs, empty);
	 *     },
	 *
	 *     end: function(name) {
	 *         console.log('End:', name);
	 *     },
	 *
	 *     pi: function(name, text) {
	 *         console.log('PI:', name, text);
	 *     },
	 *
	 *     doctype: function(text) {
	 *         console.log('DocType:', text);
	 *     }
	 * }, schema);
	 * @class tinymce.html.SaxParser
	 * @version 3.4
	 */

	/**
	 * Constructs a new SaxParser instance.
	 *
	 * @constructor
	 * @method SaxParser
	 * @param {Object} settings Name/value collection of settings. comment, cdata, text, start and end are callbacks.
	 * @param {tinymce.html.Schema} schema HTML Schema class to use when parsing.
	 */
	tinymce.html.SaxParser = function(settings, schema) {
		var self = this, noop = function() {};

		settings = settings || {};
		self.schema = schema = schema || new tinymce.html.Schema();

		if (settings.fix_self_closing !== false)
			settings.fix_self_closing = true;

		// Add handler functions from settings and setup default handlers
		tinymce.each('comment cdata text start end pi doctype'.split(' '), function(name) {
			if (name)
				self[name] = settings[name] || noop;
		});

		/**
		 * Parses the specified HTML string and executes the callbacks for each item it finds.
		 *
		 * @example
		 * new SaxParser({...}).parse('text');
		 * @method parse
		 * @param {String} html Html string to sax parse.
		 */
		self.parse = function(html) {
			var self = this, matches, index = 0, value, endRegExp, stack = [], attrList, i, text, name, isInternalElement, removeInternalElements,
				shortEndedElements, fillAttrsMap, isShortEnded, validate, elementRule, isValidElement, attr, attribsValue, invalidPrefixRegExp,
				validAttributesMap, validAttributePatterns, attributesRequired, attributesDefault, attributesForced, selfClosing,
				tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0, decode = tinymce.html.Entities.decode, fixSelfClosing, isIE;

			function processEndTag(name) {
				var pos, i;

				// Find position of parent of the same type
				pos = stack.length;
				while (pos--) {
					if (stack[pos].name === name)
						break;
				}

				// Found parent
				if (pos >= 0) {
					// Close all the open elements
					for (i = stack.length - 1; i >= pos; i--) {
						name = stack[i];

						if (name.valid)
							self.end(name.name);
					}

					// Remove the open elements from the stack
					stack.length = pos;
				}
			};

			function parseAttribute(match, name, value, val2, val3) {
				var attrRule, i;

				name = name.toLowerCase();
				value = name in fillAttrsMap ? name : decode(value || val2 || val3 || ''); // Handle boolean attribute than value attribute

				// Validate name and value
				if (validate && !isInternalElement && name.indexOf('data-') !== 0) {
					attrRule = validAttributesMap[name];

					// Find rule by pattern matching
					if (!attrRule && validAttributePatterns) {
						i = validAttributePatterns.length;
						while (i--) {
							attrRule = validAttributePatterns[i];
							if (attrRule.pattern.test(name))
								break;
						}

						// No rule matched
						if (i === -1)
							attrRule = null;
					}

					// No attribute rule found
					if (!attrRule)
						return;

					// Validate value
					if (attrRule.validValues && !(value in attrRule.validValues))
						return;
				}

				// Add attribute to list and map
				attrList.map[name] = value;
				attrList.push({
					name: name,
					value: value
				});
			};

			// Precompile RegExps and map objects
			tokenRegExp = new RegExp('<(?:' +
				'(?:!--([\\w\\W]*?)-->)|' + // Comment
				'(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|' + // CDATA
				'(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE
				'(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI
				'(?:\\/([^>]+)>)|' + // End element
				'(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
			')', 'g');

			attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;
			specialElements = {
				'script' : /<\/script[^>]*>/gi,
				'style' : /<\/style[^>]*>/gi,
				'noscript' : /<\/noscript[^>]*>/gi
			};

			// Setup lookup tables for empty elements and boolean attributes
			shortEndedElements = schema.getShortEndedElements();
			selfClosing = settings.self_closing_elements || schema.getSelfClosingElements();
			fillAttrsMap = schema.getBoolAttrs();
			validate = settings.validate;
			removeInternalElements = settings.remove_internals;
			fixSelfClosing = settings.fix_self_closing;
			isIE = tinymce.isIE;
			invalidPrefixRegExp = /^:/;

			while (matches = tokenRegExp.exec(html)) {
				// Text
				if (index < matches.index)
					self.text(decode(html.substr(index, matches.index - index)));

				if (value = matches[6]) { // End element
					value = value.toLowerCase();

					// IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements
					if (isIE && invalidPrefixRegExp.test(value))
						value = value.substr(1);

					processEndTag(value);
				} else if (value = matches[7]) { // Start element
					value = value.toLowerCase();

					// IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements
					if (isIE && invalidPrefixRegExp.test(value))
						value = value.substr(1);

					isShortEnded = value in shortEndedElements;

					// Is self closing tag for example an
 after an open

					if (fixSelfClosing && selfClosing[value] && stack.length > 0 && stack[stack.length - 1].name === value)
						processEndTag(value);

					// Validate element
					if (!validate || (elementRule = schema.getElementRule(value))) {
						isValidElement = true;

						// Grab attributes map and patters when validation is enabled
						if (validate) {
							validAttributesMap = elementRule.attributes;
							validAttributePatterns = elementRule.attributePatterns;
						}

						// Parse attributes
						if (attribsValue = matches[8]) {
							isInternalElement = attribsValue.indexOf('data-mce-type') !== -1; // Check if the element is an internal element

							// If the element has internal attributes then remove it if we are told to do so
							if (isInternalElement && removeInternalElements)
								isValidElement = false;

							attrList = [];
							attrList.map = {};

							attribsValue.replace(attrRegExp, parseAttribute);
						} else {
							attrList = [];
							attrList.map = {};
						}

						// Process attributes if validation is enabled
						if (validate && !isInternalElement) {
							attributesRequired = elementRule.attributesRequired;
							attributesDefault = elementRule.attributesDefault;
							attributesForced = elementRule.attributesForced;

							// Handle forced attributes
							if (attributesForced) {
								i = attributesForced.length;
								while (i--) {
									attr = attributesForced[i];
									name = attr.name;
									attrValue = attr.value;

									if (attrValue === '{$uid}')
										attrValue = 'mce_' + idCount++;

									attrList.map[name] = attrValue;
									attrList.push({name: name, value: attrValue});
								}
							}

							// Handle default attributes
							if (attributesDefault) {
								i = attributesDefault.length;
								while (i--) {
									attr = attributesDefault[i];
									name = attr.name;

									if (!(name in attrList.map)) {
										attrValue = attr.value;

										if (attrValue === '{$uid}')
											attrValue = 'mce_' + idCount++;

										attrList.map[name] = attrValue;
										attrList.push({name: name, value: attrValue});
									}
								}
							}

							// Handle required attributes
							if (attributesRequired) {
								i = attributesRequired.length;
								while (i--) {
									if (attributesRequired[i] in attrList.map)
										break;
								}

								// None of the required attributes where found
								if (i === -1)
									isValidElement = false;
							}

							// Invalidate element if it's marked as bogus
							if (attrList.map['data-mce-bogus'])
								isValidElement = false;
						}

						if (isValidElement)
							self.start(value, attrList, isShortEnded);
					} else
						isValidElement = false;

					// Treat script, noscript and style a bit different since they may include code that looks like elements
					if (endRegExp = specialElements[value]) {
						endRegExp.lastIndex = index = matches.index + matches[0].length;

						if (matches = endRegExp.exec(html)) {
							if (isValidElement)
								text = html.substr(index, matches.index - index);

							index = matches.index + matches[0].length;
						} else {
							text = html.substr(index);
							index = html.length;
						}

						if (isValidElement && text.length > 0)
							self.text(text, true);

						if (isValidElement)
							self.end(value);

						tokenRegExp.lastIndex = index;
						continue;
					}

					// Push value on to stack
					if (!isShortEnded) {
						if (!attribsValue || attribsValue.indexOf('/') != attribsValue.length - 1)
							stack.push({name: value, valid: isValidElement});
						else if (isValidElement)
							self.end(value);
					}
				} else if (value = matches[1]) { // Comment
					self.comment(value);
				} else if (value = matches[2]) { // CDATA
					self.cdata(value);
				} else if (value = matches[3]) { // DOCTYPE
					self.doctype(value);
				} else if (value = matches[4]) { // PI
					self.pi(value, matches[5]);
				}

				index = matches.index + matches[0].length;
			}

			// Text
			if (index = 0; i--) {
				value = stack[i];

				if (value.valid)
					self.end(value.name);
			}
		};
	}
})(tinymce);
<|endoftext|>


<commit_before>var path = require('path'),
	fs = require('fs'),
	gulp = require('gulp'),
	rmdir = require('rmdir'),
	mkdirp = require('mkdirp'),
	merge = require('merge2'),
	runSequence = require('run-sequence'),
	gulpLoadPlugins = require('gulp-load-plugins');

var plugins = gulpLoadPlugins();

var config = {
	src: './src',
	dist: './dist',
	test: './test'
};

gulp.task('clean', function() {
	return Promise.all([
		new Promise(function(resolve, reject) {
			function done() {
				mkdirp(config.dist);
				resolve();
			}
			try {
				if(fs.existsSync(config.dist)) {
					rmdir(config.dist, done);
				} else {
					done();
				}
			} catch(e) {
				reject(e);
			}
		}),
		new Promise(function(resolve, reject) {
			var dir = path.join(config.test, 'test/dist');
			function done() {
				mkdirp(dir);
				resolve();
			}
			try {
				if(fs.existsSync(dir)) {
					rmdir(config.dist, done);
				} else {
					done();
				}
			} catch(e) {
				reject(e);
			}
		})
	]);
});

gulp.task('typescript:test', function() {

	var tsResult = gulp.src(path.join(config.test, 'mocks/src/*.ts'))
	.pipe(plugins.typescript({
		declaration: true
	}));

	var dest = gulp.dest(path.join(config.test, 'mocks/dist'));

	return merge([
		tsResult.dts.pipe(dest),
		tsResult.js.pipe(dest)
	]);

});

gulp.task('typescript:assets', function() {

	var tsResult = gulp.src(path.join(config.src, 'kendo-template-loader.ts'))
	.pipe(plugins.typescript({
		declaration: true
	}));

	return merge([
		tsResult.dts.pipe(gulp.dest(config.dist)),
		tsResult.js.pipe(gulp.dest(config.dist))
	]);

});

gulp.task('typescript', ['typescript:test', 'typescript:assets']);

gulp.task('mocha', function() {
	return gulp.src(path.join(config.test, 'runner.html'), {
		read: false
	}).pipe(plugins.mochaPhantomjs({
		reporter: 'spec',
		phantomjs: {
			useColors: true
		}
	}));
});

gulp.task('test', function(cb) {
	return runSequence('build', 'typescript:test', 'mocha', cb);
});
gulp.task('build', function(cb) {
	return runSequence('clean', 'typescript:assets', cb);
});
gulp.task('default', ['build']);
<commit_msg>fix test mocks build dir clean task<commit_after>var path = require('path'),
	fs = require('fs'),
	gulp = require('gulp'),
	rmdir = require('rmdir'),
	mkdirp = require('mkdirp'),
	merge = require('merge2'),
	runSequence = require('run-sequence'),
	gulpLoadPlugins = require('gulp-load-plugins');

var plugins = gulpLoadPlugins();

var config = {
	src: './src',
	dist: './dist',
	test: './test'
};

gulp.task('clean', function() {
	return Promise.all([
		new Promise(function(resolve, reject) {
			function done() {
				mkdirp(config.dist);
				resolve();
			}
			try {
				if(fs.existsSync(config.dist)) {
					rmdir(config.dist, done);
				} else {
					done();
				}
			} catch(e) {
				reject(e);
			}
		}),
		new Promise(function(resolve, reject) {
			var dir = path.join(config.test, 'test/mocks/dist');
			function done() {
				mkdirp(dir);
				resolve();
			}
			try {
				if(fs.existsSync(dir)) {
					rmdir(config.dist, done);
				} else {
					done();
				}
			} catch(e) {
				reject(e);
			}
		})
	]);
});

gulp.task('typescript:test', function() {

	var tsResult = gulp.src(path.join(config.test, 'mocks/src/*.ts'))
	.pipe(plugins.typescript({
		declaration: true
	}));

	var dest = gulp.dest(path.join(config.test, 'mocks/dist'));

	return merge([
		tsResult.dts.pipe(dest),
		tsResult.js.pipe(dest)
	]);

});

gulp.task('typescript:assets', function() {

	var tsResult = gulp.src(path.join(config.src, 'kendo-template-loader.ts'))
	.pipe(plugins.typescript({
		declaration: true
	}));

	return merge([
		tsResult.dts.pipe(gulp.dest(config.dist)),
		tsResult.js.pipe(gulp.dest(config.dist))
	]);

});

gulp.task('typescript', ['typescript:test', 'typescript:assets']);

gulp.task('mocha', function() {
	return gulp.src(path.join(config.test, 'runner.html'), {
		read: false
	}).pipe(plugins.mochaPhantomjs({
		reporter: 'spec',
		phantomjs: {
			useColors: true
		}
	}));
});

gulp.task('test', function(cb) {
	return runSequence('build', 'typescript:test', 'mocha', cb);
});
gulp.task('build', function(cb) {
	return runSequence('clean', 'typescript:assets', cb);
});
gulp.task('default', ['build']);
<|endoftext|>


<commit_before>"use strict";

// TODO move out (+ enemy constraint)

var sequenceGenerator = require('./../sequences/generator'),
    bigMonsterPool = require('./../../pools/bigEnemyPool'),
    objectCollection = require('./../../objectCollection');

var monsterArray = objectCollection.getArray('enemy');

var screenWidth = 800,
    screenHeight = 600,
    widthDiv10 = screenWidth / 10,
    heightDiv10 = screenHeight / 10;

var patterns = {
    square: 1,
    pulse: 1,
    littleSeal: 1,
    perlin: 1,
    test: 1,
    sprayer: 1,
    easyConstant: 1,
    layeredSpiral: 1
};

var BigEnemiesField = function (level) {
    this.level = level;
    this.enemies = [];

    var choice = this.level.rng.random();

    if (choice > 0.60) {
        this.initializeTwoMonstersOnTop();
    } else if (choice > 0.25) {
        this.initializeThreeMonstersOnTop();
    } else if (choice > 0.10) {
        this.initializeTwoMonstersAtEdges();
    } else {
        this.initializeFourMonstersInCorners();
    }

    this.reset();
};

BigEnemiesField.prototype.level = null;
BigEnemiesField.prototype.enemies = null;
BigEnemiesField.prototype.spawned = null;

BigEnemiesField.prototype.generateSequence = function (preferences, difficulty) {
    return sequenceGenerator.generateSequence(this.level.rng, this.level.generatePatternMetaData(difficulty), preferences);
};

BigEnemiesField.prototype.initializeTwoMonstersOnTop = function () {
    var difficulty = 1;

    var x = this.level.rng.randomBounded(widthDiv10, widthDiv10 * 4) | 0,
        y = this.level.rng.randomBounded(heightDiv10, heightDiv10 * 4) | 0,
        sequence = this.generateSequence(patterns, difficulty);

    this.enemies.push({
        x: x,
        y: y,
        sequence: sequence
    });

    this.enemies.push({
        x: screenWidth - x,
        y: y,
        sequence: sequence.clone()
    });
};

BigEnemiesField.prototype.initializeThreeMonstersOnTop = function () {
    var difficulty = 1;

    var edgeDifficuly = difficulty * 0.90;

    var x = this.level.rng.randomBounded(widthDiv10 * 2, widthDiv10 * 4) | 0,
        y = this.level.rng.randomBounded(heightDiv10 * 2, heightDiv10 * 3) | 0,
        y3 = y + (this.level.rng.randomBounded(heightDiv10, heightDiv10 * 1.5) | 0) * (this.level.rng.random() > 0.5 ? -1 : 1),
        sequence = this.generateSequence(patterns, edgeDifficuly),
        sequence3 = this.generateSequence(patterns, difficulty);

    this.enemies.push({
        x: screenWidth / 2,
        y: y3,
        sequence: sequence3
    });

    this.enemies.push({
        x: x,
        y: y,
        sequence: sequence
    });

    this.enemies.push({
        x: screenWidth - x,
        y: y,
        sequence: sequence.clone()
    });
};

BigEnemiesField.prototype.initializeFourMonstersInCorners = function () {
    var difficulty = 1;

    // reduce pattern difficulty proportionnally to x

    var x = this.level.rng.randomBounded(widthDiv10 * 0.5, widthDiv10 * 2) | 0,
        y = (x * screenHeight / screenWidth) | 0,
        sequenceDifficulty = difficulty * (0.90 - x / screenWidth),
        sequence = this.generateSequence(patterns, sequenceDifficulty);

    this.enemies.push({
        x: x,
        y: y,
        sequence: sequence
    });

    this.enemies.push({
        x: screenWidth - x,
        y: y,
        sequence: sequence.clone()
    });

    this.enemies.push({
        x: x,
        y: screenHeight - y,
        sequence: sequence.clone()
    });

    this.enemies.push({
        x: screenWidth - x,
        y: screenHeight - y,
        sequence: sequence.clone()
    });
};

BigEnemiesField.prototype.initializeTwoMonstersAtEdges = function () {
    var difficulty = 1;

    var x = this.level.rng.randomBounded(widthDiv10 * 0.5, widthDiv10 * 1.5) | 0,
        y = this.level.rng.randomBounded(heightDiv10 * 4, heightDiv10 * 5) | 0,
        sequence = this.generateSequence(patterns, difficulty);

    this.enemies.push({
        x: x,
        y: y,
        sequence: sequence
    });

    this.enemies.push({
        x: screenWidth - x,
        y: y,
        sequence: sequence.clone()
    });
};

BigEnemiesField.prototype.reset = function () {
    this.internalTimer = 0;
    this.spawned = false;
};

BigEnemiesField.prototype.update = function (dt) {
    if (!this.spawned && this.internalTimer > 2000) {
        for (var i = 0; i < this.enemies.length; i += 1) {
            var pos = this.enemies[i];

            pos.explosionSize = 1;
            pos.explosionColors = this.level.colors;
            pos.totalLife = 20;

            objectCollection.add('enemy', bigMonsterPool.get(pos));
        }

        this.spawned = true;
    }

    this.internalTimer += dt;

    return !(this.spawned && monsterArray.length === 0);
};

module.exports = BigEnemiesField;
<commit_msg>balance the 'four enemies'<commit_after>"use strict";

// TODO move out (+ enemy constraint)

var sequenceGenerator = require('./../sequences/generator'),
    bigMonsterPool = require('./../../pools/bigEnemyPool'),
    objectCollection = require('./../../objectCollection');

var monsterArray = objectCollection.getArray('enemy');

var screenWidth = 800,
    screenHeight = 600,
    widthDiv10 = screenWidth / 10,
    heightDiv10 = screenHeight / 10;

var patterns = {
    square: 1,
    pulse: 1,
    littleSeal: 1,
    perlin: 1,
    test: 1,
    sprayer: 1,
    easyConstant: 1,
    layeredSpiral: 1
};

var patternsForFour = {
    perlin: 1,
    layeredSpiral: 1
};

var BigEnemiesField = function (level) {
    this.level = level;
    this.enemies = [];

    var choice = this.level.rng.random();

    if (choice > 0.60) {
        this.initializeTwoMonstersOnTop();
    } else if (choice > 0.25) {
        this.initializeThreeMonstersOnTop();
    } else if (choice > 0.06) {
        this.initializeTwoMonstersAtEdges();
    } else {
        this.initializeFourMonstersInCorners();
    }

    this.reset();
};

BigEnemiesField.prototype.level = null;
BigEnemiesField.prototype.enemies = null;
BigEnemiesField.prototype.spawned = null;

BigEnemiesField.prototype.generateSequence = function (preferences, difficulty) {
    return sequenceGenerator.generateSequence(this.level.rng, this.level.generatePatternMetaData(difficulty), preferences);
};

BigEnemiesField.prototype.initializeTwoMonstersOnTop = function () {
    var difficulty = 1;

    var x = this.level.rng.randomBounded(widthDiv10, widthDiv10 * 4) | 0,
        y = this.level.rng.randomBounded(heightDiv10, heightDiv10 * 4) | 0,
        sequence = this.generateSequence(patterns, difficulty);

    this.enemies.push({
        x: x,
        y: y,
        sequence: sequence
    });

    this.enemies.push({
        x: screenWidth - x,
        y: y,
        sequence: sequence.clone()
    });
};

BigEnemiesField.prototype.initializeThreeMonstersOnTop = function () {
    var difficulty = 1;

    var edgeDifficuly = difficulty * 0.8;

    var x = this.level.rng.randomBounded(widthDiv10 * 2, widthDiv10 * 4) | 0,
        y = this.level.rng.randomBounded(heightDiv10 * 2, heightDiv10 * 3) | 0,
        y3 = y + (this.level.rng.randomBounded(heightDiv10, heightDiv10 * 1.5) | 0) * (this.level.rng.random() > 0.5 ? -1 : 1),
        sequence = this.generateSequence(patterns, edgeDifficuly),
        sequence3 = this.generateSequence(patterns, difficulty);

    this.enemies.push({
        x: screenWidth / 2,
        y: y3,
        sequence: sequence3
    });

    this.enemies.push({
        x: x,
        y: y,
        sequence: sequence
    });

    this.enemies.push({
        x: screenWidth - x,
        y: y,
        sequence: sequence.clone()
    });
};

BigEnemiesField.prototype.initializeFourMonstersInCorners = function () {
    var difficulty = 1;

    // reduce pattern difficulty proportionnally to x

    var x = this.level.rng.randomBounded(widthDiv10 * 0.5, widthDiv10 * 2) | 0,
        y = (x * screenHeight / screenWidth) | 0,
        sequenceDifficulty = (difficulty * (0.9 - x / screenWidth)) / 3,
        sequence = this.generateSequence(patternsForFour, sequenceDifficulty);

    this.enemies.push({
        x: x,
        y: y,
        sequence: sequence
    });

    this.enemies.push({
        x: screenWidth - x,
        y: y,
        sequence: sequence.clone()
    });

    this.enemies.push({
        x: x,
        y: screenHeight - y,
        sequence: sequence.clone()
    });

    this.enemies.push({
        x: screenWidth - x,
        y: screenHeight - y,
        sequence: sequence.clone()
    });
};

BigEnemiesField.prototype.initializeTwoMonstersAtEdges = function () {
    var difficulty = 1;

    var x = this.level.rng.randomBounded(widthDiv10 * 0.5, widthDiv10 * 1.5) | 0,
        y = this.level.rng.randomBounded(heightDiv10 * 4, heightDiv10 * 5) | 0,
        sequence = this.generateSequence(patterns, difficulty);

    this.enemies.push({
        x: x,
        y: y,
        sequence: sequence
    });

    this.enemies.push({
        x: screenWidth - x,
        y: y,
        sequence: sequence.clone()
    });
};

BigEnemiesField.prototype.reset = function () {
    this.internalTimer = 0;
    this.spawned = false;
};

BigEnemiesField.prototype.update = function (dt) {
    if (!this.spawned && this.internalTimer > 2000) {
        for (var i = 0; i < this.enemies.length; i += 1) {
            var pos = this.enemies[i];

            pos.explosionSize = 1;
            pos.explosionColors = this.level.colors;
            pos.totalLife = 20;

            objectCollection.add('enemy', bigMonsterPool.get(pos));
        }

        this.spawned = true;
    }

    this.internalTimer += dt;

    return !(this.spawned && monsterArray.length === 0);
};

module.exports = BigEnemiesField;
<|endoftext|>


<commit_before>var _ = require('lodash');
var express = require('express');
var fs = require('fs');
var gulp = require('gulp');
var lr = require('tiny-lr');
var path = require('path');

var browserify = require('gulp-browserify');
var concat = require('gulp-concat');
var gulpif = require('gulp-if');
var gzip = require('gulp-gzip');
var haml = require('gulp-haml');
var imagemin = require('gulp-imagemin');
var jshint = require('gulp-jshint');
var mocha = require('gulp-mocha');
var refresh = require('gulp-livereload');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
var stylus = require('gulp-stylus');

var server = lr();
var config = _.extend({
  port: 8080,
  lrport: 35729,
  env: 'development'
}, gulp.env);
console.log(config);
var production = config.env === 'production';

gulp.task('lr-server', function () {
  server.listen(config.lrport, function (err) {
    if (err) {
      console.log(err);
    }
  });
});

gulp.task('commands', function () {
  var commands =
    fs.readdirSync('src/js/lib/commands')
      .filter(function (f) {
        return f[0] != '.' && f.substr(-3) == '.js';
      }).map(function (f) {
        return 'require("' + './commands/' + f + '");';
      });

  fs.writeFileSync('src/js/lib/commands.js', commands.join('\n'));
});

gulp.task('file-system', function () {
  var _fs = {};
  var _ignore = [
    '.DS_Store'
  ];
  var root = 'src/js/lib/fs';

  (function readdir(path, container) {
    var files = fs.readdirSync(path);

    files.forEach(function (file) {
      if (~_ignore.indexOf(file)) {
        return;
      }

      var stat = fs.statSync(path + '/' + file);

      if (stat.isDirectory()) {
        var f = {};
        readdir(path + '/' + file, f);
        container[file] = f;
      } else {
        container[file] = fs.readFileSync(path + '/' + file).toString();
      }
    });
  })(root, _fs);

  fs.writeFileSync('src/js/lib/file-system.json', JSON.stringify(_fs, null, 2));
});

gulp.task('jshint', function() {
  gulp.src(['Gulpfile.js', 'spec/**/*.js', 'src/js/**/*.js'])
    .pipe(jshint())
    .pipe(jshint.reporter('jshint-stylish'));
});

gulp.task('js', ['jshint', 'commands', 'file-system'], function () {
  gulp.src('src/js/main.js')
    .pipe(browserify({ debug: !production }))
    .pipe(concat('all.js'))
    .pipe(gulpif(production, uglify()))
    .pipe(gulp.dest('out/js'))
    .pipe(gulpif(production, gzip()))
    .pipe(gulpif(production, gulp.dest('out/js')))
    .pipe(refresh(server));
});

gulp.task('css', function () {
  gulp.src('src/css/**/*.styl')
    .pipe(stylus({ set: production ? ['compress'] : [] }))
    .pipe(concat('all.css'))
    .pipe(gulp.dest('out/css'))
    .pipe(gulpif(production, gzip()))
    .pipe(gulp.dest('out/css'))
    .pipe(refresh(server));
});

gulp.task('images', function () {
  gulp.src('src/images/**')
    .pipe(gulpif(production, imagemin()))
    .pipe(gulp.dest('out/images'))
    .pipe(refresh(server));
});

gulp.task('html', function () {
  gulp.src('src/**/*.haml')
    .pipe(haml({ optimize: production }))
    .pipe(gulp.dest('out'))
    .pipe(gulpif(production, gzip()))
    .pipe(gulp.dest('out'))
    .pipe(refresh(server));
});

gulp.task('start-server', function() {
  express()
    .use(express.static(path.resolve("./out")))
    .use(express.directory(path.resolve("./out")))
    .listen(config.port, function() {
      console.log("Listening on ", config.port);
    });
});

gulp.task('spec', ['js'], function () {
  gulp.src('spec/**/*-spec.js')
    .pipe(mocha());
});

gulp.task('build', ['js', 'css', 'images', 'html']);

gulp.task('server', ['build', 'lr-server', 'start-server'], function () {
  gulp.watch(['src/js/**/*.js', 'src/js/lib/fs/**'], function () {
    gulp.run('js');
  });

  gulp.watch('src/css/**/*.styl', function () {
    gulp.run('css');
  });

  gulp.watch('src/images/**', function () {
    gulp.run('images');
  });

  gulp.watch('src/**/*.haml', function () {
    gulp.run('html');
  });
});

gulp.task('spec-live', function(){
  gulp.watch('src/js/**/*.js', function () {
    gulp.run('js');
  });

  gulp.watch('spec/**/*.js', function(){
    gulp.run('spec');
  });
});
<commit_msg>fix: prevent reading .swp files from file system<commit_after>var _ = require('lodash');
var express = require('express');
var fs = require('fs');
var gulp = require('gulp');
var lr = require('tiny-lr');
var path = require('path');

var browserify = require('gulp-browserify');
var concat = require('gulp-concat');
var gulpif = require('gulp-if');
var gzip = require('gulp-gzip');
var haml = require('gulp-haml');
var imagemin = require('gulp-imagemin');
var jshint = require('gulp-jshint');
var mocha = require('gulp-mocha');
var refresh = require('gulp-livereload');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
var stylus = require('gulp-stylus');

var server = lr();
var config = _.extend({
  port: 8080,
  lrport: 35729,
  env: 'development'
}, gulp.env);
console.log(config);
var production = config.env === 'production';

gulp.task('lr-server', function () {
  server.listen(config.lrport, function (err) {
    if (err) {
      console.log(err);
    }
  });
});

gulp.task('commands', function () {
  var commands =
    fs.readdirSync('src/js/lib/commands')
      .filter(function (f) {
        return f[0] != '.' && f.substr(-3) == '.js';
      }).map(function (f) {
        return 'require("' + './commands/' + f + '");';
      });

  fs.writeFileSync('src/js/lib/commands.js', commands.join('\n'));
});

gulp.task('file-system', function () {
  var _fs = {};
  var _ignore = [
    '\\.DS_Store',
    '.*\\.swp'
  ];
  var root = 'src/js/lib/fs';

  (function readdir(path, container) {
    var files = fs.readdirSync(path);

    files.forEach(function (file) {
      for (var i = 0, l = _ignore.length; i < l; i++) {
        if (file.match(new RegExp('^' + _ignore[i] + '$'))) {
          return;
        }
      }

      var stat = fs.statSync(path + '/' + file);

      if (stat.isDirectory()) {
        var f = {};
        readdir(path + '/' + file, f);
        container[file] = f;
      } else {
        container[file] = fs.readFileSync(path + '/' + file).toString();
      }
    });
  })(root, _fs);

  fs.writeFileSync('src/js/lib/file-system.json', JSON.stringify(_fs, null, 2));
});

gulp.task('jshint', function() {
  gulp.src(['Gulpfile.js', 'spec/**/*.js', 'src/js/**/*.js'])
    .pipe(jshint())
    .pipe(jshint.reporter('jshint-stylish'));
});

gulp.task('js', ['jshint', 'commands', 'file-system'], function () {
  gulp.src('src/js/main.js')
    .pipe(browserify({ debug: !production }))
    .pipe(concat('all.js'))
    .pipe(gulpif(production, uglify()))
    .pipe(gulp.dest('out/js'))
    .pipe(gulpif(production, gzip()))
    .pipe(gulpif(production, gulp.dest('out/js')))
    .pipe(refresh(server));
});

gulp.task('css', function () {
  gulp.src('src/css/**/*.styl')
    .pipe(stylus({ set: production ? ['compress'] : [] }))
    .pipe(concat('all.css'))
    .pipe(gulp.dest('out/css'))
    .pipe(gulpif(production, gzip()))
    .pipe(gulp.dest('out/css'))
    .pipe(refresh(server));
});

gulp.task('images', function () {
  gulp.src('src/images/**')
    .pipe(gulpif(production, imagemin()))
    .pipe(gulp.dest('out/images'))
    .pipe(refresh(server));
});

gulp.task('html', function () {
  gulp.src('src/**/*.haml')
    .pipe(haml({ optimize: production }))
    .pipe(gulp.dest('out'))
    .pipe(gulpif(production, gzip()))
    .pipe(gulp.dest('out'))
    .pipe(refresh(server));
});

gulp.task('start-server', function() {
  express()
    .use(express.static(path.resolve("./out")))
    .use(express.directory(path.resolve("./out")))
    .listen(config.port, function() {
      console.log("Listening on ", config.port);
    });
});

gulp.task('spec', ['js'], function () {
  gulp.src('spec/**/*-spec.js')
    .pipe(mocha());
});

gulp.task('build', ['js', 'css', 'images', 'html']);

gulp.task('server', ['build', 'lr-server', 'start-server'], function () {
  gulp.watch(['src/js/**/*.js', 'src/js/lib/fs/**'], function () {
    gulp.run('js');
  });

  gulp.watch('src/css/**/*.styl', function () {
    gulp.run('css');
  });

  gulp.watch('src/images/**', function () {
    gulp.run('images');
  });

  gulp.watch('src/**/*.haml', function () {
    gulp.run('html');
  });
});

gulp.task('spec-live', function(){
  gulp.watch('src/js/**/*.js', function () {
    gulp.run('js');
  });

  gulp.watch('spec/**/*.js', function(){
    gulp.run('spec');
  });
});
<|endoftext|>


<commit_before>var babel   = require('gulp-babel');
var eslint  = require('gulp-eslint');
var gulp    = require('gulp');
var del     = require('del');
var Promise = require('pinkie');
var os      = require('os');

require('babel-polyfill');

var config = {
    1: [
        {
            os:        'android',
            osVersion: '4.4',
            browser:   'Android Browser',
            device:    'Samsung Galaxy S5',
            alias:     'android'
        },
        {
            os:        'ios',
            osVersion: '10.0',
            browser:   'Mobile Safari',
            device:    'iPad Pro (9.7 inch)',
            alias:     'ipad'
        },
        {
            os:        'ios',
            osVersion: '10.0',
            device:    'iPhone 7 Plus',
            browser:   'Mobile Safari',
            alias:     'iphone'
        }],

    2: [
        {
            os:        'OS X',
            osVersion: 'Sierra',
            name:      'safari',
            version:   '10.0',
            alias:     'safari'
        },
        {
            os:        'OS X',
            osVersion: 'Sierra',
            name:      'chrome',
            version:   '57.0',
            alias:     'chrome-osx'
        },
        {
            os:        'OS X',
            osVersion: 'Sierra',
            name:      'firefox',
            version:   '52.0',
            alias:     'firefox-osx'
        },
        {
            os:        'Windows',
            osVersion: '10',
            name:      'edge',
            version:   '13.0',
            alias:     'edge',
        }
    ]
};

gulp.task('clean', function () {
    return del('lib');
});

gulp.task('build', ['clean'], function () {
    return gulp.src('src/**/*.js')
        .pipe(babel())
        .pipe(gulp.dest('lib/'));
});

gulp.task('travis', [process.env.GULP_TASK || '']);

gulp.task('run1', ['build'], function () {
    var Сonnector = require('./lib');
    var connector = new Сonnector(process.env.user, process.env.key);
    var site      = require('./site.js');

    return connector
        .connect()
        .then(function () {
            var url = 'http://' + os.hostname() + ':' + 5000 + '/redirect';

            var openBrowserPromises = config['1'].map(function (browserInfo) {
                return connector.startBrowser(browserInfo, url);
            });

            return Promise.all(openBrowserPromises);
        })
        .then(function (browsers) {
            return new Promise(function (res) {
                setTimeout(res, 9 * 60 * 1000);
            });
        });
});

gulp.task('run2', ['build'], function () {
    var Сonnector = require('./lib');
    var connector = new Сonnector(process.env.user, process.env.key);
    var site      = require('./site.js');

    return connector
        .connect()
        .then(function () {
            var url = 'http://' + os.hostname() + ':' + 5000 + '/redirect';

            var openBrowserPromises = config['2'].map(function (browserInfo) {
                return connector.startBrowser(browserInfo, url);
            });

            return Promise.all(openBrowserPromises);
        })
        .then(function (browsers) {
            return new Promise(function (res) {
                setTimeout(res, 9 * 60 * 1000);
            });
        });
});

gulp.task('lint', function () {
    return gulp
        .src(['src/**/*.js', 'Gulpfile.js'])
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failOnError());
});
<commit_msg>leave only one browser in each task<commit_after>var babel   = require('gulp-babel');
var eslint  = require('gulp-eslint');
var gulp    = require('gulp');
var del     = require('del');
var Promise = require('pinkie');
var os      = require('os');

require('babel-polyfill');

var config = {
    1: [
        {
            os:        'android',
            osVersion: '4.4',
            browser:   'Android Browser',
            device:    'Samsung Galaxy S5',
            alias:     'android'
        }],

    2: [
        {
            os:        'OS X',
            osVersion: 'Sierra',
            name:      'safari',
            version:   '10.0',
            alias:     'safari'
        }
    ]
};

gulp.task('clean', function () {
    return del('lib');
});

gulp.task('build', ['clean'], function () {
    return gulp.src('src/**/*.js')
        .pipe(babel())
        .pipe(gulp.dest('lib/'));
});

gulp.task('travis', [process.env.GULP_TASK || '']);

gulp.task('run1', ['build'], function () {
    var Сonnector = require('./lib');
    var connector = new Сonnector(process.env.user, process.env.key);
    var site      = require('./site.js');

    return connector
        .connect()
        .then(function () {
            var url = 'http://' + os.hostname() + ':' + 5000 + '/redirect';

            var openBrowserPromises = config['1'].map(function (browserInfo) {
                return connector.startBrowser(browserInfo, url);
            });

            return Promise.all(openBrowserPromises);
        })
        .then(function (browsers) {
            return new Promise(function (res) {
                setTimeout(res, 9 * 60 * 1000);
            });
        });
});

gulp.task('run2', ['build'], function () {
    var Сonnector = require('./lib');
    var connector = new Сonnector(process.env.user, process.env.key);
    var site      = require('./site.js');

    return connector
        .connect()
        .then(function () {
            var url = 'http://' + os.hostname() + ':' + 5000 + '/redirect';

            var openBrowserPromises = config['2'].map(function (browserInfo) {
                return connector.startBrowser(browserInfo, url);
            });

            return Promise.all(openBrowserPromises);
        })
        .then(function (browsers) {
            return new Promise(function (res) {
                setTimeout(res, 9 * 60 * 1000);
            });
        });
});

gulp.task('lint', function () {
    return gulp
        .src(['src/**/*.js', 'Gulpfile.js'])
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failOnError());
});
<|endoftext|>


<commit_before>var gulp = require("gulp");

gulp.task('default', function() {
  // place code for your default task here
});
<commit_msg>Added a gulpfile<commit_after>var gulp = require("gulp");

gulp.task('default', function() {
  // place code for your default task here
});<|endoftext|>


<commit_before>"user strict";
var gulp    = require('gulp'),
    bower   = require('gulp-bower'),
    jshint  = require('gulp-jshint'),
    refresh = require('gulp-livereload'),
    notify  = require('gulp-notify'),
    plumber = require('gulp-plumber'),
    client  = require('tiny-lr')(),
    list    = require('gulp-task-listing'),
    nodemon = require('gulp-nodemon'),
    lr_port = 35729,
    less   = require('gulp-less'),
    stripDebug = require('gulp-strip-debug'),
    uglify = require('gulp-uglify'),
    ngmin = require('gulp-ngmin'),
    concat = require('gulp-concat')
    clean = require('gulp-clean')
    nodePath = require('path')
    minifycss = require('gulp-minify-css');

var paths = {
  scripts: ['!client/lib/**/*.js', 'client/**/*.js', '!client/*.min.js'],
  appjsminify: { src: ['!client/lib/**/*.js', 'client/**/*.js'], dest: 'client', filename: 'ngscripts.min.js' },
  mincss: {dest: 'client/styles/css.min'},
  views: ['!client/lib/*.html', 'client/**/*.html', 'client/index.html'],
  styles: {
    css: ['!client/lib/**/*.css', '!client/styles/css.min/*.css', 'client/styles/css/*.css', 'client/**/*.css'],
    less: ['client/styles/less/*.less', 'client/**/*.less'],
    dest: 'client/styles/css'
  }
};
var build = ['distCode', 'minify-css'];

gulp.task('less' , ['deleteOldMin'], function () {
  return gulp.src(paths.styles.less)
    .pipe(plumber())
    .pipe(less({
      paths: [paths.styles.less]
    }))
    .pipe(gulp.dest(paths.styles.dest))
    .pipe(refresh(client))
    .pipe(notify({message: 'Less done'}));
});

gulp.task('bowerInstall', function  () {
  bower()
  .pipe();
});

gulp.task('html', function () {
  return gulp.src(paths.views)
    .pipe(plumber())
    .pipe(refresh(client))
    .pipe(notify({message: 'Views refreshed'}));
});

gulp.task('css', ['less', 'deleteOldMin'],function () {
  return gulp.src(paths.styles.css)
    .pipe(plumber())
    .pipe(refresh(client))
    .pipe(notify({message: 'CSS refreshed'}));
});

gulp.task('lint', ['deleteOldMin'], function () {
  return gulp.src(paths.scripts)
    .pipe(plumber())
    .pipe(jshint())
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(refresh(client))
    .pipe(notify({message: 'Lint done'}));
});

gulp.task('serve', ['build'], function () {
  nodemon({script: 'server.js', ignore: ['node_modules/**/*.js']})
    .on('restart', function () {
      refresh(client);
    });
});

gulp.task('live', ['build'], function () {
  client.listen(lr_port, function (err) {
    if (err) {
      return console.error(err);
    }
  });
});

gulp.task('watch', ['deleteOldMin'], function () {
  gulp.watch(paths.styles.less, ['less', 'distCode', 'minify-css']);
  gulp.watch(paths.views, ['html']);
  gulp.watch(paths.scripts, ['lint', 'distCode', 'minify-css']);
});

gulp.task('distCode', ['lint', 'deleteOldMin'], function() {
  return gulp.src(paths.appjsminify.src)
    .pipe(plumber())
    .pipe(stripDebug())
    .pipe(ngmin({dynamic: false}))
    .pipe(uglify({mangle: false}))
    .pipe(concat(paths.appjsminify.filename))
    .pipe(gulp.dest(paths.appjsminify.dest))
    .pipe(notify({message: 'Distribution code compiled'}));
});

gulp.task('deleteOldMin', function() {
  return gulp.src([nodePath.join(paths.appjsminify.dest, paths.appjsminify.filename), paths.mincss.dest], {read: false})
    .pipe(plumber())
    .pipe(clean())
    .pipe(notify({message: 'Old file deleted'}));
});

gulp.task('minify-css', ['deleteOldMin' , 'css'], function () {
  return gulp.src(paths.styles.css)
    .pipe(plumber())
    .pipe(minifycss({keepBreaks:true}))
    .pipe(gulp.dest(paths.mincss.dest))
    .pipe(notify({message: 'CSS minified'}));
});

gulp.task('build', build);
gulp.task('default', ['build', 'live', 'serve', 'watch']);
<commit_msg>More gulp sequence changes. Potential issue - html views refer to nonexistent file sometimes.<commit_after>"user strict";
var gulp    = require('gulp'),
    bower   = require('gulp-bower'),
    jshint  = require('gulp-jshint'),
    refresh = require('gulp-livereload'),
    notify  = require('gulp-notify'),
    plumber = require('gulp-plumber'),
    client  = require('tiny-lr')(),
    list    = require('gulp-task-listing'),
    nodemon = require('gulp-nodemon'),
    lr_port = 35729,
    less   = require('gulp-less'),
    stripDebug = require('gulp-strip-debug'),
    uglify = require('gulp-uglify'),
    ngmin = require('gulp-ngmin'),
    concat = require('gulp-concat')
    clean = require('gulp-clean')
    nodePath = require('path')
    minifycss = require('gulp-minify-css');

var paths = {
  scripts: ['!client/lib/**/*.js', 'client/**/*.js', '!client/*.min.js'],
  appjsminify: { src: ['!client/lib/**/*.js', 'client/**/*.js'], dest: 'client', filename: 'ngscripts.min.js' },
  mincss: {dest: 'client/styles/css.min'},
  views: ['!client/lib/*.html', 'client/**/*.html', 'client/index.html'],
  styles: {
    css: ['!client/lib/**/*.css', '!client/styles/css.min/*.css', 'client/styles/css/*.css', 'client/**/*.css'],
    less: ['client/styles/less/*.less', 'client/**/*.less'],
    dest: 'client/styles/css'
  }
};
var build = ['distCode', 'minify-css'];

gulp.task('less' , ['deleteOldMin'], function () {
  return gulp.src(paths.styles.less)
    .pipe(plumber())
    .pipe(less({
      paths: [paths.styles.less]
    }))
    .pipe(gulp.dest(paths.styles.dest))
    .pipe(refresh(client))
    .pipe(notify({message: 'Less done'}));
});

gulp.task('bowerInstall', function  () {
  bower()
  .pipe();
});

gulp.task('html', function () {
  return gulp.src(paths.views)
    .pipe(plumber())
    .pipe(refresh(client))
    .pipe(notify({message: 'Views refreshed'}));
});

gulp.task('css', ['less', 'deleteOldMin'],function () {
  return gulp.src(paths.styles.css)
    .pipe(plumber())
    .pipe(refresh(client))
    .pipe(notify({message: 'CSS refreshed'}));
});

gulp.task('lint', ['deleteOldMin'], function () {
  return gulp.src(paths.scripts)
    .pipe(plumber())
    .pipe(jshint())
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(refresh(client))
    .pipe(notify({message: 'Lint done'}));
});

gulp.task('serve', ['build'], function () {
  nodemon({script: 'server.js', ignore: ['node_modules/**/*.js']})
    .on('restart', function () {
      refresh(client);
    });
});

gulp.task('live', ['build'], function () {
  client.listen(lr_port, function (err) {
    if (err) {
      return console.error(err);
    }
  });
});

gulp.task('watch', function () {
  gulp.watch(paths.styles.less, ['build']);
  gulp.watch(paths.views, ['html']);
  gulp.watch(paths.scripts, ['build']);
});

gulp.task('distCode', ['deleteOldMin', 'lint'], function() {
  return gulp.src(paths.appjsminify.src)
    .pipe(plumber())
    .pipe(stripDebug())
    .pipe(ngmin({dynamic: false}))
    .pipe(uglify({mangle: false}))
    .pipe(concat(paths.appjsminify.filename))
    .pipe(gulp.dest(paths.appjsminify.dest))
    .pipe(notify({message: 'Distribution code compiled'}));
});

gulp.task('deleteOldMin', function() {
  return gulp.src([nodePath.join(paths.appjsminify.dest, paths.appjsminify.filename), paths.mincss.dest], {read: false})
    .pipe(plumber())
    .pipe(clean())
    .pipe(notify({message: 'Old file deleted'}));
});

gulp.task('minify-css', ['deleteOldMin' , 'css'], function () {
  return gulp.src(paths.styles.css)
    .pipe(plumber())
    .pipe(minifycss({keepBreaks:true}))
    .pipe(gulp.dest(paths.mincss.dest))
    .pipe(notify({message: 'CSS minified'}));
});

gulp.task('build', build);
gulp.task('default', ['build', 'live', 'serve', 'watch']);
<|endoftext|>


<commit_before>// File: Gulpfile.js
'use strict';

var gulp      = require('gulp'),
    connect   = require('gulp-connect'),
    stylus    = require('gulp-stylus'),
    nib       = require('nib'),
    jshint    = require('gulp-jshint'),
    stylish   = require('jshint-stylish'),
    inject    = require('gulp-inject'),
    wiredep   = require('wiredep').stream,
    gulpif    = require('gulp-if'),
    minifyCss = require('gulp-minify-css'),
    useref    = require('gulp-useref'),
    uglify    = require('gulp-uglify'),
    uncss     = require('gulp-uncss'),
    angularFilesort = require('gulp-angular-filesort'),
    templateCache = require('gulp-angular-templatecache'),
    historyApiFallback = require('connect-history-api-fallback');

// Servidor web de desarrollo
gulp.task('server', function() {
  connect.server({
    root: './app',
    hostname: '0.0.0.0',
    port: 8080,
    livereload: true,
    middleware: function(connect, opt) {
      return [ historyApiFallback ];
    }
  });
});

// Servidor web para probar el entorno de producción
gulp.task('server-dist', function() {
  connect.server({
    root: './dist',
    hostname: '0.0.0.0',
    port: 8080,
    livereload: true,
    middleware: function(connect, opt) {
      return [ historyApiFallback ];
    }
  });
});

// Busca errores en el JS y nos los muestra por pantalla
gulp.task('jshint', function() {
  return gulp.src('./app/scripts/**/*.js')
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'));
});

// Preprocesa archivos Stylus a CSS y recarga los cambios
gulp.task('css', function() {
  gulp.src('./app/stylesheets/main.styl')
    .pipe(stylus({ use: nib() }))
    .pipe(gulp.dest('./app/stylesheets'))
    .pipe(connect.reload());
});

// Recarga el navegador cuando hay cambios en el HTML
gulp.task('html', function() {
  gulp.src('./app/**/*.html')
    .pipe(connect.reload());
});

// Busca en las carpetas de estilos y javascript los archivos
// para inyectarlos en el index.html
gulp.task('inject', function() {
  return gulp.src('index.html', {cwd: './app'})
    .pipe(inject(
      gulp.src(['./app/scripts/**/*.js']).pipe(angularFilesort()), {
      read: false,
      ignorePath: '/app'
    }))
    .pipe(inject(
      gulp.src(['./app/stylesheets/**/*.css']), {
        read: false,
        ignorePath: '/app'
      }
    ))
    .pipe(gulp.dest('./app'));
});

// Inyecta las librerias que instalemos vía Bower
gulp.task('wiredep', function () {
  gulp.src('./app/index.html')
    .pipe(wiredep({
      directory: './app/lib'
    }))
    .pipe(gulp.dest('./app'));
});

// Compila las plantillas HTML parciales a JavaScript
// para ser inyectadas por AngularJS y minificar el código
gulp.task('templates', function() {
  gulp.src('./app/views/**/*.tpl.html')
    .pipe(templateCache({
      root: 'views/',
      module: 'app.templates',
      standalone: true
    }))
    .pipe(gulp.dest('./app/scripts'));
});

// Comprime los archivos CSS y JS enlazados en el index.html
// y los minifica.
gulp.task('compress', function() {
  gulp.src('./app/index.html')
    .pipe(useref.assets())
    .pipe(gulpif('*.js', uglify({mangle: false })))
    .pipe(gulpif('*.css', minifyCss()))
    .pipe(gulp.dest('./dist'));
});

// Elimina el CSS que no es utilizado para reducir el peso del archivo
gulp.task('uncss', function() {
  gulp.src('./dist/css/style.min.css')
    .pipe(uncss({
      html: ['./app/index.html', './app/views/week-list.tpl.html', './app/views/week-detail.tpl.html', './app/views/day-detail.tpl.html']
    }))
    .pipe(gulp.dest('./dist/css'));
});

// Copia el contenido de los estáticos e index.html al directorio
// de producción sin tags de comentarios
gulp.task('copy', function() {
  gulp.src('./app/index.html')
    .pipe(useref())
    .pipe(gulp.dest('./dist'));
  gulp.src('./app/lib/fontawesome/fonts/**')
    .pipe(gulp.dest('./dist/fonts'));
});

// Vigila cambios que se produzcan en el código
// y lanza las tareas relacionadas
gulp.task('watch', function() {
  gulp.watch(['./app/**/*.html'], ['html', 'templates']);
  gulp.watch(['./app/stylesheets/**/*.styl'], ['css', 'inject']);
  gulp.watch(['./app/scripts/**/*.js', './Gulpfile.js'], ['jshint', 'inject']);
  gulp.watch(['./bower.json'], ['wiredep']);
});

gulp.task('default', ['server', 'templates', 'inject', 'wiredep', 'watch']);
gulp.task('build', ['templates', 'compress', 'copy', 'uncss']);
<commit_msg>live reload to false for dist<commit_after>// File: Gulpfile.js
'use strict';

var gulp      = require('gulp'),
    connect   = require('gulp-connect'),
    stylus    = require('gulp-stylus'),
    nib       = require('nib'),
    jshint    = require('gulp-jshint'),
    stylish   = require('jshint-stylish'),
    inject    = require('gulp-inject'),
    wiredep   = require('wiredep').stream,
    gulpif    = require('gulp-if'),
    minifyCss = require('gulp-minify-css'),
    useref    = require('gulp-useref'),
    uglify    = require('gulp-uglify'),
    uncss     = require('gulp-uncss'),
    angularFilesort = require('gulp-angular-filesort'),
    templateCache = require('gulp-angular-templatecache'),
    historyApiFallback = require('connect-history-api-fallback');

// Servidor web de desarrollo
gulp.task('server', function() {
  connect.server({
    root: './app',
    hostname: '0.0.0.0',
    port: 8080,
    livereload: true,
    middleware: function(connect, opt) {
      return [ historyApiFallback ];
    }
  });
});

// Servidor web para probar el entorno de producción
gulp.task('server-dist', function() {
  connect.server({
    root: './dist',
    hostname: '0.0.0.0',
    port: 8080,
    livereload: false,
    middleware: function(connect, opt) {
      return [ historyApiFallback ];
    }
  });
});

// Busca errores en el JS y nos los muestra por pantalla
gulp.task('jshint', function() {
  return gulp.src('./app/scripts/**/*.js')
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'));
});

// Preprocesa archivos Stylus a CSS y recarga los cambios
gulp.task('css', function() {
  gulp.src('./app/stylesheets/main.styl')
    .pipe(stylus({ use: nib() }))
    .pipe(gulp.dest('./app/stylesheets'))
    .pipe(connect.reload());
});

// Recarga el navegador cuando hay cambios en el HTML
gulp.task('html', function() {
  gulp.src('./app/**/*.html')
    .pipe(connect.reload());
});

// Busca en las carpetas de estilos y javascript los archivos
// para inyectarlos en el index.html
gulp.task('inject', function() {
  return gulp.src('index.html', {cwd: './app'})
    .pipe(inject(
      gulp.src(['./app/scripts/**/*.js']).pipe(angularFilesort()), {
      read: false,
      ignorePath: '/app'
    }))
    .pipe(inject(
      gulp.src(['./app/stylesheets/**/*.css']), {
        read: false,
        ignorePath: '/app'
      }
    ))
    .pipe(gulp.dest('./app'));
});

// Inyecta las librerias que instalemos vía Bower
gulp.task('wiredep', function () {
  gulp.src('./app/index.html')
    .pipe(wiredep({
      directory: './app/lib'
    }))
    .pipe(gulp.dest('./app'));
});

// Compila las plantillas HTML parciales a JavaScript
// para ser inyectadas por AngularJS y minificar el código
gulp.task('templates', function() {
  gulp.src('./app/views/**/*.tpl.html')
    .pipe(templateCache({
      root: 'views/',
      module: 'app.templates',
      standalone: true
    }))
    .pipe(gulp.dest('./app/scripts'));
});

// Comprime los archivos CSS y JS enlazados en el index.html
// y los minifica.
gulp.task('compress', function() {
  gulp.src('./app/index.html')
    .pipe(useref.assets())
    .pipe(gulpif('*.js', uglify({mangle: false })))
    .pipe(gulpif('*.css', minifyCss()))
    .pipe(gulp.dest('./dist'));
});

// Elimina el CSS que no es utilizado para reducir el peso del archivo
gulp.task('uncss', function() {
  gulp.src('./dist/css/style.min.css')
    .pipe(uncss({
      html: ['./app/index.html', './app/views/week-list.tpl.html', './app/views/week-detail.tpl.html', './app/views/day-detail.tpl.html']
    }))
    .pipe(gulp.dest('./dist/css'));
});

// Copia el contenido de los estáticos e index.html al directorio
// de producción sin tags de comentarios
gulp.task('copy', function() {
  gulp.src('./app/index.html')
    .pipe(useref())
    .pipe(gulp.dest('./dist'));
  gulp.src('./app/lib/fontawesome/fonts/**')
    .pipe(gulp.dest('./dist/fonts'));
});

// Vigila cambios que se produzcan en el código
// y lanza las tareas relacionadas
gulp.task('watch', function() {
  gulp.watch(['./app/**/*.html'], ['html', 'templates']);
  gulp.watch(['./app/stylesheets/**/*.styl'], ['css', 'inject']);
  gulp.watch(['./app/scripts/**/*.js', './Gulpfile.js'], ['jshint', 'inject']);
  gulp.watch(['./bower.json'], ['wiredep']);
});

gulp.task('default', ['server', 'templates', 'inject', 'wiredep', 'watch']);
gulp.task('build', ['templates', 'compress', 'copy', 'uncss']);
<|endoftext|>


<commit_before>'use strict';

var gulp       = require('gulp'),
    bump       = require('gulp-bump'),
    concat     = require('gulp-concat'),
    cssmin     = require('gulp-cssmin'),
    del        = require('del'),
    fs         = require('fs'),
    htmlmin    = require('gulp-htmlmin'),
    livereload = require('gulp-livereload'),
    newer      = require('gulp-newer'),
    nunjucks   = require('gulp-nunjucks-html'),
    //sass       = require('gulp-sass'),
    sourcemaps = require('gulp-sourcemaps'),
    uglify     = require('gulp-uglify'),
    prod       = false,
    path       = {
      app: {
        css: [
          'src/lib/**/*.css', 'src/app/**/*.css'
        ],
        js: [
          'src/lib/jquery/**.js', 'src/lib/**.js',
          'src/app/prototype.js', 'src/app/core.js', 'src/app/**.js'
        ]
      },
      assets: [
        'src/assets/**/*', 'src/*.json'
      ],
      background: {
        js: [
          'src/background/background.js', 'src/modules/**/*.background.js'
        ]
      },
      options: {
        css: [
          'src/options/options.css', 'src/modules/**/*.options.css'
        ],
        html: 'src/options/options.html',
        js: [
          'src/options/options.js', 'src/modules/**/*.options.js'
        ]
      },
      scripts: {
        css: [
          'src/modules/**/*.scripts.css'
        ],
        js: [
          'src/modules/**/*.scripts.js'
        ]
      }
    },
    res = {};

function buildResource(path, res) {
  var k;
  for ( k in path ) {
    if ( typeof path[k] === 'string' || Array.isArray(path[k]) ) {
      res[k] = gulp.src(path[k]);
    } else {
      res[k] = {};
      buildResource(path[k], res[k]);
    }
  }
}
buildResource(path, res);

function getManifest() {
  if ( getManifest.manifest ) {
    return getManifest.manifest;
  }

  function getFile(path) {
    try {
      return fs.readFileSync(path, 'utf8');
    } catch ( e ) {
      return '';
    }
  }

  var manifest = require('./src/manifest.json'),
      modules = require('./src/modules.json');
  manifest.modules = modules;
  modules.forEach(function(module) {
    module.depends.map(function(dep) {
      var i = modules.length - 1;
      for ( ; i >= 0; i-- ) {
        if ( modules[i].id === dep ) {
          return modules[i];
        }
      }
      return { id: dep, name: dep };
    });

    module.contents = {
      options: getFile('src/modules/'+module.id+'/'+module.id+'.options.html')
    };
  });

  getManifest.manifest = manifest;
  return manifest;
}

function getPipes(key, file) {
  if ( typeof key === 'string' ) {
    if ( key === 'css' ) {
      return [
        prod && sourcemaps.init(),
        concat(file),
        prod && cssmin(),
        prod && sourcemaps.write('.'),
        gulp.dest('dist')
      ];
    } else if ( key === 'html' ) {
      //nunjucks.nunjucks.configure(['./src']);
      return [
        nunjucks({
          locals: {
            manifest: getManifest()
          },
          searchPaths: ['src']
        }),
        htmlmin({
          removeComments: true,
          collapseWhitespace: true
        }),
        gulp.dest('dist')
      ];
    } else if ( key === 'js' ) {
      return [
        prod && sourcemaps.init(),
        concat(file),
        prod && uglify({preserveComments: 'some'}),
        gulp.dest('dist')
      ]
    }
  }
  return key;
}

function build(file, pipes) {
  var ret = res,
      keys = file.split(/\./g),
      key = keys.pop();
  keys.forEach(function(key) {
    if ( ret[key] ) {
      ret = ret[key];
    }
  });
  getPipes(pipes || key, file).forEach(function(pipe) {
    if ( pipe ) {
      ret[key] = ret[key].pipe(pipe).on('error', function(error) {
        console.log('oops!');
      });
    }
  });
  ret[key] = ret[key].on('error', function(error) {
    console.log('oops!');
  });
  return ret[key];
}

function build(file, pipes) {
  var keys = file.split(/\./g),
      key = keys.pop(),
      src = path;
  keys.forEach(function(key) {
    if ( src[key] ) {
      src = src[key];
    }
  });
  src = gulp.src(src[key]);
  getPipes(pipes || key, file).forEach(function(pipe) {
    if ( pipe ) {
      src = src.pipe(pipe).on('error', function(error) {
        console.log('An error occured in ' + error.plugin);
        console.log(error.stack || error.message);
      });
    }
  });
  return src;
}

gulp.task('build-app', function() {
  build('app.css');
  build('app.js');
});

gulp.task('build-assets', function() {
  build('assets', [
    gulp.dest('dist')
  ]);
});

gulp.task('build-background', function() {
  build('background.js');
});

gulp.task('build-options', function() {
  build('options.css');
  build('options.js');
  build('options.html');
});

gulp.task('build-scripts', function() {
  build('scripts.css');
  build('scripts.js');
});

gulp.task('build', ['clean'], function() {
  return gulp.start([
    'build-app', 'build-assets',
    'build-background', 'build-options', 'build-scripts'
  ]);
});

gulp.task('build-prod', function() {
  prod = true;
  return gulp.start('build');
});

gulp.task('clean', function(done) {
  del(['dist/**/*'], done);
});

gulp.task('watch', ['build'], function() {
  livereload.listen();
  /*
  gulp.watch(path.app.css,       ['build-app']);
  gulp.watch(path.app.js,        ['build-app']);
  gulp.watch(path.assets,        ['build-assets']);
  gulp.watch(path.background.js, ['build-background']);
  gulp.watch(path.options.css,   ['build-options']);
  gulp.watch(path.options.js,    ['build-options']);
  gulp.watch(path.options.html,  ['build-options']);
  gulp.watch(path.scripts.css,   ['build-scripts']);
  gulp.watch(path.scripts.js,    ['build-scripts']);
  */
  gulp.watch('src/**', ['build']).on('error', function(error) {
    console.log(error);
  });
  gulp.watch('dist/**').on('change', livereload.changed);
});

gulp.task('default', ['watch']);<commit_msg>Gulp updates - file downloads, nunjuck filters<commit_after>'use strict';

var gulp       = require('gulp'),
    bump       = require('gulp-bump'),
    concat     = require('gulp-concat'),
    cssmin     = require('gulp-cssmin'),
    del        = require('del'),
    fs         = require('fs'),
    htmlmin    = require('gulp-htmlmin'),
    http       = require('http'),
    https      = require('https'),
    livereload = require('gulp-livereload'),
    newer      = require('gulp-newer'),
    nunjucks   = require('gulp-nunjucks-html'),
    //sass       = require('gulp-sass'),
    sourcemaps = require('gulp-sourcemaps'),
    uglify     = require('gulp-uglify'),
    prod       = false,
    path       = {
      app: {
        css: [
          'src/lib/**/*.css', 'src/app/**/*.css'
        ],
        js: [
          'src/lib/jquery/**.js', 'src/lib/**.js',
          'src/app/prototype.js', 'src/app/core.js', 'src/app/**.js'
        ]
      },
      assets: [
        'src/assets/**/*', 'src/*.json'
      ],
      background: {
        js: [
          'src/background/background.js', 'src/modules/**/*.background.js'
        ]
      },
      options: {
        css: [
          'src/options/options.css', 'src/modules/**/*.options.css'
        ],
        html: 'src/options/options.html',
        js: [
          'src/options/options.js', 'src/modules/**/*.options.js'
        ]
      },
      scripts: {
        css: [
          'src/modules/**/*.scripts.css'
        ],
        js: [
          'src/modules/**/*.scripts.js'
        ]
      }
    };

function downloadFile(url, path, done) {
  var file = fs.createWriteStream(path),
      module = url.indexOf('https') > -1 ? https : http;
  module.get(url, function(res) {
    res.on('data', function(chunk) {
      file.write(chunk);
    }).on('end', function() {
      file.end();
      done();
    });
  });
}

function getManifest() {
  if ( getManifest.manifest ) {
    return getManifest.manifest;
  }

  function getFile(path) {
    try {
      return fs.readFileSync(path, 'utf8');
    } catch ( e ) {
      return '';
    }
  }

  var manifest = require('./src/manifest.json'),
      modules = require('./src/modules.json'),
      changelog = require('./src/changelog.json');

  manifest.modules = modules;
  manifest.changelog = changelog;

  modules.forEach(function(module) {
    module.depends.map(function(dep) {
      var i = modules.length - 1;
      for ( ; i >= 0; i-- ) {
        if ( modules[i].id === dep ) {
          return modules[i];
        }
      }
      return { id: dep, name: dep };
    });

    module.contents = {
      options: getFile('src/modules/'+module.id+'/'+module.id+'.options.html')
    };
  });

  getManifest.manifest = manifest;
  return manifest;
}

function getPipes(key, file) {
  if ( typeof key === 'string' ) {
    if ( key === 'css' ) {
      return [
        prod && sourcemaps.init(),
        concat(file),
        prod && cssmin(),
        prod && sourcemaps.write('.'),
        gulp.dest('dist')
      ];
    } else if ( key === 'html' ) {
      return [
        nunjucks({
          locals: {
            manifest: getManifest()
          },
          searchPaths: ['src'],
          setUp: function(env) {
            env.addFilter('version', function(version) {
              var res = /^\d+\.\d+/.exec(version);
              if ( res && res.length ) {
                return res[0];
              }
              return version;
            });
            return env;
          }
        }),
        htmlmin({
          removeComments: true,
          collapseWhitespace: true
        }),
        gulp.dest('dist')
      ];
    } else if ( key === 'js' ) {
      return [
        prod && sourcemaps.init(),
        concat(file),
        prod && uglify({preserveComments: 'some'}),
        gulp.dest('dist')
      ]
    }
  }
  return key;
}

function build(file, pipes) {
  var keys = file.split(/\./g),
      key = keys.pop(),
      src = path;
  keys.forEach(function(key) {
    if ( src[key] ) {
      src = src[key];
    }
  });
  src = gulp.src(src[key]);
  getPipes(pipes || key, file).forEach(function(pipe) {
    if ( pipe ) {
      src = src.pipe(pipe).on('error', function(error) {
        console.log('An error occured in ' + error.plugin);
        console.log(error.stack || error.message);
      });
    }
  });
  return src;
}

gulp.task('build-app', function() {
  build('app.css');
  build('app.js');
});

gulp.task('build-assets', function() {
  build('assets', [
    gulp.dest('dist')
  ]);
});

gulp.task('build-background', function() {
  build('background.js');
});

gulp.task('build-options', function() {
  build('options.css');
  build('options.js');
  build('options.html');
});

gulp.task('build-scripts', function() {
  build('scripts.css');
  build('scripts.js');
});

gulp.task('build', ['clean'], function() {
  return gulp.start([
    'build-app', 'build-assets',
    'build-background', 'build-options', 'build-scripts'
  ]);
});

gulp.task('build-prod', ['update-resources'], function() {
  prod = true;
  return gulp.start('build');
});

gulp.task('clean', function(done) {
  del(['dist/**/*'], done);
});

gulp.task('update-resources', function(done) {
  var count = 0,
      changelog,
      about;
  function checkDone() {
    count++;
    if ( count == 2 ) {
      done();
    }
  }

  downloadFile(
    'https://github.com/michaeldrotar/Better-Cupid/wiki/Changelog',
    'src/options/changelog.html',
    checkDone
  );

  downloadFile(
    'https://github.com/michaeldrotar/Better-Cupid/wiki/About',
    'src/options/about.html',
    checkDone
  );
});

gulp.task('watch', ['build'], function() {
  livereload.listen();
  gulp.watch(path.app.css,       ['build-app']);
  gulp.watch(path.app.js,        ['build-app']);
  gulp.watch(path.assets,        ['build-assets']);
  gulp.watch(path.background.js, ['build-background']);
  gulp.watch(path.options.css,   ['build-options']);
  gulp.watch(path.options.js,    ['build-options']);
  gulp.watch(path.options.html,  ['build-options']);
  gulp.watch(path.scripts.css,   ['build-scripts']);
  gulp.watch(path.scripts.js,    ['build-scripts']);
  gulp.watch('dist/**').on('change', livereload.changed);
});

gulp.task('default', ['watch']);<|endoftext|>