<commit_before>var Operator = new function() {
	var operators = {
		add: '+', subtract: '-', multiply: '*', divide: '/', equals: '==',
		modulo: '%'
	};
	var operatorNames = {
		add: 'Addition', subtract: 'Subtraction', multiply: 'Multiplication',
		divide: 'Division', equals: 'Comparison', modulo: 'Modulo'
	};

	var operatorClasses = {
		Point: true,
		Size: true
	};

	return {
		isOperator: function(symbol) {
			// As a convention, only add non static bean properties to
			// the documentation. static properties are all supposed to
			// be uppercae and constants.
			if (symbol.operator == 'none')
				print(!(symbol.operator && symbol.operator != 'none'));
			return symbol.params.length == 1 && !symbol.isStatic && (
					/^(add|subtract|multiply|divide|modulo)(\^[0-9])*$/.test(symbol.name)
					&& (symbol.operator != 'none')
				) || ( // equals
					symbol.name == 'equals'
					&& symbol.returns.length && symbol.returns[0].type == 'boolean'
				);
		},

		getOperator: function(symbol) {
			return operators[symbol.name.replace(/\^[0-9]$/,'')];
		}
	}
}

var Helpers = {
	getSymbolId: function(symbol) {
		var id = [symbol.name.toLowerCase().replace(/[\^][0-9]/g, '')];
		if (symbol.params) {
			for (var i = 0, l = symbol.params.length; i < l; i++) {
				var param = symbol.params[i];
				if (!param.isOptional)
					id.push(param.name);
			}
		}
		return id.join('-');
	}
};

var templates;
/** Called automatically by JsDoc Toolkit. */
function publish(symbolSet) {
	publish.conf = {  // trailing slash expected for dirs
		ext:		 ".html",
		outDir:	  JSDOC.opt.d || SYS.pwd+"../out/jsdoc/",
		templatesDir: JSDOC.opt.t || SYS.pwd+"../templates/jsdoc/",
		symbolsDir:  "symbols/",
		srcDir:	  "symbols/src/"
	};

	templates = {
		_class: new JSDOC.JsPlate(publish.conf.templatesDir + "class.tmpl"),
		method: new JSDOC.JsPlate(publish.conf.templatesDir + "method.tmpl"),
		property: new JSDOC.JsPlate(publish.conf.templatesDir + "property.tmpl"),
		parameters: new JSDOC.JsPlate(publish.conf.templatesDir + "parameters.tmpl"),
		operators: new JSDOC.JsPlate(publish.conf.templatesDir + "operators.tmpl"),
		examples: new JSDOC.JsPlate(publish.conf.templatesDir + "examples.tmpl")
	};

	// is source output is suppressed, just display the links to the source file
	if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) {
		Link.prototype._makeSrcLink = function(srcFilePath) {
			return "<"+srcFilePath+">";
		}
	}

	// Copy over the static files
	copyDirectory(
		new java.io.File(publish.conf.templatesDir + 'resources/'),
		new java.io.File(publish.conf.outDir + 'resources/')
	);

	// used to allow Link to check the details of things being linked to
	Link.symbolSet = symbolSet;

	// create the required templates
	try {
		var classTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"class.tmpl");
		var classesTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl");
	}
	catch(e) {
		print("Couldn't create the required templates: "+e);
		quit();
	}

	// some ustility filters
	function hasNoParent($) {return ($.memberOf == "")}
	function isaFile($) {return ($.is("FILE"))}
	function isaClass($) {return ($.is("CONSTRUCTOR") || $.isNamespace)}

	// get an array version of the symbolset, useful for filtering
	var symbols = symbolSet.toArray();

	// create the hilited source code files
	var files = JSDOC.opt.srcFiles;
	 	for (var i = 0, l = files.length; i < l; i++) {
	 		var file = files[i];
	 		var srcDir = publish.conf.outDir + "symbols/src/";
		makeSrcFile(file, srcDir);
	 	}

 	// get a list of all the classes in the symbolset
 	var classes = symbols.filter(isaClass).sort(makeSortby("alias"));

	// create a filemap in which outfiles must be to be named uniquely, ignoring case
	if (JSDOC.opt.u) {
		var filemapCounts = {};
		Link.filemap = {};
		for (var i = 0, l = classes.length; i < l; i++) {
			var lcAlias = classes[i].alias.toLowerCase();

			if (!filemapCounts[lcAlias]) filemapCounts[lcAlias] = 1;
			else filemapCounts[lcAlias]++;

			Link.filemap[classes[i].alias] =
				(filemapCounts[lcAlias] > 1)?
				lcAlias+"_"+filemapCounts[lcAlias] : lcAlias;
		}
	}

	// create a class index, displayed in the left-hand column of every class page
	Link.base = "../";
 	publish.classesIndex = classesTemplate.process(classes); // kept in memory

	// create each of the class pages
	for (var i = 0, l = classes.length; i < l; i++) {
		var symbol = classes[i];

		symbol.events = symbol.getEvents();   // 1 order matters
		symbol.methods = symbol.getMethods(); // 2
		for (var j = 0; j < symbol.methods.length; j++) {
			var method = symbol.methods[j];
			method.isOperator = Operator.isOperator(method);
		}

		Link.currentSymbol= symbol;
		var output = "";
		output = classTemplate.process(symbol);

		IO.saveFile(publish.conf.outDir+"symbols/", ((JSDOC.opt.u)? Link.filemap[symbol.alias] : symbol.alias) + publish.conf.ext, output);
	}

	// regenerate the index with different relative links, used in the index pages
	Link.base = "";
	publish.classesIndex = classesTemplate.process(classes);

	// create the class index page
	try {
		var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"index.tmpl");
	}
	catch(e) { print(e.message); quit(); }

	var classesIndex = classesindexTemplate.process(classes);
	IO.saveFile(publish.conf.outDir, "index"+publish.conf.ext, classesIndex);
	classesindexTemplate = classesIndex = classes = null;

	// create the file index page
	try {
		var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl");
	}
	catch(e) { print(e.message); quit(); }

	var documentedFiles = symbols.filter(isaFile); // files that have file-level docs
	var allFiles = []; // not all files have file-level docs, but we need to list every one

	for (var i = 0; i < files.length; i++) {
		allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */")));
	}

	for (var i = 0; i < documentedFiles.length; i++) {
		var offset = files.indexOf(documentedFiles[i].alias);
		allFiles[offset] = documentedFiles[i];
	}

	allFiles = allFiles.sort(makeSortby("name"));

	// output the file index page
	var filesIndex = fileindexTemplate.process(allFiles);
	IO.saveFile(publish.conf.outDir, "files"+publish.conf.ext, filesIndex);
	fileindexTemplate = filesIndex = files = null;
}

/** Just the first sentence (up to a full stop). Should not break on dotted variable names. */
function summarize(desc) {
	if (typeof desc != "undefined")
		return desc.match(/([\w\W]+?\.)[^a-z0-9_$]/i)? RegExp.$1 : desc;
}

/** Make a symbol sorter by some attribute. */
function makeSortby(attribute) {
	return function(a, b) {
		if (a[attribute] != undefined && b[attribute] != undefined) {
			a = a[attribute].toLowerCase();
			b = b[attribute].toLowerCase();
			if (a  b) return 1;
			return 0;
		}
	}
}

/** Pull in the contents of an external file at the given path. */
function include(path) {
	var path = publish.conf.templatesDir+path;
	return IO.readFile(path);
}

/** Turn a raw source file into a code-hilited page in the docs. */
function makeSrcFile(path, srcDir, name) {
	if (JSDOC.opt.s) return;

	if (!name) {
		name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_");
		name = name.replace(/\:/g, "_");
	}

	var src = {path: path, name:name, charset: IO.encoding, hilited: ""};

	if (defined(JSDOC.PluginManager)) {
		JSDOC.PluginManager.run("onPublishSrc", src);
	}

	if (src.hilited) {
		IO.saveFile(srcDir, name+publish.conf.ext, src.hilited);
	}
}

/** Build output for displaying function parameters. */
function makeSignature(params) {
	if (!params) return "()";
	var postString = '';
	var first = true;
	params = params.filter(
		function($) {
			return $.name.indexOf(".") == -1; // don't show config params in signature
		}
	);
	var signature = '';
	var postSignature = '';
	for (var i = 0, l = params.length; i < l; i++) {
		var param = params[i];
		if (param.isOptional) {
			signature += '[';
			postSignature += ']';
		}
		if (i > 0)
			signature += ', ';
		signature += param.name;
	}
	return '(' + signature + postSignature + ')';
}

function processGroupTitle(str, symbol) {
	// if (/grouptitle/.test(str))
	// 	print('yeah');
	// print(str);
	var groupTitle = str.match(/\{@grouptitle ([^}]+)\}/);
	if (groupTitle) {
		symbol.groupTitle = groupTitle[1];
		str = str.replace(/\{@grouptitle ([^}]+)\}/, '');
	}
	return str;
}

function processInlineTags(str, param) {
	if (!param)
		param = {};
	// .. ->
..

	str = str.replace(/<(\/)*(code)>/g, '<$1pre>');

	// {@link ...} -> html links
	str = str.replace(/\{@link ([^} ]+) ?\}/gi,
		function(match, symbolName) {
			return new Link().toSymbol(symbolName.replace(/[\^]/g, '-'));
		}
	);
	// {@code ...} -> code blocks
	str = str.replace(/\{@code[\s]([^}]+)\}/gi,
		function(match, code) {
			return '<tt>' + code + '</tt>';
		}
	);

	// {@true ...} -> true if.. false otherwise..
	str = str.replace(/\{@true[\s]([^}]+)\}/gi,
		function(match, text) {
			return '<tt>true</tt> ' + text + ', <tt>false</tt> otherwise';
		}
	);

	var lineBreak = java.lang.System.getProperty('line.separator');

	// Convert any type of lineBreak to the one we're using now:
	str = str.replace(/(\r\n|\n|\r)/g, function(match, lineBreak) {
		return lineBreak;
	});

	// Replace inline  with <tt></tt>
	str = str.replace(/[ \t]*([^\n\r]*?)[ \t]*<\/code>/g, function(match, content) {
		return '<tt>' + content + '</tt>';
	});

	// Put code and pre tags on the same line as the content, as white-space: pre is set:
	str = str.replace(/(<(?:code|pre)>)\s*([\u0000-\uffff]*?)\s*(<\/(?:code|pre)>)/g, function(match, open, content, close) {
		// Filter out the first white space at the beginning of each line, since
		// that stems from the space after the * in the comment and replace
		// with
, to fix a IE problem where lighter.js does not receive
		// linebreaks from code tags weven when white-space: pre is set.
		return '
' + content.replace(/(\r\n|\n|\r) /mg, function(match, lineBreak) {
			return lineBreak;
		}) + '
';
	});
	// Empty lines -> Paragraphs
	if (!param.stripParagraphs) {
		if (param.wrapInParagraphs === undefined || param.wrapInParagraphs)
			str = '
' + str.trim() + '
';
		str = str.trim().replace(/(\r\n|\n|\r)\s*(\r\n|\n|\r)/g, function(match, lineBreak) {
			return '
' + lineBreak + '
';
		});
		// Automatically put

 at the end of sentences with line breaks.
		// Match following
 and
 tags and swallow them. This happens when
		// the original content contains these.
		str = str.trim().replace(/([.:?!;])\s*(\r\n|\n|\r)(\s*)(<\/p>|
|)/g, function(match, before, lineBreak, whiteSpace, after) {
			// Include following whiteSpace as well, since for code blocks they are relevant (e.g. indentation on new line)
			return before + '
' + lineBreak + whiteSpace + '
';
		});
		// Filter out
 tags within and around  and
 blocks again
		str = str.replace(/((?:
\s*|)<(?:code|pre)[^>]*>[\u0000-\uffff]*<\/(?:code|pre)>(?:\s*<\/p>|))/g, function(match, code) {
			return stripTags(code, 'p');
		});
		// Filter out empty paragraphs
		str = str.replace(/
<\/p>/g, '');
	}

	return str;
}

function stripTags(str, tag) {
	var tag = tag || '.*?'; // Default: all tags
	return str.replace(new RegExp('<' + tag + '>|</' + tag + '>', 'g'), '');
}

function copyStatic(dir) {
	var dir = publish.conf.templatesDir + 'resources/';

}

function copyDirectory(sourceLocation, targetLocation) {
	if (sourceLocation.isDirectory()) {
		if (!targetLocation.exists()) {
			targetLocation.mkdir();
		}

		var children = sourceLocation.list();
		for (var i = 0; i < children.length; i++) {
			copyDirectory(new File(sourceLocation, children[i]),
					new File(targetLocation, children[i]));
		}
	} else {
		// Copy the file with FileChannels:
		targetLocation.createNewFile();
		var src = new java.io.FileInputStream(sourceLocation).getChannel();
		var dst = new java.io.FileOutputStream(targetLocation).getChannel();
		var amount = dst.transferFrom(src, 0, src.size());
		src.close();
		dst.close();
	}
}<commit_msg>jsdoc publish.js: remove debug statement.<commit_after>var Operator = new function() {
	var operators = {
		add: '+', subtract: '-', multiply: '*', divide: '/', equals: '==',
		modulo: '%'
	};
	var operatorNames = {
		add: 'Addition', subtract: 'Subtraction', multiply: 'Multiplication',
		divide: 'Division', equals: 'Comparison', modulo: 'Modulo'
	};

	var operatorClasses = {
		Point: true,
		Size: true
	};

	return {
		isOperator: function(symbol) {
			// As a convention, only add non static bean properties to
			// the documentation. static properties are all supposed to
			// be uppercase and constants.
			return symbol.params.length == 1 && !symbol.isStatic && (
					/^(add|subtract|multiply|divide|modulo)(\^[0-9])*$/.test(symbol.name)
					&& (symbol.operator != 'none')
				) || ( // equals
					symbol.name == 'equals'
					&& symbol.returns.length && symbol.returns[0].type == 'boolean'
				);
		},

		getOperator: function(symbol) {
			return operators[symbol.name.replace(/\^[0-9]$/,'')];
		}
	}
}

var Helpers = {
	getSymbolId: function(symbol) {
		var id = [symbol.name.toLowerCase().replace(/[\^][0-9]/g, '')];
		if (symbol.params) {
			for (var i = 0, l = symbol.params.length; i < l; i++) {
				var param = symbol.params[i];
				if (!param.isOptional)
					id.push(param.name);
			}
		}
		return id.join('-');
	}
};

var templates;
/** Called automatically by JsDoc Toolkit. */
function publish(symbolSet) {
	publish.conf = {  // trailing slash expected for dirs
		ext:		 ".html",
		outDir:	  JSDOC.opt.d || SYS.pwd+"../out/jsdoc/",
		templatesDir: JSDOC.opt.t || SYS.pwd+"../templates/jsdoc/",
		symbolsDir:  "symbols/",
		srcDir:	  "symbols/src/"
	};

	templates = {
		_class: new JSDOC.JsPlate(publish.conf.templatesDir + "class.tmpl"),
		method: new JSDOC.JsPlate(publish.conf.templatesDir + "method.tmpl"),
		property: new JSDOC.JsPlate(publish.conf.templatesDir + "property.tmpl"),
		parameters: new JSDOC.JsPlate(publish.conf.templatesDir + "parameters.tmpl"),
		operators: new JSDOC.JsPlate(publish.conf.templatesDir + "operators.tmpl"),
		examples: new JSDOC.JsPlate(publish.conf.templatesDir + "examples.tmpl")
	};

	// is source output is suppressed, just display the links to the source file
	if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) {
		Link.prototype._makeSrcLink = function(srcFilePath) {
			return "<"+srcFilePath+">";
		}
	}

	// Copy over the static files
	copyDirectory(
		new java.io.File(publish.conf.templatesDir + 'resources/'),
		new java.io.File(publish.conf.outDir + 'resources/')
	);

	// used to allow Link to check the details of things being linked to
	Link.symbolSet = symbolSet;

	// create the required templates
	try {
		var classTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"class.tmpl");
		var classesTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl");
	}
	catch(e) {
		print("Couldn't create the required templates: "+e);
		quit();
	}

	// some ustility filters
	function hasNoParent($) {return ($.memberOf == "")}
	function isaFile($) {return ($.is("FILE"))}
	function isaClass($) {return ($.is("CONSTRUCTOR") || $.isNamespace)}

	// get an array version of the symbolset, useful for filtering
	var symbols = symbolSet.toArray();

	// create the hilited source code files
	var files = JSDOC.opt.srcFiles;
	 	for (var i = 0, l = files.length; i < l; i++) {
	 		var file = files[i];
	 		var srcDir = publish.conf.outDir + "symbols/src/";
		makeSrcFile(file, srcDir);
	 	}

 	// get a list of all the classes in the symbolset
 	var classes = symbols.filter(isaClass).sort(makeSortby("alias"));

	// create a filemap in which outfiles must be to be named uniquely, ignoring case
	if (JSDOC.opt.u) {
		var filemapCounts = {};
		Link.filemap = {};
		for (var i = 0, l = classes.length; i < l; i++) {
			var lcAlias = classes[i].alias.toLowerCase();

			if (!filemapCounts[lcAlias]) filemapCounts[lcAlias] = 1;
			else filemapCounts[lcAlias]++;

			Link.filemap[classes[i].alias] =
				(filemapCounts[lcAlias] > 1)?
				lcAlias+"_"+filemapCounts[lcAlias] : lcAlias;
		}
	}

	// create a class index, displayed in the left-hand column of every class page
	Link.base = "../";
 	publish.classesIndex = classesTemplate.process(classes); // kept in memory

	// create each of the class pages
	for (var i = 0, l = classes.length; i < l; i++) {
		var symbol = classes[i];

		symbol.events = symbol.getEvents();   // 1 order matters
		symbol.methods = symbol.getMethods(); // 2
		for (var j = 0; j < symbol.methods.length; j++) {
			var method = symbol.methods[j];
			method.isOperator = Operator.isOperator(method);
		}

		Link.currentSymbol= symbol;
		var output = "";
		output = classTemplate.process(symbol);

		IO.saveFile(publish.conf.outDir+"symbols/", ((JSDOC.opt.u)? Link.filemap[symbol.alias] : symbol.alias) + publish.conf.ext, output);
	}

	// regenerate the index with different relative links, used in the index pages
	Link.base = "";
	publish.classesIndex = classesTemplate.process(classes);

	// create the class index page
	try {
		var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"index.tmpl");
	}
	catch(e) { print(e.message); quit(); }

	var classesIndex = classesindexTemplate.process(classes);
	IO.saveFile(publish.conf.outDir, "index"+publish.conf.ext, classesIndex);
	classesindexTemplate = classesIndex = classes = null;

	// create the file index page
	try {
		var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl");
	}
	catch(e) { print(e.message); quit(); }

	var documentedFiles = symbols.filter(isaFile); // files that have file-level docs
	var allFiles = []; // not all files have file-level docs, but we need to list every one

	for (var i = 0; i < files.length; i++) {
		allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */")));
	}

	for (var i = 0; i < documentedFiles.length; i++) {
		var offset = files.indexOf(documentedFiles[i].alias);
		allFiles[offset] = documentedFiles[i];
	}

	allFiles = allFiles.sort(makeSortby("name"));

	// output the file index page
	var filesIndex = fileindexTemplate.process(allFiles);
	IO.saveFile(publish.conf.outDir, "files"+publish.conf.ext, filesIndex);
	fileindexTemplate = filesIndex = files = null;
}

/** Just the first sentence (up to a full stop). Should not break on dotted variable names. */
function summarize(desc) {
	if (typeof desc != "undefined")
		return desc.match(/([\w\W]+?\.)[^a-z0-9_$]/i)? RegExp.$1 : desc;
}

/** Make a symbol sorter by some attribute. */
function makeSortby(attribute) {
	return function(a, b) {
		if (a[attribute] != undefined && b[attribute] != undefined) {
			a = a[attribute].toLowerCase();
			b = b[attribute].toLowerCase();
			if (a  b) return 1;
			return 0;
		}
	}
}

/** Pull in the contents of an external file at the given path. */
function include(path) {
	var path = publish.conf.templatesDir+path;
	return IO.readFile(path);
}

/** Turn a raw source file into a code-hilited page in the docs. */
function makeSrcFile(path, srcDir, name) {
	if (JSDOC.opt.s) return;

	if (!name) {
		name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_");
		name = name.replace(/\:/g, "_");
	}

	var src = {path: path, name:name, charset: IO.encoding, hilited: ""};

	if (defined(JSDOC.PluginManager)) {
		JSDOC.PluginManager.run("onPublishSrc", src);
	}

	if (src.hilited) {
		IO.saveFile(srcDir, name+publish.conf.ext, src.hilited);
	}
}

/** Build output for displaying function parameters. */
function makeSignature(params) {
	if (!params) return "()";
	var postString = '';
	var first = true;
	params = params.filter(
		function($) {
			return $.name.indexOf(".") == -1; // don't show config params in signature
		}
	);
	var signature = '';
	var postSignature = '';
	for (var i = 0, l = params.length; i < l; i++) {
		var param = params[i];
		if (param.isOptional) {
			signature += '[';
			postSignature += ']';
		}
		if (i > 0)
			signature += ', ';
		signature += param.name;
	}
	return '(' + signature + postSignature + ')';
}

function processGroupTitle(str, symbol) {
	// if (/grouptitle/.test(str))
	// 	print('yeah');
	// print(str);
	var groupTitle = str.match(/\{@grouptitle ([^}]+)\}/);
	if (groupTitle) {
		symbol.groupTitle = groupTitle[1];
		str = str.replace(/\{@grouptitle ([^}]+)\}/, '');
	}
	return str;
}

function processInlineTags(str, param) {
	if (!param)
		param = {};
	// .. ->
..

	str = str.replace(/<(\/)*(code)>/g, '<$1pre>');

	// {@link ...} -> html links
	str = str.replace(/\{@link ([^} ]+) ?\}/gi,
		function(match, symbolName) {
			return new Link().toSymbol(symbolName.replace(/[\^]/g, '-'));
		}
	);
	// {@code ...} -> code blocks
	str = str.replace(/\{@code[\s]([^}]+)\}/gi,
		function(match, code) {
			return '<tt>' + code + '</tt>';
		}
	);

	// {@true ...} -> true if.. false otherwise..
	str = str.replace(/\{@true[\s]([^}]+)\}/gi,
		function(match, text) {
			return '<tt>true</tt> ' + text + ', <tt>false</tt> otherwise';
		}
	);

	var lineBreak = java.lang.System.getProperty('line.separator');

	// Convert any type of lineBreak to the one we're using now:
	str = str.replace(/(\r\n|\n|\r)/g, function(match, lineBreak) {
		return lineBreak;
	});

	// Replace inline  with <tt></tt>
	str = str.replace(/[ \t]*([^\n\r]*?)[ \t]*<\/code>/g, function(match, content) {
		return '<tt>' + content + '</tt>';
	});

	// Put code and pre tags on the same line as the content, as white-space: pre is set:
	str = str.replace(/(<(?:code|pre)>)\s*([\u0000-\uffff]*?)\s*(<\/(?:code|pre)>)/g, function(match, open, content, close) {
		// Filter out the first white space at the beginning of each line, since
		// that stems from the space after the * in the comment and replace
		// with
, to fix a IE problem where lighter.js does not receive
		// linebreaks from code tags weven when white-space: pre is set.
		return '
' + content.replace(/(\r\n|\n|\r) /mg, function(match, lineBreak) {
			return lineBreak;
		}) + '
';
	});
	// Empty lines -> Paragraphs
	if (!param.stripParagraphs) {
		if (param.wrapInParagraphs === undefined || param.wrapInParagraphs)
			str = '
' + str.trim() + '
';
		str = str.trim().replace(/(\r\n|\n|\r)\s*(\r\n|\n|\r)/g, function(match, lineBreak) {
			return '
' + lineBreak + '
';
		});
		// Automatically put

 at the end of sentences with line breaks.
		// Match following
 and
 tags and swallow them. This happens when
		// the original content contains these.
		str = str.trim().replace(/([.:?!;])\s*(\r\n|\n|\r)(\s*)(<\/p>|
|)/g, function(match, before, lineBreak, whiteSpace, after) {
			// Include following whiteSpace as well, since for code blocks they are relevant (e.g. indentation on new line)
			return before + '
' + lineBreak + whiteSpace + '
';
		});
		// Filter out
 tags within and around  and
 blocks again
		str = str.replace(/((?:
\s*|)<(?:code|pre)[^>]*>[\u0000-\uffff]*<\/(?:code|pre)>(?:\s*<\/p>|))/g, function(match, code) {
			return stripTags(code, 'p');
		});
		// Filter out empty paragraphs
		str = str.replace(/
<\/p>/g, '');
	}

	return str;
}

function stripTags(str, tag) {
	var tag = tag || '.*?'; // Default: all tags
	return str.replace(new RegExp('<' + tag + '>|</' + tag + '>', 'g'), '');
}

function copyStatic(dir) {
	var dir = publish.conf.templatesDir + 'resources/';

}

function copyDirectory(sourceLocation, targetLocation) {
	if (sourceLocation.isDirectory()) {
		if (!targetLocation.exists()) {
			targetLocation.mkdir();
		}

		var children = sourceLocation.list();
		for (var i = 0; i < children.length; i++) {
			copyDirectory(new File(sourceLocation, children[i]),
					new File(targetLocation, children[i]));
		}
	} else {
		// Copy the file with FileChannels:
		targetLocation.createNewFile();
		var src = new java.io.FileInputStream(sourceLocation).getChannel();
		var dst = new java.io.FileOutputStream(targetLocation).getChannel();
		var amount = dst.transferFrom(src, 0, src.size());
		src.close();
		dst.close();
	}
}<|endoftext|>


<commit_before>angular
  .module('app')
  .component('checkIn', {
    templateUrl: 'app/clients/checkIn.html',
    controller: makecheckIn,
    controllerAs: 'CheckIn'
  });

function makecheckIn(clientsApi, reservationApi, agencyApi) {
    let vm = this;

    vm.newCheckIn = {};

    clientsApi.all().then(function (response) {
      vm.clients = response.data;
    });

    vm.availableEthnicities = [
      {
        id: 'american_indian',
        title: 'American Indian'
      },
      {
        id: 'asian',
        title: 'Asian'
      },
      {
        id: 'black',
        title: 'Black'
      },
      {
        id: 'white',
        title: 'White'
      },
      {
        id: 'no_race',
        title: 'No Race'
      },
      {
        id: 'hi_or_pac_island',
        title: 'Hawaiian or Pacific Islander'
      }
    ];

    vm.createClient = function () {
      if (vm.ethnicitySelections) {
        vm.ethnicitySelections.forEach(selctionTitle => {
          let target = _.find(vm.availableEthnicities, {title: selctionTitle});
          vm.newCheckIn[target.id] = true;
        });
      }

      return agencyApi.getCurrent().then(agencyResponse => {
        return clientsApi.create(vm.newCheckIn).then((clientResponse) => {
          return reservationApi.checkin(agencyResponse.id, clientResponse.data.id).then(reservationResponse => {
            console.log(reservationResponse)
          })
        })
      })
    };

}
<commit_msg>stuff<commit_after>angular
  .module('app')
  .component('checkIn', {
    templateUrl: 'app/clients/checkIn.html',
    controller: makecheckIn,
    controllerAs: 'CheckIn'
  });

function makecheckIn(clientsApi, reservationApi, agencyApi) {
    let vm = this;

    vm.newCheckIn = {};

    clientsApi.all().then(function (response) {
      vm.clients = response.data;
    });

    vm.availableEthnicities = [
      {
        id: 'american_indian',
        title: 'American Indian'
      },
      {
        id: 'asian',
        title: 'Asian'
      },
      {
        id: 'black',
        title: 'Black'
      },
      {
        id: 'white',
        title: 'White'
      },
      {
        id: 'no_race',
        title: 'No Race'
      },
      {
        id: 'hi_or_pac_island',
        title: 'Hawaiian or Pacific Islander'
      }
    ];

    vm.checkInExistingClient = function (clientId) {

    };

    vm.createClient = function () {
      if (vm.ethnicitySelections) {
        vm.ethnicitySelections.forEach(selctionTitle => {
          let target = _.find(vm.availableEthnicities, {title: selctionTitle});
          vm.newCheckIn[target.id] = true;
        });
      }

      return agencyApi.getCurrent().then(agencyResponse => {
        return clientsApi.create(vm.newCheckIn).then((clientResponse) => {
          return reservationApi.checkin(agencyResponse.id, clientResponse.data.id).then(reservationResponse => {
            console.log(reservationResponse);
          })
        })
      })
    };

}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import ReactGA from 'react-ga';
import { IntlProvider, addLocaleData } from 'react-intl';
import App from './App';
import { IndexComponent, TermsOfService, NotFound, CreateAccount, AccessDenied, PrivacyPolicy, UserConfirmed, UserUnconfirmed } from '../components';
import { Sources, Source, User, Me } from '../components/source';
import Team from '../components/team/Team';
import { CreateProjectMedia, ProjectMedia } from '../components/media';
import TeamMembers from '../components/team/TeamMembers';
import CreateTeam from '../components/team/CreateTeam';
import JoinTeam from '../components/team/JoinTeam.js';
import Project from '../components/project/Project.js';
import ProjectHeader from '../components/project/ProjectHeader';
import ProjectEdit from '../components/project/ProjectEdit';
import Teams from '../components/team/Teams.js';
import Search from '../components/Search.js';
import CheckContext from '../CheckContext';
import translations from '../../../localization/translations/translations';
import config from 'config';

// Localization
global.Intl = require('intl'); // polyfill
let locale = config.locale || navigator.languages || navigator.language || navigator.userLanguage || 'en';
if (locale.constructor === Array) {
  locale = locale[0];
}
locale = locale.replace(/[-_].*$/, '');
try {
  const localeData = require('react-intl/locale-data/' + locale);
  addLocaleData([...localeData]);
} catch (e) {
  locale = 'en';
}

export default class Root extends Component {
  static propTypes = {
    store: PropTypes.object.isRequired,
  };

  getContext() {
    const context = new CheckContext(this);
    return context;
  }

  setStore() {
    const history = syncHistoryWithStore(browserHistory, this.props.store);
    const context = this.getContext();
    const store = context.store || this.props.store;

    const data = { history };

    if (config.pusherKey) {
      Pusher.logToConsole = !!config.pusherDebug;
      const pusher = new Pusher(config.pusherKey, { encrypted: true });
      data.pusher = pusher;
    }

    context.setContextStore(data, store);
    this.setState(data);
  }

  componentWillMount() {
    this.setStore();
  }

  componentWillUpdate() {
    this.setStore();
  }

  componentDidMount() {
    if (config.googleAnalyticsCode) {
      ReactGA.initialize(config.googleAnalyticsCode, { debug: false });
    }
  }

  logPageView() {
    if (config.googleAnalyticsCode) {
      ReactGA.set({ page: window.location.pathname });
      ReactGA.pageview(window.location.pathname);
    }
  }

  render() {
    const { store } = this.props;
    window.Checkdesk = { store };

    return (
      <IntlProvider locale={locale} messages={translations[locale]}>
        <Provider store={store}>
          <Router history={this.state.history} onUpdate={this.logPageView.bind(this)}>
            <Route path="/" component={App}>
              <IndexRoute component={Team} />
              <Route path="check/tos" component={TermsOfService} public />
              <Route path="check/privacy" component={PrivacyPolicy} public />
              <Route path="check/user/confirmed" component={UserConfirmed} public />
              <Route path="check/user/unconfirmed" component={UserUnconfirmed} public />
              <Route path="check/forbidden" component={AccessDenied} public />
              <Route path="check/404" component={NotFound} public />

              <Route path="check/sources" component={Sources} />
              <Route path="check/sources/new" component={CreateAccount} />
              <Route path="check/source/:sourceId" component={Source} />
              <Route path="check/user/:userId" component={User} />
              <Route path="check/me" component={Me} />
              <Route path="check/teams/new" component={CreateTeam} />
              <Route path="check/teams" component={Teams} />

              <Route path=":team/medias/new" component={CreateProjectMedia} />
              <Route path=":team/project/:projectId/media/:mediaId" component={ProjectMedia} />
              <Route path=":team/join" component={JoinTeam} />
              <Route path=":team/members" component={TeamMembers} />
              <Route path=":team/project/:projectId" component={Project} />
              <Route path=":team/project/:projectId/edit" component={ProjectEdit} />
              <Route path=":team/search(/:query)" component={Search} />
              <Route path=":team" component={Team} />

              <Route path="*" component={NotFound} public />
            </Route>
          </Router>
        </Provider>
      </IntlProvider>
    );
  }
}

Root.contextTypes = {
  store: React.PropTypes.object,
};
<commit_msg>Load Intl polyfill and locale data as needed. #5624<commit_after>import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import ReactGA from 'react-ga';
import { IntlProvider, addLocaleData } from 'react-intl';
import App from './App';
import { IndexComponent, TermsOfService, NotFound, CreateAccount, AccessDenied, PrivacyPolicy, UserConfirmed, UserUnconfirmed } from '../components';
import { Sources, Source, User, Me } from '../components/source';
import Team from '../components/team/Team';
import { CreateProjectMedia, ProjectMedia } from '../components/media';
import TeamMembers from '../components/team/TeamMembers';
import CreateTeam from '../components/team/CreateTeam';
import JoinTeam from '../components/team/JoinTeam.js';
import Project from '../components/project/Project.js';
import ProjectHeader from '../components/project/ProjectHeader';
import ProjectEdit from '../components/project/ProjectEdit';
import Teams from '../components/team/Teams.js';
import Search from '../components/Search.js';
import CheckContext from '../CheckContext';
import translations from '../../../localization/translations/translations';
import config from 'config';

// Localization
let locale = config.locale || navigator.languages || navigator.language || navigator.userLanguage || 'en';
if (locale.constructor === Array) {
  locale = locale[0];
}
locale = locale.replace(/[-_].*$/, '');

if (!global.Intl) {
  require(['intl'], function(intl){
    global.Intl = intl;
    require('intl/locale-data/jsonp/' + locale + '.js');
  });
}

try {
  const localeData = require('react-intl/locale-data/' + locale);
  addLocaleData([...localeData]);
} catch (e) {
  locale = 'en';
}

export default class Root extends Component {
  static propTypes = {
    store: PropTypes.object.isRequired,
  };

  getContext() {
    const context = new CheckContext(this);
    return context;
  }

  setStore() {
    const history = syncHistoryWithStore(browserHistory, this.props.store);
    const context = this.getContext();
    const store = context.store || this.props.store;

    const data = { history };

    if (config.pusherKey) {
      Pusher.logToConsole = !!config.pusherDebug;
      const pusher = new Pusher(config.pusherKey, { encrypted: true });
      data.pusher = pusher;
    }

    context.setContextStore(data, store);
    this.setState(data);
  }

  componentWillMount() {
    this.setStore();
  }

  componentWillUpdate() {
    this.setStore();
  }

  componentDidMount() {
    if (config.googleAnalyticsCode) {
      ReactGA.initialize(config.googleAnalyticsCode, { debug: false });
    }
  }

  logPageView() {
    if (config.googleAnalyticsCode) {
      ReactGA.set({ page: window.location.pathname });
      ReactGA.pageview(window.location.pathname);
    }
  }

  render() {
    const { store } = this.props;
    window.Checkdesk = { store };

    return (
      <IntlProvider locale={locale} messages={translations[locale]}>
        <Provider store={store}>
          <Router history={this.state.history} onUpdate={this.logPageView.bind(this)}>
            <Route path="/" component={App}>
              <IndexRoute component={Team} />
              <Route path="check/tos" component={TermsOfService} public />
              <Route path="check/privacy" component={PrivacyPolicy} public />
              <Route path="check/user/confirmed" component={UserConfirmed} public />
              <Route path="check/user/unconfirmed" component={UserUnconfirmed} public />
              <Route path="check/forbidden" component={AccessDenied} public />
              <Route path="check/404" component={NotFound} public />

              <Route path="check/sources" component={Sources} />
              <Route path="check/sources/new" component={CreateAccount} />
              <Route path="check/source/:sourceId" component={Source} />
              <Route path="check/user/:userId" component={User} />
              <Route path="check/me" component={Me} />
              <Route path="check/teams/new" component={CreateTeam} />
              <Route path="check/teams" component={Teams} />

              <Route path=":team/medias/new" component={CreateProjectMedia} />
              <Route path=":team/project/:projectId/media/:mediaId" component={ProjectMedia} />
              <Route path=":team/join" component={JoinTeam} />
              <Route path=":team/members" component={TeamMembers} />
              <Route path=":team/project/:projectId" component={Project} />
              <Route path=":team/project/:projectId/edit" component={ProjectEdit} />
              <Route path=":team/search(/:query)" component={Search} />
              <Route path=":team" component={Team} />

              <Route path="*" component={NotFound} public />
            </Route>
          </Router>
        </Provider>
      </IntlProvider>
    );
  }
}

Root.contextTypes = {
  store: React.PropTypes.object,
};
<|endoftext|>


<commit_before>function getClosest(el, divID)
{
	if (typeof divID == 'undefined' || divID == false)
		return null;

	do
	{
		// End the loop if quick edit is detected.
		if (el.nodeName === 'TEXTAREA' || el.nodeName === 'INPUT' || el.id === 'error_box')
			break;

		if (el.id === divID)
		{
			// tag name is found!
			return el;
		}
	}
	while (el = el.parentNode);

	// not found :(
	return null;
}

function getSelectedText(divID)
{
	if (typeof divID == 'undefined' || divID == false)
		return false;

	var text = '',
	selection,
	found = 0;

	if (window.getSelection)
	{
		selection = window.getSelection();
		text = selection.toString();
	}
	else if (document.selection && document.selection.type != 'Control')
	{
		selection = document.selection.createRange();
		text = selection.text;
	}

	// Need to be sure the selected text does belong to the right div.
	for (var i = 0; i < selection.rangeCount; i++) {
			s = getClosest(selection.getRangeAt(i).startContainer, divID);
			e = getClosest(selection.getRangeAt(i).endContainer, divID);

			if (s !== null && e !== null)
			{
				found = 1;
				break;
			}
		}

	return found === 1 ? text : false;
}

function quotedTextClick(oOptions)
{
		text = '';

		// The process has been started, hide the button.
		$('#quoteSelected_' + oOptions.msgID).hide();

		// Do a call to make sure this is a valid message.
		$.ajax({
			url: smf_prepareScriptUrl(smf_scripturl) + 'action=quotefast;quote=' + oOptions.msgID + ';xml;pb='+ oEditorID + ';mode=' + (oEditorObject.bRichTextEnabled ? 1 : 0),
			type: 'GET',
			dataType: 'xml',
			beforeSend: function () {
				ajax_indicator(true);
			},
			success: function (data, textStatus, xhr) {
				// Search the xml data to get the quote tag.
				text = $(data).find('quote').text();

				// Insert the selected text between the quotes BBC tags.
				text = text.match(/^\[quote(.*)]/ig) + oOptions.text + '[/quote]' + '\n\n';

				// Add the whole text to the editor's instance.
				$('#' + oEditorID).data('sceditor').sourceEditorInsertText(text);

				// Move the view to the quick reply box. If available.
				if (typeof oJumpAnchor != 'undefined'){
					if (navigator.appName == 'Microsoft Internet Explorer')
						window.location.hash = oJumpAnchor;
					else
						window.location.hash = '#' + oJumpAnchor;
				}

				ajax_indicator(false);
			},
			error: function (xhr, textStatus, errorThrown) {
				ajax_indicator(false);
			}
		});
}

$(function() {

	// Event for handling selected quotes.
	$(document).on('mouseup', '.inner, .list_posts', function() {

		// Get everything we need.
		var oSelected = {
			divID : $(this).attr('id'),
			msgID : $(this).data('msgid'),
		};

		// If the button is already visible, hide it!
		$('#quoteSelected_' + oSelected.msgID).hide();

		// Get any selected text.
		oSelected.text = getSelectedText(oSelected.divID);

		// Do we have some selected text?
		if (typeof oSelected.text == 'undefined' || oSelected.text == false)
			return false;

		// Show the "quote this" button.
		$('#quoteSelected_' + oSelected.msgID).show();

			$(document).one('click', '#quoteSelected_' + oSelected.msgID + ' a', function(e){
				e.preventDefault();
				quotedTextClick(oSelected);
			});

		return false;
	});
});<commit_msg>Documentation<commit_after>// Traverse the DOM tree in our spinoff of jQuery's closest()
function getClosest(el, divID)
{
	if (typeof divID == 'undefined' || divID == false)
		return null;

	do
	{
		// End the loop if quick edit is detected.
		if (el.nodeName === 'TEXTAREA' || el.nodeName === 'INPUT' || el.id === 'error_box')
			break;

		if (el.id === divID)
		{
			// tag name is found!
			return el;
		}
	}
	while (el = el.parentNode);

	// not found :(
	return null;
}

function getSelectedText(divID)
{
	if (typeof divID == 'undefined' || divID == false)
		return false;

	var text = '',
	selection,
	found = 0;

	if (window.getSelection)
	{
		selection = window.getSelection();
		text = selection.toString();
	}
	else if (document.selection && document.selection.type != 'Control')
	{
		selection = document.selection.createRange();
		text = selection.text;
	}

	// Need to be sure the selected text does belong to the right div.
	for (var i = 0; i < selection.rangeCount; i++) {
			s = getClosest(selection.getRangeAt(i).startContainer, divID);
			e = getClosest(selection.getRangeAt(i).endContainer, divID);

			if (s !== null && e !== null)
			{
				found = 1;
				break;
			}
		}

	return found === 1 ? text : false;
}

function quotedTextClick(oOptions)
{
		text = '';

		// The process has been started, hide the button.
		$('#quoteSelected_' + oOptions.msgID).hide();

		// Do a call to make sure this is a valid message.
		$.ajax({
			url: smf_prepareScriptUrl(smf_scripturl) + 'action=quotefast;quote=' + oOptions.msgID + ';xml;pb='+ oEditorID + ';mode=' + (oEditorObject.bRichTextEnabled ? 1 : 0),
			type: 'GET',
			dataType: 'xml',
			beforeSend: function () {
				ajax_indicator(true);
			},
			success: function (data, textStatus, xhr) {
				// Search the xml data to get the quote tag.
				text = $(data).find('quote').text();

				// Insert the selected text between the quotes BBC tags.
				text = text.match(/^\[quote(.*)]/ig) + oOptions.text + '[/quote]' + '\n\n';

				// Add the whole text to the editor's instance.
				$('#' + oEditorID).data('sceditor').sourceEditorInsertText(text);

				// Move the view to the quick reply box. If available.
				if (typeof oJumpAnchor != 'undefined'){
					if (navigator.appName == 'Microsoft Internet Explorer')
						window.location.hash = oJumpAnchor;
					else
						window.location.hash = '#' + oJumpAnchor;
				}

				ajax_indicator(false);
			},
			error: function (xhr, textStatus, errorThrown) {
				ajax_indicator(false);
			}
		});
}

$(function() {

	// Event for handling selected quotes.
	$(document).on('mouseup', '.inner, .list_posts', function() {

		// Get everything we need.
		var oSelected = {
			divID : $(this).attr('id'),
			msgID : $(this).data('msgid'),
		};

		// If the button is already visible, hide it!
		$('#quoteSelected_' + oSelected.msgID).hide();

		// Get any selected text.
		oSelected.text = getSelectedText(oSelected.divID);

		// Do we have some selected text?
		if (typeof oSelected.text == 'undefined' || oSelected.text == false)
			return false;

		// Show the "quote this" button.
		$('#quoteSelected_' + oSelected.msgID).show();

			$(document).one('click', '#quoteSelected_' + oSelected.msgID + ' a', function(e){
				e.preventDefault();
				quotedTextClick(oSelected);
			});

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


<commit_before>/* global Node */
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var javascriptserialize = require('javascript-serialize')
var jsbeautify = require('js-beautify')
var type = require('component-type')
var EventManager = require('ethereum-remix').lib.EventManager

var css = csjs`
  .panel              {
    position          : relative;
    display           : flex;
    flex-direction    : column;
    font-size         : 12px;
    font-family       : monospace;
    color             : white;
    background-color  : black;
    margin-top        : auto;
    height            : 100%;
    min-height        : 1.7em;
  }

  .bar                {
    display           : flex;
    justify-content   : flex-end;
    min-height        : 1.7em;
    padding           : 2px;
    cursor            : ns-resize;
    background-color  : #eef;
  }
  .minimize           {
    text-align        : center;
    padding-top       : 3px;
    width             : 10px;
    min-height        : 100%;
    cursor            : pointer;
    color             : black;
  }
  .hover              {
    color             : orange;
  }

  .terminal           {
    display           : flex;
    flex-direction    : column;
    height            : 100%;
    padding-left      : 5px;
    padding-right     : 5px;
    padding-bottom    : 3px;
    overflow-y        : auto;
    font-family       : monospace;
  }

  .log                {
    margin-top        : auto;
    font-family       : monospace;
  }
  .block              {
    word-break        : break-all;
    white-space       : pre-wrap;
    line-height       : 2ch;
    width             : 80ch;
    background-color  : black;
    margin            : 1ch;
  }

  .cli                {
    line-height       : 1.7em;
    font-family       : monospace;
  }
  .prompt             {
    margin-right      : 0.5em;
    font-family       : monospace;
  }
  .input              {
    word-break        : break-all;
    outline           : none;
    font-family       : monospace;
  }
  .error              {
    color             : red;
  }
  .info               {
    color             : blue;
  }
  .default            {
    color             : white;
  }
  .ghostbar           {
    position          : absolute;
    height            : 6px;
    background-color  : #C6CFF7;
    opacity           : 0.5;
    cursor            : row-resize;
    z-index           : 9999;
    left              : 0;
    right             : 0;
  }
`

var currentError

window.addEventListener('error', function (event) {
  currentError = new Error(event.message)
  currentError.timeStamp = event.timeStamp
  currentError.isTrusted = event.isTrusted
  currentError.filename = event.filename
  currentError.lineno = event.lineno
  currentError.colno = event.colno
  currentError.error = event.error
  currentError.type = event.type
})

window.onerror = function (msg, url, lineno, col, error) {
  if (!error) error = currentError
  var val = { msg: msg, url: url, lineno: lineno, col: col, error: error }
  console.error(val)
}

var KONSOLES = []
// var KONSOLES = [{
//   error: console.error.bind(console),
//   info: console.info.bind(console),
//   log: console.log.bind(console)
// }]
// console.error = broadcast('error')
// console.info = broadcast('info')
// console.log = broadcast('log')
//
// function broadcast (mode) {
//   return function broadcastMode () {
//     var args = arguments
//     KONSOLES.forEach(function (api) { api[mode].apply(api, args) })
//   }
// }

function register (api) { KONSOLES.push(api) }

var ghostbar = yo`<div class=${css.ghostbar}></div>`

class Terminal {
  constructor (opts = { auto: true }) {
    var self = this
    self.data = {
      lineLength: opts.lineLength || 80,
      session: [],
      banner: opts.banner || `
/******************************************************************************

  ...........................................
  .....................:.....................
  ....................o:;....................
  ...................oo:;;...................
  ..................ooo:;;;..................
  .................oooo:;;;;.................
  ................ooooo:;;;;;................
  ...............oooooo:;;;;;;...............
  ..............ooooooo:;;;;;;;..............
  .............ooooooo;:';;;;;;;.............
  ............ooooo;;;;:'''';;;;;............
  ...........oo;;;;;;;;:'''''''';;...........
  ..........;;;;;;;;;;;:'''''''''''..........
  ..............;;;;;;;:'''''''..............
  ...........oo...;;;;;:'''''...;;...........
  ............oooo...;;:''...;;;;............
  ..............oooo...:...;;;;..............
  ...............oooooo:;;;;;;...............
  ................ooooo:;;;;;................
  .................oooo:;;;;.................
  ..................ooo:;;;..................
  ...................oo:;;...................
  ....................o:;....................
  .....................:.....................
  ...........................................

  ########  ######## ##     ## #### ##     ##
  ##     ## ##       ###   ###  ##   ##   ##
  ##     ## ##       #### ####  ##    ## ##
  ########  ######   ## ### ##  ##     ###
  ##   ##   ##       ##     ##  ##    ## ##
  ##    ##  ##       ##     ##  ##   ##   ##
  ##     ## ######## ##     ## #### ##     ##

  welcome to browser solidity

  new features:
    - dom terminal v0.0.1-alpha

******************************************************************************/
`
    }
    self.event = new EventManager()
    self._api = opts.api
    self._view = { panel: null, bar: null, input: null, term: null, log: null, cli: null }
    self._templates = {}
    self._templates.default = self._blocksRenderer('default')
    self._templates.error = self._blocksRenderer('error')
    self._templates.info = self._blocksRenderer('info')
    if (opts.shell) self._shell = opts.shell
    // @TODO: listen to all relevant events
    // var events = opts.events
    // events.txlistener.register('newBlock', function (block) {
    //   self.log(block)
    // })
    // events.udapp.register('transactionExecuted', function (address, data, lookupOnly, txResult) {
    //   self.log({ address, data, lookupOnly, txResult })
    //   // - trans.sent and info about it once it's mined
    //   // - everything related to the address
    // })
    register(self)
  }
  render () {
    var self = this
    if (self._view.panel) return self._view.panel
    self._view.log = yo`<div class=${css.log}></div>`
    self._view.input = yo`

    `
    self._view.cli = yo`

 self._view.input.focus()}>
        ${'>'}
        ${self._view.input}

    `
    self._view.icon = yo`<i onmouseenter=${hover} onmouseleave=${hover} onmousedown=${minimize} class="${css.minimize} fa fa-angle-double-down"></i>`
    self._view.bar = yo`

        ${self._view.icon}

    `
    self._view.term = yo`

        ${self._view.log}
        ${self._view.cli}

    `
    self._view.panel = yo`

        ${self._view.bar}
        ${self._view.term}

    `
    self.log(self.data.banner)

    function reattach (event) {
      var el = event.currentTarget
      var isBottomed = el.scrollHeight - el.scrollTop === el.clientHeight
      if (isBottomed) {
        delete self.scroll2bottom
        // @TODO: delete new message indicator
      } else {
        self.scroll2bottom = function () { }
        // @TODO: while in stopped mode: show indicator about new lines getting logged
      }
    }
    function hover (event) { event.currentTarget.classList.toggle(css.hover) }
    function minimize (event) {
      event.preventDefault()
      event.stopPropagation()
      var classList = self._view.icon.classList
      classList.toggle('fa-angle-double-down')
      classList.toggle('fa-angle-double-up')
      self.event.trigger('resize', [])
    }
    // ----------------- resizeable ui ---------------
    function mousedown (event) {
      event.preventDefault()
      if (event.which === 1) {
        moveGhostbar(event)
        document.body.appendChild(ghostbar)
        document.addEventListener('mousemove', moveGhostbar)
        document.addEventListener('mouseup', removeGhostbar)
        document.addEventListener('keydown', cancelGhostbar)
      }
    }
    function cancelGhostbar (event) {
      if (event.keyCode === 27) {
        document.body.removeChild(ghostbar)
        document.removeEventListener('mousemove', moveGhostbar)
        document.removeEventListener('mouseup', removeGhostbar)
        document.removeEventListener('keydown', cancelGhostbar)
      }
    }
    function moveGhostbar (event) { // @NOTE HORIZONTAL ghostbar
      ghostbar.style.top = self._api.getPosition(event) + 'px'
    }
    function removeGhostbar (event) {
      if (self._view.icon.classList.contains('fa-angle-double-up')) {
        self._view.icon.classList.toggle('fa-angle-double-down')
        self._view.icon.classList.toggle('fa-angle-double-up')
      }
      document.body.removeChild(ghostbar)
      document.removeEventListener('mousemove', moveGhostbar)
      document.removeEventListener('mouseup', removeGhostbar)
      document.removeEventListener('keydown', cancelGhostbar)
      self.event.trigger('resize', [self._api.getPosition(event)])
    }

    return self._view.panel

    function change (event) {
      if (event.which === 13) {
        if (event.ctrlKey) { // <ctrl+enter>
          self._view.input.appendChild(document.createElement('br'))
          self.scroll2bottom()
          putCursor2End(self._view.input)
        } else { // <enter>
          event.preventDefault()
          self.execute(self._view.input.innerText)
          self._view.input.innerHTML = ''
        }
      }
    }
    function putCursor2End (editable) {
      var range = document.createRange()
      range.selectNode(editable)
      var child = editable
      var chars

      while (child) {
        if (child.lastChild) child = child.lastChild
        else break
        if (child.nodeType === Node.TEXT_NODE) {
          chars = child.textContent.length
        } else {
          chars = child.innerHTML.length
        }
      }

      range.setEnd(child, chars)
      var toStart = true
      var toEnd = !toStart
      range.collapse(toEnd)

      var sel = window.getSelection()
      sel.removeAllRanges()
      sel.addRange(range)

      editable.focus()
    }
  }
  _blocksRenderer (mode) {
    var self = this
    var modes = { log: true, info: true, error: true }
    if (modes[mode]) {
      return function render () {
        var args = [].slice.call(arguments)
        var types = args.map(type)
        var values = javascriptserialize.apply(null, args).map(function (val, idx) {
          if (types[idx] === 'element') val = jsbeautify.html(val)
          var pattern = '.{1,' + self.data.lineLength + '}'
          var lines = val.match(new RegExp(pattern, 'g'))
          return lines.map(str => document.createTextNode(`${str}\n`))
        })
        return values
      }
    } else {
      throw new Error('mode is not supported')
    }
  }
  registerType (typename, template) {
    var self = this
    if (typeof template !== 'function') throw new Error('invalid template')
    self._template[typename] = template
  }
  log () {
    var self = this
    var args = [...arguments]
    self.data.session.push(args)
    args.forEach(function (data = {}) {
      if (!data.type) data = { type: 'default', value: data }
      var render = self._templates[data.type]
      if (!render) render = self._templates.default
      var blocks = render(data.value)
      blocks.forEach(function (block) {
        self._view.log.appendChild(yo`

            ${block}

        `)
        self.scroll2bottom()
      })
    })
  }
  scroll2bottom () {
    var self = this
    setTimeout(function () {
      self._view.term.scrollTop = self._view.term.scrollHeight
    }, 0)
  }
  execute (input) {
    var self = this
    input = String(input)
    self.log(`> ${input}`)
    self._shell(input, function (error, output) {
      if (error) {
        self.error(error)
        return error
      } else {
        self.log(output)
        return output
      }
    })
  }
  _shell (input, done) { // default shell
    // @TODO: add environment and proxy console.log to self.log
    // make `web3` object available in the console vm
    // web3.object creates contract
    // * create transaction
    // * when transaction is mined
    //   => show all transactions, that are mined and have known addresses
    try {
      var result = eval(input) // eslint-disable-line
      done(null, result)
    } catch (error) {
      done(error.message)
    }
  }
}

module.exports = Terminal
<commit_msg>add default mode (Terminal)<commit_after>/* global Node */
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var javascriptserialize = require('javascript-serialize')
var jsbeautify = require('js-beautify')
var type = require('component-type')
var EventManager = require('ethereum-remix').lib.EventManager

var css = csjs`
  .panel              {
    position          : relative;
    display           : flex;
    flex-direction    : column;
    font-size         : 12px;
    font-family       : monospace;
    color             : white;
    background-color  : black;
    margin-top        : auto;
    height            : 100%;
    min-height        : 1.7em;
  }

  .bar                {
    display           : flex;
    justify-content   : flex-end;
    min-height        : 1.7em;
    padding           : 2px;
    cursor            : ns-resize;
    background-color  : #eef;
  }
  .minimize           {
    text-align        : center;
    padding-top       : 3px;
    width             : 10px;
    min-height        : 100%;
    cursor            : pointer;
    color             : black;
  }
  .hover              {
    color             : orange;
  }

  .terminal           {
    display           : flex;
    flex-direction    : column;
    height            : 100%;
    padding-left      : 5px;
    padding-right     : 5px;
    padding-bottom    : 3px;
    overflow-y        : auto;
    font-family       : monospace;
  }

  .log                {
    margin-top        : auto;
    font-family       : monospace;
  }
  .block              {
    word-break        : break-all;
    white-space       : pre-wrap;
    line-height       : 2ch;
    width             : 80ch;
    background-color  : black;
    margin            : 1ch;
  }

  .cli                {
    line-height       : 1.7em;
    font-family       : monospace;
  }
  .prompt             {
    margin-right      : 0.5em;
    font-family       : monospace;
  }
  .input              {
    word-break        : break-all;
    outline           : none;
    font-family       : monospace;
  }
  .error              {
    color             : red;
  }
  .info               {
    color             : blue;
  }
  .default            {
    color             : white;
  }
  .ghostbar           {
    position          : absolute;
    height            : 6px;
    background-color  : #C6CFF7;
    opacity           : 0.5;
    cursor            : row-resize;
    z-index           : 9999;
    left              : 0;
    right             : 0;
  }
`

var currentError

window.addEventListener('error', function (event) {
  currentError = new Error(event.message)
  currentError.timeStamp = event.timeStamp
  currentError.isTrusted = event.isTrusted
  currentError.filename = event.filename
  currentError.lineno = event.lineno
  currentError.colno = event.colno
  currentError.error = event.error
  currentError.type = event.type
})

window.onerror = function (msg, url, lineno, col, error) {
  if (!error) error = currentError
  var val = { msg: msg, url: url, lineno: lineno, col: col, error: error }
  console.error(val)
}

var KONSOLES = []
// var KONSOLES = [{
//   error: console.error.bind(console),
//   info: console.info.bind(console),
//   log: console.log.bind(console)
// }]
// console.error = broadcast('error')
// console.info = broadcast('info')
// console.log = broadcast('log')
//
// function broadcast (mode) {
//   return function broadcastMode () {
//     var args = arguments
//     KONSOLES.forEach(function (api) { api[mode].apply(api, args) })
//   }
// }

function register (api) { KONSOLES.push(api) }

var ghostbar = yo`<div class=${css.ghostbar}></div>`

class Terminal {
  constructor (opts = { auto: true }) {
    var self = this
    self.data = {
      lineLength: opts.lineLength || 80,
      session: [],
      banner: opts.banner || `
/******************************************************************************

  ...........................................
  .....................:.....................
  ....................o:;....................
  ...................oo:;;...................
  ..................ooo:;;;..................
  .................oooo:;;;;.................
  ................ooooo:;;;;;................
  ...............oooooo:;;;;;;...............
  ..............ooooooo:;;;;;;;..............
  .............ooooooo;:';;;;;;;.............
  ............ooooo;;;;:'''';;;;;............
  ...........oo;;;;;;;;:'''''''';;...........
  ..........;;;;;;;;;;;:'''''''''''..........
  ..............;;;;;;;:'''''''..............
  ...........oo...;;;;;:'''''...;;...........
  ............oooo...;;:''...;;;;............
  ..............oooo...:...;;;;..............
  ...............oooooo:;;;;;;...............
  ................ooooo:;;;;;................
  .................oooo:;;;;.................
  ..................ooo:;;;..................
  ...................oo:;;...................
  ....................o:;....................
  .....................:.....................
  ...........................................

  ########  ######## ##     ## #### ##     ##
  ##     ## ##       ###   ###  ##   ##   ##
  ##     ## ##       #### ####  ##    ## ##
  ########  ######   ## ### ##  ##     ###
  ##   ##   ##       ##     ##  ##    ## ##
  ##    ##  ##       ##     ##  ##   ##   ##
  ##     ## ######## ##     ## #### ##     ##

  welcome to browser solidity

  new features:
    - dom terminal v0.0.1-alpha

******************************************************************************/
`
    }
    self.event = new EventManager()
    self._api = opts.api
    self._view = { panel: null, bar: null, input: null, term: null, log: null, cli: null }
    self._templates = {}
    self._templates.default = self._blocksRenderer('default')
    self._templates.error = self._blocksRenderer('error')
    self._templates.info = self._blocksRenderer('info')
    if (opts.shell) self._shell = opts.shell
    // @TODO: listen to all relevant events
    // var events = opts.events
    // events.txlistener.register('newBlock', function (block) {
    //   self.log(block)
    // })
    // events.udapp.register('transactionExecuted', function (address, data, lookupOnly, txResult) {
    //   self.log({ address, data, lookupOnly, txResult })
    //   // - trans.sent and info about it once it's mined
    //   // - everything related to the address
    // })
    register(self)
  }
  render () {
    var self = this
    if (self._view.panel) return self._view.panel
    self._view.log = yo`<div class=${css.log}></div>`
    self._view.input = yo`

    `
    self._view.cli = yo`

 self._view.input.focus()}>
        ${'>'}
        ${self._view.input}

    `
    self._view.icon = yo`<i onmouseenter=${hover} onmouseleave=${hover} onmousedown=${minimize} class="${css.minimize} fa fa-angle-double-down"></i>`
    self._view.bar = yo`

        ${self._view.icon}

    `
    self._view.term = yo`

        ${self._view.log}
        ${self._view.cli}

    `
    self._view.panel = yo`

        ${self._view.bar}
        ${self._view.term}

    `
    self.log(self.data.banner)

    function reattach (event) {
      var el = event.currentTarget
      var isBottomed = el.scrollHeight - el.scrollTop === el.clientHeight
      if (isBottomed) {
        delete self.scroll2bottom
        // @TODO: delete new message indicator
      } else {
        self.scroll2bottom = function () { }
        // @TODO: while in stopped mode: show indicator about new lines getting logged
      }
    }
    function hover (event) { event.currentTarget.classList.toggle(css.hover) }
    function minimize (event) {
      event.preventDefault()
      event.stopPropagation()
      var classList = self._view.icon.classList
      classList.toggle('fa-angle-double-down')
      classList.toggle('fa-angle-double-up')
      self.event.trigger('resize', [])
    }
    // ----------------- resizeable ui ---------------
    function mousedown (event) {
      event.preventDefault()
      if (event.which === 1) {
        moveGhostbar(event)
        document.body.appendChild(ghostbar)
        document.addEventListener('mousemove', moveGhostbar)
        document.addEventListener('mouseup', removeGhostbar)
        document.addEventListener('keydown', cancelGhostbar)
      }
    }
    function cancelGhostbar (event) {
      if (event.keyCode === 27) {
        document.body.removeChild(ghostbar)
        document.removeEventListener('mousemove', moveGhostbar)
        document.removeEventListener('mouseup', removeGhostbar)
        document.removeEventListener('keydown', cancelGhostbar)
      }
    }
    function moveGhostbar (event) { // @NOTE HORIZONTAL ghostbar
      ghostbar.style.top = self._api.getPosition(event) + 'px'
    }
    function removeGhostbar (event) {
      if (self._view.icon.classList.contains('fa-angle-double-up')) {
        self._view.icon.classList.toggle('fa-angle-double-down')
        self._view.icon.classList.toggle('fa-angle-double-up')
      }
      document.body.removeChild(ghostbar)
      document.removeEventListener('mousemove', moveGhostbar)
      document.removeEventListener('mouseup', removeGhostbar)
      document.removeEventListener('keydown', cancelGhostbar)
      self.event.trigger('resize', [self._api.getPosition(event)])
    }

    return self._view.panel

    function change (event) {
      if (event.which === 13) {
        if (event.ctrlKey) { // <ctrl+enter>
          self._view.input.appendChild(document.createElement('br'))
          self.scroll2bottom()
          putCursor2End(self._view.input)
        } else { // <enter>
          event.preventDefault()
          self.execute(self._view.input.innerText)
          self._view.input.innerHTML = ''
        }
      }
    }
    function putCursor2End (editable) {
      var range = document.createRange()
      range.selectNode(editable)
      var child = editable
      var chars

      while (child) {
        if (child.lastChild) child = child.lastChild
        else break
        if (child.nodeType === Node.TEXT_NODE) {
          chars = child.textContent.length
        } else {
          chars = child.innerHTML.length
        }
      }

      range.setEnd(child, chars)
      var toStart = true
      var toEnd = !toStart
      range.collapse(toEnd)

      var sel = window.getSelection()
      sel.removeAllRanges()
      sel.addRange(range)

      editable.focus()
    }
  }
  _blocksRenderer (mode) {
    var self = this
    var modes = { log: true, info: true, error: true, default: true }
    if (modes[mode]) {
      return function render () {
        var args = [].slice.call(arguments)
        var types = args.map(type)
        var values = javascriptserialize.apply(null, args).map(function (val, idx) {
          if (types[idx] === 'element') val = jsbeautify.html(val)
          var pattern = '.{1,' + self.data.lineLength + '}'
          var lines = val.match(new RegExp(pattern, 'g'))
          return lines.map(str => document.createTextNode(`${str}\n`))
        })
        return values
      }
    } else {
      throw new Error('mode is not supported')
    }
  }
  registerType (typename, template) {
    var self = this
    if (typeof template !== 'function') throw new Error('invalid template')
    self._template[typename] = template
  }
  log () {
    var self = this
    var args = [...arguments]
    self.data.session.push(args)
    args.forEach(function (data = {}) {
      if (!data.type) data = { type: 'default', value: data }
      var render = self._templates[data.type]
      if (!render) render = self._templates.default
      var blocks = render(data.value)
      blocks.forEach(function (block) {
        self._view.log.appendChild(yo`

            ${block}

        `)
        self.scroll2bottom()
      })
    })
  }
  scroll2bottom () {
    var self = this
    setTimeout(function () {
      self._view.term.scrollTop = self._view.term.scrollHeight
    }, 0)
  }
  execute (input) {
    var self = this
    input = String(input)
    self.log(`> ${input}`)
    self._shell(input, function (error, output) {
      if (error) {
        self.error(error)
        return error
      } else {
        self.log(output)
        return output
      }
    })
  }
  _shell (input, done) { // default shell
    // @TODO: add environment and proxy console.log to self.log
    // make `web3` object available in the console vm
    // web3.object creates contract
    // * create transaction
    // * when transaction is mined
    //   => show all transactions, that are mined and have known addresses
    try {
      var result = eval(input) // eslint-disable-line
      done(null, result)
    } catch (error) {
      done(error.message)
    }
  }
}

module.exports = Terminal
<|endoftext|>


<commit_before>/* global Node */
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var javascriptserialize = require('javascript-serialize')
var jsbeautify = require('js-beautify')
var type = require('component-type')
var EventManager = require('ethereum-remix').lib.EventManager

var css = csjs`
  .panel              {
    position          : relative;
    display           : flex;
    flex-direction    : column;
    font-size         : 12px;
    font-family       : monospace;
    color             : white;
    background-color  : grey;
    margin-top        : auto;
    height            : 100%;
    min-height        : 1.7em;
  }

  .bar                {
    display           : flex;
    justify-content   : flex-end;
    min-height        : 1.7em;
    padding           : 2px;
    cursor            : ns-resize;
    background-color  : #eef;
  }
  .minimize           {
    text-align        : center;
    padding-top       : 3px;
    width             : 10px;
    min-height        : 100%;
    cursor            : pointer;
    color             : black;
  }
  .hover              {
    color             : orange;
  }

  .terminal           {
    display           : flex;
    flex-direction    : column;
    height            : 100%;
    padding-left      : 5px;
    padding-right     : 5px;
    padding-bottom    : 3px;
    overflow-y        : auto;
    font-family       : monospace;
  }

  .log                {
    margin-top        : auto;
    font-family       : monospace;
  }
  .block              {
    word-break        : break-all;
    white-space       : pre-wrap;
    line-height       : 2ch;
    margin            : 1ch;
  }

  .cli                {
    line-height       : 1.7em;
    font-family       : monospace;
  }
  .prompt             {
    margin-right      : 0.5em;
    font-family       : monospace;
  }
  .input              {
    word-break        : break-all;
    outline           : none;
    font-family       : monospace;
  }
  .error              {
    color             : red;
  }
  .info               {
    color             : blue;
  }
  .default            {
    color             : white;
  }
  .ghostbar           {
    position          : absolute;
    height            : 6px;
    background-color  : #C6CFF7;
    opacity           : 0.5;
    cursor            : row-resize;
    z-index           : 9999;
    left              : 0;
    right             : 0;
  }
`

var currentError

window.addEventListener('error', function (event) {
  currentError = new Error(event.message)
  currentError.timeStamp = event.timeStamp
  currentError.isTrusted = event.isTrusted
  currentError.filename = event.filename
  currentError.lineno = event.lineno
  currentError.colno = event.colno
  currentError.error = event.error
  currentError.type = event.type
})

window.onerror = function (msg, url, lineno, col, error) {
  if (!error) error = currentError
  var val = { msg: msg, url: url, lineno: lineno, col: col, error: error }
  console.error(val)
}

var KONSOLES = []
// var KONSOLES = [{
//   error: console.error.bind(console),
//   info: console.info.bind(console),
//   log: console.log.bind(console)
// }]
// console.error = broadcast('error')
// console.info = broadcast('info')
// console.log = broadcast('log')
//
// function broadcast (mode) {
//   return function broadcastMode () {
//     var args = arguments
//     KONSOLES.forEach(function (api) { api[mode].apply(api, args) })
//   }
// }

function register (api) { KONSOLES.push(api) }

var ghostbar = yo`<div class=${css.ghostbar}></div>`

class Terminal {
  constructor (opts = { auto: true }) {
    var self = this
    self.data = {
      lineLength: opts.lineLength || 80,
      session: [],
      banner: opts.banner || `
/******************************************************************************

  ...........................................
  .....................:.....................
  ....................o:;....................
  ...................oo:;;...................
  ..................ooo:;;;..................
  .................oooo:;;;;.................
  ................ooooo:;;;;;................
  ...............oooooo:;;;;;;...............
  ..............ooooooo:;;;;;;;..............
  .............ooooooo;:';;;;;;;.............
  ............ooooo;;;;:'''';;;;;............
  ...........oo;;;;;;;;:'''''''';;...........
  ..........;;;;;;;;;;;:'''''''''''..........
  ..............;;;;;;;:'''''''..............
  ...........oo...;;;;;:'''''...;;...........
  ............oooo...;;:''...;;;;............
  ..............oooo...:...;;;;..............
  ...............oooooo:;;;;;;...............
  ................ooooo:;;;;;................
  .................oooo:;;;;.................
  ..................ooo:;;;..................
  ...................oo:;;...................
  ....................o:;....................
  .....................:.....................
  ...........................................

  ########  ######## ##     ## #### ##     ##
  ##     ## ##       ###   ###  ##   ##   ##
  ##     ## ##       #### ####  ##    ## ##
  ########  ######   ## ### ##  ##     ###
  ##   ##   ##       ##     ##  ##    ## ##
  ##    ##  ##       ##     ##  ##   ##   ##
  ##     ## ######## ##     ## #### ##     ##

  welcome to browser solidity

  new features:
    - dom terminal v0.0.1-alpha

******************************************************************************/
`
    }
    self.event = new EventManager()
    self._api = opts.api
    self._view = { panel: null, bar: null, input: null, term: null, log: null, cli: null }
    self._templates = {}
    self._templates.default = self._blocksRenderer('default')
    self._templates.error = self._blocksRenderer('error')
    self._templates.info = self._blocksRenderer('info')
    if (opts.shell) self._shell = opts.shell
    // @TODO: listen to all relevant events
    // var events = opts.events
    // events.txlistener.register('newBlock', function (block) {
    //   self.log(block)
    // })
    // events.udapp.register('transactionExecuted', function (address, data, lookupOnly, txResult) {
    //   self.log({ address, data, lookupOnly, txResult })
    //   // - trans.sent and info about it once it's mined
    //   // - everything related to the address
    // })
    register(self)
  }
  render () {
    var self = this
    if (self._view.panel) return self._view.panel
    self._view.log = yo`<div class=${css.log}></div>`
    self._view.input = yo`

    `
    self._view.cli = yo`

 self._view.input.focus()}>
        ${'>'}
        ${self._view.input}

    `
    self._view.icon = yo`<i onmouseenter=${hover} onmouseleave=${hover} onmousedown=${minimize} class="${css.minimize} fa fa-angle-double-down"></i>`
    self._view.bar = yo`

        ${self._view.icon}

    `
    self._view.term = yo`

        ${self._view.log}
        ${self._view.cli}

    `
    self._view.panel = yo`

        ${self._view.bar}
        ${self._view.term}

    `
    self.log(self.data.banner)

    function reattach (event) {
      var el = event.currentTarget
      var isBottomed = el.scrollHeight - el.scrollTop === el.clientHeight
      if (isBottomed) {
        delete self.scroll2bottom
        // @TODO: delete new message indicator
      } else {
        // self.scroll2bottom = function () { }
        // @TODO: the reattach is not working
        // @TODO: while in stopped mode: show indicator about new lines getting logged
      }
    }
    function hover (event) { event.currentTarget.classList.toggle(css.hover) }
    function minimize (event) {
      event.preventDefault()
      event.stopPropagation()
      var classList = self._view.icon.classList
      classList.toggle('fa-angle-double-down')
      classList.toggle('fa-angle-double-up')
      self.event.trigger('resize', [])
    }
    // ----------------- resizeable ui ---------------
    function mousedown (event) {
      event.preventDefault()
      if (event.which === 1) {
        moveGhostbar(event)
        document.body.appendChild(ghostbar)
        document.addEventListener('mousemove', moveGhostbar)
        document.addEventListener('mouseup', removeGhostbar)
        document.addEventListener('keydown', cancelGhostbar)
      }
    }
    function cancelGhostbar (event) {
      if (event.keyCode === 27) {
        document.body.removeChild(ghostbar)
        document.removeEventListener('mousemove', moveGhostbar)
        document.removeEventListener('mouseup', removeGhostbar)
        document.removeEventListener('keydown', cancelGhostbar)
      }
    }
    function moveGhostbar (event) { // @NOTE HORIZONTAL ghostbar
      ghostbar.style.top = self._api.getPosition(event) + 'px'
    }
    function removeGhostbar (event) {
      if (self._view.icon.classList.contains('fa-angle-double-up')) {
        self._view.icon.classList.toggle('fa-angle-double-down')
        self._view.icon.classList.toggle('fa-angle-double-up')
      }
      document.body.removeChild(ghostbar)
      document.removeEventListener('mousemove', moveGhostbar)
      document.removeEventListener('mouseup', removeGhostbar)
      document.removeEventListener('keydown', cancelGhostbar)
      self.event.trigger('resize', [self._api.getPosition(event)])
    }

    return self._view.panel

    function change (event) {
      if (event.which === 13) {
        if (event.ctrlKey) { // <ctrl+enter>
          self._view.input.appendChild(document.createElement('br'))
          self.scroll2bottom()
          putCursor2End(self._view.input)
        } else { // <enter>
          event.preventDefault()
          self.execute(self._view.input.innerText)
          self._view.input.innerHTML = ''
        }
      }
    }
    function putCursor2End (editable) {
      var range = document.createRange()
      range.selectNode(editable)
      var child = editable
      var chars

      while (child) {
        if (child.lastChild) child = child.lastChild
        else break
        if (child.nodeType === Node.TEXT_NODE) {
          chars = child.textContent.length
        } else {
          chars = child.innerHTML.length
        }
      }

      range.setEnd(child, chars)
      var toStart = true
      var toEnd = !toStart
      range.collapse(toEnd)

      var sel = window.getSelection()
      sel.removeAllRanges()
      sel.addRange(range)

      editable.focus()
    }
  }
  _blocksRenderer (mode) {
    var self = this
    var modes = { log: true, info: true, error: true, default: true }
    if (modes[mode]) {
      return function render () {
        var args = [].slice.call(arguments)
        var types = args.map(type)
        var values = javascriptserialize.apply(null, args).map(function (val, idx) {
          if (types[idx] === 'element') val = jsbeautify.html(val)
          var pattern = '.{1,' + self.data.lineLength + '}'
          var lines = val.match(new RegExp(pattern, 'g'))
          return lines.map(str => document.createTextNode(`${str}\n`))
        })
        return values
      }
    } else {
      throw new Error('mode is not supported')
    }
  }
  registerType (typename, template) {
    var self = this
    if (typeof template !== 'function') throw new Error('invalid template')
    self._templates[typename] = template
  }
  log () {
    var self = this
    var args = [...arguments]
    self.data.session.push(args)
    args.forEach(function (data = {}) {
      if (!data.type) data = { type: 'default', value: data }
      var render = self._templates[data.type]
      if (!render) render = self._templates.default
      var blocks = render(data.value)
      blocks = blocks instanceof Array ? blocks : [blocks]
      blocks.forEach(function (block) {
        self._view.log.appendChild(yo`

            ${block}

        `)
        self.scroll2bottom()
      })
    })
  }
  scroll2bottom () {
    var self = this
    setTimeout(function () {
      self._view.term.scrollTop = self._view.term.scrollHeight
    }, 0)
  }
  execute (input) {
    var self = this
    input = String(input)
    self.log(`> ${input}`)
    self._shell(input, function (error, output) {
      if (error) {
        self.error(error)
        return error
      } else {
        self.log(output)
        return output
      }
    })
  }
  _shell (input, done) { // default shell
    // @TODO: add environment and proxy console.log to self.log
    // make `web3` object available in the console vm
    // web3.object creates contract
    // * create transaction
    // * when transaction is mined
    //   => show all transactions, that are mined and have known addresses
    try {
      var result = eval(input) // eslint-disable-line
      done(null, result)
    } catch (error) {
      done(error.message)
    }
  }
}

module.exports = Terminal
<commit_msg>remove stories done<commit_after>/* global Node */
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var javascriptserialize = require('javascript-serialize')
var jsbeautify = require('js-beautify')
var type = require('component-type')
var EventManager = require('ethereum-remix').lib.EventManager

var css = csjs`
  .panel              {
    position          : relative;
    display           : flex;
    flex-direction    : column;
    font-size         : 12px;
    font-family       : monospace;
    color             : white;
    background-color  : grey;
    margin-top        : auto;
    height            : 100%;
    min-height        : 1.7em;
  }

  .bar                {
    display           : flex;
    justify-content   : flex-end;
    min-height        : 1.7em;
    padding           : 2px;
    cursor            : ns-resize;
    background-color  : #eef;
  }
  .minimize           {
    text-align        : center;
    padding-top       : 3px;
    width             : 10px;
    min-height        : 100%;
    cursor            : pointer;
    color             : black;
  }
  .hover              {
    color             : orange;
  }

  .terminal           {
    display           : flex;
    flex-direction    : column;
    height            : 100%;
    padding-left      : 5px;
    padding-right     : 5px;
    padding-bottom    : 3px;
    overflow-y        : auto;
    font-family       : monospace;
  }

  .log                {
    margin-top        : auto;
    font-family       : monospace;
  }
  .block              {
    word-break        : break-all;
    white-space       : pre-wrap;
    line-height       : 2ch;
    margin            : 1ch;
  }

  .cli                {
    line-height       : 1.7em;
    font-family       : monospace;
  }
  .prompt             {
    margin-right      : 0.5em;
    font-family       : monospace;
  }
  .input              {
    word-break        : break-all;
    outline           : none;
    font-family       : monospace;
  }
  .error              {
    color             : red;
  }
  .info               {
    color             : blue;
  }
  .default            {
    color             : white;
  }
  .ghostbar           {
    position          : absolute;
    height            : 6px;
    background-color  : #C6CFF7;
    opacity           : 0.5;
    cursor            : row-resize;
    z-index           : 9999;
    left              : 0;
    right             : 0;
  }
`

var currentError

window.addEventListener('error', function (event) {
  currentError = new Error(event.message)
  currentError.timeStamp = event.timeStamp
  currentError.isTrusted = event.isTrusted
  currentError.filename = event.filename
  currentError.lineno = event.lineno
  currentError.colno = event.colno
  currentError.error = event.error
  currentError.type = event.type
})

window.onerror = function (msg, url, lineno, col, error) {
  if (!error) error = currentError
  var val = { msg: msg, url: url, lineno: lineno, col: col, error: error }
  console.error(val)
}

var KONSOLES = []
// var KONSOLES = [{
//   error: console.error.bind(console),
//   info: console.info.bind(console),
//   log: console.log.bind(console)
// }]
// console.error = broadcast('error')
// console.info = broadcast('info')
// console.log = broadcast('log')
//
// function broadcast (mode) {
//   return function broadcastMode () {
//     var args = arguments
//     KONSOLES.forEach(function (api) { api[mode].apply(api, args) })
//   }
// }

function register (api) { KONSOLES.push(api) }

var ghostbar = yo`<div class=${css.ghostbar}></div>`

class Terminal {
  constructor (opts = { auto: true }) {
    var self = this
    self.data = {
      lineLength: opts.lineLength || 80,
      session: [],
      banner: opts.banner || `
/******************************************************************************

  ...........................................
  .....................:.....................
  ....................o:;....................
  ...................oo:;;...................
  ..................ooo:;;;..................
  .................oooo:;;;;.................
  ................ooooo:;;;;;................
  ...............oooooo:;;;;;;...............
  ..............ooooooo:;;;;;;;..............
  .............ooooooo;:';;;;;;;.............
  ............ooooo;;;;:'''';;;;;............
  ...........oo;;;;;;;;:'''''''';;...........
  ..........;;;;;;;;;;;:'''''''''''..........
  ..............;;;;;;;:'''''''..............
  ...........oo...;;;;;:'''''...;;...........
  ............oooo...;;:''...;;;;............
  ..............oooo...:...;;;;..............
  ...............oooooo:;;;;;;...............
  ................ooooo:;;;;;................
  .................oooo:;;;;.................
  ..................ooo:;;;..................
  ...................oo:;;...................
  ....................o:;....................
  .....................:.....................
  ...........................................

  ########  ######## ##     ## #### ##     ##
  ##     ## ##       ###   ###  ##   ##   ##
  ##     ## ##       #### ####  ##    ## ##
  ########  ######   ## ### ##  ##     ###
  ##   ##   ##       ##     ##  ##    ## ##
  ##    ##  ##       ##     ##  ##   ##   ##
  ##     ## ######## ##     ## #### ##     ##

  welcome to browser solidity

  new features:
    - dom terminal v0.0.1-alpha

******************************************************************************/
`
    }
    self.event = new EventManager()
    self._api = opts.api
    self._view = { panel: null, bar: null, input: null, term: null, log: null, cli: null }
    self._templates = {}
    self._templates.default = self._blocksRenderer('default')
    self._templates.error = self._blocksRenderer('error')
    self._templates.info = self._blocksRenderer('info')
    if (opts.shell) self._shell = opts.shell
    // @TODO: listen to all relevant events
    // var events = opts.events
    // events.txlistener.register('newBlock', function (block) {
    //   self.log(block)
    // })
    // events.udapp.register('transactionExecuted', function (address, data, lookupOnly, txResult) {
    //   self.log({ address, data, lookupOnly, txResult })
    //   // - trans.sent and info about it once it's mined
    //   // - everything related to the address
    // })
    register(self)
  }
  render () {
    var self = this
    if (self._view.panel) return self._view.panel
    self._view.log = yo`<div class=${css.log}></div>`
    self._view.input = yo`

    `
    self._view.cli = yo`

 self._view.input.focus()}>
        ${'>'}
        ${self._view.input}

    `
    self._view.icon = yo`<i onmouseenter=${hover} onmouseleave=${hover} onmousedown=${minimize} class="${css.minimize} fa fa-angle-double-down"></i>`
    self._view.bar = yo`

        ${self._view.icon}

    `
    self._view.term = yo`

        ${self._view.log}
        ${self._view.cli}

    `
    self._view.panel = yo`

        ${self._view.bar}
        ${self._view.term}

    `
    self.log(self.data.banner)

    function reattach (event) {
      var el = event.currentTarget
      var isBottomed = el.scrollHeight - el.scrollTop === el.clientHeight
      if (isBottomed) {
        delete self.scroll2bottom
        // @TODO: delete new message indicator
      } else {
        // self.scroll2bottom = function () { }
        // @TODO: the reattach is not working
        // @TODO: while in stopped mode: show indicator about new lines getting logged
      }
    }
    function hover (event) { event.currentTarget.classList.toggle(css.hover) }
    function minimize (event) {
      event.preventDefault()
      event.stopPropagation()
      var classList = self._view.icon.classList
      classList.toggle('fa-angle-double-down')
      classList.toggle('fa-angle-double-up')
      self.event.trigger('resize', [])
    }
    // ----------------- resizeable ui ---------------
    function mousedown (event) {
      event.preventDefault()
      if (event.which === 1) {
        moveGhostbar(event)
        document.body.appendChild(ghostbar)
        document.addEventListener('mousemove', moveGhostbar)
        document.addEventListener('mouseup', removeGhostbar)
        document.addEventListener('keydown', cancelGhostbar)
      }
    }
    function cancelGhostbar (event) {
      if (event.keyCode === 27) {
        document.body.removeChild(ghostbar)
        document.removeEventListener('mousemove', moveGhostbar)
        document.removeEventListener('mouseup', removeGhostbar)
        document.removeEventListener('keydown', cancelGhostbar)
      }
    }
    function moveGhostbar (event) { // @NOTE HORIZONTAL ghostbar
      ghostbar.style.top = self._api.getPosition(event) + 'px'
    }
    function removeGhostbar (event) {
      if (self._view.icon.classList.contains('fa-angle-double-up')) {
        self._view.icon.classList.toggle('fa-angle-double-down')
        self._view.icon.classList.toggle('fa-angle-double-up')
      }
      document.body.removeChild(ghostbar)
      document.removeEventListener('mousemove', moveGhostbar)
      document.removeEventListener('mouseup', removeGhostbar)
      document.removeEventListener('keydown', cancelGhostbar)
      self.event.trigger('resize', [self._api.getPosition(event)])
    }

    return self._view.panel

    function change (event) {
      if (event.which === 13) {
        if (event.ctrlKey) { // <ctrl+enter>
          self._view.input.appendChild(document.createElement('br'))
          self.scroll2bottom()
          putCursor2End(self._view.input)
        } else { // <enter>
          event.preventDefault()
          self.execute(self._view.input.innerText)
          self._view.input.innerHTML = ''
        }
      }
    }
    function putCursor2End (editable) {
      var range = document.createRange()
      range.selectNode(editable)
      var child = editable
      var chars

      while (child) {
        if (child.lastChild) child = child.lastChild
        else break
        if (child.nodeType === Node.TEXT_NODE) {
          chars = child.textContent.length
        } else {
          chars = child.innerHTML.length
        }
      }

      range.setEnd(child, chars)
      var toStart = true
      var toEnd = !toStart
      range.collapse(toEnd)

      var sel = window.getSelection()
      sel.removeAllRanges()
      sel.addRange(range)

      editable.focus()
    }
  }
  _blocksRenderer (mode) {
    var self = this
    var modes = { log: true, info: true, error: true, default: true }
    if (modes[mode]) {
      return function render () {
        var args = [].slice.call(arguments)
        var types = args.map(type)
        var values = javascriptserialize.apply(null, args).map(function (val, idx) {
          if (types[idx] === 'element') val = jsbeautify.html(val)
          var pattern = '.{1,' + self.data.lineLength + '}'
          var lines = val.match(new RegExp(pattern, 'g'))
          return lines.map(str => document.createTextNode(`${str}\n`))
        })
        return values
      }
    } else {
      throw new Error('mode is not supported')
    }
  }
  registerType (typename, template) {
    var self = this
    if (typeof template !== 'function') throw new Error('invalid template')
    self._templates[typename] = template
  }
  log () {
    var self = this
    var args = [...arguments]
    self.data.session.push(args)
    args.forEach(function (data = {}) {
      if (!data.type) data = { type: 'default', value: data }
      var render = self._templates[data.type]
      if (!render) render = self._templates.default
      var blocks = render(data.value)
      blocks = blocks instanceof Array ? blocks : [blocks]
      blocks.forEach(function (block) {
        self._view.log.appendChild(yo`

            ${block}

        `)
        self.scroll2bottom()
      })
    })
  }
  scroll2bottom () {
    var self = this
    setTimeout(function () {
      self._view.term.scrollTop = self._view.term.scrollHeight
    }, 0)
  }
  execute (input) {
    var self = this
    input = String(input)
    self.log(`> ${input}`)
    self._shell(input, function (error, output) {
      if (error) {
        self.error(error)
        return error
      } else {
        self.log(output)
        return output
      }
    })
  }
  _shell (input, done) { // default shell
    // @TODO: add environment and proxy console.log to self.log
    // make `web3` object available in the console vm
    try {
      var result = eval(input) // eslint-disable-line
      done(null, result)
    } catch (error) {
      done(error.message)
    }
  }
}

module.exports = Terminal
<|endoftext|>