<commit_before>dojo.provide("dojox.json.ref");
dojo.require("dojo.date.stamp");

// summary:
// Adds advanced JSON {de}serialization capabilities to the base json library.
// This enhances the capabilities of dojo.toJson and dojo.fromJson,
// adding referencing support, date handling, and other extra format handling.
// On parsing, references are resolved. When references are made to
// ids/objects that have been loaded yet, the loader function will be set to
// _loadObject to denote a lazy loading (not loaded yet) object.

dojox.json.ref = {
	resolveJson: function(/*Object*/ root,/*Object?*/ args){
		// summary:
		// 		Indexes and resolves references in the JSON object.
		// description:
		// 		A JSON Schema object that can be used to advise the handling of the JSON (defining ids, date properties, urls, etc)
		//
		// root:
		//		The root object of the object graph to be processed
		// args:
		//		Object with additional arguments:
		//
		// The *index* parameter.
		//		This is the index object (map) to use to store an index of all the objects.
		// 		If you are using inter-message referencing, you must provide the same object for each call.
		// The *defaultId* parameter.
		//		This is the default id to use for the root object (if it doesn't define it's own id)
		//	The *idPrefix* parameter.
		//		This the prefix to use for the ids as they enter the index. This allows multiple tables
		// 		to use ids (that might otherwise collide) that enter the same global index.
		// 		idPrefix should be in the form "/Service/".  For example,
		//		if the idPrefix is "/Table/", and object is encountered {id:"4",...}, this would go in the
		//		index as "/Table/4".
		//	The *idAttribute* parameter.
		//		This indicates what property is the identity property. This defaults to "id"
		//	The *assignAbsoluteIds* parameter.
		//		This indicates that the resolveJson should assign absolute ids (__id) as the objects are being parsed.
		//
		// The *schemas* parameter
		//		This provides a map of schemas, from which prototypes can be retrieved
		// The *loader* parameter
		//		This is a function that is called added to the reference objects that can't be resolved (lazy objects)
		// return:
		//		An object, the result of the processing
		args = args || {};
		var idAttribute = args.idAttribute || 'id';
		var prefix = args.idPrefix || '';
		var assignAbsoluteIds = args.assignAbsoluteIds;
		var index = args.index || {}; // create an index if one doesn't exist
		var timeStamps = args.timeStamps;
		var ref,reWalk=[];
		var pathResolveRegex = /^(.*\/)?(\w+:\/\/)|[^\/\.]+\/\.\.\/|^.*\/(\/)/;
		var addProp = this._addProp;
		var F = function(){};
		function walk(it, stop, defaultId, schema, defaultObject){
			// this walks the new graph, resolving references and making other changes
		 	var update, val, id = it[idAttribute] || defaultId;
		 	if(id !== undefined){
		 		id = (prefix + id).replace(pathResolveRegex,'$2$3');
		 	}
		 	var target = defaultObject || it;
			if(id !== undefined){ // if there is an id available...
				if(assignAbsoluteIds){
					it.__id = id;
				}
				if(args.schemas && (!(it instanceof Array)) && // won't try on arrays to do prototypes, plus it messes with queries
		 					(val = id.match(/^(.+\/)[^\.\[]*$/))){ // if it has a direct table id (no paths)
		 			schema = args.schemas[val[1]];
				}
				// if the id already exists in the system, we should use the existing object, and just
				// update it... as long as the object is compatible
				if(index[id] && ((it instanceof Array) == (index[id] instanceof Array))){
					target = index[id];
					delete target.$ref; // remove this artifact
					update = true;
				}else{
				 	var proto = schema && schema.prototype; // and if has a prototype
					if(proto){
						// if the schema defines a prototype, that needs to be the prototype of the object
						F.prototype = proto;
						target = new F();
					}
				}
				index[id] = target; // add the prefix, set _id, and index it
				if(timeStamps){
					timeStamps[id] = args.time;
				}
			}
			var properties = schema && schema.properties;
			var length = it.length;
			for(var i in it){
				if(i==length){
					break;
				}
				if(it.hasOwnProperty(i)){
					val=it[i];
					var propertyDefinition = properties && properties[i];
					if(propertyDefinition && propertyDefinition.format == 'date-time' && typeof val == 'string'){
						val = dojo.date.stamp.fromISOString(val);
					}else if((typeof val =='object') && val){
						ref=val.$ref;
						if(ref){ // a reference was found
							var stripped = ref.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');// trim it
							if(/[\w\[\]\.\$# \/\r\n\t]/.test(stripped) && !/\=|((^|\W)new\W)/.test(stripped)){
								// make sure it is a safe reference
								delete it[i];// remove the property so it doesn't resolve to itself in the case of id.propertyName lazy values
								var path = ref.match(/(^([^\[]*\/)?[^\.\[]*)([\.\[].*)?/); // divide along the path
								if((ref = (path[1]=='$' || path[1]=='this' || path[1]=='#') ? root : index[(prefix + path[1]).replace(pathResolveRegex,'$2$3')])){  // a $ indicates to start with the root, otherwise start with an id
									// // starting point was found, use eval to resolve remaining property references
									// // need to also make reserved words safe by replacing with index operator
									try{
										ref = path[3] ? eval('ref' + path[3].replace(/^#/,'').replace(/^([^\[\.])/,'.$1').replace(/\.([\w$_]+)/g,'["$1"]')) : ref;
									}catch(e){
										ref = null;
									}
								}
								if(ref){
									// otherwise, no starting point was found (id not found), if stop is set, it does not exist, we have
									// unloaded reference, if stop is not set, it may be in a part of the graph not walked yet,
									// we will wait for the second loop
									val = ref;
								}else{
									if(!stop){
										var rewalking;
										if(!rewalking){
											reWalk.push(target); // we need to rewalk it to resolve references
										}
										rewalking = true; // we only want to add it once
									}else{
										val = walk(val, false, val.$ref, propertyDefinition);
										// create a lazy loaded object
										val._loadObject = args.loader;
									}
								}
							}
						}else{
							if(!stop){ // if we are in stop, that means we are in the second loop, and we only need to check this current one,
								// further walking may lead down circular loops
								val = walk(
									val,
									reWalk==it,
									id && addProp(id, i), // the default id to use
									propertyDefinition,
									// if we have an existing object child, we want to
									// maintain it's identity, so we pass it as the default object
									target != it && typeof target[i] == 'object' && target[i]
								);
							}
						}
					}
					it[i] = val;
					if(target!=it){// performance guard
						var old = target[i];
						target[i] = val; // update the target
						if(update && val !== old){ // only update if it changed
							if(index.onUpdate){
								index.onUpdate(target,i,old,val); // call the listener for each update
							}
						}
					}
				}
			}

			if(update){
				// this means we are updating, we need to remove deleted
				for(i in target){
					if(!it.hasOwnProperty(i) && i != '__id' && i != '__clientId' && !(target instanceof Array && isNaN(i))){
						if(index.onUpdate){
							index.onUpdate(target,i,target[i],undefined); // call the listener for each update
						}
						delete target[i];
						while(target instanceof Array && target.length && target[target.length-1] === undefined){
							// shorten the target if necessary
							target.length--;
						}
					}
				}
			}else{
				if(index.onLoad){
					index.onLoad(target);
				}
			}
			return target;
		}
		if(root && typeof root == 'object'){
			root = walk(root,false,args.defaultId); // do the main walk through
			walk(reWalk,false); // re walk any parts that were not able to resolve references on the first round
		}
		return root;
	},

	fromJson: function(/*String*/ str,/*Object?*/ args){
	// summary:
	// 		evaluates the passed string-form of a JSON object.
	//
	// str:
	//		a string literal of a JSON item, for instance:
	//			'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'
	// args: See resolveJson
	//
	// return:
	//		An object, the result of the evaluation
		function ref(target){ // support call styles references as well
			return {$ref:target};
		}
		var root = eval('(' + str + ')'); // do the eval
		if(root){
			return this.resolveJson(root, args);
		}
		return root;
	},

	toJson: function(/*Object*/ it, /*Boolean?*/ prettyPrint, /*Object?*/ idPrefix, /*Object?*/ indexSubObjects){
		// summary:
		//		Create a JSON serialization of an object.
		//		This has support for referencing, including circular references, duplicate references, and out-of-message references
		// 		id and path-based referencing is supported as well and is based on http://www.json.com/2007/10/19/json-referencing-proposal-and-library/.
		//
		// it:
		//		an object to be serialized.
		//
		// prettyPrint:
		//		if true, we indent objects and arrays to make the output prettier.
		//		The variable dojo.toJsonIndentStr is used as the indent string
		//		-- to use something other than the default (tab),
		//		change that variable before calling dojo.toJson().
		//
		// idPrefix: The prefix that has been used for the absolute ids
		//
		// return:
		//		a String representing the serialized version of the passed object.
		var useRefs = this._useRefs;
		var addProp = this._addProp;
		idPrefix = idPrefix || ''; // the id prefix for this context
		var paths={};
		function serialize(it,path,_indentStr){
			if(typeof it == 'object' && it){
				var value;
				if(it instanceof Date){ // properly serialize dates
					return '"' + dojo.date.stamp.toISOString(it,{zulu:true}) + '"';
				}
				var id = it.__id;
				if(id){ // we found an identifiable object, we will just serialize a reference to it... unless it is the root
					if(path != '#' && ((useRefs && !id.match(/#/)) || paths[id])){
						var ref = id;
						if(id.charAt(0)!='#'){
							if(it.__clientId == id){
								ref = "cid:" + id;
							}else if(id.substring(0, idPrefix.length) == idPrefix){ // see if the reference is in the current context
								// a reference with a prefix matching the current context, the prefix should be removed
								ref = id.substring(idPrefix.length);
							}else{
								// a reference to a different context, assume relative url based referencing
								ref = id;
							}
						}
						return serialize({
							$ref: ref
						},'#');
					}
					path = id;
				}else{
					it.__id = path; // we will create path ids for other objects in case they are circular
					paths[path] = it;// save it here so they can be deleted at the end
				}
				_indentStr = _indentStr || "";
				var nextIndent = prettyPrint ? _indentStr + dojo.toJsonIndentStr : "";
				var newLine = prettyPrint ? "\n" : "";
				var sep = prettyPrint ? " " : "";

				if(it instanceof Array){
					var res = dojo.map(it, function(obj,i){
						var val = serialize(obj, addProp(path, i), nextIndent);
						if(typeof val != "string"){
							val = "undefined";
						}
						return newLine + nextIndent + val;
					});
					return "[" + res.join("," + sep) + newLine + _indentStr + "]";
				}

				var output = [];
				for(var i in it){
					if(it.hasOwnProperty(i)){
						var keyStr;
						if(typeof i == "number"){
							keyStr = '"' + i + '"';
						}else if(typeof i == "string" && i.charAt(0) != '_'){
							keyStr = dojo._escapeString(i);
						}else{
							// skip non-string or number keys
							continue;
						}
						var val = serialize(it[i],addProp(path, i),nextIndent);
						if(typeof val != "string"){
							// skip non-serializable values
							continue;
						}
						output.push(newLine + nextIndent + keyStr + ":" + sep + val);
					}
				}
				return "{" + output.join("," + sep) + newLine + _indentStr + "}";
			}else if(typeof it == "function" && dojox.json.ref.serializeFunctions){
				return it.toString();
			}

			return dojo.toJson(it); // use the default serializer for primitives
		}
		var json = serialize(it,'#','');
		if(!indexSubObjects){
			for(var i in paths)  {// cleanup the temporary path-generated ids
				delete paths[i].__id;
			}
		}
		return json;
	},
	_addProp: function(id, prop){
		return id + (id.match(/#/) ? '' : '#') +
					(typeof prop == 'string' ? // is it a string
						prop.match(/^[a-zA-Z]\w*$/) ? ('.' + prop) : // yes, otherwise we have to escape it
							('[' + dojo._escapeString(prop).replace(/"/g,"'") + ']') :
						('[' + prop + ']'));
	},
	_useRefs: false,
	serializeFunctions: false
}
<commit_msg>Provides more lenient referencing and properly cleans up ids after serialization<commit_after>dojo.provide("dojox.json.ref");
dojo.require("dojo.date.stamp");

// summary:
// Adds advanced JSON {de}serialization capabilities to the base json library.
// This enhances the capabilities of dojo.toJson and dojo.fromJson,
// adding referencing support, date handling, and other extra format handling.
// On parsing, references are resolved. When references are made to
// ids/objects that have been loaded yet, the loader function will be set to
// _loadObject to denote a lazy loading (not loaded yet) object.

dojox.json.ref = {
	resolveJson: function(/*Object*/ root,/*Object?*/ args){
		// summary:
		// 		Indexes and resolves references in the JSON object.
		// description:
		// 		A JSON Schema object that can be used to advise the handling of the JSON (defining ids, date properties, urls, etc)
		//
		// root:
		//		The root object of the object graph to be processed
		// args:
		//		Object with additional arguments:
		//
		// The *index* parameter.
		//		This is the index object (map) to use to store an index of all the objects.
		// 		If you are using inter-message referencing, you must provide the same object for each call.
		// The *defaultId* parameter.
		//		This is the default id to use for the root object (if it doesn't define it's own id)
		//	The *idPrefix* parameter.
		//		This the prefix to use for the ids as they enter the index. This allows multiple tables
		// 		to use ids (that might otherwise collide) that enter the same global index.
		// 		idPrefix should be in the form "/Service/".  For example,
		//		if the idPrefix is "/Table/", and object is encountered {id:"4",...}, this would go in the
		//		index as "/Table/4".
		//	The *idAttribute* parameter.
		//		This indicates what property is the identity property. This defaults to "id"
		//	The *assignAbsoluteIds* parameter.
		//		This indicates that the resolveJson should assign absolute ids (__id) as the objects are being parsed.
		//
		// The *schemas* parameter
		//		This provides a map of schemas, from which prototypes can be retrieved
		// The *loader* parameter
		//		This is a function that is called added to the reference objects that can't be resolved (lazy objects)
		// return:
		//		An object, the result of the processing
		args = args || {};
		var idAttribute = args.idAttribute || 'id';
		var prefix = args.idPrefix || '';
		var assignAbsoluteIds = args.assignAbsoluteIds;
		var index = args.index || {}; // create an index if one doesn't exist
		var timeStamps = args.timeStamps;
		var ref,reWalk=[];
		var pathResolveRegex = /^(.*\/)?(\w+:\/\/)|[^\/\.]+\/\.\.\/|^.*\/(\/)/;
		var addProp = this._addProp;
		var F = function(){};
		function walk(it, stop, defaultId, schema, defaultObject){
			// this walks the new graph, resolving references and making other changes
		 	var update, val, id = it[idAttribute] || defaultId;
		 	if(id !== undefined){
		 		id = (prefix + id).replace(pathResolveRegex,'$2$3');
		 	}
		 	var target = defaultObject || it;
			if(id !== undefined){ // if there is an id available...
				if(assignAbsoluteIds){
					it.__id = id;
				}
				if(args.schemas && (!(it instanceof Array)) && // won't try on arrays to do prototypes, plus it messes with queries
		 					(val = id.match(/^(.+\/)[^\.\[]*$/))){ // if it has a direct table id (no paths)
		 			schema = args.schemas[val[1]];
				}
				// if the id already exists in the system, we should use the existing object, and just
				// update it... as long as the object is compatible
				if(index[id] && ((it instanceof Array) == (index[id] instanceof Array))){
					target = index[id];
					delete target.$ref; // remove this artifact
					update = true;
				}else{
				 	var proto = schema && schema.prototype; // and if has a prototype
					if(proto){
						// if the schema defines a prototype, that needs to be the prototype of the object
						F.prototype = proto;
						target = new F();
					}
				}
				index[id] = target; // add the prefix, set _id, and index it
				if(timeStamps){
					timeStamps[id] = args.time;
				}
			}
			var properties = schema && schema.properties;
			var length = it.length;
			for(var i in it){
				if(i==length){
					break;
				}
				if(it.hasOwnProperty(i)){
					val=it[i];
					var propertyDefinition = properties && properties[i];
					if(propertyDefinition && propertyDefinition.format == 'date-time' && typeof val == 'string'){
						val = dojo.date.stamp.fromISOString(val);
					}else if((typeof val =='object') && val && !(val instanceof Date)){
						ref=val.$ref;
						if(ref){ // a reference was found
							var stripped = ref.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');// trim it
							if(/[\w\[\]\.\$# \/\r\n\t]/.test(stripped) && !/\=|((^|\W)new\W)/.test(stripped)){
								// make sure it is a safe reference
								delete it[i];// remove the property so it doesn't resolve to itself in the case of id.propertyName lazy values
								var path = ref.replace(/(#)([^\.\[])/,'$1.$2').match(/(^([^\[]*\/)?[^#\.\[]*)#?([\.\[].*)?/); // divide along the path
								if((ref = (path[1]=='$' || path[1]=='this' || path[1]=='') ? root : index[(prefix + path[1]).replace(pathResolveRegex,'$2$3')])){  // a $ indicates to start with the root, otherwise start with an id
									// // starting point was found, use eval to resolve remaining property references
									// // need to also make reserved words safe by replacing with index operator
									try{
										ref = path[3] ? eval('ref' + path[3].replace(/^#/,'').replace(/^([^\[\.])/,'.$1').replace(/\.([\w$_]+)/g,'["$1"]')) : ref;
									}catch(e){
										ref = null;
									}
								}
								if(ref){
									// otherwise, no starting point was found (id not found), if stop is set, it does not exist, we have
									// unloaded reference, if stop is not set, it may be in a part of the graph not walked yet,
									// we will wait for the second loop
									val = ref;
								}else{
									if(!stop){
										var rewalking;
										if(!rewalking){
											reWalk.push(target); // we need to rewalk it to resolve references
										}
										rewalking = true; // we only want to add it once
									}else{
										val = walk(val, false, val.$ref, propertyDefinition);
										// create a lazy loaded object
										val._loadObject = args.loader;
									}
								}
							}
						}else{
							if(!stop){ // if we are in stop, that means we are in the second loop, and we only need to check this current one,
								// further walking may lead down circular loops
								val = walk(
									val,
									reWalk==it,
									id && addProp(id, i), // the default id to use
									propertyDefinition,
									// if we have an existing object child, we want to
									// maintain it's identity, so we pass it as the default object
									target != it && typeof target[i] == 'object' && target[i]
								);
							}
						}
					}
					it[i] = val;
					if(target!=it){// performance guard
						var old = target[i];
						target[i] = val; // update the target
						if(update && val !== old){ // only update if it changed
							if(index.onUpdate){
								index.onUpdate(target,i,old,val); // call the listener for each update
							}
						}
					}
				}
			}

			if(update){
				// this means we are updating, we need to remove deleted
				for(i in target){
					if(!it.hasOwnProperty(i) && i != '__id' && i != '__clientId' && !(target instanceof Array && isNaN(i))){
						if(index.onUpdate){
							index.onUpdate(target,i,target[i],undefined); // call the listener for each update
						}
						delete target[i];
						while(target instanceof Array && target.length && target[target.length-1] === undefined){
							// shorten the target if necessary
							target.length--;
						}
					}
				}
			}else{
				if(index.onLoad){
					index.onLoad(target);
				}
			}
			return target;
		}
		if(root && typeof root == 'object'){
			root = walk(root,false,args.defaultId); // do the main walk through
			walk(reWalk,false); // re walk any parts that were not able to resolve references on the first round
		}
		return root;
	},

	fromJson: function(/*String*/ str,/*Object?*/ args){
	// summary:
	// 		evaluates the passed string-form of a JSON object.
	//
	// str:
	//		a string literal of a JSON item, for instance:
	//			'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'
	// args: See resolveJson
	//
	// return:
	//		An object, the result of the evaluation
		function ref(target){ // support call styles references as well
			return {$ref:target};
		}
		var root = eval('(' + str + ')'); // do the eval
		if(root){
			return this.resolveJson(root, args);
		}
		return root;
	},

	toJson: function(/*Object*/ it, /*Boolean?*/ prettyPrint, /*Object?*/ idPrefix, /*Object?*/ indexSubObjects){
		// summary:
		//		Create a JSON serialization of an object.
		//		This has support for referencing, including circular references, duplicate references, and out-of-message references
		// 		id and path-based referencing is supported as well and is based on http://www.json.com/2007/10/19/json-referencing-proposal-and-library/.
		//
		// it:
		//		an object to be serialized.
		//
		// prettyPrint:
		//		if true, we indent objects and arrays to make the output prettier.
		//		The variable dojo.toJsonIndentStr is used as the indent string
		//		-- to use something other than the default (tab),
		//		change that variable before calling dojo.toJson().
		//
		// idPrefix: The prefix that has been used for the absolute ids
		//
		// return:
		//		a String representing the serialized version of the passed object.
		var useRefs = this._useRefs;
		var addProp = this._addProp;
		idPrefix = idPrefix || ''; // the id prefix for this context
		var paths={};
		var generated = {};
		function serialize(it,path,_indentStr){
			if(typeof it == 'object' && it){
				var value;
				if(it instanceof Date){ // properly serialize dates
					return '"' + dojo.date.stamp.toISOString(it,{zulu:true}) + '"';
				}
				var id = it.__id;
				if(id){ // we found an identifiable object, we will just serialize a reference to it... unless it is the root
					if(path != '#' && ((useRefs && !id.match(/#/)) || paths[id])){
						var ref = id;
						if(id.charAt(0)!='#'){
							if(it.__clientId == id){
								ref = "cid:" + id;
							}else if(id.substring(0, idPrefix.length) == idPrefix){ // see if the reference is in the current context
								// a reference with a prefix matching the current context, the prefix should be removed
								ref = id.substring(idPrefix.length);
							}else{
								// a reference to a different context, assume relative url based referencing
								ref = id;
							}
						}
						return serialize({
							$ref: ref
						},'#');
					}
					path = id;
				}else{
					it.__id = path; // we will create path ids for other objects in case they are circular
					generated[path] = it;
				}
				paths[path] = it;// save it here so they can be deleted at the end
				_indentStr = _indentStr || "";
				var nextIndent = prettyPrint ? _indentStr + dojo.toJsonIndentStr : "";
				var newLine = prettyPrint ? "\n" : "";
				var sep = prettyPrint ? " " : "";

				if(it instanceof Array){
					var res = dojo.map(it, function(obj,i){
						var val = serialize(obj, addProp(path, i), nextIndent);
						if(typeof val != "string"){
							val = "undefined";
						}
						return newLine + nextIndent + val;
					});
					return "[" + res.join("," + sep) + newLine + _indentStr + "]";
				}

				var output = [];
				for(var i in it){
					if(it.hasOwnProperty(i)){
						var keyStr;
						if(typeof i == "number"){
							keyStr = '"' + i + '"';
						}else if(typeof i == "string" && i.charAt(0) != '_'){
							keyStr = dojo._escapeString(i);
						}else{
							// skip non-string or number keys
							continue;
						}
						var val = serialize(it[i],addProp(path, i),nextIndent);
						if(typeof val != "string"){
							// skip non-serializable values
							continue;
						}
						output.push(newLine + nextIndent + keyStr + ":" + sep + val);
					}
				}
				return "{" + output.join("," + sep) + newLine + _indentStr + "}";
			}else if(typeof it == "function" && dojox.json.ref.serializeFunctions){
				return it.toString();
			}

			return dojo.toJson(it); // use the default serializer for primitives
		}
		var json = serialize(it,'#','');
		if(!indexSubObjects){
			for(var i in generated)  {// cleanup the temporary path-generated ids
				delete generated[i].__id;
			}
		}
		return json;
	},
	_addProp: function(id, prop){
		return id + (id.match(/#/) ? '' : '#') +
					(typeof prop == 'string' ? // is it a string
						prop.match(/^[a-zA-Z]\w*$/) ? ('.' + prop) : // yes, otherwise we have to escape it
							('[' + dojo._escapeString(prop).replace(/"/g,"'") + ']') :
						('[' + prop + ']'));
	},
	_useRefs: false,
	serializeFunctions: false
}
<|endoftext|>


<commit_before>/**
 * HTTP Server Settings
 * Configuration for the underlying HTTP server in Sails
 */

import express from 'express';

export default {
  /**
   * Port where to run this app
   * @type {Number}
   */
  port: 3000,

  /**
   * Your SSL certificates
   * @description They are should be as result of fs.readFileSync() method
   * @type {Object}
   * @example
   * ssl: {
   *    cert: fs.readFileSync('your/path/to/cert.pem'),
   *    key: fs.readFileSync('your/path/to/key.pem')
   * }
   */
  ssl: {
    cert: false,
    key: false
  },

  http: {
    /**
     * This is the options object for the `createServer` method, as discussed here:
     * http://nodejs.org/api/https.html#https_class_https_server
     *
     * @type {Object|Boolean}
     */
    serverOptions: undefined,

    /**
     * You can define own custom middleware here
     * @param app Express application
     */
    customMiddleware: app => {
      app.use('/explorer', express.static(process.cwd() + '/explorer/'));
    },

    /**
     * Configures the middleware function used for parsing the HTTP request body
     * Defaults to the Formidable-based version built into Express/Connect
     *
     * To enable streaming file uploads (to disk or somewhere else)
     * you'll want to set this option to `false` to disable the body parser
     *
     * @type {Function|Boolean|Object}
     */
    bodyParser: undefined,

    /**
     * Express middleware to use for every Sails request
     * @type {Object}
     */
    middleware: {
      /**
       * Middleware for setting Connection: keep-alive to all responses
       */
      keepAlive: (req, res, next) => {
        res.set('Connection', 'keep-alive');
        next();
      },

      /**
       * The order in which middleware should be run for HTTP request
       * @type {Array}
       */
      order: [
        'compress',
        'keepAlive',
        'bodyParser',
        '$custom',
        'router',
        '404',
        '500'
      ]
    }
  }
};
<commit_msg>refactor(swagger): Remove config/http.js file<commit_after><|endoftext|>


<commit_before>
var express = require('../')
  , request = require('./support/http');

describe('res', function(){
  describe('.render(name)', function(){
    it('should support absolute paths', function(done){
      var app = express();

      app.locals.user = { name: 'tobi' };

      app.use(function(req, res){
        res.render(__dirname + '/fixtures/user.jade');
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should support absolute paths with "view engine"', function(done){
      var app = express();

      app.locals.user = { name: 'tobi' };
      app.set('view engine', 'jade');

      app.use(function(req, res){
        res.render(__dirname + '/fixtures/user');
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should expose app.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      app.locals.user = { name: 'tobi' };

      app.use(function(req, res){
        res.render('user.jade');
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should support index.<engine>', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      app.set('view engine', 'jade');

      app.use(function(req, res){
        res.render('blog/post');
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
blog post
');
        done();
      });
    })

    describe('when an error occurs', function(){
      it('should next(err)', function(done){
        var app = express();

        app.set('views', __dirname + '/fixtures');

        app.use(function(req, res){
          res.render('user.jade');
        });

        app.use(function(err, req, res, next){
          res.end(err.message);
        });

        request(app)
        .get('/')
        .end(function(res){
          res.body.should.match(/user is not defined/);
          done();
        });
      })
    })

    describe('when "view engine" is given', function(){
      it('should render the template', function(done){
        var app = express();

        app.set('view engine', 'jade');
        app.set('views', __dirname + '/fixtures');

        app.use(function(req, res){
          res.render('email');
        });

        request(app)
        .get('/')
        .end(function(res){
          res.body.should.equal('
This is an email
');
          done();
        });
      })
    })
  })

  describe('.render(name, option)', function(){
    it('should render the template', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');

      var user = { name: 'tobi' };

      app.use(function(req, res){
        res.render('user.jade', { user: user });
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should expose app.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      app.locals.user = { name: 'tobi' };

      app.use(function(req, res){
        res.render('user.jade', {});
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should expose res.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');

      app.use(function(req, res){
        res.locals.user = { name: 'tobi' };
        res.render('user.jade', {});
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should give precedence to res.locals over app.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      app.locals.user = { name: 'tobi' };

      app.use(function(req, res){
        res.locals.user = { name: 'jane' };
        res.render('user.jade', {});
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
jane
');
        done();
      });
    })

    it('should give precedence to res.render() locals over res.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      var jane = { name: 'jane' };

      app.use(function(req, res){
        res.locals.user = { name: 'tobi' };
        res.render('user.jade', { user: jane });
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
jane
');
        done();
      });
    })

    it('should give precedence to res.render() locals over app.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      app.locals.user = { name: 'tobi' };
      var jane = { name: 'jane' };

      app.use(function(req, res){
        res.render('user.jade', { user: jane });
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
jane
');
        done();
      });
    })
  })

  describe('.render(name, options, fn)', function(){
    it('should pass the resulting string', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');

      app.use(function(req, res){
        var tobi = { name: 'tobi' };
        res.render('user.jade', { user: tobi }, function(err, html){
          html = html.replace('tobi', 'loki');
          res.end(html);
        });
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
loki
');
        done();
      });
    })
  })

  describe('.render(name, fn)', function(){
    it('should pass the resulting string', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');

      app.use(function(req, res){
        res.locals.user = { name: 'tobi' };
        res.render('user.jade', function(err, html){
          html = html.replace('tobi', 'loki');
          res.end(html);
        });
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
loki
');
        done();
      });
    })

    describe('when an error occurs', function(){
      it('should pass it to the callback', function(done){
        var app = express();

        app.set('views', __dirname + '/fixtures');

        app.use(function(req, res){
          res.render('user.jade', function(err){
            res.end(err.message);
          });
        });

        request(app)
        .get('/')
        .end(function(res){
          res.body.should.match(/is not defined/);
          done();
        });
      })

      describe('in the callback', function(){
        it('should next(err)', function(done){
          var app = express();

          app.set('views', __dirname + '/fixtures');

          app.use(function(req, res){
            res.render('user.jade', function(err){
              req.foo();
            });
          });

          app.use(function(err, req, res, next){
            res.end(err.message);
          });

          request(app)
          .get('/')
          .end(function(res){
            res.body.should.match(/has no method 'foo'/);
            done();
          });
        })
      })
    })
  })
})
<commit_msg>removed a test<commit_after>
var express = require('../')
  , request = require('./support/http');

describe('res', function(){
  describe('.render(name)', function(){
    it('should support absolute paths', function(done){
      var app = express();

      app.locals.user = { name: 'tobi' };

      app.use(function(req, res){
        res.render(__dirname + '/fixtures/user.jade');
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should support absolute paths with "view engine"', function(done){
      var app = express();

      app.locals.user = { name: 'tobi' };
      app.set('view engine', 'jade');

      app.use(function(req, res){
        res.render(__dirname + '/fixtures/user');
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should expose app.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      app.locals.user = { name: 'tobi' };

      app.use(function(req, res){
        res.render('user.jade');
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should support index.<engine>', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      app.set('view engine', 'jade');

      app.use(function(req, res){
        res.render('blog/post');
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
blog post
');
        done();
      });
    })

    describe('when an error occurs', function(){
      it('should next(err)', function(done){
        var app = express();

        app.set('views', __dirname + '/fixtures');

        app.use(function(req, res){
          res.render('user.jade');
        });

        app.use(function(err, req, res, next){
          res.end(err.message);
        });

        request(app)
        .get('/')
        .end(function(res){
          res.body.should.match(/user is not defined/);
          done();
        });
      })
    })

    describe('when "view engine" is given', function(){
      it('should render the template', function(done){
        var app = express();

        app.set('view engine', 'jade');
        app.set('views', __dirname + '/fixtures');

        app.use(function(req, res){
          res.render('email');
        });

        request(app)
        .get('/')
        .end(function(res){
          res.body.should.equal('
This is an email
');
          done();
        });
      })
    })
  })

  describe('.render(name, option)', function(){
    it('should render the template', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');

      var user = { name: 'tobi' };

      app.use(function(req, res){
        res.render('user.jade', { user: user });
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should expose app.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      app.locals.user = { name: 'tobi' };

      app.use(function(req, res){
        res.render('user.jade', {});
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should expose res.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');

      app.use(function(req, res){
        res.locals.user = { name: 'tobi' };
        res.render('user.jade', {});
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
tobi
');
        done();
      });
    })

    it('should give precedence to res.locals over app.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      app.locals.user = { name: 'tobi' };

      app.use(function(req, res){
        res.locals.user = { name: 'jane' };
        res.render('user.jade', {});
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
jane
');
        done();
      });
    })

    it('should give precedence to res.render() locals over res.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      var jane = { name: 'jane' };

      app.use(function(req, res){
        res.locals.user = { name: 'tobi' };
        res.render('user.jade', { user: jane });
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
jane
');
        done();
      });
    })

    it('should give precedence to res.render() locals over app.locals', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');
      app.locals.user = { name: 'tobi' };
      var jane = { name: 'jane' };

      app.use(function(req, res){
        res.render('user.jade', { user: jane });
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
jane
');
        done();
      });
    })
  })

  describe('.render(name, options, fn)', function(){
    it('should pass the resulting string', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');

      app.use(function(req, res){
        var tobi = { name: 'tobi' };
        res.render('user.jade', { user: tobi }, function(err, html){
          html = html.replace('tobi', 'loki');
          res.end(html);
        });
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
loki
');
        done();
      });
    })
  })

  describe('.render(name, fn)', function(){
    it('should pass the resulting string', function(done){
      var app = express();

      app.set('views', __dirname + '/fixtures');

      app.use(function(req, res){
        res.locals.user = { name: 'tobi' };
        res.render('user.jade', function(err, html){
          html = html.replace('tobi', 'loki');
          res.end(html);
        });
      });

      request(app)
      .get('/')
      .end(function(res){
        res.body.should.equal('
loki
');
        done();
      });
    })

    describe('when an error occurs', function(){
      it('should pass it to the callback', function(done){
        var app = express();

        app.set('views', __dirname + '/fixtures');

        app.use(function(req, res){
          res.render('user.jade', function(err){
            res.end(err.message);
          });
        });

        request(app)
        .get('/')
        .end(function(res){
          res.body.should.match(/is not defined/);
          done();
        });
      })

    })
  })
})
<|endoftext|>


<commit_before>function changetext(a){
  var aids = $("#aids");
  $(aids).text(a);
}

$(document).ready(function() {
  changetext(gen());
});

var intensifiers = ["savage ","gay ","deprived ","desperate ","cringy ",
"disgusting ","nasty ","hot ","erotic ", "terrifiying ","angry ", "psychotic"]
var ists = ["nastiest ""cringiest ","hottest ","unhappyist ","scariest ",
"worst ","biggest ","best "]
var noun = ["minecraft animation ","gay ","man ","kid ","video ","woman ",
"girl ","manchild ","rapper ","frozen animation ", "pussy slayer ", "youtuber ",
"music video ","furry "]
var placeish = ["on the internet","on youtube","on earth",
"on the entire internet","to ever touch the internet","to ever be witnessed",
"to ever live in this world"]
var cherry = [" roasts me"," wants me"," drinks bleach"," ever",
" says he is going to kill me"," is in love with me"," (literally eats rocks)",
" (literally drills himself)"," exposes me"]
var fontfaces = ["'Ubuntu', sans-serif", "'Dancing Script', cursive"];

function randombool(){
  var randbool = Math.random()
  return randbool
}

function fontToggle(){
  $('.aids').css('font-family', fontfaces[0]);
  fontfaces.reverse();
}

function gen(){
  aids = "the ";
  if (randombool() > .5){
    aids = aids.concat("most ");
    aids = aids.concat(intensifiers[Math.floor(Math.random() * intensifiers.length)]);
  }
  else{
    aids = aids.concat(ists[Math.floor(Math.random() * ists.length)]);
  }

  aids = aids.concat(noun[Math.floor(Math.random() * noun.length)]);
  aids = aids.concat(placeish[Math.floor(Math.random() * placeish.length)]);

  if (Math.random() > 1/3){
    aids = aids.concat(cherry[Math.floor(Math.random() * cherry.length)]);
  }

  aids = aids.toUpperCase();
  return aids
}

function changetext(a){
  var aids = $("#aids")
  $(aids).text(a)
}
<commit_msg>fixed an error<commit_after>function changetext(a){
  var aids = $("#aids");
  $(aids).text(a);
}

$(document).ready(function() {
  changetext(gen());
});

var intensifiers = ["savage ","gay ","deprived ","desperate ","cringy ",
"disgusting ","nasty ","hot ","erotic ", "terrifiying ","angry ", "psychotic"]
var ists = ["nastiest ","cringiest ","hottest ","unhappyist ","scariest ",
"worst ","biggest ","best "]
var noun = ["minecraft animation ","gay ","man ","kid ","video ","woman ",
"girl ","manchild ","rapper ","frozen animation ", "pussy slayer ", "youtuber ",
"music video ","furry "]
var placeish = ["on the internet","on youtube","on earth",
"on the entire internet","to ever touch the internet","to ever be witnessed",
"to ever live in this world"]
var cherry = [" roasts me"," wants me"," drinks bleach"," ever",
" says he is going to kill me"," is in love with me"," (literally eats rocks)",
" (literally drills himself)"," exposes me"]
var fontfaces = ["'Ubuntu', sans-serif", "'Dancing Script', cursive"];

function randombool(){
  var randbool = Math.random()
  return randbool
}

function fontToggle(){
  $('.aids').css('font-family', fontfaces[0]);
  fontfaces.reverse();
}

function gen(){
  aids = "the ";
  if (randombool() > .5){
    aids = aids.concat("most ");
    aids = aids.concat(intensifiers[Math.floor(Math.random() * intensifiers.length)]);
  }
  else{
    aids = aids.concat(ists[Math.floor(Math.random() * ists.length)]);
  }

  aids = aids.concat(noun[Math.floor(Math.random() * noun.length)]);
  aids = aids.concat(placeish[Math.floor(Math.random() * placeish.length)]);

  if (Math.random() > 1/3){
    aids = aids.concat(cherry[Math.floor(Math.random() * cherry.length)]);
  }

  aids = aids.toUpperCase();
  return aids
}
<|endoftext|>


<commit_before>/*global jsobj */
/*jslint */

(function (jsobj) {
	"use strict";

	function Cell() {
		var val, myRowH, myRowV, myBlock;

		this.value = function () {
			return val;
		};

		this.setValue = function (newValue) {
			if (val !== undefined) {
				throw new Error("Attempt to set value on a Cell that already has a value.");
			}
			val = newValue;
			this.trigger("update");
		};

		this.rowH = function () {
			return myRowH;
		};

		this.setRowH = function (row) {
			if (myRowH !== undefined) {
				throw new Error('Attempt to set rowH on a Cell that already has a rowH.');
			}
			myRowH = row;
		};

		this.rowV = function () {
			return myRowV;
		};

		this.setRowV = function (row) {
			if (myRowV !== undefined) {
				throw new Error('Attempt to set rowV on a Cell that already has a rowV.');
			}
			myRowV = row;
		};

		this.block = function () {
			return myBlock;
		};

		this.setBlock = function (block) {
			if (myBlock !== undefined) {
				throw new Error('Attempt to set block on a Cell that already has a block.');
			}
			myBlock = block;
		};
	}

	Cell.prototype = new jsobj.EventAware();

	jsobj.Cell = function () {
		return new Cell();
	};
}(jsobj));<commit_msg>cell - track possible values, subscribe to row and block update events to update possibles<commit_after>/*global jsobj */
/*jslint plusplus: true */

(function (jsobj) {
	"use strict";

	function Cell() {
		var val, myRowH, myRowV, myBlock,
			possibles = { 1: null, 2: null, 3: null, 4: null, 5: null, 6: null, 7: null, 8: null, 9: null },
			possibleCount = 9;

		function updatePossibles(newValue) {
			if (possibles[newValue] !== undefined) {
				delete possibles[newValue];
				possibleCount--;
			}
		}

		this.value = function () {
			return val;
		};

		this.setValue = function (newValue) {
			if (val !== undefined) {
				throw new Error("Attempt to set value on a Cell that already has a value.");
			}
			val = newValue;
			this.trigger("update");
		};

		this.rowH = function () {
			return myRowH;
		};

		this.setRowH = function (row) {
			if (myRowH !== undefined) {
				throw new Error('Attempt to set rowH on a Cell that already has a rowH.');
			}
			myRowH = row;

			// update possible values of the cell when its row is updated
			myRowH.on("update", updatePossibles);
		};

		this.rowV = function () {
			return myRowV;
		};

		this.setRowV = function (row) {
			if (myRowV !== undefined) {
				throw new Error('Attempt to set rowV on a Cell that already has a rowV.');
			}
			myRowV = row;

			// update possible values of the cell when its row is updated
			myRowV.on("update", updatePossibles);
		};

		this.block = function () {
			return myBlock;
		};

		this.setBlock = function (block) {
			if (myBlock !== undefined) {
				throw new Error('Attempt to set block on a Cell that already has a block.');
			}
			myBlock = block;

			// update possible values of the cell when its row is updated
			myBlock.on("update", updatePossibles);
		};
	}

	Cell.prototype = new jsobj.EventAware();

	jsobj.Cell = function () {
		return new Cell();
	};
}(jsobj));<|endoftext|>


<commit_before>/*globals describe */

var assert = require('assert');
var test = require("./helpers").test;
var testError = require("./helpers").testError;
var testMinimize = require("./helpers").testMinimize;

describe("simple", function() {
	test("empty", "", [
		[1, "", ""]
	]);
	testMinimize("empty minimized", "", [
		[1, "", ""]
	]);
	test("simple", ".class { a: b c d; }", [
		[1, ".class { a: b c d; }", ""]
	]);
	test("simple2", ".class { a: b c d; }\n.two {}", [
		[1, ".class { a: b c d; }\n.two {}", ""]
	]);
	test("escape characters (uppercase)", ".class { content: \"\\F10C\" }", [
		[1, ".class { content: \"\\F10C\" }", ""]
	]);
	// Need uncomment after resolve https://github.com/css-modules/postcss-modules-local-by-default/issues/108
	/*test("escape characters (lowercase)", ".class { content: \"\\f10C\" }", [
		[1, ".class { content: \"\\f10C\" }", ""]
	]);*/
	// Need uncomment after resolve https://github.com/mathiasbynens/cssesc/issues/10
	/*test("escape characters (two)", ".class { content: \"\\F10C \\F10D\" }", [
		[1, ".class { content: \"\\F10C \\F10D\" }", ""]
	]);*/
	testMinimize("minimized simple", ".class { a: b c d; }", [
		[1, ".class{a:b c d}", ""]
	]);
	testError("error formatting", ".some {\n invalid css;\n}", function(err) {
		assert.equal(err.message, [
			'Unknown word (2:2)',
			'',
			'  1 | .some {',
			'> 2 |  invalid css;',
			'    |  ^',
			'  3 | }',
			'',
		].join('\n'));
	});
});
<commit_msg>test: `charset` directive (#502)<commit_after>/*globals describe */

var assert = require('assert');
var test = require("./helpers").test;
var testError = require("./helpers").testError;
var testMinimize = require("./helpers").testMinimize;

describe("simple", function() {
	test("empty", "", [
		[1, "", ""]
	]);
	testMinimize("empty minimized", "", [
		[1, "", ""]
	]);
	test("simple", ".class { a: b c d; }", [
		[1, ".class { a: b c d; }", ""]
	]);
	test("simple2", ".class { a: b c d; }\n.two {}", [
		[1, ".class { a: b c d; }\n.two {}", ""]
	]);
	test("escape characters (uppercase)", ".class { content: \"\\F10C\" }", [
		[1, ".class { content: \"\\F10C\" }", ""]
	]);
	// Need uncomment after resolve https://github.com/css-modules/postcss-modules-local-by-default/issues/108
	/*test("escape characters (lowercase)", ".class { content: \"\\f10C\" }", [
		[1, ".class { content: \"\\f10C\" }", ""]
	]);*/
	// Need uncomment after resolve https://github.com/mathiasbynens/cssesc/issues/10
	/*test("escape characters (two)", ".class { content: \"\\F10C \\F10D\" }", [
		[1, ".class { content: \"\\F10C \\F10D\" }", ""]
	]);*/
	testMinimize("minimized simple", ".class { a: b c d; }", [
		[1, ".class{a:b c d}", ""]
	]);
	test("charset directive", "@charset \"UTF-8\";\n .class { a: b c d; }", [
		[1, "@charset \"UTF-8\";\n .class { a: b c d; }", ""]
	]);
	testError("error formatting", ".some {\n invalid css;\n}", function(err) {
		assert.equal(err.message, [
			'Unknown word (2:2)',
			'',
			'  1 | .some {',
			'> 2 |  invalid css;',
			'    |  ^',
			'  3 | }',
			'',
		].join('\n'));
	});
});
<|endoftext|>


<commit_before>"use strict";

// render fractal
(function () {
    let width, height, offsetX, offsetY, renderedX;
    let zoom = 350;
    let iterations = 10 * Math.sqrt(zoom);

    // setup continuous rendering
    let isTiming = false;
    const canvas = document.querySelector('canvas');
    const context = canvas.getContext('2d');
    const render = () => {
        if (renderedX < width) {
            if (!isTiming) {
                console.time('rendering');
                isTiming = true;
            }

            // Chrome 56 cannot optimize compound let assignments
            let x = renderedX;
            renderedX = renderedX + 100;
            // renderedX += 100;

            // render progressively in columns
            for (; x <= renderedX; x++) {
                for (let y = 0; y <= height; y++) {
                    context.fillStyle = colorAtPoint((x - offsetX) / zoom, (y - offsetY) / zoom, iterations);
                    context.fillRect(x, y, 1, 1);
                }
            }
        } else if (isTiming) {
            console.timeEnd('rendering');
            isTiming = false;
        }

        requestAnimationFrame(render);
    };

    // react to resizing
    const resizeHandler = () => {
        canvas.width = width = document.body.clientWidth;
        canvas.height = height = document.body.clientHeight;
        renderedX = 0;
    };
    window.addEventListener('resize', resizeHandler);

    // react to mouse drags
    let downEvent = null;
    canvas.addEventListener('mousedown', event => downEvent = event);
    canvas.addEventListener('mouseup', event => {
        offsetX += event.clientX - downEvent.clientX;
        offsetY += event.clientY - downEvent.clientY;
        downEvent = null;

        renderedX = 0;
    });

    // react to scrolling
    const scrollHandler = event => {
        // there shall be a fixed point under the cursor
        const delta = event.wheelDelta ? event.wheelDelta * 10 : -event.detail * 400;
        const ratio = (zoom + delta) / zoom;
        offsetX = event.clientX - ratio * (event.clientX - offsetX);
        offsetY = event.clientY - ratio * (event.clientY - offsetY);

        // redraw everything
        zoom += delta;
        iterations = 10 * Math.sqrt(zoom);
        renderedX = 0;
    };
    canvas.addEventListener('DOMMouseScroll', scrollHandler);
    canvas.addEventListener('mousewheel', scrollHandler);

    // TODO: trigger initial resizing
    resizeHandler();
    offsetX = width / 2 + 200;
    offsetY = height / 2;
    requestAnimationFrame(render);
})();

function colorAtPoint(x, y, max) {
    // always buffer real part (both calculations need to be simulations)
    let currentRe = 0, currentIm = 0, buffer = 0;
    for (let n = 0; n < max; n++) {
        buffer = currentRe * currentRe - currentIm * currentIm + x;
        currentIm = 2 * currentRe * currentIm + y;
        currentRe = buffer;

        if (currentRe * currentRe + currentIm * currentIm > 4) {
            return 'hsl(' + (n / max * 360) + ', 90%, 50%)';
        }
    }

    return 'black';
}
<commit_msg>Mark current rendering position<commit_after>"use strict";

// render fractal
(function () {
    let width, height, offsetX, offsetY, renderedX;
    let zoom = 350;
    let iterations = 10 * Math.sqrt(zoom);

    // setup continuous rendering
    let isTiming = false;
    const canvas = document.querySelector('canvas');
    const context = canvas.getContext('2d');
    const render = () => {
        if (renderedX < width) {
            if (!isTiming) {
                console.time('rendering');
                isTiming = true;
            }

            // Chrome 56 cannot optimize compound let assignments
            let x = renderedX;
            renderedX = renderedX + 100;
            // renderedX += 100;

            // render progressively in columns
            for (; x <= renderedX; x++) {
                for (let y = 0; y <= height; y++) {
                    context.fillStyle = colorAtPoint((x - offsetX) / zoom, (y - offsetY) / zoom, iterations);
                    context.fillRect(x, y, 1, 1);
                }
            }

            // mark current rendering position
            context.fillStyle = 'white';
            context.fillRect(x + 1, 0, 1, height);
        } else if (isTiming) {
            console.timeEnd('rendering');
            isTiming = false;
        }

        requestAnimationFrame(render);
    };

    // react to resizing
    const resizeHandler = () => {
        canvas.width = width = document.body.clientWidth;
        canvas.height = height = document.body.clientHeight;
        renderedX = 0;
    };
    window.addEventListener('resize', resizeHandler);

    // react to mouse drags
    let downEvent = null;
    canvas.addEventListener('mousedown', event => downEvent = event);
    canvas.addEventListener('mouseup', event => {
        offsetX += event.clientX - downEvent.clientX;
        offsetY += event.clientY - downEvent.clientY;
        downEvent = null;

        renderedX = 0;
    });

    // react to scrolling
    const scrollHandler = event => {
        // there shall be a fixed point under the cursor
        const delta = event.wheelDelta ? event.wheelDelta * 10 : -event.detail * 400;
        const ratio = (zoom + delta) / zoom;
        offsetX = event.clientX - ratio * (event.clientX - offsetX);
        offsetY = event.clientY - ratio * (event.clientY - offsetY);

        // redraw everything
        zoom += delta;
        iterations = 10 * Math.sqrt(zoom);
        renderedX = 0;
    };
    canvas.addEventListener('DOMMouseScroll', scrollHandler);
    canvas.addEventListener('mousewheel', scrollHandler);

    // TODO: trigger initial resizing
    resizeHandler();
    offsetX = width / 2 + 200;
    offsetY = height / 2;
    requestAnimationFrame(render);
})();

function colorAtPoint(x, y, max) {
    // always buffer real part (both calculations need to be simulations)
    let currentRe = 0, currentIm = 0, buffer = 0;
    for (let n = 0; n < max; n++) {
        buffer = currentRe * currentRe - currentIm * currentIm + x;
        currentIm = 2 * currentRe * currentIm + y;
        currentRe = buffer;

        if (currentRe * currentRe + currentIm * currentIm > 4) {
            return 'hsl(' + (n / max * 360) + ', 90%, 50%)';
        }
    }

    return 'black';
}
<|endoftext|>


<commit_before>"use strict";

var assert = require("@sinonjs/referee").assert;
var Sandbox = require("../lib/sinon/sandbox");
var proxyquire = require("proxyquire");

describe("sinon module", function() {
    var sinon, fakeNise;

    before(function() {
        if (typeof Promise !== "function") {
            this.skip();
        }
    });

    beforeEach(function() {
        fakeNise = {
            fakeServer: {
                create: function() {
                    return "47c86a4c-6b48-4748-bb8c-d853f999720c";
                }
            },
            fakeServerWithClock: {
                create: function() {
                    return "e69974f8-4568-48d1-a5e9-2b511a59c14b";
                }
            },
            fakeXhr: {
                xhr: "958e8996-0cc3-4136-8a0e-6a120f5311bc",
                FakeXMLHttpRequest: "6adbf569-f6d7-4b86-be22-38340ae0f8c8",
                useFakeXMLHttpRequest: "ba8bd609-c921-4a62-a1b9-49336bd426a4"
            }
        };
        sinon = proxyquire("../lib/sinon", {
            nise: fakeNise
        });
    });

    describe("deprecated methods", function() {
        it(".sandbox.create", function() {
            // use full sinon for this test as it compares sinon instance
            // proxyquire changes the instance, so `actual instanceof Sandbox` returns `false`
            // see https://github.com/sinonjs/sinon/pull/1586#issuecomment-354457231
            sinon = require("../lib/sinon");

            // eslint-disable-next-line max-len
            var expectedMessage =
                "`sandbox.create()` is deprecated. Use default sandbox at `sinon.sandbox` or create new sandboxes with `sinon.createSandbox()`";
            var infoStub = sinon.stub(console, "info");
            var actual = sinon.sandbox.create();

            sinon.assert.calledWith(infoStub, expectedMessage);

            assert.hasPrototype(actual, Sandbox.prototype);

            infoStub.restore();
        });
    });

    describe("exports", function() {
        describe("default sandbox", function() {
            it("should be an instance of Sandbox", function() {
                // use full sinon for this test as it compares sinon instance
                // proxyquire changes the instance, so `actual instanceof Sandbox` returns `false`
                // see https://github.com/sinonjs/sinon/pull/1586#issuecomment-354457231
                sinon = require("../lib/sinon");

                assert.hasPrototype(sinon, Sandbox.prototype);
            });
        });

        describe("createSandbox", function() {
            it("should be a unary Function named 'createSandbox'", function() {
                assert.isFunction(sinon.createSandbox);
                assert.equals(sinon.createSandbox.length, 1);
                assert.equals(sinon.createSandbox.name, "createSandbox");
            });
        });

        describe("fakeServer", function() {
            it("should be the fakeServer export from nise", function() {
                assert.same(sinon.fakeServer, fakeNise.fakeServer);
            });
        });

        describe("createFakeServer", function() {
            it("should be fakeServer.create from nise", function() {
                assert.equals(sinon.createFakeServer(), fakeNise.fakeServer.create());
            });
        });

        describe("fakeServerWithClock", function() {
            it("should be the fakeServerWithClock export from nise", function() {
                assert.same(sinon.fakeServerWithClock, fakeNise.fakeServerWithClock);
            });
        });

        describe("createFakeServerWithClock", function() {
            it("should be fakeServerWithClock.create from nise", function() {
                assert.equals(sinon.createFakeServerWithClock(), fakeNise.fakeServerWithClock.create());
            });
        });

        describe("xhr", function() {
            it("should be the fakeXhr.xhr export from nise", function() {
                assert.equals(sinon.xhr, fakeNise.fakeXhr.xhr);
            });
        });

        describe("FakeXMLHttpRequest", function() {
            it("should be the fakeXhr.FakeXMLHttpRequest export from nise", function() {
                assert.equals(sinon.FakeXMLHttpRequest, fakeNise.fakeXhr.FakeXMLHttpRequest);
            });
        });

        describe("useFakeXMLHttpRequest", function() {
            var nise;

            beforeEach(function() {
                // use full sinon for this test as it compares sinon instance
                // proxyquire changes the instance, so `actual instanceof Sandbox` returns `false`
                // see https://github.com/sinonjs/sinon/pull/1586#issuecomment-354457231
                sinon = require("../lib/sinon");

                nise = require("nise");
            });

            afterEach(function() {
                nise.fakeXhr.useFakeXMLHttpRequest.restore();
            });

            it("should be the fakeXhr.useFakeXMLHttpRequest export from nise", function() {
                sinon.spy(nise.fakeXhr, "useFakeXMLHttpRequest");
                sinon.useFakeXMLHttpRequest();
                assert.isTrue(nise.fakeXhr.useFakeXMLHttpRequest.called);
            });
        });
    });
});
<commit_msg>Fix test failing in IE 11<commit_after>"use strict";

var assert = require("@sinonjs/referee").assert;
var functionName = require("@sinonjs/commons").functionName;
var Sandbox = require("../lib/sinon/sandbox");
var proxyquire = require("proxyquire");

describe("sinon module", function() {
    var sinon, fakeNise;

    before(function() {
        if (typeof Promise !== "function") {
            this.skip();
        }
    });

    beforeEach(function() {
        fakeNise = {
            fakeServer: {
                create: function() {
                    return "47c86a4c-6b48-4748-bb8c-d853f999720c";
                }
            },
            fakeServerWithClock: {
                create: function() {
                    return "e69974f8-4568-48d1-a5e9-2b511a59c14b";
                }
            },
            fakeXhr: {
                xhr: "958e8996-0cc3-4136-8a0e-6a120f5311bc",
                FakeXMLHttpRequest: "6adbf569-f6d7-4b86-be22-38340ae0f8c8",
                useFakeXMLHttpRequest: "ba8bd609-c921-4a62-a1b9-49336bd426a4"
            }
        };
        sinon = proxyquire("../lib/sinon", {
            nise: fakeNise
        });
    });

    describe("deprecated methods", function() {
        it(".sandbox.create", function() {
            // use full sinon for this test as it compares sinon instance
            // proxyquire changes the instance, so `actual instanceof Sandbox` returns `false`
            // see https://github.com/sinonjs/sinon/pull/1586#issuecomment-354457231
            sinon = require("../lib/sinon");

            // eslint-disable-next-line max-len
            var expectedMessage =
                "`sandbox.create()` is deprecated. Use default sandbox at `sinon.sandbox` or create new sandboxes with `sinon.createSandbox()`";
            var infoStub = sinon.stub(console, "info");
            var actual = sinon.sandbox.create();

            sinon.assert.calledWith(infoStub, expectedMessage);

            assert.hasPrototype(actual, Sandbox.prototype);

            infoStub.restore();
        });
    });

    describe("exports", function() {
        describe("default sandbox", function() {
            it("should be an instance of Sandbox", function() {
                // use full sinon for this test as it compares sinon instance
                // proxyquire changes the instance, so `actual instanceof Sandbox` returns `false`
                // see https://github.com/sinonjs/sinon/pull/1586#issuecomment-354457231
                sinon = require("../lib/sinon");

                assert.hasPrototype(sinon, Sandbox.prototype);
            });
        });

        describe("createSandbox", function() {
            it("should be a unary Function named 'createSandbox'", function() {
                assert.isFunction(sinon.createSandbox);
                assert.equals(sinon.createSandbox.length, 1);
                // Use helper because IE 11 doesn't support the `name` property:
                assert.equals(functionName(sinon.createSandbox), "createSandbox");
            });
        });

        describe("fakeServer", function() {
            it("should be the fakeServer export from nise", function() {
                assert.same(sinon.fakeServer, fakeNise.fakeServer);
            });
        });

        describe("createFakeServer", function() {
            it("should be fakeServer.create from nise", function() {
                assert.equals(sinon.createFakeServer(), fakeNise.fakeServer.create());
            });
        });

        describe("fakeServerWithClock", function() {
            it("should be the fakeServerWithClock export from nise", function() {
                assert.same(sinon.fakeServerWithClock, fakeNise.fakeServerWithClock);
            });
        });

        describe("createFakeServerWithClock", function() {
            it("should be fakeServerWithClock.create from nise", function() {
                assert.equals(sinon.createFakeServerWithClock(), fakeNise.fakeServerWithClock.create());
            });
        });

        describe("xhr", function() {
            it("should be the fakeXhr.xhr export from nise", function() {
                assert.equals(sinon.xhr, fakeNise.fakeXhr.xhr);
            });
        });

        describe("FakeXMLHttpRequest", function() {
            it("should be the fakeXhr.FakeXMLHttpRequest export from nise", function() {
                assert.equals(sinon.FakeXMLHttpRequest, fakeNise.fakeXhr.FakeXMLHttpRequest);
            });
        });

        describe("useFakeXMLHttpRequest", function() {
            var nise;

            beforeEach(function() {
                // use full sinon for this test as it compares sinon instance
                // proxyquire changes the instance, so `actual instanceof Sandbox` returns `false`
                // see https://github.com/sinonjs/sinon/pull/1586#issuecomment-354457231
                sinon = require("../lib/sinon");

                nise = require("nise");
            });

            afterEach(function() {
                nise.fakeXhr.useFakeXMLHttpRequest.restore();
            });

            it("should be the fakeXhr.useFakeXMLHttpRequest export from nise", function() {
                sinon.spy(nise.fakeXhr, "useFakeXMLHttpRequest");
                sinon.useFakeXMLHttpRequest();
                assert.isTrue(nise.fakeXhr.useFakeXMLHttpRequest.called);
            });
        });
    });
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import SortableTree, { getTreeFromFlatData, changeNodeAtPath, addNodeUnderParent, removeNodeAtPath } from 'react-sortable-tree';
import EditModal from './EditModal.js';
import AddModal from './AddModal.js';
import DeleteModal from './DeleteModal.js';
import UUID from 'uuid';

export default class Tree extends Component {
    constructor(props) {
        super(props);

        var notebookTree = [];

        //returns the id of the parent node of notebook.subnotes[nodeIndex]
        function getParentKey(notebook, nodeIndex) {
          var currentID = Object.keys(notebook.subnotes)[nodeIndex];

          if (currentID === notebook.rootSubnote) { //return 0 for parentID of root node
            return 0;
          }

          for (var key in notebook.subnotes) { //go through each subnote
            if (!notebook.subnotes.hasOwnProperty(key)) continue;
            var node = notebook.subnotes[key];
            if ("subnotes" in node) { //if node has children
              for (var i = 0; i < node.subnotes.length; i++) { //search through each child
                if (currentID === node.subnotes[i]) { //if we find a match, return that id
                  return key;
                }
              }
            }
          }
          return notebook.rootSubnote; //if no match was found, we know the parent is the root subnote
        }

        //build notebookTree from notebook
        for (var i = 0; i < Object.keys(this.props.notebook.subnotes).length; i++) {
          var currentID = Object.keys(this.props.notebook.subnotes)[i];
          notebookTree.push({ id: currentID,
                              parentId: getParentKey(this.props.notebook, i),
                              title: this.props.notebook.subnotes[currentID].subtopic,
                              subtitle: this.props.notebook.subnotes[currentID].note,
                              tags: this.props.notebook.subnotes[currentID].tags,
                              flashcards: this.props.notebook.subnotes[currentID].flashcards
                            });
        }

        this.state = {
            treeData: getTreeFromFlatData({flatData: notebookTree})
        };

        //recursive function that adds all descendants of parentNode to notebookFlat
        function addChildrenToFlat(parentNode, notebookFlat) {
          if ("children" in parentNode) { //if the node has child nodes
            var id = parentNode.id;
            notebookFlat.subnotes[id].subnotes = [];
            for (var i = 0; i < parentNode.children.length; i++) {
              //add child IDs to subnotes array of current subnote
              notebookFlat.subnotes[id].subnotes.push(parentNode.children[i].id);
              //add children to notebook
              var childID = parentNode.children[i].id;
              notebookFlat.subnotes[childID] = {};
              notebookFlat.subnotes[childID].subtopic = parentNode.children[i].title;
              notebookFlat.subnotes[childID].note = parentNode.children[i].subtitle;
              notebookFlat.subnotes[childID].tags = parentNode.children[i].tags;
              notebookFlat.subnotes[childID].flashcards = parentNode.children[i].flashcards;
              addChildrenToFlat(parentNode.children[i], notebookFlat);
            }
          }
        }

        //converts treeData structure to notebook format for exporting/saving to google drive
        function saveTreeData(treeData) {
          var notebookFlat = {};
          notebookFlat.subnotes = {};
          //root subnote is the top object of treeData (if there is one)
          if (Object.keys(treeData).length === 1) {
            notebookFlat.rootSubnote = treeData[0].id;
          }
          //if there are multiple "roots", set rootSubnote to 0
          else {
            notebookFlat.rootSubnote = 0;
          }

          for (var i = 0; i < Object.keys(treeData).length; i++) {
            var id = treeData[i].id;
            notebookFlat.subnotes[id] = {};
            notebookFlat.subnotes[id].subtopic = treeData[i].title;
            notebookFlat.subnotes[id].note = treeData[i].subtitle;
            notebookFlat.subnotes[id].tags = treeData[i].tags;
            notebookFlat.subnotes[id].flashcards = treeData[i].flashcards;
            addChildrenToFlat(treeData[i], notebookFlat); //add info from all children (and children of children, etc)
          }
          return notebookFlat;
        }
        this.saveTreeData = saveTreeData;

        //replaces a given subnote with values from newValues (id and children not changed)
        function replaceSubnote(rowInfo, newValues) {

          //function to pass to changeNodeAtPath
          function getNodeKey({node, treeIndex}) {
            return treeIndex;
          }

          //update node information
          rowInfo.node.title = newValues.subtopic;
          rowInfo.node.subtitle = newValues.note;
          rowInfo.node.tags = newValues.tags;

          //return the updated treeData
          return changeNodeAtPath({ treeData: this.state.treeData, path: rowInfo.path, newNode: rowInfo.node, getNodeKey: getNodeKey });
        }
        this.replaceSubnote = replaceSubnote.bind(this);

        //adds a new subnote under a given parent subnote
        function addSubnote(rowInfo, newValues) {
          //function to pass to addNodeUnderParent
          function getNodeKey({node, treeIndex}) {
            return treeIndex;
          }

          //create new node, populate with values from newValues
          var newNode = {};
          newNode.id = UUID.v4();
          newNode.parentId = rowInfo.node.id;
          newNode.title = newValues.subtopic;
          newNode.subtitle = newValues.note;
          newNode.tags = newValues.tags;
          newNode.flashcards = [];
          //add node in treeData
          var result = addNodeUnderParent({ treeData: this.state.treeData, newNode: newNode, parentKey: rowInfo.treeIndex, getNodeKey: getNodeKey, expandParent: true });
          return result;
        }
        this.addSubnote = addSubnote.bind(this);

        //deletes a given subnote
        function deleteSubnote(rowInfo) {

          //function to pass to removeNodeAtPath
          function getNodeKey({node, treeIndex}) {
            return treeIndex;
          }

          //delete node and get updated treeData
          var result = removeNodeAtPath({ treeData: this.state.treeData, path: rowInfo.path, getNodeKey: getNodeKey });
          return result;
        }
        this.deleteSubnote = deleteSubnote.bind(this);

        //updates the state of Tree and updates the notebook in google drive via this.props.updateNotebook
        function updateTreeDataState(newTreeData) {
          //update state
          this.setState({
            treeData: newTreeData
          });
          //send updated notebook to updateNotebook to save to google drive
          this.props.updateNotebook(this.saveTreeData(newTreeData));
        }
        this.updateTreeDataState = updateTreeDataState.bind(this);

    } //end of constructor

    //Parent-->Child-->Grandchildren
    //Tree-->SortableTree-->edit/add/delete components
    render() {
      //console.log("treeData:");
      //console.log(this.state.treeData);
      //console.log("treeData back to notebook:")
      //console.log(this.saveTreeData(this.state.treeData));
        return (

                <SortableTree
                    treeData={this.state.treeData}
                    onChange={treeData => this.setState({ treeData })}
                    onMoveNode={function() {console.log("node moved");}}
                    generateNodeProps={rowInfo => ({
                                buttons: [
                                    <EditModal
                                      rowInfo={rowInfo}
                                      replaceSubnote={this.replaceSubnote}
                                      treeData={this.state.treeData}
                                      updateTreeDataState={this.updateTreeDataState}
                                    />,
                                    <AddModal
                                      rowInfo={rowInfo}
                                      addSubnote={this.addSubnote}
                                      treeData={this.state.treeData}
                                      updateTreeDataState={this.updateTreeDataState}
                                    />,
                                    <DeleteModal
                                      rowInfo={rowInfo}
                                      deleteSubnote={this.deleteSubnote}
                                      treeData={this.state.treeData}
                                      updateTreeDataState={this.updateTreeDataState}
                                    />,
                                ],
                    })}
                />

        );
    }
}
<commit_msg>moving nodes in the tree now causes write to google drive<commit_after>import React, { Component } from 'react';
import SortableTree, { getTreeFromFlatData, changeNodeAtPath, addNodeUnderParent, removeNodeAtPath } from 'react-sortable-tree';
import EditModal from './EditModal.js';
import AddModal from './AddModal.js';
import DeleteModal from './DeleteModal.js';
import UUID from 'uuid';

export default class Tree extends Component {
    constructor(props) {
        super(props);

        var notebookTree = [];

        //returns the id of the parent node of notebook.subnotes[nodeIndex]
        function getParentKey(notebook, nodeIndex) {
          var currentID = Object.keys(notebook.subnotes)[nodeIndex];

          if (currentID === notebook.rootSubnote) { //return 0 for parentID of root node
            return 0;
          }

          for (var key in notebook.subnotes) { //go through each subnote
            if (!notebook.subnotes.hasOwnProperty(key)) continue;
            var node = notebook.subnotes[key];
            if ("subnotes" in node) { //if node has children
              for (var i = 0; i < node.subnotes.length; i++) { //search through each child
                if (currentID === node.subnotes[i]) { //if we find a match, return that id
                  return key;
                }
              }
            }
          }
          return notebook.rootSubnote; //if no match was found, we know the parent is the root subnote
        }

        //build notebookTree from notebook
        for (var i = 0; i < Object.keys(this.props.notebook.subnotes).length; i++) {
          var currentID = Object.keys(this.props.notebook.subnotes)[i];
          notebookTree.push({ id: currentID,
                              parentId: getParentKey(this.props.notebook, i),
                              title: this.props.notebook.subnotes[currentID].subtopic,
                              subtitle: this.props.notebook.subnotes[currentID].note,
                              tags: this.props.notebook.subnotes[currentID].tags,
                              flashcards: this.props.notebook.subnotes[currentID].flashcards
                            });
        }

        this.state = {
            treeData: getTreeFromFlatData({flatData: notebookTree})
        };

        //recursive function that adds all descendants of parentNode to notebookFlat
        function addChildrenToFlat(parentNode, notebookFlat) {
          if ("children" in parentNode) { //if the node has child nodes
            var id = parentNode.id;
            notebookFlat.subnotes[id].subnotes = [];
            for (var i = 0; i < parentNode.children.length; i++) {
              //add child IDs to subnotes array of current subnote
              notebookFlat.subnotes[id].subnotes.push(parentNode.children[i].id);
              //add children to notebook
              var childID = parentNode.children[i].id;
              notebookFlat.subnotes[childID] = {};
              notebookFlat.subnotes[childID].subtopic = parentNode.children[i].title;
              notebookFlat.subnotes[childID].note = parentNode.children[i].subtitle;
              notebookFlat.subnotes[childID].tags = parentNode.children[i].tags;
              notebookFlat.subnotes[childID].flashcards = parentNode.children[i].flashcards;
              addChildrenToFlat(parentNode.children[i], notebookFlat);
            }
          }
        }

        //converts treeData structure to notebook format for exporting/saving to google drive
        function saveTreeData(treeData) {
          var notebookFlat = {};
          notebookFlat.subnotes = {};
          //root subnote is the top object of treeData (if there is one)
          if (Object.keys(treeData).length === 1) {
            notebookFlat.rootSubnote = treeData[0].id;
          }
          //if there are multiple "roots", set rootSubnote to 0
          else {
            notebookFlat.rootSubnote = 0;
          }

          for (var i = 0; i < Object.keys(treeData).length; i++) {
            var id = treeData[i].id;
            notebookFlat.subnotes[id] = {};
            notebookFlat.subnotes[id].subtopic = treeData[i].title;
            notebookFlat.subnotes[id].note = treeData[i].subtitle;
            notebookFlat.subnotes[id].tags = treeData[i].tags;
            notebookFlat.subnotes[id].flashcards = treeData[i].flashcards;
            addChildrenToFlat(treeData[i], notebookFlat); //add info from all children (and children of children, etc)
          }
          return notebookFlat;
        }
        this.saveTreeData = saveTreeData;

        //replaces a given subnote with values from newValues (id and children not changed)
        function replaceSubnote(rowInfo, newValues) {

          //function to pass to changeNodeAtPath
          function getNodeKey({node, treeIndex}) {
            return treeIndex;
          }

          //update node information
          rowInfo.node.title = newValues.subtopic;
          rowInfo.node.subtitle = newValues.note;
          rowInfo.node.tags = newValues.tags;

          //return the updated treeData
          return changeNodeAtPath({ treeData: this.state.treeData, path: rowInfo.path, newNode: rowInfo.node, getNodeKey: getNodeKey });
        }
        this.replaceSubnote = replaceSubnote.bind(this);

        //adds a new subnote under a given parent subnote
        function addSubnote(rowInfo, newValues) {
          //function to pass to addNodeUnderParent
          function getNodeKey({node, treeIndex}) {
            return treeIndex;
          }

          //create new node, populate with values from newValues
          var newNode = {};
          newNode.id = UUID.v4();
          newNode.parentId = rowInfo.node.id;
          newNode.title = newValues.subtopic;
          newNode.subtitle = newValues.note;
          newNode.tags = newValues.tags;
          newNode.flashcards = [];
          //add node in treeData
          var result = addNodeUnderParent({ treeData: this.state.treeData, newNode: newNode, parentKey: rowInfo.treeIndex, getNodeKey: getNodeKey, expandParent: true });
          return result;
        }
        this.addSubnote = addSubnote.bind(this);

        //deletes a given subnote
        function deleteSubnote(rowInfo) {

          //function to pass to removeNodeAtPath
          function getNodeKey({node, treeIndex}) {
            return treeIndex;
          }

          //delete node and get updated treeData
          var result = removeNodeAtPath({ treeData: this.state.treeData, path: rowInfo.path, getNodeKey: getNodeKey });
          return result;
        }
        this.deleteSubnote = deleteSubnote.bind(this);

        //updates the state of Tree and updates the notebook in google drive via this.props.updateNotebook
        function updateTreeDataState(newTreeData) {
          //update state
          this.setState({
            treeData: newTreeData
          });
          //send updated notebook to updateNotebook to save to google drive
          this.props.updateNotebook(this.saveTreeData(newTreeData));
        }
        this.updateTreeDataState = updateTreeDataState.bind(this);

    } //end of constructor

    //Parent-->Child-->Grandchildren
    //Tree-->SortableTree-->edit/add/delete components
    render() {
      //console.log("treeData:");
      //console.log(this.state.treeData);
      //console.log("treeData back to notebook:")
      //console.log(this.saveTreeData(this.state.treeData));
        return (

                <SortableTree
                    treeData={this.state.treeData}
                    onChange={treeData => this.setState({ treeData })}
                    onMoveNode={() => this.props.updateNotebook(this.saveTreeData(this.state.treeData))}
                    generateNodeProps={rowInfo => ({
                                buttons: [
                                    <EditModal
                                      rowInfo={rowInfo}
                                      replaceSubnote={this.replaceSubnote}
                                      treeData={this.state.treeData}
                                      updateTreeDataState={this.updateTreeDataState}
                                    />,
                                    <AddModal
                                      rowInfo={rowInfo}
                                      addSubnote={this.addSubnote}
                                      treeData={this.state.treeData}
                                      updateTreeDataState={this.updateTreeDataState}
                                    />,
                                    <DeleteModal
                                      rowInfo={rowInfo}
                                      deleteSubnote={this.deleteSubnote}
                                      treeData={this.state.treeData}
                                      updateTreeDataState={this.updateTreeDataState}
                                    />,
                                ],
                    })}
                />

        );
    }
}
<|endoftext|>


<commit_before>
const hello = function() {

  var socket = io('http://co-board.herokuapp.com');
  var canvas = document.getElementsByClassName('whiteboard')[0];
  var colors = document.getElementsByClassName('color');
  var context = canvas.getContext('2d');

  var current = {
    color: 'black',
    width: 2
  };
  var drawing = false;

  canvas.addEventListener('mousedown', onMouseDown, false);
  canvas.addEventListener('mouseup', onMouseUp, false);
  canvas.addEventListener('mouseout', onMouseUp, false);
  canvas.addEventListener('mousemove', throttle(onMouseMove, 10), false);

  canvas.addEventListener('touchstart', onMouseDown, false);
  canvas.addEventListener('touchend', onMouseUp, false);
  canvas.addEventListener('touchmove', onMouseMove, false);

  for (var i = 0; i < colors.length; i++){
    colors[i].addEventListener('click', onSettingUpdate, false);
  }

  socket.on('drawing', onDrawingEvent);

  window.addEventListener('resize', onResize, false);
  onResize();

  function getX(e) {
    var touchX = null;
    if (e.touches) {
      if (e.touches.length == 1) { // Only deal with one finger
          var touch = e.touches[0]; // Get the information for finger #1
          touchX=touch.pageX-touch.target.offsetLeft;
          touchY=touch.pageY-touch.target.offsetTop;
      }
    };
    return e.clientX || e.targetTouches[0].clientX;
  }

  function getY(e) {
    var touchY = null;
    if (e.touches) {
      if (e.touches.length == 1) { // Only deal with one finger
          var touch = e.touches[0]; // Get the information for finger #1
          touchX=touch.pageX-touch.target.offsetLeft;
          touchY=touch.pageY-touch.target.offsetTop;
      }
    };
    return e.clientY || e.targetTouches[0].clientY;
  }

  function drawLine(x0, y0, x1, y1, color, width, emit){
    context.beginPath();
    context.moveTo(x0, y0);
    context.lineTo(x1, y1);
    context.strokeStyle = color;
    context.lineWidth = width;
    context.lineCap = 'round';
    context.lineJoin = 'round';
    context.stroke();
    context.closePath();

    if (!emit) { return; }
    var w = canvas.width;
    var h = canvas.height;

    socket.emit('drawing', {
      x0: x0 / w,
      y0: y0 / h,
      x1: x1 / w,
      y1: y1 / h,
      color: color,
      width: width
    });
  }

  function onMouseDown(e){
    drawing = true;
    current.x = getX(e);
    current.y = getY(e);
  }

  function onMouseUp(e){
    if (!drawing && !e.touches) { return; }
    drawing = false;
    drawLine(current.x, current.y, getX(e), getY(e), current.color, current.width, true);
  }

  function onMouseMove(e){
    if (!drawing && !e.touches) { return; }
    drawLine(current.x, current.y, getX(e), getY(e), current.color, current.width, true);
    current.x = getX(e);
    current.y = getY(e);
  }

  function onSettingUpdate(e){
    if(e.target.className.split(' ')[1] === 'eraser'){
      current.color = 'white';
      current.width = 15;
    }else{
      current.color = e.target.className.split(' ')[1];
      current.width = 2;
    }
  }

  // limit the number of events per second
  function throttle(callback, delay) {
    var previousCall = new Date().getTime();
    return function() {
      var time = new Date().getTime();

      if ((time - previousCall) >= delay) {
        previousCall = time;
        callback.apply(null, arguments);
      }
    };
  }

  function onDrawingEvent(data){
    var w = canvas.width;
    var h = canvas.height;
    drawLine(data.x0 * w, data.y0 * h, data.x1 * w, data.y1 * h, data.color, data.width);
  }

  // make the canvas fill its parent
  function onResize() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
  }

};

hello();
<commit_msg>Add resize.<commit_after>
const hello = function() {

  var socket = io('http://co-board.herokuapp.com');
  var canvas = document.getElementsByClassName('whiteboard')[0];
  var colors = document.getElementsByClassName('color');
  var context = canvas.getContext('2d');

  var current = {
    color: 'black',
    width: 2
  };
  var drawing = false;

  canvas.addEventListener('mousedown', onMouseDown, false);
  canvas.addEventListener('mouseup', onMouseUp, false);
  canvas.addEventListener('mouseout', onMouseUp, false);
  canvas.addEventListener('mousemove', throttle(onMouseMove, 10), false);

  canvas.addEventListener('touchstart', onMouseDown, false);
  canvas.addEventListener('touchend', onMouseUp, false);
  canvas.addEventListener('touchmove', onMouseMove, false);

  for (var i = 0; i < colors.length; i++){
    colors[i].addEventListener('click', onSettingUpdate, false);
  }

  socket.on('drawing', onDrawingEvent);

  window.addEventListener('resize', onResize, false);
  onResize();

  function getX(e) {
    var touchX = null;
    if (e.touches) {
      if (e.touches.length == 1) { // Only deal with one finger
          var touch = e.touches[0]; // Get the information for finger #1
          touchX=touch.pageX-touch.target.offsetLeft;
          touchY=touch.pageY-touch.target.offsetTop;
      }
    };
    return e.clientX || e.targetTouches[0].clientX;
  }

  function getY(e) {
    var touchY = null;
    if (e.touches) {
      if (e.touches.length == 1) { // Only deal with one finger
          var touch = e.touches[0]; // Get the information for finger #1
          touchX=touch.pageX-touch.target.offsetLeft;
          touchY=touch.pageY-touch.target.offsetTop;
      }
    };
    return e.clientY || e.targetTouches[0].clientY;
  }

  function drawLine(x0, y0, x1, y1, color, width, emit){
    context.beginPath();
    context.moveTo(x0, y0);
    context.lineTo(x1, y1);
    context.strokeStyle = color;
    context.lineWidth = width;
    context.lineCap = 'round';
    context.lineJoin = 'round';
    context.stroke();
    context.closePath();

    if (!emit) { return; }
    var w = canvas.width;
    var h = canvas.height;

    socket.emit('drawing', {
      x0: x0 / w,
      y0: y0 / h,
      x1: x1 / w,
      y1: y1 / h,
      color: color,
      width: width
    });
  }

  function onMouseDown(e){
    drawing = true;
    current.x = getX(e);
    current.y = getY(e);
  }

  function onMouseUp(e){
    if (!drawing && !e.touches) { return; }
    drawing = false;
    drawLine(current.x, current.y, getX(e), getY(e), current.color, current.width, true);
  }

  function onMouseMove(e){
    if (!drawing && !e.touches) { return; }
    drawLine(current.x, current.y, getX(e), getY(e), current.color, current.width, true);
    current.x = getX(e);
    current.y = getY(e);
  }

  function onSettingUpdate(e){
    if(e.target.className.split(' ')[1] === 'eraser'){
      current.color = 'white';
      current.width = 15;
    }else{
      current.color = e.target.className.split(' ')[1];
      current.width = 2;
    }
  }

  // limit the number of events per second
  function throttle(callback, delay) {
    var previousCall = new Date().getTime();
    return function() {
      var time = new Date().getTime();

      if ((time - previousCall) >= delay) {
        previousCall = time;
        callback.apply(null, arguments);
      }
    };
  }

  function onDrawingEvent(data){
    var w = canvas.width;
    var h = canvas.height;
    drawLine(data.x0 * w, data.y0 * h, data.x1 * w, data.y1 * h, data.color, data.width);
  }

  // make the canvas fill its parent
  function onResize() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
  }

  setTimeout(onResize , 1000);

};

hello();
<|endoftext|>