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

	window.KC3Translation = {
		/* EXECUTE
		Triggers translations into current page
		-----------------------------------------*/
		execute :function(){
			this.applyWords();
			this.applyHTML();
		},

		/* APPLY WORDS
		Change words inside visible DOM elements
		-----------------------------------------*/
		applyWords :function(){
			// Interchange element contents with translations
			$(".i18n").each(function(){
				$(this).html( KC3Meta.term( $(this).text() ) );
				$(this).css("visibility", "visible");
			});
			// Update title attribute with translations
			$(".i18n_title").each(function(){
				$(this).attr("title", KC3Meta.term( $(this).attr("title") ) );
			});
		},

		/* APPLY HTML
		Specialized Language HTML adjustments
		-----------------------------------------*/
		applyHTML :function(){
			// Specialized fonts
			var fontFamily = false;
			switch(ConfigManager.language){

				case "scn": fontFamily = '"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue",Helvetica,"Nimbus Sans L",Arial,"Lucida Grande","Liberation Sans","Microsoft YaHei UI","Microsoft YaHei","Hiragino Sans GB","Wenquanyi Micro Hei","WenQuanYi Zen Hei","ST Heiti",SimHei,"WenQuanYi Zen Hei Sharp",sans-serif'; break;

				case "jp": fontFamily = '"Helvetica Neue", "Tahoma", Helvetica, Arial, "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", Osaka, "メイリオ", "Meiryo", "Yu Gothic UI Semibold", "ＭＳ Ｐゴシック", "MS PGothic", sans-serif'; break;

				default: break;
			}

			if(fontFamily){ $("body").css("font-family", fontFamily); }

			// Apply HTML language code
			$("html").attr("lang", ConfigManager.language);
		},

		/*
		  Recursively changing any non-object value "v" into "{val: v, tag: <tag>}".
		 */
		addTags: function(obj, tag) {
			function track(obj) {
				if (typeof obj === "object") {
					$.each( obj, function(k,v) {
						// should work for both arrays and objects
						obj[k] = track(v);
					});
				} else {
					return {val: obj, tag: tag};
				}
				return obj;
			}

			console.assert(
				typeof obj === "object",
				"addTags should only be applied on objects");
			return track(obj);
		},

		getJSONWithOptions: function(repo, filename, extendEnglish,
									 language, info_force_ship_lang, info_eng_stype,
									 track_source) {
			var self = this;

			if (filename === "quotes") {
				console.log("warning: using KC3Translation.getQuotes to get quotes");
				return this.getQuotes(repo);
			}

			// Check if desired to extend english files
			if (typeof extendEnglish=="undefined") { extendEnglish=false; }
			if (typeof track_source==="undefined") { track_source = false; }

			// Japanese special case where ships and items sources are already in JP
			if(
				(["jp", "tcn"].indexOf(language) > -1)
				&& (filename==="ships" || filename==="items")
			){
				extendEnglish = false;
			}
			// make ships.json and items.json an option to be always in specified one
			if (!!info_force_ship_lang
				&& (filename==="ships" || filename==="items")){
				extendEnglish = false;
				language = info_force_ship_lang;
			}
			// make "stype.json" an option:
			if (filename === "stype" && info_eng_stype){
				language = "en";
			}

			var translationBase = {}, enJSON;
			if(extendEnglish && language!="en"){
				// Load english file
				enJSON = JSON.parse($.ajax({
					url : repo+'lang/data/en/' + filename + '.json',
					async: false
				}).responseText);

				if (track_source) {
					self.addTags(enJSON, "en");
				}

				// Make is as the translation base
				translationBase = enJSON;
			}

			// if we can't fetch this file, the English
			// version will be used instead
			var translation;
			try {
				translation = JSON.parse($.ajax({
					url : repo+'lang/data/' +language+ '/' + filename + '.json',
					async: false
				}).responseText);

				if (track_source) {
					self.addTags(translation, language);
				}
			} catch (e) {
				if (e instanceof SyntaxError && extendEnglish && language!="en"){
					console.warn(e.stack);
					translation = null;
				} else {
					throw e;
				}
			}
			return $.extend(true, translationBase, translation);
		},

		// insert quote id as key if descriptive key is used.
		transformQuotes: function(quotes) {
			function isIntStr(s) {
				return parseInt(s,10).toString() === s;
			}

			var descToId = {
				"Intro" : 1,
				"Library" : 25,
				"Poke(1)" : 2,
				"Poke(2)" : 3,
				"Poke(3)" : 4,
				"Married" : 28,
				"Wedding" : 24,
				"Ranking" : 8,
				"Join" : 13,
				"Equip(1)" : 9,
				"Equip(2)" : 10,
				"Equip(3)" : 26,
				"Supply" : 27,
				"Docking(1)" : 11,
				"Docking(2)" : 12,
				"Construction" : 5,
				"Return" : 7,
				"Sortie" : 14,
				"Battle" : 15,
				"Attack" : 16,
				"Yasen(1)" : 18,
				"Yasen(2)" : 17,
				"MVP" : 23,
				"Damaged(1)" : 19,
				"Damaged(2)" : 20,
				"Damaged(3)" : 21,
				"Sunk" : 22,
				"Idle" : 29,
				"Repair" : 6,

				"H0000":30, "H0100":31, "H0200":32, "H0300":33,
				"H0400":34, "H0500":35, "H0600":36, "H0700":37,
				"H0800":38, "H0900":39, "H1000":40, "H1100":41,
				"H1200":42, "H1300":43, "H1400":44, "H1500":45,
				"H1600":46, "H1700":47, "H1800":48, "H1900":49,
				"H2000":50, "H2100":51, "H2200":52, "H2300":53
			};
			$.each( quotes, function(k,v) {
				if (! isIntStr(k) )
					return;
				// transforming "v" object

				// get an immutable list of keys for further operation
				var subKeys = Object.keys(v);
				$.each(subKeys, function(i,subKey) {
					var subId = descToId[subKey];
					if (subId) {
						// force overwriting regardless of original content

						// empty content not replaced
						if (v[subKey] && v[subKey].length) {
							v[subId] = v[subKey];
						}
					} else {
						if (! isIntStr(subKey) ) {
							// neither a descriptive key nor a normal number
							console.warn( "Unrecognized subtitle key: " + subKey
										  + " (masterId=" + k + ")");
						}
					}
				});

			});
			return quotes;
		},

		getQuotes: function(repo) {
			// we always use English version quotes as the base,
			// assuming all quotes are complete so there
			// is no need to extend the table by considering pre-remodel ship quotes.
			var	enJSON = {};
			var language = ConfigManager.language;
			try {
				enJSON = JSON.parse($.ajax({
					url : repo+'lang/data/en/quotes.json',
					async: false
				}).responseText);
			} catch(e) {
				if (e instanceof SyntaxError){
					console.warn(e.stack);
					translation = null;
				} else {
					throw e;
				}
			}

			// if it's already English the we are done.
			if (language === "en") return enJSON;

			// load language specific quotes.json
			var langJSON;
			try {
				langJSON = JSON.parse($.ajax({
					url : repo+'lang/data/' +language+ '/quotes.json',
					async: false
				}).responseText);
			} catch (e) {
				console.warn("failed to retrieve language specific quotes.");
				if (e instanceof SyntaxError){
					console.warn(e.stack);
					console.log("falling back to eng version");
					return enJSON;
				} else {
					throw e;
				}
			}

			// 1st pass: interpret descriptive keys as keys
			this.transformQuotes(langJSON);

			// extend quotes by reusing ship's pre-remodels
			// 2nd pass: extend langJSON by considering pre-models
			if (typeof RemodelDb !== "undefined" && typeof RemodelDb._db !== "undefined") {
				$.each(RemodelDb._db.remodelGroups, function(orgShipIdStr,groupInfo) {
					// a group of ship ids that consider as "same ship"
					// sorted by remodels
					var group = groupInfo.group;

					var i,curShipId;
					// accumulate quotes
					var curQuotes = {};
					var q;
					for (i=0; i<group.length; ++i) {
						curShipId = group[i];
						// implicit casting index from num to str
						q = langJSON[curShipId] || {};
						// accumulate to curQuotes
						curQuotes = $.extend(true, {}, curQuotes, q);
						// note that curQuotes now refers to a different obj
						// and we haven't done any modification on curQuotes
						// so it's safe to be assigned to a table
						langJSON[curShipId] = curQuotes;
					}
				});
			} else {
				console.warn("Translation: failed to load RemodelDb, " +
							 "please make sure it's been initialized properly");
			}

			// 3rd pass: extend langJSON using enJSON to fill in any missing parts
			langJSON = $.extend(true, {}, enJSON, langJSON);
			return langJSON;
		},

		/* GET JSON
		Used by KC3Meta.js to load json files
		-----------------------------------------*/
		getJSON :function(repo, filename, extendEnglish){
			return this.getJSONWithOptions(
				repo,
				filename,
				extendEnglish,
				ConfigManager.language,
				ConfigManager.info_force_ship_lang,
				ConfigManager.info_eng_stype);
		}

	};

})();
<commit_msg>source tracking on getQuotes<commit_after>(function(){
	"use strict";

	window.KC3Translation = {
		/* EXECUTE
		Triggers translations into current page
		-----------------------------------------*/
		execute :function(){
			this.applyWords();
			this.applyHTML();
		},

		/* APPLY WORDS
		Change words inside visible DOM elements
		-----------------------------------------*/
		applyWords :function(){
			// Interchange element contents with translations
			$(".i18n").each(function(){
				$(this).html( KC3Meta.term( $(this).text() ) );
				$(this).css("visibility", "visible");
			});
			// Update title attribute with translations
			$(".i18n_title").each(function(){
				$(this).attr("title", KC3Meta.term( $(this).attr("title") ) );
			});
		},

		/* APPLY HTML
		Specialized Language HTML adjustments
		-----------------------------------------*/
		applyHTML :function(){
			// Specialized fonts
			var fontFamily = false;
			switch(ConfigManager.language){

				case "scn": fontFamily = '"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue",Helvetica,"Nimbus Sans L",Arial,"Lucida Grande","Liberation Sans","Microsoft YaHei UI","Microsoft YaHei","Hiragino Sans GB","Wenquanyi Micro Hei","WenQuanYi Zen Hei","ST Heiti",SimHei,"WenQuanYi Zen Hei Sharp",sans-serif'; break;

				case "jp": fontFamily = '"Helvetica Neue", "Tahoma", Helvetica, Arial, "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", Osaka, "メイリオ", "Meiryo", "Yu Gothic UI Semibold", "ＭＳ Ｐゴシック", "MS PGothic", sans-serif'; break;

				default: break;
			}

			if(fontFamily){ $("body").css("font-family", fontFamily); }

			// Apply HTML language code
			$("html").attr("lang", ConfigManager.language);
		},

		/*
		  Recursively changing any non-object value "v" into "{val: v, tag: <tag>}".
		 */
		addTags: function(obj, tag) {
			function track(obj) {
				if (typeof obj === "object") {
					$.each( obj, function(k,v) {
						// should work for both arrays and objects
						obj[k] = track(v);
					});
				} else {
					return {val: obj, tag: tag};
				}
				return obj;
			}

			console.assert(
				typeof obj === "object",
				"addTags should only be applied on objects");
			return track(obj);
		},

		getJSONWithOptions: function(repo, filename, extendEnglish,
									 language, info_force_ship_lang, info_eng_stype,
									 track_source) {
			var self = this;

			if (filename === "quotes") {
				console.log("warning: using KC3Translation.getQuotes to get quotes");
				return this.getQuotes(repo);
			}

			// Check if desired to extend english files
			if (typeof extendEnglish=="undefined") { extendEnglish=false; }
			if (typeof track_source==="undefined") { track_source = false; }

			// Japanese special case where ships and items sources are already in JP
			if(
				(["jp", "tcn"].indexOf(language) > -1)
				&& (filename==="ships" || filename==="items")
			){
				extendEnglish = false;
			}
			// make ships.json and items.json an option to be always in specified one
			if (!!info_force_ship_lang
				&& (filename==="ships" || filename==="items")){
				extendEnglish = false;
				language = info_force_ship_lang;
			}
			// make "stype.json" an option:
			if (filename === "stype" && info_eng_stype){
				language = "en";
			}

			var translationBase = {}, enJSON;
			if(extendEnglish && language!="en"){
				// Load english file
				enJSON = JSON.parse($.ajax({
					url : repo+'lang/data/en/' + filename + '.json',
					async: false
				}).responseText);

				if (track_source) {
					self.addTags(enJSON, "en");
				}

				// Make is as the translation base
				translationBase = enJSON;
			}

			// if we can't fetch this file, the English
			// version will be used instead
			var translation;
			try {
				translation = JSON.parse($.ajax({
					url : repo+'lang/data/' +language+ '/' + filename + '.json',
					async: false
				}).responseText);

				if (track_source) {
					self.addTags(translation, language);
				}
			} catch (e) {
				if (e instanceof SyntaxError && extendEnglish && language!="en"){
					console.warn(e.stack);
					translation = null;
				} else {
					throw e;
				}
			}
			return $.extend(true, translationBase, translation);
		},

		// insert quote id as key if descriptive key is used.
		transformQuotes: function(quotes) {
			function isIntStr(s) {
				return parseInt(s,10).toString() === s;
			}

			var descToId = {
				"Intro" : 1,
				"Library" : 25,
				"Poke(1)" : 2,
				"Poke(2)" : 3,
				"Poke(3)" : 4,
				"Married" : 28,
				"Wedding" : 24,
				"Ranking" : 8,
				"Join" : 13,
				"Equip(1)" : 9,
				"Equip(2)" : 10,
				"Equip(3)" : 26,
				"Supply" : 27,
				"Docking(1)" : 11,
				"Docking(2)" : 12,
				"Construction" : 5,
				"Return" : 7,
				"Sortie" : 14,
				"Battle" : 15,
				"Attack" : 16,
				"Yasen(1)" : 18,
				"Yasen(2)" : 17,
				"MVP" : 23,
				"Damaged(1)" : 19,
				"Damaged(2)" : 20,
				"Damaged(3)" : 21,
				"Sunk" : 22,
				"Idle" : 29,
				"Repair" : 6,

				"H0000":30, "H0100":31, "H0200":32, "H0300":33,
				"H0400":34, "H0500":35, "H0600":36, "H0700":37,
				"H0800":38, "H0900":39, "H1000":40, "H1100":41,
				"H1200":42, "H1300":43, "H1400":44, "H1500":45,
				"H1600":46, "H1700":47, "H1800":48, "H1900":49,
				"H2000":50, "H2100":51, "H2200":52, "H2300":53
			};
			$.each( quotes, function(k,v) {
				if (! isIntStr(k) )
					return;
				// transforming "v" object

				// get an immutable list of keys for further operation
				var subKeys = Object.keys(v);
				$.each(subKeys, function(i,subKey) {
					var subId = descToId[subKey];
					if (subId) {
						// force overwriting regardless of original content

						// empty content not replaced
						if (v[subKey] && v[subKey].length) {
							v[subId] = v[subKey];
						}
					} else {
						if (! isIntStr(subKey) ) {
							// neither a descriptive key nor a normal number
							console.warn( "Unrecognized subtitle key: " + subKey
										  + " (masterId=" + k + ")");
						}
					}
				});

			});
			return quotes;
		},

		getQuotes: function(repo, track) {
			var self = this;
			if (typeof track === "undefined")
				track = false;

			// we always use English version quotes as the base,
			// assuming all quotes are complete so there
			// is no need to extend the table by considering pre-remodel ship quotes.
			var	enJSON = {};
			var language = ConfigManager.language;
			try {
				enJSON = JSON.parse($.ajax({
					url : repo+'lang/data/en/quotes.json',
					async: false
				}).responseText);
				if (track) {
					self.addTags(enJSON,"en");
				}
			} catch(e) {
				if (e instanceof SyntaxError){
					console.warn(e.stack);
					translation = null;
				} else {
					throw e;
				}
			}

			// if it's already English the we are done.
			if (language === "en") return enJSON;

			// load language specific quotes.json
			var langJSON;
			try {
				langJSON = JSON.parse($.ajax({
					url : repo+'lang/data/' +language+ '/quotes.json',
					async: false
				}).responseText);
			} catch (e) {
				console.warn("failed to retrieve language specific quotes.");
				if (e instanceof SyntaxError){
					console.warn(e.stack);
					console.log("falling back to eng version");
					return enJSON;
				} else {
					throw e;
				}
			}

			// 1st pass: interpret descriptive keys as keys
			this.transformQuotes(langJSON);
			if (track) {
				self.addTags(langJSON,language);
			}

			// extend quotes by reusing ship's pre-remodels
			// 2nd pass: extend langJSON by considering pre-models
			if (typeof RemodelDb !== "undefined" && typeof RemodelDb._db !== "undefined") {
				$.each(RemodelDb._db.remodelGroups, function(orgShipIdStr,groupInfo) {
					// a group of ship ids that consider as "same ship"
					// sorted by remodels
					var group = groupInfo.group;

					var i,curShipId;
					// accumulate quotes
					var curQuotes = {};
					var q;
					for (i=0; i<group.length; ++i) {
						curShipId = group[i];
						// implicit casting index from num to str
						q = langJSON[curShipId] || {};
						if (track) {
							$.each(q,function(k,v) {
								q[k].tag = curShipId;
							});
						}
						// accumulate to curQuotes
						curQuotes = $.extend(true, {}, curQuotes, q);
						// note that curQuotes now refers to a different obj
						// and we haven't done any modification on curQuotes
						// so it's safe to be assigned to a table
						langJSON[curShipId] = curQuotes;
					}
				});
			} else {
				console.warn("Translation: failed to load RemodelDb, " +
							 "please make sure it's been initialized properly");
			}

			// 3rd pass: extend langJSON using enJSON to fill in any missing parts
			langJSON = $.extend(true, {}, enJSON, langJSON);
			return langJSON;
		},

		/* GET JSON
		Used by KC3Meta.js to load json files
		-----------------------------------------*/
		getJSON :function(repo, filename, extendEnglish){
			return this.getJSONWithOptions(
				repo,
				filename,
				extendEnglish,
				ConfigManager.language,
				ConfigManager.info_force_ship_lang,
				ConfigManager.info_eng_stype);
		}

	};

})();
<|endoftext|>


<commit_before>'use strict';

var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var util = util || bitcore.util;
var buffertools = require('buffertools');

var should = chai.should();

var Key = bitcore.Key;
describe('Key randomness tests', function() {
  var RUNS = 32;
  it('should pass Frequency (Monobits) Test', function() {
    /*
    Description: The focus of the test is the proportion
    of zeroes and ones for the entire sequence. The purpose
    of this test is to determine whether that number of
    ones and zeros in a sequence are approximately the same
    as would be expected for a truly random sequence. The
    test assesses the closeness of the fraction of ones to ½,
    that is, the number of ones and zeroes in a sequence
    should be about the same.
    */
    var count = [0, 0];
    for (var i = 0; i < RUNS; i++) {
      var key = Key.generateSync().private;
      for (var j = 0; j < key.length; j++) {
        var b = key[j];
        for (var k = 0; k < 8; k++) {
          var bitk = (b >> k) & 1;
          count[bitk] += 1;
        }
      }
    }
    var p0 = count[0] / (count[0] + count[1]);
    (p0-0.5).should.be.below(0.01);
  });

  it('should pass Test For Frequency Within A Block', function() {
    /*
    Description: The focus of the test is the proportion
    of zeroes and ones within M-bit blocks. The purpose
    of this test is to determine whether the frequency
    of ones in an M-bit block is approximately M/2.
    Test for M=8
    */
    var ones = 0;
    var count = 0;
    for (var i = 0; i < RUNS; i++) {
      var key = Key.generateSync().private;
      for (var j = 0; j < key.length; j++) {
        var b = key[j];
        for (var k = 0; k < 8; k++) {
          var bitk = (b >> k) & 1;
          ones += bitk;
        }
        count += 8;
      }
    }
    var p1 = ones/count;
    (p1-0.5).should.be.below(0.01);
  });
  var getBitInByte = function(b, index) {
    return (b >> index) & 1;
  };
  var getBitInKey = function(key, index) {
    var bindex = parseInt(index / 8);
    return getBitInByte(key[bindex], index - bindex * 8);
  };
  var getBitInKeys = function(keys, index) {
    var kindex = parseInt(index / (keys[0].length*8));
    return getBitInKey(keys[kindex], index - (keys[0].length*8) * kindex);
  };
  it('should pass Runs Test', function() {
    var keys = [];
    for (var i = 0; i < RUNS; i++) {
      keys.push(Key.generateSync().private);
    }
    var prev = -1;
    var count = 0;
    var h = {};
    var bits = RUNS * keys[0].length * 8;
    for (i = 0; i < bits; i++) {
      var b = getBitInKeys(keys, i);
      if (prev !== b) {
        h[count] = (h[count] || 0) + 1;
        count = 0;
        prev = b;
      }
      count += 1;
    }
    var ratio = 0;
    count = 0;
    for(i = 1; i < 8; i++) {
      var next = h[i+1];
      var current = h[i];
      if (typeof current === 'undefined' || current === 0) continue;
      if (typeof next === 'undefined') continue;
      var r = next / current;
      ratio += r * current;
      count += 1 * current;
    }
    var p = ratio / count;
    (p-0.5).should.be.below(0.01);

  });
  it('should pass Test For The Longest Run Of Ones In A Block', function() {
  });
  it('should pass Random Binary Matrix Rank Test', function() {
  });
  it('should pass Discrete Fourier Transform (Spectral) Test', function() {
  });
  it('should pass Non-Overlapping (Aperiodic) Template Matching Test', function() {
  });
  it('should pass Overlapping (Periodic) Template Matching Test', function() {
  });
  it('should pass Maurers Universal Statistical Test', function() {
  });
  it('should pass Linear Complexity Test', function() {
  });
  it('should pass Serial Test', function() {
  });
  it('should pass Approximate Entropy Test', function() {
  });
  it('should pass Cumulative Sum (Cusum) Test', function() {
  });
  it('should pass Random Excursions Test', function() {
  });
  it('should pass Random Excursions Variant Test', function() {
  });
});
<commit_msg>skip pending tests:wq<commit_after>'use strict';

var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var util = util || bitcore.util;
var buffertools = require('buffertools');

var should = chai.should();

var Key = bitcore.Key;
describe('Key randomness tests', function() {
  var RUNS = 32;
  it('should pass Frequency (Monobits) Test', function() {
    /*
    Description: The focus of the test is the proportion
    of zeroes and ones for the entire sequence. The purpose
    of this test is to determine whether that number of
    ones and zeros in a sequence are approximately the same
    as would be expected for a truly random sequence. The
    test assesses the closeness of the fraction of ones to ½,
    that is, the number of ones and zeroes in a sequence
    should be about the same.
    */
    var count = [0, 0];
    for (var i = 0; i < RUNS; i++) {
      var key = Key.generateSync().private;
      for (var j = 0; j < key.length; j++) {
        var b = key[j];
        for (var k = 0; k < 8; k++) {
          var bitk = (b >> k) & 1;
          count[bitk] += 1;
        }
      }
    }
    var p0 = count[0] / (count[0] + count[1]);
    (p0-0.5).should.be.below(0.01);
  });

  it('should pass Test For Frequency Within A Block', function() {
    /*
    Description: The focus of the test is the proportion
    of zeroes and ones within M-bit blocks. The purpose
    of this test is to determine whether the frequency
    of ones in an M-bit block is approximately M/2.
    Test for M=8
    */
    var ones = 0;
    var count = 0;
    for (var i = 0; i < RUNS; i++) {
      var key = Key.generateSync().private;
      for (var j = 0; j < key.length; j++) {
        var b = key[j];
        for (var k = 0; k < 8; k++) {
          var bitk = (b >> k) & 1;
          ones += bitk;
        }
        count += 8;
      }
    }
    var p1 = ones/count;
    (p1-0.5).should.be.below(0.01);
  });
  var getBitInByte = function(b, index) {
    return (b >> index) & 1;
  };
  var getBitInKey = function(key, index) {
    var bindex = parseInt(index / 8);
    return getBitInByte(key[bindex], index - bindex * 8);
  };
  var getBitInKeys = function(keys, index) {
    var kindex = parseInt(index / (keys[0].length*8));
    return getBitInKey(keys[kindex], index - (keys[0].length*8) * kindex);
  };
  it('should pass Runs Test', function() {
    var keys = [];
    for (var i = 0; i < RUNS; i++) {
      keys.push(Key.generateSync().private);
    }
    var prev = -1;
    var count = 0;
    var h = {};
    var bits = RUNS * keys[0].length * 8;
    for (i = 0; i < bits; i++) {
      var b = getBitInKeys(keys, i);
      if (prev !== b) {
        h[count] = (h[count] || 0) + 1;
        count = 0;
        prev = b;
      }
      count += 1;
    }
    var ratio = 0;
    count = 0;
    for(i = 1; i < 8; i++) {
      var next = h[i+1];
      var current = h[i];
      if (typeof current === 'undefined' || current === 0) continue;
      if (typeof next === 'undefined') continue;
      var r = next / current;
      ratio += r * current;
      count += 1 * current;
    }
    var p = ratio / count;
    (p-0.5).should.be.below(0.01);

  });
  it.skip('should pass Test For The Longest Run Of Ones In A Block', function() {
  });
  it.skip('should pass Random Binary Matrix Rank Test', function() {
  });
  it.skip('should pass Discrete Fourier Transform (Spectral) Test', function() {
  });
  it.skip('should pass Non-Overlapping (Aperiodic) Template Matching Test', function() {
  });
  it.skip('should pass Overlapping (Periodic) Template Matching Test', function() {
  });
  it.skip('should pass Maurers Universal Statistical Test', function() {
  });
  it.skip('should pass Linear Complexity Test', function() {
  });
  it.skip('should pass Serial Test', function() {
  });
  it.skip('should pass Approximate Entropy Test', function() {
  });
  it.skip('should pass Cumulative Sum (Cusum) Test', function() {
  });
  it.skip('should pass Random Excursions Test', function() {
  });
  it.skip('should pass Random Excursions Variant Test', function() {
  });
});
<|endoftext|>


<commit_before>(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Animato=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){var process=module.exports={};var queue=[];var draining=false;var currentQueue;var queueIndex=-1;function cleanUpNextTick(){draining=false;if(currentQueue.length){queue=currentQueue.concat(queue)}else{queueIndex=-1}if(queue.length){drainQueue()}}function drainQueue(){if(draining){return}var timeout=setTimeout(cleanUpNextTick);draining=true;var len=queue.length;while(len){currentQueue=queue;queue=[];while(++queueIndex<len){currentQueue[queueIndex].run()}queueIndex=-1;len=queue.length}currentQueue=null;draining=false;clearTimeout(timeout)}process.nextTick=function(fun){var args=new Array(arguments.length-1);if(arguments.length>1){for(var i=1;i<arguments.length;i++){args[i-1]=arguments[i]}}queue.push(new Item(fun,args));if(queue.length===1&&!draining){setTimeout(drainQueue,0)}};function Item(fun,array){this.fun=fun;this.array=array}Item.prototype.run=function(){this.fun.apply(null,this.array)};process.title="browser";process.browser=true;process.env={};process.argv=[];process.version="";process.versions={};function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")};process.umask=function(){return 0}},{}],2:[function(require,module,exports){var Raf=require("raf");function Animato(from,to,time,step,complete){if(arguments.length===1&&from&&typeof from.from==="object"&&typeof from.to==="object"){return new Animato(from.from,from.to,from.duration,from.step,from.complete)}if(this.constructor!==Animato){return new Animato(from,to,time,step,complete)}this._from=from;this._inter={};this._to=to||null;this._duration=time||200;this._step=step||function(){};this._complete=function(){};if(typeof complete==="function"){this.start(complete)}}Animato.prototype.to=function(to){this._to=to;return this};Animato.prototype.duration=function(duration){this._duration=duration;return this};Animato.prototype.step=function(fn){this._step=fn;return this};Animato.prototype.complete=function(fn){this._complete=fn;return this};Animato.prototype.start=function(fn){var self=this;self.deltas={};for(var k in self._from){if(!self._from.hasOwnProperty(k))continue;self.deltas[k]=self._to[k]-self._from[k]}if(typeof fn==="function"){this._complete=fn}self._step(self._from);return Raf(function tick(delta){var proc=delta/self._duration,k;for(k in self._from){if(!self._from.hasOwnProperty(k))continue;self._inter[k]=self._from[k]+self.deltas[k]*proc}if(proc>=1){self._step(self._to);return self._complete()}self._step(self._inter);Raf(tick)})};Animato.Frames=function(from,to,count){if(this.constructor!==Animato.Frames){return new Animato.Frames(from,to,count)}this._from=from;this._to=to;this._count=count;this._step=function(){};this._complete=function(){};this._duration=200};Animato.Frames.prototype.toArray=function(){var frames=[this._from],deltas={},steps={},inter={},k=null;for(k in this._from){if(!this._from.hasOwnProperty(k))continue;steps[k]=(deltas[k]=this._to[k]-this._from[k])/this._count}for(var i=1;i<this._count;++i){inter={};for(k in this._from){if(!this._from.hasOwnProperty(k))continue;inter[k]=this._from[k]+steps[k]*i}frames.push(inter)}frames.push(this._to);return frames};Animato.Frames.prototype.step=function(fn){this._step=fn||this._step;return this};Animato.Frames.prototype.duration=function(duration){this._duration=duration;return this};Animato.Frames.prototype.start=function(fn){var self=this,frames=this.toArray(),delay=this._duration/this._count,index=-1,interval=setInterval(function(){var frame=frames[--index];if(!frame){return self._complete()}self._step(frame)},delay);self._complete=fn||self._complete};module.exports=Animato},{raf:3}],3:[function(require,module,exports){var now=require("performance-now"),global=typeof window==="undefined"?{}:window,vendors=["moz","webkit"],suffix="AnimationFrame",raf=global["request"+suffix],caf=global["cancel"+suffix]||global["cancelRequest"+suffix];for(var i=0;i<vendors.length&&!raf;i++){raf=global[vendors[i]+"Request"+suffix];caf=global[vendors[i]+"Cancel"+suffix]||global[vendors[i]+"CancelRequest"+suffix]}if(!raf||!caf){var last=0,id=0,queue=[],frameDuration=1e3/60;raf=function(callback){if(queue.length===0){var _now=now(),next=Math.max(0,frameDuration-(_now-last));last=next+_now;setTimeout(function(){var cp=queue.slice(0);queue.length=0;for(var i=0;i<cp.length;i++){if(!cp[i].cancelled){try{cp[i].callback(last)}catch(e){setTimeout(function(){throw e},0)}}}},Math.round(next))}queue.push({handle:++id,callback:callback,cancelled:false});return id};caf=function(handle){for(var i=0;i<queue.length;i++){if(queue[i].handle===handle){queue[i].cancelled=true}}}}module.exports=function(fn){return raf.call(global,fn)};module.exports.cancel=function(){caf.apply(global,arguments)}},{"performance-now":4}],4:[function(require,module,exports){(function(process){(function(){var getNanoSeconds,hrtime,loadTime;if(typeof performance!=="undefined"&&performance!==null&&performance.now){module.exports=function(){return performance.now()}}else if(typeof process!=="undefined"&&process!==null&&process.hrtime){module.exports=function(){return(getNanoSeconds()-loadTime)/1e6};hrtime=process.hrtime;getNanoSeconds=function(){var hr;hr=hrtime();return hr[0]*1e9+hr[1]};loadTime=getNanoSeconds()}else if(Date.now){module.exports=function(){return Date.now()-loadTime};loadTime=Date.now()}else{module.exports=function(){return(new Date).getTime()-loadTime};loadTime=(new Date).getTime()}}).call(this)}).call(this,require("_process"))},{_process:1}]},{},[2])(2)});<commit_msg>Rebuild<commit_after>(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Animato=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){var process=module.exports={};var queue=[];var draining=false;var currentQueue;var queueIndex=-1;function cleanUpNextTick(){draining=false;if(currentQueue.length){queue=currentQueue.concat(queue)}else{queueIndex=-1}if(queue.length){drainQueue()}}function drainQueue(){if(draining){return}var timeout=setTimeout(cleanUpNextTick);draining=true;var len=queue.length;while(len){currentQueue=queue;queue=[];while(++queueIndex<len){currentQueue[queueIndex].run()}queueIndex=-1;len=queue.length}currentQueue=null;draining=false;clearTimeout(timeout)}process.nextTick=function(fun){var args=new Array(arguments.length-1);if(arguments.length>1){for(var i=1;i<arguments.length;i++){args[i-1]=arguments[i]}}queue.push(new Item(fun,args));if(queue.length===1&&!draining){setTimeout(drainQueue,0)}};function Item(fun,array){this.fun=fun;this.array=array}Item.prototype.run=function(){this.fun.apply(null,this.array)};process.title="browser";process.browser=true;process.env={};process.argv=[];process.version="";process.versions={};function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")};process.umask=function(){return 0}},{}],2:[function(require,module,exports){var Raf=require("raf");function Animato(from,to,time,step,complete){if(arguments.length===1&&from&&typeof from.from==="object"&&typeof from.to==="object"){return new Animato(from.from,from.to,from.duration,from.step,from.complete)}if(this.constructor!==Animato){return new Animato(from,to,time,step,complete)}this._from=from;this._inter={};this._to=to||null;this._duration=time||200;this._step=step||function(){};this._complete=function(){};if(typeof complete==="function"){this.start(complete)}}Animato.prototype.to=function(to){this._to=to;return this};Animato.prototype.duration=function(duration){this._duration=duration;return this};Animato.prototype.step=function(fn){this._step=fn;return this};Animato.prototype.complete=function(fn){this._complete=fn;return this};Animato.prototype.start=function(fn){var self=this;self.deltas={};for(var k in self._from){if(!self._from.hasOwnProperty(k))continue;self.deltas[k]=self._to[k]-self._from[k]}if(typeof fn==="function"){this._complete=fn}self._step(self._from);return Raf(function tick(delta){var proc=delta/self._duration,k;for(k in self._from){if(!self._from.hasOwnProperty(k))continue;self._inter[k]=self._from[k]+self.deltas[k]*proc}if(proc>=1){self._step(self._to);return self._complete()}self._step(self._inter);Raf(tick)})};Animato.Frames=function(from,to,count){if(this.constructor!==Animato.Frames){return new Animato.Frames(from,to,count)}this._from=from;this._to=to;this._count=count;this._step=function(){};this._complete=function(){};this._duration=200};Animato.Frames.prototype.toArray=function(){var frames=[this._from],deltas={},steps={},inter={},k=null;for(k in this._from){if(!this._from.hasOwnProperty(k))continue;steps[k]=(deltas[k]=this._to[k]-this._from[k])/this._count}for(var i=1;i<this._count;++i){inter={};for(k in this._from){if(!this._from.hasOwnProperty(k))continue;inter[k]=this._from[k]+steps[k]*i}frames.push(inter)}frames.push(this._to);return frames};Animato.Frames.prototype.step=function(fn){this._step=fn||this._step;return this};Animato.Frames.prototype.duration=function(duration){this._duration=duration;return this};Animato.Frames.prototype.start=function(fn){var self=this,frames=this.toArray(),delay=this._duration/this._count,index=-1,interval=setInterval(function(){var frame=frames[++index];if(!frame){clearInterval(interval);return self._complete()}self._step(frame)},delay);self._complete=fn||self._complete};module.exports=Animato},{raf:3}],3:[function(require,module,exports){var now=require("performance-now"),global=typeof window==="undefined"?{}:window,vendors=["moz","webkit"],suffix="AnimationFrame",raf=global["request"+suffix],caf=global["cancel"+suffix]||global["cancelRequest"+suffix];for(var i=0;i<vendors.length&&!raf;i++){raf=global[vendors[i]+"Request"+suffix];caf=global[vendors[i]+"Cancel"+suffix]||global[vendors[i]+"CancelRequest"+suffix]}if(!raf||!caf){var last=0,id=0,queue=[],frameDuration=1e3/60;raf=function(callback){if(queue.length===0){var _now=now(),next=Math.max(0,frameDuration-(_now-last));last=next+_now;setTimeout(function(){var cp=queue.slice(0);queue.length=0;for(var i=0;i<cp.length;i++){if(!cp[i].cancelled){try{cp[i].callback(last)}catch(e){setTimeout(function(){throw e},0)}}}},Math.round(next))}queue.push({handle:++id,callback:callback,cancelled:false});return id};caf=function(handle){for(var i=0;i<queue.length;i++){if(queue[i].handle===handle){queue[i].cancelled=true}}}}module.exports=function(fn){return raf.call(global,fn)};module.exports.cancel=function(){caf.apply(global,arguments)}},{"performance-now":4}],4:[function(require,module,exports){(function(process){(function(){var getNanoSeconds,hrtime,loadTime;if(typeof performance!=="undefined"&&performance!==null&&performance.now){module.exports=function(){return performance.now()}}else if(typeof process!=="undefined"&&process!==null&&process.hrtime){module.exports=function(){return(getNanoSeconds()-loadTime)/1e6};hrtime=process.hrtime;getNanoSeconds=function(){var hr;hr=hrtime();return hr[0]*1e9+hr[1]};loadTime=getNanoSeconds()}else if(Date.now){module.exports=function(){return Date.now()-loadTime};loadTime=Date.now()}else{module.exports=function(){return(new Date).getTime()-loadTime};loadTime=(new Date).getTime()}}).call(this)}).call(this,require("_process"))},{_process:1}]},{},[2])(2)});<|endoftext|>


<commit_before>var BH = require('../lib/bh');
require('chai').should();

describe('bh.toHtml()', function() {
    describe('content', function() {
        var bh;
        beforeEach(function() {
            bh = new BH();
        });
        it('should return empty content #1', function() {
            bh.apply([
                false,
                null,
                undefined,
                [],
                '',
                { content: false }, // `div` is here
                { tag: false }
            ]).should.equal('

');
        });
    });

    describe('tags', function() {
        var bh;
        beforeEach(function() {
            bh = new BH();
        });
        it('should return html tag
 by default', function() {
            bh.apply({}).should.equal('

');
        });
        it('should return html tag ', function() {
            bh.apply({ tag: 'span' }).should.equal('');
        });
        it('should return content when `tag` is empty', function() {
            bh.apply({ tag: false, content: 'label' }).should.equal('label');
        });
    });

    describe('attrs', function() {
        var bh;
        beforeEach(function() {
            bh = new BH();
        });
        it('should ignore null attrs', function() {
            bh.match('button', function(ctx) {
                ctx.tag('a');
                ctx.attr('href', '#');
            });
            bh.match('button', function(ctx) {
                ctx.attr('href', null);
            });
            bh.apply({ block: 'button' }).should.equal(
                ''
            );
        });
        it('should not ignore empty attrs', function() {
            bh.match('button', function(ctx) {
                ctx.tag('a');
                ctx.attr('href', '#');
            });
            bh.match('button', function(ctx) {
                ctx.attr('href', '');
            });
            bh.apply({ block: 'button' }).should.equal(
                ''
            );
        });
    });

    describe('mods', function() {
        var bh;
        beforeEach(function() {
            bh = new BH();
        });
        it('should ignore null mods', function() {
            bh.match('button', function(ctx) {
                ctx.tag('a');
                ctx.mod('type', 'active');
            });
            bh.match('button', function(ctx) {
                ctx.mod('type', null);
            });
            bh.apply({ block: 'button' }).should.equal(
                ''
            );
        });
        it('should ignore empty mods', function() {
            bh.match('button', function(ctx) {
                ctx.tag('a');
                ctx.mod('type', 'active');
            });
            bh.match('button', function(ctx) {
                ctx.mod('type', '');
            });
            bh.apply({ block: 'button' }).should.equal(
                ''
            );
        });
        it('should not ignore boolean mods', function() {
            bh.match('button', function(ctx) {
                ctx.tag('button');
                ctx.mod('disabled', 'disabled');
            });
            bh.match('button', function(ctx) {
                ctx.mod('visible', false);
                ctx.mod('disabled', true);
            });
            bh.apply({ block: 'button' }).should.equal(
                '<button class="button button_disabled"></button>'
            );
        });
    });

    describe('mix', function() {
        var bh;
        beforeEach(function() {
            bh = new BH();
        });
        it('should not set undefined mix', function() {
            bh.apply({
                block: 'button',
                mix: [null, undefined]
            }).should.equal('

');
        });
        it('should set elem mix', function() {
            bh.match('button', function(ctx) {
                ctx.mix({ elem: 'mix' });
            });
            bh.apply({ block: 'button' }).should.equal('

');
        });
        it('should set mods mix', function() {
            bh.match('button', function(ctx) {
                ctx.mix({ mods: { disabled: true, theme: 'normal' } });
            });
            bh.apply({ block: 'button' }).should.equal(
                '

'
            );
        });
        it('should set elem mods mix', function() {
            bh.match('button', function(ctx) {
                ctx.mix({ elem: 'control', mods: { disabled: true } });
            });
            bh.apply({ block: 'button' }).should.equal(
                '

'
            );
        });
        it('should set elem elemMods mix', function() {
            bh.match('button', function(ctx) {
                ctx.mix({ elem: 'control', elemMods: { disabled: true } });
            });
            bh.apply({ block: 'button' }).should.equal(
                '

'
            );
        });
        it('should set several mixes', function() {
            bh.match('button', function(ctx) {
                ctx.mix([
                    { block: 'link' },
                    { elem: 'control' },
                    { mods: { disabled: true } },
                    { block: 'label', elem: 'first', mods: { color: 'red' } }
                ]);
            });
            bh.apply({ block: 'button' }).should.equal(
                '

'
            );
        });
    });
});
<commit_msg>toHtml: attrs escaping test (close #64)<commit_after>var BH = require('../lib/bh');
require('chai').should();

describe('bh.toHtml()', function() {
    describe('content', function() {
        var bh;
        beforeEach(function() {
            bh = new BH();
        });
        it('should return empty content #1', function() {
            bh.apply([
                false,
                null,
                undefined,
                [],
                '',
                { content: false }, // `div` is here
                { tag: false }
            ]).should.equal('

');
        });
    });

    describe('tags', function() {
        var bh;
        beforeEach(function() {
            bh = new BH();
        });
        it('should return html tag
 by default', function() {
            bh.apply({}).should.equal('

');
        });
        it('should return html tag ', function() {
            bh.apply({ tag: 'span' }).should.equal('');
        });
        it('should return content when `tag` is empty', function() {
            bh.apply({ tag: false, content: 'label' }).should.equal('label');
        });
    });

    describe('attrs', function() {
        var bh;
        beforeEach(function() {
            bh = new BH();
        });
        it('should ignore null attrs', function() {
            bh.match('button', function(ctx) {
                ctx.tag('a');
                ctx.attr('href', '#');
            });
            bh.match('button', function(ctx) {
                ctx.attr('href', null);
            });
            bh.apply({ block: 'button' }).should.equal(
                ''
            );
        });
        it('should not ignore empty attrs', function() {
            bh.match('button', function(ctx) {
                ctx.tag('a');
                ctx.attr('href', '#');
            });
            bh.match('button', function(ctx) {
                ctx.attr('href', '');
            });
            bh.apply({ block: 'button' }).should.equal(
                ''
            );
        });
        it('should escape attrs', function() {
            bh.apply({
                tag: 'a',
                attrs: { href: '' },
                content: 'link'
            }).should.equal('link');
        });
    });

    describe('mods', function() {
        var bh;
        beforeEach(function() {
            bh = new BH();
        });
        it('should ignore null mods', function() {
            bh.match('button', function(ctx) {
                ctx.tag('a');
                ctx.mod('type', 'active');
            });
            bh.match('button', function(ctx) {
                ctx.mod('type', null);
            });
            bh.apply({ block: 'button' }).should.equal(
                ''
            );
        });
        it('should ignore empty mods', function() {
            bh.match('button', function(ctx) {
                ctx.tag('a');
                ctx.mod('type', 'active');
            });
            bh.match('button', function(ctx) {
                ctx.mod('type', '');
            });
            bh.apply({ block: 'button' }).should.equal(
                ''
            );
        });
        it('should not ignore boolean mods', function() {
            bh.match('button', function(ctx) {
                ctx.tag('button');
                ctx.mod('disabled', 'disabled');
            });
            bh.match('button', function(ctx) {
                ctx.mod('visible', false);
                ctx.mod('disabled', true);
            });
            bh.apply({ block: 'button' }).should.equal(
                '<button class="button button_disabled"></button>'
            );
        });
    });

    describe('mix', function() {
        var bh;
        beforeEach(function() {
            bh = new BH();
        });
        it('should not set undefined mix', function() {
            bh.apply({
                block: 'button',
                mix: [null, undefined]
            }).should.equal('

');
        });
        it('should set elem mix', function() {
            bh.match('button', function(ctx) {
                ctx.mix({ elem: 'mix' });
            });
            bh.apply({ block: 'button' }).should.equal('

');
        });
        it('should set mods mix', function() {
            bh.match('button', function(ctx) {
                ctx.mix({ mods: { disabled: true, theme: 'normal' } });
            });
            bh.apply({ block: 'button' }).should.equal(
                '

'
            );
        });
        it('should set elem mods mix', function() {
            bh.match('button', function(ctx) {
                ctx.mix({ elem: 'control', mods: { disabled: true } });
            });
            bh.apply({ block: 'button' }).should.equal(
                '

'
            );
        });
        it('should set elem elemMods mix', function() {
            bh.match('button', function(ctx) {
                ctx.mix({ elem: 'control', elemMods: { disabled: true } });
            });
            bh.apply({ block: 'button' }).should.equal(
                '

'
            );
        });
        it('should set several mixes', function() {
            bh.match('button', function(ctx) {
                ctx.mix([
                    { block: 'link' },
                    { elem: 'control' },
                    { mods: { disabled: true } },
                    { block: 'label', elem: 'first', mods: { color: 'red' } }
                ]);
            });
            bh.apply({ block: 'button' }).should.equal(
                '

'
            );
        });
    });
});
<|endoftext|>


<commit_before>!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.argErr=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
/*jslint indent: 2, node: true, continue: true*/
"use strict";

var kindof = _dereq_("kindof");

function regexpErrMsg(args) {
  return "expected" + (args.optional ? " optional" : "")
    + " argument " + args.propName
    + " to match " + args.inputPattern.toString()
    + " (was \"" + args.input + "\")";
}

function errMsg(args) {
  return "expected" + (args.optional ? " optional" : "")
    + " argument " + args.propName
    + " to be of type " + args.schemaType
    + " (was " + args.inputType + ")";
}

function functionErrMsg(args) {
  var functionName;

  // extract the function name from its source
  // to try and give a useful error message
  try {
    functionName = /function\s+([a-zA-Z0-9_]+)\s*\(/.exec(args.functionSource)[1];
  } catch (e) {
    functionName = "anonymous function";
  }

  return "expected" + (args.optional ? " optional" : "")
    + " argument " + args.propName
    + " to pass " + functionName;
}

function recursiveFlatten(array, result) {
  var i,
    result = result || [];

  for (i = 0; i < array.length; i++) {
    if (kindof(array[i]) === "array") {
      recursiveFlatten(array[i], result);
    } else {
      result.push(array[i]);
    }
  }
  return result;
}

function getExpectedTypeFromSchemaProperty(schemaProperty) {
  var typeToReturn,
    actualType = kindof(schemaProperty);

  if (actualType === "object") {
    typeToReturn = "object";
  } else if (actualType === "regexp") {
    typeToReturn = "string";
  } else if (actualType === "array") {
    typeToReturn = schemaProperty.map(getExpectedTypeFromSchemaProperty).join(" or ");
  } else {
    typeToReturn = schemaProperty;
  }

  return typeToReturn;
}

function getErrs(args) {
  // not checking whether args is valid because... seriously?
  var prop,
    schema = args.schema,
    input = args.input,
    prefix = args.prefix || "",
    optional = args.optional || false,
    type,
    schemaType,
    expectedType,
    passedSpecialCases,
    errs = [];

  for (prop in schema) {
    if (schema.hasOwnProperty(prop)) {
      passedSpecialCases = false;
      type = kindof(input[prop]);
      schemaType = kindof(schema[prop]);

      // any kinds of checks are pointless if optional schema
      // if property is undefined
      if (optional && type === "undefined") {
        continue;
      }

      // special cases where the schema prop is not defined as a string
      // if input prop does not fit the special case,
      // defer to normal type checking
      if (schemaType === "array") {
        // if schema type is an array, we need to check
        // whether some of them validate
        //
        // if at least one validates, there's no error
        if (schema[prop].some(function (possibleType) {
            var tempInput = {},
              tempSchema = {},
              tempErrs;

            tempInput[prop] = input[prop];
            tempSchema[prop] = possibleType;
            tempErrs = getErrs({
              input: tempInput,
              schema: tempSchema,
              optional: optional
            });

            return tempErrs.length === 0;
          })) {
          passedSpecialCases = true;
        }
      } else if (schemaType === "object") {
        if (type === "object") {
          // if both input and schema properties are objects
          // we'll need to recurse
          errs.push(getErrs({
            input: input[prop],
            schema: schema[prop],
            prefix: prefix + prop + ".",
            optional: optional
          }));

          passedSpecialCases = true;
        }
      } else if (schemaType === "regexp") {
        // special case regex
        // assuming regex matched fields are always strings
        if (type === "string" && !schema[prop].test(input[prop])) {
          errs.push(regexpErrMsg({
            propName: prefix + prop,
            inputPattern: schema[prop],
            input: input[prop],
            optional: optional
          }));

          passedSpecialCases = true;
        }
      } else if (schemaType === "function") {
        // special case function
        // run the property against the function
        if (!schema[prop](input[prop])) {
          errs.push(functionErrMsg({
            propName: prefix + prop,
            functionSource: schema[prop].toString(),
            optional: optional
          }));
        }

        passedSpecialCases = true;
      } else if (schemaType !== "string") {
        throw new Error("Unsupported schema type: " + schemaType + ". Supported ones are string, object, regexp or array");
      }

      expectedType = getExpectedTypeFromSchemaProperty(schema[prop]);
      if (!passedSpecialCases && type !== expectedType) {
        errs.push(errMsg({
          propName: prefix + prop,
          inputType: type,
          schemaType: expectedType,
          optional: optional
        }));
      }
    }
  }

  return errs;
}

exports.err = function (input, schema, optionalSchema) {
  var errs = getErrs({
    input: input,
    schema: schema
  });

  if (optionalSchema) {
    errs = errs.concat(getErrs({
      input: input,
      schema: optionalSchema,
      optional: true
    }));
  }

  // in complex schemas (think nested objects two levels deep)
  // join() doesn't work properly and leaves artifacts
  // so we need to flatten everything first
  errs = recursiveFlatten(errs);

  return errs.length ? errs.join(", ") : null;
};

},{"kindof":2}],2:[function(_dereq_,module,exports){
if (typeof module != "undefined") module.exports = kindof

function kindof(obj) {
  if (obj === undefined) return "undefined"
  if (obj === null) return "null"

  switch (Object.prototype.toString.call(obj)) {
    case "[object Boolean]": return "boolean"
    case "[object Number]": return "number"
    case "[object String]": return "string"
    case "[object RegExp]": return "regexp"
    case "[object Date]": return "date"
    case "[object Array]": return "array"
    default: return typeof obj
  }
}

},{}]},{},[1])
(1)
});<commit_msg>rebuilt bundle<commit_after>(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.argErr = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";

var kindof = require("kindof"),
  wordToUse = "argument";

function regexpErrMsg(args) {
  return "expected" + (args.optional ? " optional" : "")
    + " " + wordToUse + " " + args.propName
    + " to match " + args.inputPattern.toString()
    + " (was \"" + args.input + "\")";
}

function errMsg(args) {
  return "expected" + (args.optional ? " optional" : "")
    + " " + wordToUse + " " + args.propName
    + " to be of type " + args.schemaType
    + " (was " + args.inputType + ")";
}

function functionErrMsg(args) {
  var functionName;

  // extract the function name from its source
  // to try and give a useful error message
  try {
    functionName = /function\s+([a-zA-Z0-9_]+)\s*\(/.exec(args.functionSource)[1];
  } catch (e) {
    functionName = "anonymous function";
  }

  return "expected" + (args.optional ? " optional" : "")
    + " " + wordToUse + " " + args.propName
    + " to pass " + functionName;
}

function recursiveFlatten(array, result) {
  var i;

  result = result || [];

  for (i = 0; i < array.length; i += 1) {
    if (kindof(array[i]) === "array") {
      recursiveFlatten(array[i], result);
    } else {
      result.push(array[i]);
    }
  }
  return result;
}

function getExpectedTypeFromSchemaProperty(schemaProperty) {
  var typeToReturn,
    actualType = kindof(schemaProperty);

  if (actualType === "object") {
    typeToReturn = "object";
  } else if (actualType === "regexp") {
    typeToReturn = "string";
  } else if (actualType === "array") {
    typeToReturn = schemaProperty.map(getExpectedTypeFromSchemaProperty).join(" or ");
  } else {
    typeToReturn = schemaProperty;
  }

  return typeToReturn;
}

function getErrs(args) {
  // not checking whether args is valid because... seriously?
  var prop,
    schema = args.schema,
    input = args.input,
    prefix = args.prefix || "",
    optional = args.optional || false,
    type,
    schemaType,
    expectedType,
    passedSpecialCases,
    errs = [];

  // used for array schema types
  // where all we need is to pass a single array element
  function someSchemasValidate(propName) {
    return schema[propName].some(function (possibleType) {
      var tempInput = {},
        tempSchema = {},
        tempErrs;

      tempInput[propName] = input[propName];
      tempSchema[propName] = possibleType;
      tempErrs = getErrs({
        input: tempInput,
        schema: tempSchema,
        optional: optional
      });

      return tempErrs.length === 0;
    });
  }

  for (prop in schema) {
    if (schema.hasOwnProperty(prop)) {
      passedSpecialCases = false;
      type = kindof(input[prop]);
      schemaType = kindof(schema[prop]);

      // any kinds of checks are pointless if optional schema
      // if property is undefined
      if (optional && type === "undefined") {
        continue;
      }

      // special cases where the schema prop is not defined as a string
      // if input prop does not fit the special case,
      // defer to normal type checking
      if (schemaType === "array") {
        // if schema type is an array, we need to check
        // whether some of them validate
        //
        // if at least one validates, there's no error
        if (someSchemasValidate(prop)) {
          passedSpecialCases = true;
        }
      } else if (schemaType === "object") {
        if (type === "object") {
          // if both input and schema properties are objects
          // we'll need to recurse
          errs.push(getErrs({
            input: input[prop],
            schema: schema[prop],
            prefix: prefix + prop + ".",
            optional: optional
          }));

          passedSpecialCases = true;
        }
      } else if (schemaType === "regexp") {
        // special case regex
        // assuming regex matched fields are always strings
        if (type === "string" && !schema[prop].test(input[prop])) {
          errs.push(regexpErrMsg({
            propName: prefix + prop,
            inputPattern: schema[prop],
            input: input[prop],
            optional: optional
          }));

          passedSpecialCases = true;
        }
      } else if (schemaType === "function") {
        // special case function
        // run the property against the function
        if (!schema[prop](input[prop])) {
          errs.push(functionErrMsg({
            propName: prefix + prop,
            functionSource: schema[prop].toString(),
            optional: optional
          }));
        }

        passedSpecialCases = true;
      } else if (schemaType !== "string") {
        throw new Error("Unsupported schema type: " + schemaType + ". Supported ones are string, object, regexp or array");
      }

      expectedType = getExpectedTypeFromSchemaProperty(schema[prop]);
      if (!passedSpecialCases && type !== expectedType) {
        errs.push(errMsg({
          propName: prefix + prop,
          inputType: type,
          schemaType: expectedType,
          optional: optional
        }));
      }
    }
  }

  return errs;
}

exports.config = function (opts) {
  // if you'd rather be pedantic about what you're checking
  wordToUse = opts.propErr ? "property" : "argument";

  return this;
};

exports.err = function (input, schema, optionalSchema) {
  var errs = getErrs({
    input: input,
    schema: schema
  });

  if (optionalSchema) {
    errs = errs.concat(getErrs({
      input: input,
      schema: optionalSchema,
      optional: true
    }));
  }

  // in complex schemas (think nested objects two levels deep)
  // join() doesn't work properly and leaves artifacts
  // so we need to flatten everything first
  errs = recursiveFlatten(errs);

  return errs.length ? errs.join(", ") : null;
};

},{"kindof":2}],2:[function(require,module,exports){
if (typeof module != "undefined") module.exports = kindof

function kindof(obj) {
  var type
  if (obj === undefined) return "undefined"
  if (obj === null) return "null"

  switch (type = typeof obj) {
    case "object":
      switch (Object.prototype.toString.call(obj)) {
        case "[object RegExp]": return "regexp"
        case "[object Date]": return "date"
        case "[object Array]": return "array"
      }

    default: return type
  }
}

},{}]},{},[1])(1)
});<|endoftext|>


<commit_before>// File save dialog
// Arguments:
//  - cback: Callback for when things happen.
//  - options: Dictionary of settings:
//    - "type"  'isFile'    - renders file browser with file name box (default)
//              'isDir'     - renders file browser with folder name box
//              'isCommit'  - renders file browser without file view, just commit box
//              'isProj'    - renders file browser without file view, just project name box

function Browser(cback, options) {
	// Public functions:
	//  - clickSaveFile(bool noMsg): event handler for when save is clicked, if noMsg is true: ignore lack of commit msg
	//  - clickCancelSave(): cancel and close browser
	//  - dirSelected(): event handler for when a directory is selected in the left hand pane
	//  - display(): show all browser css
	//  - hide():hide all browser css

	// Private functions:
	//  - _init:	Constructor. Displays filebrowser, grabs file tree and connects up events.
	//  - _receiveTree: AJAX success callback
	//  - _errorReceiveTree: AJAX fail callback
	//  - _getFileTree: Grab file tree from server
	//  - _processTree: Recursive function to turn filelist into DOM

	this.newDirectory = '/';
	this.newFname = "";
	this.commitMsg = "";

	this._DEFAULT_MSG = "Commit message";
	this._DEFAULT_DNAME = "new-directory";
	this._DEFAULT_FNAME = "new.py";
	this._DEFAULT_PNAME = "new-project";
	this._DEFAULT_TNAME = "new-tag";

	this._List = new Array();
	this.type = options.type;
	this.title = options.title;

	//hold the ident for the escape catcher
	this._esc_press = null;

	//hold the ident for showing the diff box
	this._show_diff = null;

	this.fileTree = null;
	this.callback = cback;
	this._selector = null;
	this._init();
}

Browser.prototype._init = function() {

	getElement("new-commit-msg").value = this._DEFAULT_MSG;
	var newFileNameElem = getElement("new-file-name");
	switch (this.type) {
		case 'isDir':
			newFileNameElem.value = this._DEFAULT_DNAME;
			break;
		case 'isProj':
			newFileNameElem.value = this._DEFAULT_PNAME;
			break;
		case 'isTag':
			newFileNameElem.value = this._DEFAULT_TNAME;
			break;
		default:
			newFileNameElem.value = this._DEFAULT_FNAME;
			break;
	}

	//make visible
	this.display();

	//get file listings - if not just commit message
	if (this.type == 'isFile'
	 || this.type == 'isDir'
	) {
		var projlist = new ProjList();
		projlist.update(team);
		// The selection box for selecting a project
		this._selector = new ProjSelect(projlist, getElement("browser-project-select"));
		connect( this._selector, "onchange", bind(this._getFileTree, this) );
	}

	//clear previous events
	disconnectAll("save-new-file");
	disconnectAll("cancel-new-file");
	disconnectAll("new-commit-msg");
	disconnectAll("new-file-name");
	disconnectAll("left-pane");
	disconnect(this._esc_press);
	//set up event handlers
	this._esc_press = connect(document, 'onkeydown', bind(this._window_keydown, this));
	connect("new-file-name", 'onkeypress', bind(this._new_file_keypress, this));
	connect("save-new-file", 'onclick', bind(this.clickSaveFile, this, false, false));
	connect("cancel-new-file", 'onclick', bind(this.clickCancelSave, this));
	connect("new-commit-msg","onfocus", bind(this._msg_focus, this));
	connect("new-file-name","onfocus", bind(this._fname_focus, this));
	connect("left-pane","onclick", bind(this.rootSelected, this));

	if(this.type == 'isProj'
	 || this.type == 'isTag'
	) {
		getElement("new-file-name").focus();
	} else {
		getElement("new-commit-msg").focus();
	}
}

// show the diff as part of the commit
// should only be called for isCommit
Browser.prototype.showDiff = function(path, rev, code) {
	if (user.get_setting('save.showdiff') == false) {
		return null;
	}
	var diff = Diff.Create('browser-diff', path, rev, code);
	this._show_diff = connect(diff, 'ready', partial(showElement, 'browser-diff'));
	return diff;
}

Browser.prototype._new_file_keypress = function(ev) {
	if(ev._event.keyCode == 13 && ev._modifier == null) {
		log('Enter pressed - browser saving')
		signal("save-new-file", 'onclick');
	}
}

Browser.prototype._window_keydown = function(ev) {
	if(ev._event.keyCode == 27 && ev._modifier == null) {
		log('Escape pressed - hiding browser')
		signal("cancel-new-file", 'onclick');
	}
}

Browser.prototype._receiveTree = function(nodes) {
	this.fileTree = nodes.tree;
	getElement('save-new-file').disabled = false;
	//default to the first directory
	replaceChildNodes("left-pane-list", null);
	replaceChildNodes("right-pane-list", null);
	this._processTree(getElement("left-pane-list"), this.fileTree, "");
	//fake a click on the LHS root to show the root files on the RHS
	signal("left-pane", 'onclick');
}

Browser.prototype._errorReceiveTree = function(a) {
	getElement("browser-status").innerHTML = "ERROR :: Unable to retrieve file list for "+a;
	signal("left-pane", 'onclick');
}

Browser.prototype._getFileTree = function(project, tm) {
	// Initial load
	if (project == '') {
		return;
	}

	this._receiveTree({tree:[{autosave:0,children:[],kind:'FOLDER',name:'Loading...',path:'@',rev:-1}]});
	getElement('save-new-file').disabled = true;

	IDE_backend_request("file/compat-tree", {team: tm, project: project},
	                                        bind(this._receiveTree, this),
	                                        bind(this._errorReceiveTree, this, project));
}

Browser.prototype._badCommitMsg = function(msg) {
	//test for is-nothing or is-only-whitespace
	return this.commitMsg == this._DEFAULT_MSG || /^$|^\s+$/.test(msg);
}

Browser.prototype._badFname = function(name) {
	//test for is-nothing or starts-with-whitespace or starts-with-a-dot
	//      or contains-colon
	//      or contains-double-quotes
	//      or contains-forward-slash
	return /^$|^\s|^[.]|:|"|\//.test(name);
}

//when user clicks save
Browser.prototype.clickSaveFile = function(noMsg) {
	disconnectAll("browser-status");
	this.commitMsg = getElement("new-commit-msg").value;
	this.newFname = getElement("new-file-name").value;

	switch(this.type) {
		case 'isFile':
			var type = 'file';
			break;
		case 'isDir':
			var type = 'directory';
			break;
		case 'isProj':
			var type = 'project';
			break;
		case 'isTag':
			var type = 'tag';
			break;
	}

	//don't allow null strings or pure whitespace
	if(this._badFname(this.newFname)) {
		getElement("browser-status").innerHTML = "Please specify a valid "+type+" name:";
		getElement("new-file-name").focus();
		return;
	}

	//fail if the file list is requested, but hasn't loaded
	if((this.type == 'isFile' || this.type == 'isDir') && this.fileTree == null) {
		getElement("browser-status").innerHTML = "Unable to save - file list not yet loaded";
		return;
	}

	//file, dir or project name already exists
	logDebug('Checking file existence: '+this.newFname+' in '+this._List+' : '+(findValue(this._List, this.newFname) > -1) );
	if( ( ( this.type == 'isFile' || this.type == 'isDir' ) && findValue(this._List, this.newFname) > -1 ) ||
		( this.type == 'isProj' && projpage.project_exists(this.newFname) )
	) {
		var warn = '"'+this.newFname+'" already exists';
		if(this.type == 'isProj')
			warn = 'Project '+warn;
		else if(this.type == 'isTag')
			warn = 'Tag '+warn;
		else
			warn += ' in "'+this.newDirectory.substr(1)+'"';

		getElement("browser-status").innerHTML = warn+"!";
		getElement("new-file-name").focus();
		return;
	}

	var commitErrFlag = ( !noMsg &&
		this.type != 'isProj' &&
		this.type != 'isTag' &&
		this._badCommitMsg(this.commitMsg) );

	if(commitErrFlag) {
		getElement("browser-status").innerHTML = "No commit message added - click to ignore";
		connect("browser-status", 'onclick', bind(this.clickSaveFile, this, true));
		getElement("new-commit-msg").focus();
		return;
	}

	disconnectAll("browser-status");

	switch(this.type) {
		case 'isFile' :
		case 'isDir' :
			this.callback("/"+this._selector.project+this.newDirectory+this.newFname, this.commitMsg);
			break;
		case 'isProj' :
		case 'isTag' :
			this.callback(this.newFname);
			break;
		case 'isCommit' :
			this.callback(this.commitMsg);
			break;
	}
	this.hide();
}

//cancel save operation
Browser.prototype.clickCancelSave = function() {
	status_hide();
	this.commitMsg = "";
	this.newFilePath = "";
	this.hide();
}

//Recursive function to convert filetree into valid DOM tree
Browser.prototype._processTree = function(parentDOM, tree, pathSoFar) {
	for (var i = 0; i < tree.length; i++) {
		if(tree[i].kind == "FOLDER") {
			//create entry in folder list
			var newPathSoFar = pathSoFar+"/"+tree[i].name;

			var newLeaf = LI(null, tree[i].name+(tree[i].path == '@' ? '' : "/"));

			connect(newLeaf, 'onclick', bind(this.dirSelected, this, newPathSoFar+"/", tree[i].children));

			//create new list for child folder
			var newBranch = LI(null, "");
			appendChildNodes(newBranch, UL(null, ""));
			appendChildNodes(parentDOM, newLeaf);

			//recursive call, with newly created branch
			appendChildNodes(parentDOM, this._processTree(newBranch.childNodes[1], tree[i].children, newPathSoFar));
		}
	}
	return parentDOM;
}

Browser.prototype.rootSelected = function() {
	log('Browser: root folder selected');
	this.dirSelected('/', this.fileTree);
}

Browser.prototype.dirSelected = function(directory, thingsInside, ev) {
	if(ev != undefined)
		ev.stop();
	logDebug("Folder selected :"+directory);
	//update selected directory
	this.newDirectory = directory;
	getElement("selected-dir").innerHTML = directory;

	//empty file list
	replaceChildNodes("right-pane-list");

	//populate file list with only files from all the things contained within this directory
	this._List = new Array();
	for (var j = 0; j < thingsInside.length; j++) {
		if(thingsInside[j].kind == "FILE") {	//build li and append to pane
			var li = LI(null, "");
			li.innerHTML = thingsInside[j].name;
			appendChildNodes("right-pane-list", li);
		}
		this._List.push(thingsInside[j].name);	//add to the list of all things regardless
	}
}

Browser.prototype.display = function() {
	showElement("file-browser");
	showElement("grey-out");
	hideElement('browser-diff');

	switch(this.type) {
		case 'isFile':
			getElement("browser-status").innerHTML = "Please Select a save directory & new file name";
			getElement("browser-title").innerHTML = this.title || "File Save As";
			showElement("save-path");
			showElement("right-pane");
			showElement("left-pane");
			showElement("new-commit-msg");
			showElement("new-file-name");
			break;
		case 'isDir' :
			getElement("browser-status").innerHTML = "Please Select a save directory & new directory name";
			getElement("browser-title").innerHTML = this.title || "New Directory";
			showElement("save-path");
			showElement("right-pane");
			showElement("left-pane");
			showElement("new-commit-msg");
			showElement("new-file-name");
			break;
		case 'isCommit' :
			getElement("browser-status").innerHTML = "Please add a commit message before saving";
			getElement("browser-title").innerHTML = "Commit Changes:";
			hideElement("save-path");
			hideElement("right-pane");
			hideElement("left-pane");
			showElement("new-commit-msg");
			hideElement("new-file-name");
			break;
		case 'isTag' :
			getElement("browser-status").innerHTML = "Enter new tag name:";
			getElement("browser-title").innerHTML = this.title || "New Tag";
			hideElement("save-path");
			hideElement("right-pane");
			hideElement("left-pane");
			hideElement("new-commit-msg");
			showElement("new-file-name");
			break;
		case 'isProj' :
			getElement("browser-status").innerHTML = "Enter new project name:";
			getElement("browser-title").innerHTML = this.title || "New Project";
			hideElement("save-path");
			hideElement("right-pane");
			hideElement("left-pane");
			hideElement("new-commit-msg");
			showElement("new-file-name");
			break;
	}
}
Browser.prototype.hide = function() {
	logDebug("Hiding File Browser");
	disconnectAll("save-new-file");
	disconnectAll("cancel-new-file");
	disconnectAll("new-commit-msg");
	disconnectAll("new-file-name");
	disconnectAll("left-pane");
	disconnectAll("browser-status");
	disconnect(this._show_diff);
	disconnect(this._esc_press);
	hideElement("file-browser");
	hideElement("grey-out");
	replaceChildNodes("left-pane-list");
	replaceChildNodes("right-pane-list");
}

Browser.prototype._msg_focus = function() {
	var t = getElement("new-commit-msg");

	if( t.value == this._DEFAULT_MSG )
		// Select all
		t.select();
}

Browser.prototype._fname_focus = function() {
	var t = getElement("new-file-name");

	if( t.value == this._DEFAULT_FNAME )
		// Select all
		t.select();
}
<commit_msg>Move description switch closer to usage.<commit_after>// File save dialog
// Arguments:
//  - cback: Callback for when things happen.
//  - options: Dictionary of settings:
//    - "type"  'isFile'    - renders file browser with file name box (default)
//              'isDir'     - renders file browser with folder name box
//              'isCommit'  - renders file browser without file view, just commit box
//              'isProj'    - renders file browser without file view, just project name box

function Browser(cback, options) {
	// Public functions:
	//  - clickSaveFile(bool noMsg): event handler for when save is clicked, if noMsg is true: ignore lack of commit msg
	//  - clickCancelSave(): cancel and close browser
	//  - dirSelected(): event handler for when a directory is selected in the left hand pane
	//  - display(): show all browser css
	//  - hide():hide all browser css

	// Private functions:
	//  - _init:	Constructor. Displays filebrowser, grabs file tree and connects up events.
	//  - _receiveTree: AJAX success callback
	//  - _errorReceiveTree: AJAX fail callback
	//  - _getFileTree: Grab file tree from server
	//  - _processTree: Recursive function to turn filelist into DOM

	this.newDirectory = '/';
	this.newFname = "";
	this.commitMsg = "";

	this._DEFAULT_MSG = "Commit message";
	this._DEFAULT_DNAME = "new-directory";
	this._DEFAULT_FNAME = "new.py";
	this._DEFAULT_PNAME = "new-project";
	this._DEFAULT_TNAME = "new-tag";

	this._List = new Array();
	this.type = options.type;
	this.title = options.title;

	//hold the ident for the escape catcher
	this._esc_press = null;

	//hold the ident for showing the diff box
	this._show_diff = null;

	this.fileTree = null;
	this.callback = cback;
	this._selector = null;
	this._init();
}

Browser.prototype._init = function() {

	getElement("new-commit-msg").value = this._DEFAULT_MSG;
	var newFileNameElem = getElement("new-file-name");
	switch (this.type) {
		case 'isDir':
			newFileNameElem.value = this._DEFAULT_DNAME;
			break;
		case 'isProj':
			newFileNameElem.value = this._DEFAULT_PNAME;
			break;
		case 'isTag':
			newFileNameElem.value = this._DEFAULT_TNAME;
			break;
		default:
			newFileNameElem.value = this._DEFAULT_FNAME;
			break;
	}

	//make visible
	this.display();

	//get file listings - if not just commit message
	if (this.type == 'isFile'
	 || this.type == 'isDir'
	) {
		var projlist = new ProjList();
		projlist.update(team);
		// The selection box for selecting a project
		this._selector = new ProjSelect(projlist, getElement("browser-project-select"));
		connect( this._selector, "onchange", bind(this._getFileTree, this) );
	}

	//clear previous events
	disconnectAll("save-new-file");
	disconnectAll("cancel-new-file");
	disconnectAll("new-commit-msg");
	disconnectAll("new-file-name");
	disconnectAll("left-pane");
	disconnect(this._esc_press);
	//set up event handlers
	this._esc_press = connect(document, 'onkeydown', bind(this._window_keydown, this));
	connect("new-file-name", 'onkeypress', bind(this._new_file_keypress, this));
	connect("save-new-file", 'onclick', bind(this.clickSaveFile, this, false, false));
	connect("cancel-new-file", 'onclick', bind(this.clickCancelSave, this));
	connect("new-commit-msg","onfocus", bind(this._msg_focus, this));
	connect("new-file-name","onfocus", bind(this._fname_focus, this));
	connect("left-pane","onclick", bind(this.rootSelected, this));

	if(this.type == 'isProj'
	 || this.type == 'isTag'
	) {
		getElement("new-file-name").focus();
	} else {
		getElement("new-commit-msg").focus();
	}
}

// show the diff as part of the commit
// should only be called for isCommit
Browser.prototype.showDiff = function(path, rev, code) {
	if (user.get_setting('save.showdiff') == false) {
		return null;
	}
	var diff = Diff.Create('browser-diff', path, rev, code);
	this._show_diff = connect(diff, 'ready', partial(showElement, 'browser-diff'));
	return diff;
}

Browser.prototype._new_file_keypress = function(ev) {
	if(ev._event.keyCode == 13 && ev._modifier == null) {
		log('Enter pressed - browser saving')
		signal("save-new-file", 'onclick');
	}
}

Browser.prototype._window_keydown = function(ev) {
	if(ev._event.keyCode == 27 && ev._modifier == null) {
		log('Escape pressed - hiding browser')
		signal("cancel-new-file", 'onclick');
	}
}

Browser.prototype._receiveTree = function(nodes) {
	this.fileTree = nodes.tree;
	getElement('save-new-file').disabled = false;
	//default to the first directory
	replaceChildNodes("left-pane-list", null);
	replaceChildNodes("right-pane-list", null);
	this._processTree(getElement("left-pane-list"), this.fileTree, "");
	//fake a click on the LHS root to show the root files on the RHS
	signal("left-pane", 'onclick');
}

Browser.prototype._errorReceiveTree = function(a) {
	getElement("browser-status").innerHTML = "ERROR :: Unable to retrieve file list for "+a;
	signal("left-pane", 'onclick');
}

Browser.prototype._getFileTree = function(project, tm) {
	// Initial load
	if (project == '') {
		return;
	}

	this._receiveTree({tree:[{autosave:0,children:[],kind:'FOLDER',name:'Loading...',path:'@',rev:-1}]});
	getElement('save-new-file').disabled = true;

	IDE_backend_request("file/compat-tree", {team: tm, project: project},
	                                        bind(this._receiveTree, this),
	                                        bind(this._errorReceiveTree, this, project));
}

Browser.prototype._badCommitMsg = function(msg) {
	//test for is-nothing or is-only-whitespace
	return this.commitMsg == this._DEFAULT_MSG || /^$|^\s+$/.test(msg);
}

Browser.prototype._badFname = function(name) {
	//test for is-nothing or starts-with-whitespace or starts-with-a-dot
	//      or contains-colon
	//      or contains-double-quotes
	//      or contains-forward-slash
	return /^$|^\s|^[.]|:|"|\//.test(name);
}

//when user clicks save
Browser.prototype.clickSaveFile = function(noMsg) {
	disconnectAll("browser-status");
	this.commitMsg = getElement("new-commit-msg").value;
	this.newFname = getElement("new-file-name").value;

	//don't allow null strings or pure whitespace
	if(this._badFname(this.newFname)) {
		var human_type;
		switch (this.type) {
			case 'isDir':
				human_type = 'directory';
				break;
			case 'isProj':
				human_type = 'project';
				break;
			case 'isTag':
				human_type = 'tag';
				break;
			case 'isFile':
			default:
				human_type = 'file';
				break;
		}

		getElement("browser-status").innerHTML = "Please specify a valid "+human_type+" name:";
		getElement("new-file-name").focus();
		return;
	}

	//fail if the file list is requested, but hasn't loaded
	if((this.type == 'isFile' || this.type == 'isDir') && this.fileTree == null) {
		getElement("browser-status").innerHTML = "Unable to save - file list not yet loaded";
		return;
	}

	//file, dir or project name already exists
	logDebug('Checking file existence: '+this.newFname+' in '+this._List+' : '+(findValue(this._List, this.newFname) > -1) );
	if( ( ( this.type == 'isFile' || this.type == 'isDir' ) && findValue(this._List, this.newFname) > -1 ) ||
		( this.type == 'isProj' && projpage.project_exists(this.newFname) )
	) {
		var warn = '"'+this.newFname+'" already exists';
		if(this.type == 'isProj')
			warn = 'Project '+warn;
		else if(this.type == 'isTag')
			warn = 'Tag '+warn;
		else
			warn += ' in "'+this.newDirectory.substr(1)+'"';

		getElement("browser-status").innerHTML = warn+"!";
		getElement("new-file-name").focus();
		return;
	}

	var commitErrFlag = ( !noMsg &&
		this.type != 'isProj' &&
		this.type != 'isTag' &&
		this._badCommitMsg(this.commitMsg) );

	if(commitErrFlag) {
		getElement("browser-status").innerHTML = "No commit message added - click to ignore";
		connect("browser-status", 'onclick', bind(this.clickSaveFile, this, true));
		getElement("new-commit-msg").focus();
		return;
	}

	disconnectAll("browser-status");

	switch(this.type) {
		case 'isFile' :
		case 'isDir' :
			this.callback("/"+this._selector.project+this.newDirectory+this.newFname, this.commitMsg);
			break;
		case 'isProj' :
		case 'isTag' :
			this.callback(this.newFname);
			break;
		case 'isCommit' :
			this.callback(this.commitMsg);
			break;
	}
	this.hide();
}

//cancel save operation
Browser.prototype.clickCancelSave = function() {
	status_hide();
	this.commitMsg = "";
	this.newFilePath = "";
	this.hide();
}

//Recursive function to convert filetree into valid DOM tree
Browser.prototype._processTree = function(parentDOM, tree, pathSoFar) {
	for (var i = 0; i < tree.length; i++) {
		if(tree[i].kind == "FOLDER") {
			//create entry in folder list
			var newPathSoFar = pathSoFar+"/"+tree[i].name;

			var newLeaf = LI(null, tree[i].name+(tree[i].path == '@' ? '' : "/"));

			connect(newLeaf, 'onclick', bind(this.dirSelected, this, newPathSoFar+"/", tree[i].children));

			//create new list for child folder
			var newBranch = LI(null, "");
			appendChildNodes(newBranch, UL(null, ""));
			appendChildNodes(parentDOM, newLeaf);

			//recursive call, with newly created branch
			appendChildNodes(parentDOM, this._processTree(newBranch.childNodes[1], tree[i].children, newPathSoFar));
		}
	}
	return parentDOM;
}

Browser.prototype.rootSelected = function() {
	log('Browser: root folder selected');
	this.dirSelected('/', this.fileTree);
}

Browser.prototype.dirSelected = function(directory, thingsInside, ev) {
	if(ev != undefined)
		ev.stop();
	logDebug("Folder selected :"+directory);
	//update selected directory
	this.newDirectory = directory;
	getElement("selected-dir").innerHTML = directory;

	//empty file list
	replaceChildNodes("right-pane-list");

	//populate file list with only files from all the things contained within this directory
	this._List = new Array();
	for (var j = 0; j < thingsInside.length; j++) {
		if(thingsInside[j].kind == "FILE") {	//build li and append to pane
			var li = LI(null, "");
			li.innerHTML = thingsInside[j].name;
			appendChildNodes("right-pane-list", li);
		}
		this._List.push(thingsInside[j].name);	//add to the list of all things regardless
	}
}

Browser.prototype.display = function() {
	showElement("file-browser");
	showElement("grey-out");
	hideElement('browser-diff');

	switch(this.type) {
		case 'isFile':
			getElement("browser-status").innerHTML = "Please Select a save directory & new file name";
			getElement("browser-title").innerHTML = this.title || "File Save As";
			showElement("save-path");
			showElement("right-pane");
			showElement("left-pane");
			showElement("new-commit-msg");
			showElement("new-file-name");
			break;
		case 'isDir' :
			getElement("browser-status").innerHTML = "Please Select a save directory & new directory name";
			getElement("browser-title").innerHTML = this.title || "New Directory";
			showElement("save-path");
			showElement("right-pane");
			showElement("left-pane");
			showElement("new-commit-msg");
			showElement("new-file-name");
			break;
		case 'isCommit' :
			getElement("browser-status").innerHTML = "Please add a commit message before saving";
			getElement("browser-title").innerHTML = "Commit Changes:";
			hideElement("save-path");
			hideElement("right-pane");
			hideElement("left-pane");
			showElement("new-commit-msg");
			hideElement("new-file-name");
			break;
		case 'isTag' :
			getElement("browser-status").innerHTML = "Enter new tag name:";
			getElement("browser-title").innerHTML = this.title || "New Tag";
			hideElement("save-path");
			hideElement("right-pane");
			hideElement("left-pane");
			hideElement("new-commit-msg");
			showElement("new-file-name");
			break;
		case 'isProj' :
			getElement("browser-status").innerHTML = "Enter new project name:";
			getElement("browser-title").innerHTML = this.title || "New Project";
			hideElement("save-path");
			hideElement("right-pane");
			hideElement("left-pane");
			hideElement("new-commit-msg");
			showElement("new-file-name");
			break;
	}
}
Browser.prototype.hide = function() {
	logDebug("Hiding File Browser");
	disconnectAll("save-new-file");
	disconnectAll("cancel-new-file");
	disconnectAll("new-commit-msg");
	disconnectAll("new-file-name");
	disconnectAll("left-pane");
	disconnectAll("browser-status");
	disconnect(this._show_diff);
	disconnect(this._esc_press);
	hideElement("file-browser");
	hideElement("grey-out");
	replaceChildNodes("left-pane-list");
	replaceChildNodes("right-pane-list");
}

Browser.prototype._msg_focus = function() {
	var t = getElement("new-commit-msg");

	if( t.value == this._DEFAULT_MSG )
		// Select all
		t.select();
}

Browser.prototype._fname_focus = function() {
	var t = getElement("new-file-name");

	if( t.value == this._DEFAULT_FNAME )
		// Select all
		t.select();
}
<|endoftext|>


<commit_before>const fs = require('fs');
const cp = require('child_process');
const readline = require('readline');
const commandLineArgs = require('command-line-args');

const outDir = './clips';

const optionDefinitions = [
  { name: 'delimiter', alias: 'd', type: String },
  { name: 'infile', alias: 'i', type: String },
];
const options = commandLineArgs(optionDefinitions);

var filename = options.infile;
var delimiter = options.hasOwnProperty('delimiter') ? options.delimiter : '---';

if (!options.hasOwnProperty('infile')) {
  // Can't do anything useful without input
  return;
}

<commit_msg>Add obvious arguments and start on main code<commit_after>const fs = require('fs');
const cp = require('child_process');
const im = require('imagemagick');
const readline = require('readline');
const commandLineArgs = require('command-line-args');

const outDir = './clips';

const optionDefinitions = [
  { name: 'delimiter', alias: 'd', type: String },
  { name: 'font', alias: 'f', type: String },
  { name: 'music', alias: 'm', type: String },
  { name: 'text', alias: 't', type: String },
];
const options = commandLineArgs(optionDefinitions);

var text = options.text;
var font = options.font;
var music = options.music;
var delimiter = options.hasOwnProperty('delimiter') ? options.delimiter : '---';

if (!options.hasOwnProperty('font')
 || !options.hasOwnProperty('music')
 || !options.hasOwnProperty('text')) {
  // Can't do anything useful without input
  return;
}

var lineReader = readline.createInterface({
  terminal: false,
  input: fs.createReadStream(filename)
});
var screenful = '';
lineReader.on('line', function (line) {
}

<|endoftext|>


<commit_before>describe('urls', function () {
  // create a new pad before each test run
  beforeEach(function (cb) {
    helper.newPad(cb);
    this.timeout(60000);
  });

  it('when you enter an url, it becomes clickable', function (done) {
    const inner$ = helper.padInner$;
    const chrome$ = helper.padChrome$;

    // get the first text element out of the inner iframe
    const firstTextElement = inner$('div').first();

    // simulate key presses to delete content
    firstTextElement.sendkeys('{selectall}'); // select all
    firstTextElement.sendkeys('{del}'); // clear the first line
    firstTextElement.sendkeys('https://etherpad.org'); // insert a URL

    helper.waitFor(() => inner$('div').first().find('a').length === 1, 2000).done(done);
  });

  it('when you enter a url containing a !, it becomes clickable and contains the whole URL', function (done) {
    const inner$ = helper.padInner$;
    const chrome$ = helper.padChrome$;

    // get the first text element out of the inner iframe
    const firstTextElement = inner$('div').first();
    const url = 'https://etherpad.org/!foo';

    // simulate key presses to delete content
    firstTextElement.sendkeys('{selectall}'); // select all
    firstTextElement.sendkeys('{del}'); // clear the first line
    firstTextElement.sendkeys(url); // insert a URL

    helper.waitFor(() => {
      if (inner$('div').first().find('a').length === 1) { // if it contains an A link
        if (inner$('div').first().find('a')[0].href === url) {
          return true;
        }
      }
    }, 2000).done(done);
  });

  it('when you enter a url followed by a ], the ] is not included in the URL', function (done) {
    const inner$ = helper.padInner$;
    const chrome$ = helper.padChrome$;

    // get the first text element out of the inner iframe
    const firstTextElement = inner$('div').first();
    const url = 'https://etherpad.org/';

    // simulate key presses to delete content
    firstTextElement.sendkeys('{selectall}'); // select all
    firstTextElement.sendkeys('{del}'); // clear the first line
    firstTextElement.sendkeys(url); // insert a URL
    firstTextElement.sendkeys(']'); // put a ] after it

    helper.waitFor(() => {
      if (inner$('div').first().find('a').length === 1) { // if it contains an A link
        if (inner$('div').first().find('a')[0].href === url) {
          return true;
        }
      }
    }, 2000).done(done);
  });
});
<commit_msg>tests: Expand the tests in `urls_become_clickable.js`<commit_after>'use strict';

describe('urls', function () {
  // Returns the first text element. Note that any change to the text element will result in the
  // element being replaced with another object.
  const txt = () => helper.padInner$('div').first();

  before(async function () {
    this.timeout(60000);
    await new Promise((resolve, reject) => helper.newPad((err) => {
      if (err != null) return reject(err);
      resolve();
    }));
  });

  beforeEach(async function () {
    await helper.clearPad();
  });

  describe('entering a URL makes a link', function () {
    for (const url of ['https://etherpad.org', 'www.etherpad.org']) {
      it(url, async function () {
        const url = 'https://etherpad.org';
        await helper.edit(url);
        await helper.waitForPromise(() => txt().find('a').length === 1, 2000);
        const link = txt().find('a');
        expect(link.attr('href')).to.be(url);
        expect(link.text()).to.be(url);
      });
    }
  });

  describe('special characters inside URL', function () {
    for (const char of '-:@_.,~%+/?=&#!;()$') {
      const url = `https://etherpad.org/${char}foo`;
      it(url, async function () {
        await helper.edit(url);
        await helper.waitForPromise(() => txt().find('a').length === 1);
        const link = txt().find('a');
        expect(link.attr('href')).to.be(url);
        expect(link.text()).to.be(url);
      });
    }
  });

  describe('punctuation after URL is ignored', function () {
    for (const char of ':.,;]') {
      const want = 'https://etherpad.org';
      const input = want + char;
      it(input, async function () {
        await helper.edit(input);
        await helper.waitForPromise(() => txt().find('a').length === 1);
        const link = txt().find('a');
        expect(link.attr('href')).to.be(want);
        expect(link.text()).to.be(want);
      });
    }
  });

  // Square brackets are in the RFC3986 reserved set so they can legally appear in URIs, but they
  // are explicitly excluded from linkification because including them is usually not desired (e.g.,
  // it can interfere with wiki/markdown link syntax).
  describe('square brackets are excluded from linkified URLs', function () {
    for (const char of '[]') {
      const want = 'https://etherpad.org/';
      const input = `${want}${char}foo`;
      it(input, async function () {
        await helper.edit(input);
        await helper.waitForPromise(() => txt().find('a').length === 1);
        const link = txt().find('a');
        expect(link.attr('href')).to.be(want);
        expect(link.text()).to.be(want);
      });
    }
  });
});
<|endoftext|>