<commit_before>// ==UserScript==
// @name           Stack-Exchange-Editor-Toolkit
// @author         Cameron Bernhardt (AstroCB)
// @namespace  http://github.com/AstroCB
// @version        1.0
// @description  Fix common grammar/usage annoyances on Stack Exchange posts with a click
// @include        http://*.stackexchange.com/questions/*
// @include        http://stackoverflow.com/questions/*
// @include        http://meta.stackoverflow.com/questions/*
// @include        http://serverfault.com/questions/*
// @include        http://meta.serverfault.com/questions/*
// @include        http://superuser.com/questions/*
// @include        http://meta.superuser.com/questions/*
// @include        http://askubuntu.com/questions/*
// @include        http://meta.askubuntu.com/questions/*
// @include        http://stackapps.com/questions/*
// @include        http://*.stackexchange.com/posts/*
// @include        http://stackoverflow.com/posts/*
// @include        http://meta.stackoverflow.com/posts/*
// @include        http://serverfault.com/posts/*
// @include        http://meta.serverfault.com/posts/*
// @include        http://superuser.com/posts/*
// @include        http://meta.superuser.com/posts/*
// @include        http://askubuntu.com/posts/*
// @include        http://meta.askubuntu.com/posts/*
// @include        http://stackapps.com/posts/*
// @exclude        http://*.stackexchange.com/questions/tagged/*
// @exclude        http://stackoverflow.com/questions/tagged/*
// @exclude        http://meta.stackoverflow.com/questions/tagged/*
// @exclude        http://serverfault.com/questions/tagged/*
// @exclude        http://meta.serverfault.com/questions/*
// @exclude        http://superuser.com/questions/tagged/*
// @exclude        http://meta.superuser.com/questions/tagged/*
// @exclude        http://askubuntu.com/questions/tagged/*
// @exclude        http://meta.askubuntu.com/questions/tagged/*
// @exclude        http://stackapps.com/questions/tagged/*
// ==/UserScript==

window.addEventListener("load", function(){
  var edits = document.getElementsByClassName("edit-post");
  var rows = document.getElementsByClassName("wmd-button-row");
  var rowNum = 0;
  var privileges = true;

  var button = document.createElement("button");

  if (window.location.href.search(/\/posts\/\d*\/edit/) !== -1) { //no editing privileges
  	privileges = false;

    if(localStorage){
      if(!localStorage.hasAsked){ //only warn users about privileges once per site if their browser supports localStorage
        alert("You do not have editing privileges on this site. The script will still work, but be aware of what it is doing and understand that it may be rejected.");
        localStorage.hasAsked = true;
      }
    }else{
      alert("You do not have editing privileges on this site. The script will still work, but be aware of what it is doing and understand that it may be rejected.");
    }

    var left = parseInt(rows[0].children[rows[0].children.length - 2].style.left) + 25 + "px"; //grabs the positioning of the last element in the row and adds the proper spacing
    button.setAttribute("class", "wmd-button");
    button.setAttribute("id", "fix");
    button.setAttribute("style", "left: " + left);
    button.textContent = "Fix";
    button.addEventListener("click", go);

  	rows[0].appendChild(button);
    rowNum++;
  } else {
  	for (var x = 0; x < edits.length; x++) {
  		edits[x].addEventListener("click", function () {
        var left = parseInt(rows[rowNum].children[rows[rowNum].children.length - 2].style.left) + 25 + "px"; //grabs the positioning of the last element in the row and adds the proper spacing
        button.setAttribute("class", "wmd-button");
        button.setAttribute("id", "fix");
        button.setAttribute("style", "left: " + left);
        button.textContent = "Fix";
        button.addEventListener("click", go);

  			window.setTimeout(function () {
  				rows[rowNum].appendChild(button);
  				rowNum++;
  			}, 750); //inserts after menu loads: probably a better way to do this
  		});
  	}
  }

  function fixIt(input, expression, replacement, reasoning) {
  	var there = input.search(expression);

  	if (there !== -1) {
  		var phrase;
  		if (replacement === "") {
  			input = input.replace(expression, function (data, match1) {
  				phrase = match1;
  				return "";
  			});
  			reasoning = reasoning.replace("$1", phrase);
  		} else if (replacement == "$1vote") {
  			input = input.replace(expression, function (data, match1) {
  				phrase = match1;
  				return phrase + "vot";
  			});
  			reasoning = reasoning.replace("$1", phrase.toLowerCase());
  		} else if (replacement === "$1") {
  			input = input.replace(expression, function (data, match1) {
  				return match1.toUpperCase();
  			});
  		} else {
  			input = input.replace(expression, replacement);
  		}

  		return {
  			reason: reasoning,
  			fixed: input,
  		};
  	} else {
  		return null;
  	}
  }

  function go(e) {
  	e.preventDefault();

  	var edits = {
  		i: {
  			expr: /(^|\s|\()i(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
  			replacement: "$1I$2",
  			reason: "in the English language, the pronoun 'I' is capitalized",
  		},

  		so: {
  			expr: /(^|\s)[Ss]tack\s*overflow|StackOverflow(.|$)/gm,
  			replacement: "$1Stack Overflow$2",
  			reason: "the legal name is 'Stack Overflow' (two words, capitalized)",
  		},

  		se: {
  			expr: /(^|\s)[Ss]tack\s*exchange|StackExchange(.|$)/gm,
  			replacement: "$1Stack Exchange$2",
  			reason: "the legal name is 'Stack Exchange' (two words, capitalized)",
  		},

  		expansionSO: {
  			expr: /(^|\s)SO(\s|,|\.|!|\?|;|\/|\)|$)/gm,
  			replacement: "$1Stack Overflow$2",
  			reason: "expansion",
  		},

  		expansionSE: {
  			expr: /(^|\s)SE(\s|,|\.|!|\?|;|\/|\)|$)/gm,
  			replacement: "$1Stack Exchange$2",
  			reason: "expansion",
  		},

  		javascript: {
  			expr: /(^|\s)[Jj]ava\s*script(.|$)/gm,
  			replacement: "$1JavaScript$2",
  			reason: "the proper capitalization is 'JavaScript' (see http://en.wikipedia.org/wiki/JavaScript)"
  		},

  		jsfiddle: {
  			expr: /(^|\s)[Jj][Ss][Ff]iddle(.|$)/gm,
  			replacement: "$1JSFiddle$2",
  			reason: "the current accepted capitalization is 'JSFiddle' (see title tag on http://jsfiddle.net)"
  		},

  		caps: {
  			expr: /^(?!https?)([a-z])/gm,
  			replacement: "$1",
  			reason: "copy edited",
  		},

  		jquery: {
  			expr: /(^|\s)[Jj][Qq]uery(.|$)/gm,
  			replacement: "$1jQuery$2",
  			reason: "the proper capitalization is 'jQuery' (see http://jquery.com)",
  		},

  		html: {
  			expr: /(^|\s)[Hh]tml(?:5*)(\s|$)/gm,
  			replacement: "$1HTML$2",
  			reason: "HTML is an initialism for HyperText Markup Language",
  		},

  		css: {
  			expr: /(^|\s)[Cc]ss(\s|$)/gm,
  			replacement: "$1CSS$2",
  			reason: "CSS is an initialism for Cascading Style Sheets",
  		},

  		json: {
  			expr: /(^|\s)[Jj]son(\s|$)/gm,
  			replacement: "$1JSON$2",
  			reason: "JSON is an initialism for JavaScript Object Notation",
  		},

  		ajax: {
  			expr: /(^|\s)[Aa]jax(\s|$)/gm,
  			replacement: "$1AJAX$2",
  			reason: "AJAX is an initialism for Asynchronous JavaScript and XML",
  		},

  		angular: {
  			expr: /[Aa]ngular[Jj][Ss]/g,
  			replacement: "AngularJS",
  			reason: "the 'JS' in 'AngularJS' is capitalized",
  		},

  		thanks: {
  			expr: /(thanks|please\s+help|cheers|regards|thx|thank\s+you|my\s+first\s+question).*$/gmi,
  			replacement: "",
  			reason: "please don't include '$1' in your question: it is unnecessary noise",
  		},

  		commas: {
  			expr: /,([^\s])/g,
  			replacement: ", $1",
  			reason: "commas have one space after them",
  		},

  		php: {
  			expr: /(^|\s)[Pp]hp(\s|$)/gm,
  			replacement: "$1PHP$2",
  			reason: "PHP is an initialism for PHP: Hypertext Preprocessor (recursive)",
  		},

  		hello: {
  			expr: /(?:^|\s)(hi\s+guys|good\s(?:evening|morning|day|afternoon))(?:\.|!)/gmi,
  			replacement: "",
  			reason: "please don't include '$1' in your question: it is unnecessary noise",
  		},

  		edit: {
  			expr: /(?:\**)(edit|update):?(?:\**)/gi,
  			replacement: "",
  			reason: "Stack Exchange has an advanced revision history system: please don't include 'Edit' or 'Update' with edits, as the revision history makes the timing of your edits clear",
  		},

  		voting: {
  			expr: /([Dd]own|[Uu]p)[\s*\-]vot/g,
  			replacement: "$1vote",
  			reason: "the proper spelling (despite the tag name) is '$1vote' (one word)"
  		},

  		mysite: {
  			expr: /mysite\./g,
  			replacement: "example.",
  			reason: "links to mysite.domain are not allowed: use example.domain instead",
  		},

  	};

  	var boxes = document.getElementsByClassName("wmd-input");
  	var box = boxes[rowNum - 1].value;
  	var titles = document.getElementsByClassName("ask-title-field");
  	var title = titles[rowNum - 1].value;

  	var reasons = [];
  	var numReasons = 0;

  	for (var j in edits) {
  		if (edits.hasOwnProperty(j)) {
  			var fix = fixIt(box, edits[j].expr, edits[j].replacement, edits[j].reason); //check body
  			if (fix) {
  				reasons[numReasons] = fix.reason;
  				box = fix.fixed;
  				numReasons++;
  				edits[j].fixed = true;
  			}

  			fix = fixIt(title, edits[j].expr, edits[j].replacement, edits[j].reason); //check title
  			if (fix) {
  				title = fix.fixed;
  				if (!edits[j].fixed) {
  					reasons[numReasons] = fix.reason;
  					numReasons++;
  					edits[j].fixed = true;
  				}
  			}
  		}
  	}

  	boxes[rowNum - 1].value = box;
  	titles[rowNum - 1].value = title;

  	var summary = "";

  	for (var z = 0; z < reasons.length; z++) {
  		if (z === 0) {
  			summary += reasons[z][0].toUpperCase() + reasons[z].substring(1);
  		} else if (z !== reasons.length - 1) {
  			summary += reasons[z] + "; ";
  		} else {
  			summary += reasons[z];
  		}

  		if (z === 0 && reasons.length > 1) {
  			summary += "; ";
  		}

  		if (z === reasons.length - 1) {
  			summary += ".";
  		}
  	}

    if(privileges){
  	   document.getElementsByClassName("edit-comment")[rowNum - 1].value = summary;
     }else{
       document.getElementById("edit-comment").value = summary;
     }

  }
});
<commit_msg>Check for colons on the outside of parentheses<commit_after>// ==UserScript==
// @name           Stack-Exchange-Editor-Toolkit
// @author         Cameron Bernhardt (AstroCB)
// @namespace  http://github.com/AstroCB
// @version        1.0
// @description  Fix common grammar/usage annoyances on Stack Exchange posts with a click
// @include        http://*.stackexchange.com/questions/*
// @include        http://stackoverflow.com/questions/*
// @include        http://meta.stackoverflow.com/questions/*
// @include        http://serverfault.com/questions/*
// @include        http://meta.serverfault.com/questions/*
// @include        http://superuser.com/questions/*
// @include        http://meta.superuser.com/questions/*
// @include        http://askubuntu.com/questions/*
// @include        http://meta.askubuntu.com/questions/*
// @include        http://stackapps.com/questions/*
// @include        http://*.stackexchange.com/posts/*
// @include        http://stackoverflow.com/posts/*
// @include        http://meta.stackoverflow.com/posts/*
// @include        http://serverfault.com/posts/*
// @include        http://meta.serverfault.com/posts/*
// @include        http://superuser.com/posts/*
// @include        http://meta.superuser.com/posts/*
// @include        http://askubuntu.com/posts/*
// @include        http://meta.askubuntu.com/posts/*
// @include        http://stackapps.com/posts/*
// @exclude        http://*.stackexchange.com/questions/tagged/*
// @exclude        http://stackoverflow.com/questions/tagged/*
// @exclude        http://meta.stackoverflow.com/questions/tagged/*
// @exclude        http://serverfault.com/questions/tagged/*
// @exclude        http://meta.serverfault.com/questions/*
// @exclude        http://superuser.com/questions/tagged/*
// @exclude        http://meta.superuser.com/questions/tagged/*
// @exclude        http://askubuntu.com/questions/tagged/*
// @exclude        http://meta.askubuntu.com/questions/tagged/*
// @exclude        http://stackapps.com/questions/tagged/*
// ==/UserScript==

window.addEventListener("load", function(){
  var edits = document.getElementsByClassName("edit-post");
  var rows = document.getElementsByClassName("wmd-button-row");
  var rowNum = 0;
  var privileges = true;

  var button = document.createElement("button");

  if (window.location.href.search(/\/posts\/\d*\/edit/) !== -1) { //no editing privileges
  	privileges = false;

    if(localStorage){
      if(!localStorage.hasAsked){ //only warn users about privileges once per site if their browser supports localStorage
        alert("You do not have editing privileges on this site. The script will still work, but be aware of what it is doing and understand that it may be rejected.");
        localStorage.hasAsked = true;
      }
    }else{
      alert("You do not have editing privileges on this site. The script will still work, but be aware of what it is doing and understand that it may be rejected.");
    }

    var left = parseInt(rows[0].children[rows[0].children.length - 2].style.left) + 25 + "px"; //grabs the positioning of the last element in the row and adds the proper spacing
    button.setAttribute("class", "wmd-button");
    button.setAttribute("id", "fix");
    button.setAttribute("style", "left: " + left);
    button.textContent = "Fix";
    button.addEventListener("click", go);

  	rows[0].appendChild(button);
    rowNum++;
  } else {
  	for (var x = 0; x < edits.length; x++) {
  		edits[x].addEventListener("click", function () {
        var left = parseInt(rows[rowNum].children[rows[rowNum].children.length - 2].style.left) + 25 + "px"; //grabs the positioning of the last element in the row and adds the proper spacing
        button.setAttribute("class", "wmd-button");
        button.setAttribute("id", "fix");
        button.setAttribute("style", "left: " + left);
        button.textContent = "Fix";
        button.addEventListener("click", go);

  			window.setTimeout(function () {
  				rows[rowNum].appendChild(button);
  				rowNum++;
  			}, 750); //inserts after menu loads: probably a better way to do this
  		});
  	}
  }

  function fixIt(input, expression, replacement, reasoning) {
  	var there = input.search(expression);

  	if (there !== -1) {
  		var phrase;
  		if (replacement === "") {
  			input = input.replace(expression, function (data, match1) {
  				phrase = match1;
  				return "";
  			});
  			reasoning = reasoning.replace("$1", phrase);
  		} else if (replacement == "$1vote") {
  			input = input.replace(expression, function (data, match1) {
  				phrase = match1;
  				return phrase + "vot";
  			});
  			reasoning = reasoning.replace("$1", phrase.toLowerCase());
  		} else if (replacement === "$1") {
  			input = input.replace(expression, function (data, match1) {
  				return match1.toUpperCase();
  			});
  		} else {
  			input = input.replace(expression, replacement);
  		}

  		return {
  			reason: reasoning,
  			fixed: input,
  		};
  	} else {
  		return null;
  	}
  }

  function go(e) {
  	e.preventDefault();

  	var edits = {
  		i: {
  			expr: /(^|\s|\()i(\s|,|\.|!|\?|;|\/|\)|'|$)/gm,
  			replacement: "$1I$2",
  			reason: "in the English language, the pronoun 'I' is capitalized",
  		},

  		so: {
  			expr: /(^|\s)[Ss]tack\s*overflow|StackOverflow(.|$)/gm,
  			replacement: "$1Stack Overflow$2",
  			reason: "the legal name is 'Stack Overflow' (two words, capitalized)",
  		},

  		se: {
  			expr: /(^|\s)[Ss]tack\s*exchange|StackExchange(.|$)/gm,
  			replacement: "$1Stack Exchange$2",
  			reason: "the legal name is 'Stack Exchange' (two words, capitalized)",
  		},

  		expansionSO: {
  			expr: /(^|\s)SO(\s|,|\.|!|\?|;|\/|\)|$)/gm,
  			replacement: "$1Stack Overflow$2",
  			reason: "expansion",
  		},

  		expansionSE: {
  			expr: /(^|\s)SE(\s|,|\.|!|\?|;|\/|\)|$)/gm,
  			replacement: "$1Stack Exchange$2",
  			reason: "expansion",
  		},

  		javascript: {
  			expr: /(^|\s)[Jj]ava\s*script(.|$)/gm,
  			replacement: "$1JavaScript$2",
  			reason: "the proper capitalization is 'JavaScript' (see http://en.wikipedia.org/wiki/JavaScript)"
  		},

  		jsfiddle: {
  			expr: /(^|\s)[Jj][Ss][Ff]iddle(.|$)/gm,
  			replacement: "$1JSFiddle$2",
  			reason: "the current accepted capitalization is 'JSFiddle' (see title tag on http://jsfiddle.net)"
  		},

  		caps: {
  			expr: /^(?!https?)([a-z])/gm,
  			replacement: "$1",
  			reason: "copy edited",
  		},

  		jquery: {
  			expr: /(^|\s)[Jj][Qq]uery(.|$)/gm,
  			replacement: "$1jQuery$2",
  			reason: "the proper capitalization is 'jQuery' (see http://jquery.com)",
  		},

  		html: {
  			expr: /(^|\s)[Hh]tml(?:5*)(\s|$)/gm,
  			replacement: "$1HTML$2",
  			reason: "HTML is an initialism for HyperText Markup Language",
  		},

  		css: {
  			expr: /(^|\s)[Cc]ss(\s|$)/gm,
  			replacement: "$1CSS$2",
  			reason: "CSS is an initialism for Cascading Style Sheets",
  		},

  		json: {
  			expr: /(^|\s)[Jj]son(\s|$)/gm,
  			replacement: "$1JSON$2",
  			reason: "JSON is an initialism for JavaScript Object Notation",
  		},

  		ajax: {
  			expr: /(^|\s)[Aa]jax(\s|$)/gm,
  			replacement: "$1AJAX$2",
  			reason: "AJAX is an initialism for Asynchronous JavaScript and XML",
  		},

  		angular: {
  			expr: /[Aa]ngular[Jj][Ss]/g,
  			replacement: "AngularJS",
  			reason: "the 'JS' in 'AngularJS' is capitalized",
  		},

  		thanks: {
  			expr: /(thanks|please\s+help|cheers|regards|thx|thank\s+you|my\s+first\s+question).*$/gmi,
  			replacement: "",
  			reason: "please don't include '$1' in your question: it is unnecessary noise",
  		},

  		commas: {
  			expr: /,([^\s])/g,
  			replacement: ", $1",
  			reason: "commas have one space after them",
  		},

  		php: {
  			expr: /(^|\s)[Pp]hp(\s|$)/gm,
  			replacement: "$1PHP$2",
  			reason: "PHP is an initialism for PHP: Hypertext Preprocessor (recursive)",
  		},

  		hello: {
  			expr: /(?:^|\s)(hi\s+guys|good\s(?:evening|morning|day|afternoon))(?:\.|!)/gmi,
  			replacement: "",
  			reason: "please don't include '$1' in your question: it is unnecessary noise",
  		},

  		edit: {
  			expr: /(?:\**)(edit|update):?(?:\**):?/gi,
  			replacement: "",
  			reason: "Stack Exchange has an advanced revision history system: please don't include 'Edit' or 'Update' with edits, as the revision history makes the timing of your edits clear",
  		},

  		voting: {
  			expr: /([Dd]own|[Uu]p)[\s*\-]vot/g,
  			replacement: "$1vote",
  			reason: "the proper spelling (despite the tag name) is '$1vote' (one word)"
  		},

  		mysite: {
  			expr: /mysite\./g,
  			replacement: "example.",
  			reason: "links to mysite.domain are not allowed: use example.domain instead",
  		},

  	};

  	var boxes = document.getElementsByClassName("wmd-input");
  	var box = boxes[rowNum - 1].value;
  	var titles = document.getElementsByClassName("ask-title-field");
  	var title = titles[rowNum - 1].value;

  	var reasons = [];
  	var numReasons = 0;

  	for (var j in edits) {
  		if (edits.hasOwnProperty(j)) {
  			var fix = fixIt(box, edits[j].expr, edits[j].replacement, edits[j].reason); //check body
  			if (fix) {
  				reasons[numReasons] = fix.reason;
  				box = fix.fixed;
  				numReasons++;
  				edits[j].fixed = true;
  			}

  			fix = fixIt(title, edits[j].expr, edits[j].replacement, edits[j].reason); //check title
  			if (fix) {
  				title = fix.fixed;
  				if (!edits[j].fixed) {
  					reasons[numReasons] = fix.reason;
  					numReasons++;
  					edits[j].fixed = true;
  				}
  			}
  		}
  	}

  	boxes[rowNum - 1].value = box;
  	titles[rowNum - 1].value = title;

  	var summary = "";

  	for (var z = 0; z < reasons.length; z++) {
  		if (z === 0) {
  			summary += reasons[z][0].toUpperCase() + reasons[z].substring(1);
  		} else if (z !== reasons.length - 1) {
  			summary += reasons[z] + "; ";
  		} else {
  			summary += reasons[z];
  		}

  		if (z === 0 && reasons.length > 1) {
  			summary += "; ";
  		}

  		if (z === reasons.length - 1) {
  			summary += ".";
  		}
  	}

    if(privileges){
  	   document.getElementsByClassName("edit-comment")[rowNum - 1].value = summary;
     }else{
       document.getElementById("edit-comment").value = summary;
     }

  }
});
<|endoftext|>


<commit_before>const { getBrowserForTab } = require('sdk/tabs/utils');
const { defer } = require('sdk/core/promise');
const { viewFor } = require("sdk/view/core");

let DEBUG = false;

exports.setDebug = function (val) {
  DEBUG = val;
};

function logDebug() {
  if (! DEBUG) {
    return;
  }
  let args = [];
  for (var i=0; i<arguments.length; i++) {
    if (typeof arguments[i] == "object" &&
      JSON.stringify(arguments[i]).length > 100) {
        args.push("[Object keys: " + JSON.stringify(Object.keys(arguments[i])) + "]");
    } else {
      args.push(arguments[i]);
    }
  }
  console.log.apply(console, args);
}

function getBrowser(tab) {
  if (tab && tab.attach) {
    // Convert from SDK tab to XUL tab
    tab = viewFor(tab);
  }
  return getBrowserForTab(tab);
}

exports.addScript = function (tab, script) {
  let browser = getBrowser(tab);
  let scripts = browser.framescripterEnabledScripts;
  if (! scripts) {
    scripts = browser.framescripterEnabledScripts = {};
  }
  if (! scripts[script]) {
    logDebug("Adding script:", script);
    let browserMM = browser.messageManager;
    if (! browserMM) {
      console.error("Could not get messageManager from " + browser);
      throw new Error("Could not get messageManager");
    }
    browserMM.loadFrameScript(script, false);
    scripts[script] = {};
  } else {
    logDebug("Script already loaded:", script);
  }
};

let idCounter = 1;

function makeId() {
  return idCounter++;
}

const pendingDeferreds = {};

exports.callScript = function (tab, script, message, payload) {
  exports.addScript(tab, script);
  let browser = getBrowser(tab);
  let messages = browser.framescripterEnabledScripts[script];
  let browserMM = browser.messageManager;
  if (! messages[message]) {
    browserMM.addMessageListener(message + ":return", callScriptReturner);
    messages[message] = true;
    logDebug("Adding frame listener for:", message + ":return");
  }
  let deferred = defer();
  let id = makeId();
  pendingDeferreds[id] = deferred;
  payload.callId = id;
  logDebug("Sending [" + message + ":call]/" + id + " with payload:", payload);
  browserMM.sendAsyncMessage(message + ":call", payload);
  return deferred.promise;
};

function callScriptReturner(event) {
  let deferred = pendingDeferreds[event.data.callId];
  if (! deferred) {
    console.error("Got deferred that has expired:", event.data.callId);
    throw new Error("Expired deferred");
  }
  delete pendingDeferreds[event.data.callId];
  logDebug("Received /" + event.data.callId + " with payload:", event.data);
  if (event.data.error) {
    deferred.reject(event.data.error);
  } else {
    delete event.data.callId;
    deferred.resolve(event.data);
  }
}
<commit_msg>add jshint hints<commit_after>/* global require, exports, console */
const { getBrowserForTab } = require('sdk/tabs/utils');
const { defer } = require('sdk/core/promise');
const { viewFor } = require("sdk/view/core");

let DEBUG = false;

exports.setDebug = function (val) {
  DEBUG = val;
};

function logDebug() {
  if (! DEBUG) {
    return;
  }
  let args = [];
  for (var i=0; i<arguments.length; i++) {
    if (typeof arguments[i] == "object" &&
      JSON.stringify(arguments[i]).length > 100) {
        args.push("[Object keys: " + JSON.stringify(Object.keys(arguments[i])) + "]");
    } else {
      args.push(arguments[i]);
    }
  }
  console.log.apply(console, args);
}

function getBrowser(tab) {
  if (tab && tab.attach) {
    // Convert from SDK tab to XUL tab
    tab = viewFor(tab);
  }
  return getBrowserForTab(tab);
}

exports.addScript = function (tab, script) {
  let browser = getBrowser(tab);
  let scripts = browser.framescripterEnabledScripts;
  if (! scripts) {
    scripts = browser.framescripterEnabledScripts = {};
  }
  if (! scripts[script]) {
    logDebug("Adding script:", script);
    let browserMM = browser.messageManager;
    if (! browserMM) {
      console.error("Could not get messageManager from " + browser);
      throw new Error("Could not get messageManager");
    }
    browserMM.loadFrameScript(script, false);
    scripts[script] = {};
  } else {
    logDebug("Script already loaded:", script);
  }
};

let idCounter = 1;

function makeId() {
  return idCounter++;
}

const pendingDeferreds = {};

exports.callScript = function (tab, script, message, payload) {
  exports.addScript(tab, script);
  let browser = getBrowser(tab);
  let messages = browser.framescripterEnabledScripts[script];
  let browserMM = browser.messageManager;
  if (! messages[message]) {
    browserMM.addMessageListener(message + ":return", callScriptReturner);
    messages[message] = true;
    logDebug("Adding frame listener for:", message + ":return");
  }
  let deferred = defer();
  let id = makeId();
  pendingDeferreds[id] = deferred;
  payload.callId = id;
  logDebug("Sending [" + message + ":call]/" + id + " with payload:", payload);
  browserMM.sendAsyncMessage(message + ":call", payload);
  return deferred.promise;
};

function callScriptReturner(event) {
  let deferred = pendingDeferreds[event.data.callId];
  if (! deferred) {
    console.error("Got deferred that has expired:", event.data.callId);
    throw new Error("Expired deferred");
  }
  delete pendingDeferreds[event.data.callId];
  logDebug("Received /" + event.data.callId + " with payload:", event.data);
  if (event.data.error) {
    deferred.reject(event.data.error);
  } else {
    delete event.data.callId;
    deferred.resolve(event.data);
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

const Metalsmith = require('metalsmith');
const autoprefixer = require('autoprefixer-stylus');
const collections = require('metalsmith-collections');
const feed = require('metalsmith-feed');
const layouts = require('metalsmith-layouts');
const markdown = require('metalsmith-markdown');
const prism = require('metalsmith-prism');
const stylus = require('metalsmith-stylus');
const permalinks = require('metalsmith-permalinks');
const path = require('path');
const fs = require('fs');
const ncp = require('ncp');

const filterStylusPartials = require('./plugins/filter-stylus-partials');
const mapHandlebarsPartials = require('./plugins/map-handlebars-partials');
const versions = require('./source/versions');

/** Build **/

// load template.json for given language, but use default language as fallback
// for properties which are not present in the given language
var Handlebars = require('handlebars');

const DEFAULT_LANG = 'en';
function i18nJSON (lang) {
  var defaultJSON = require(`./locale/${DEFAULT_LANG}/site.json`);
  var templateJSON = require(`./locale/${lang}/site.json`);
  var finalJSON = JSON.parse(JSON.stringify(defaultJSON));
  var merge = function (targetJSON, customJSON) {
    Object.keys(customJSON).forEach(function (key) {
      let value = customJSON[key];
      if (typeof value === 'object') {
        merge(targetJSON[key], value);
      } else {
        targetJSON[key] = value;
      }
    });
  };
  merge(finalJSON, templateJSON);
  return finalJSON;
}

function traverse (obj, str) {
  return str.split('.').reduce(function (o, x) { return o[x]; }, obj);
}

const source = {
  project: {
    versions,
    currentVersion: versions[0].version
  }
};

function buildlocale (locale) {
  console.time('[metalsmith] build/' + locale + ' finished');
    const siteJSON = path.join(__dirname, 'locale', locale, 'site.json');
    const metalsmith = Metalsmith(__dirname);
    metalsmith
    .metadata({
      site: require(siteJSON),
      project: source.project,
      i18n: i18nJSON(locale)
    })
    .source(path.join(__dirname, 'locale', locale))
    .use(collections({
      blog : {
        pattern: 'blog/**/*.md',
        sortBy: 'date',
        reverse: true,
        refer: false
      },
      lastWeekly: {
        pattern: 'blog/weekly-updates/*.md',
        sortBy: 'date',
        reverse: true,
        refer: false,
        limit: 1
      },
      tscMinutes: {
        pattern: 'foundation/tsc/minutes/*.md',
        sortBy: 'date',
        reverse: true,
        refer: false
      }
    }))
    .use(markdown({ langPrefix: 'language-' }))
    .use(prism())
    .use(filterStylusPartials())
    .use(stylus({
      compress: true,
      paths:[path.join(__dirname, 'layouts', 'css')],
      use: [autoprefixer()]
    }))
    .use(permalinks())
    .use(feed({
      collection: 'blog',
      destination: 'blog.xml',
      title: 'Node.js Blog'
    }))
    .use(feed({
      collection: 'tscMinutes',
      destination: 'tsc-minutes.xml',
      title: 'Node.js Technical Steering Committee meetings'
    }))
    .use(layouts({
      engine: 'handlebars',
      pattern: '**/*.html',
      partials: mapHandlebarsPartials(metalsmith, 'layouts', 'partials'),
      helpers: {
        equals: function (v1, v2, options) {
          return (v1 === v2) ? options.fn(this) : options.inverse(this);
        },
        i18n: function () {
          var env, key;

          // function(key, env)
          if (arguments.length === 2) {
            key = arguments[0];
            env = arguments[1];
          }
          // function(scope, key, env)
          if (arguments.length === 3) {
            key = arguments[0] + '.' + arguments[1];
            env = arguments[2];
          }

          var data = env.data.root;
          var result = traverse(data.i18n, key);

          return new Handlebars.SafeString(result);
        }
      }
    }))
    .destination(path.join(__dirname, 'build', locale));

    metalsmith.build(function (err) {
      if (err) { throw err; }
      console.timeEnd('[metalsmith] build/' + locale + ' finished');
    });
}

function copystatic () {
  console.time('[metalsmith] build/static finished');
  fs.mkdir(path.join(__dirname, 'build'), function () {
    fs.mkdir(path.join(__dirname, 'build', 'static'), function () {
      ncp(path.join(__dirname, 'static'), path.join(__dirname, 'build', 'static'), function (err) {
        if (err) { return console.error(err); }
        console.timeEnd('[metalsmith] build/static finished');
      });
    });
  });
}

function fullbuild () {
  copystatic();
  fs.readdir(path.join(__dirname, 'locale'), function (e, locales) {
    locales.forEach(function (locale) {
      buildlocale(locale);
    });
  });
}
fullbuild();

if (process.argv[2] === 'serve') {
  server();
}

function server () {
  /** Static file server **/
  const st = require('st');
  const http = require('http');
  const mount = st({
    path: path.join(__dirname, 'build'),
    cache: false,
    index: 'index.html'
  });
  http.createServer(
    function (req, res) { mount(req, res); }
  ).listen(8080,
    function () { console.log('http://localhost:8080/en/'); }
  );

  /** File Watches for Re-Builds **/
  const chokidar = require('chokidar');
  const opts = {
    persistent: true,
    ignoreInitial: true,
    followSymlinks: true,
    usePolling: true,
    alwaysStat: false,
    depth: undefined,
    interval: 100,
    ignorePermissionErrors: false,
    atomic: true
  };
  const locales = chokidar.watch(path.join(__dirname, 'locale'), opts);
  const layouts = chokidar.watch(path.join(__dirname, 'layouts'), opts);
  const staticf = chokidar.watch(path.join(__dirname, 'static'), opts);

  function getlocale (p) {
    const pre = path.join(__dirname, 'locale');
    return p.slice(pre.length + 1, p.indexOf('/', pre.length + 1));
  }
  locales.on('change', function (p) {
    buildlocale(getlocale(p));
  });
  locales.on('add', function (p) {
    buildlocale(getlocale(p));
    locales.add(p);
  });

  layouts.on('change', fullbuild);
  layouts.on('add', function (p) { layouts.add(p); fullbuild(); });

  staticf.on('change', copystatic);
  staticf.on('add', function (p) { staticf.add(p); copystatic(); });
}
<commit_msg>Fix multiple copies of site.json in build<commit_after>#!/usr/bin/env node

'use strict';

const Metalsmith = require('metalsmith');
const autoprefixer = require('autoprefixer-stylus');
const collections = require('metalsmith-collections');
const feed = require('metalsmith-feed');
const layouts = require('metalsmith-layouts');
const markdown = require('metalsmith-markdown');
const prism = require('metalsmith-prism');
const stylus = require('metalsmith-stylus');
const permalinks = require('metalsmith-permalinks');
const path = require('path');
const fs = require('fs');
const ncp = require('ncp');

const filterStylusPartials = require('./plugins/filter-stylus-partials');
const mapHandlebarsPartials = require('./plugins/map-handlebars-partials');
const versions = require('./source/versions');

/** Build **/

// load template.json for given language, but use default language as fallback
// for properties which are not present in the given language
var Handlebars = require('handlebars');

const DEFAULT_LANG = 'en';
function i18nJSON (lang) {
  var defaultJSON = require(`./locale/${DEFAULT_LANG}/site.json`);
  var templateJSON = require(`./locale/${lang}/site.json`);
  var finalJSON = JSON.parse(JSON.stringify(defaultJSON));
  var merge = function (targetJSON, customJSON) {
    Object.keys(customJSON).forEach(function (key) {
      let value = customJSON[key];
      if (typeof value === 'object') {
        merge(targetJSON[key], value);
      } else {
        targetJSON[key] = value;
      }
    });
  };
  merge(finalJSON, templateJSON);
  return finalJSON;
}

function traverse (obj, str) {
  return str.split('.').reduce(function (o, x) { return o[x]; }, obj);
}

const source = {
  project: {
    versions,
    currentVersion: versions[0].version
  }
};

function buildlocale (locale) {
  console.time('[metalsmith] build/' + locale + ' finished');
    const siteJSON = path.join(__dirname, 'locale', locale, 'site.json');
    const metalsmith = Metalsmith(__dirname);
    metalsmith
    .metadata({
      site: require(siteJSON),
      project: source.project,
      i18n: i18nJSON(locale)
    })
    .source(path.join(__dirname, 'locale', locale))
    .use(collections({
      blog : {
        pattern: 'blog/**/*.md',
        sortBy: 'date',
        reverse: true,
        refer: false
      },
      lastWeekly: {
        pattern: 'blog/weekly-updates/*.md',
        sortBy: 'date',
        reverse: true,
        refer: false,
        limit: 1
      },
      tscMinutes: {
        pattern: 'foundation/tsc/minutes/*.md',
        sortBy: 'date',
        reverse: true,
        refer: false
      }
    }))
    .use(markdown({ langPrefix: 'language-' }))
    .use(prism())
    .use(filterStylusPartials())
    .use(stylus({
      compress: true,
      paths:[path.join(__dirname, 'layouts', 'css')],
      use: [autoprefixer()]
    }))
    .use(permalinks({
      relative: false
    }))
    .use(feed({
      collection: 'blog',
      destination: 'blog.xml',
      title: 'Node.js Blog'
    }))
    .use(feed({
      collection: 'tscMinutes',
      destination: 'tsc-minutes.xml',
      title: 'Node.js Technical Steering Committee meetings'
    }))
    .use(layouts({
      engine: 'handlebars',
      pattern: '**/*.html',
      partials: mapHandlebarsPartials(metalsmith, 'layouts', 'partials'),
      helpers: {
        equals: function (v1, v2, options) {
          return (v1 === v2) ? options.fn(this) : options.inverse(this);
        },
        i18n: function () {
          var env, key;

          // function(key, env)
          if (arguments.length === 2) {
            key = arguments[0];
            env = arguments[1];
          }
          // function(scope, key, env)
          if (arguments.length === 3) {
            key = arguments[0] + '.' + arguments[1];
            env = arguments[2];
          }

          var data = env.data.root;
          var result = traverse(data.i18n, key);

          return new Handlebars.SafeString(result);
        }
      }
    }))
    .destination(path.join(__dirname, 'build', locale));

    metalsmith.build(function (err) {
      if (err) { throw err; }
      console.timeEnd('[metalsmith] build/' + locale + ' finished');
    });
}

function copystatic () {
  console.time('[metalsmith] build/static finished');
  fs.mkdir(path.join(__dirname, 'build'), function () {
    fs.mkdir(path.join(__dirname, 'build', 'static'), function () {
      ncp(path.join(__dirname, 'static'), path.join(__dirname, 'build', 'static'), function (err) {
        if (err) { return console.error(err); }
        console.timeEnd('[metalsmith] build/static finished');
      });
    });
  });
}

function fullbuild () {
  copystatic();
  fs.readdir(path.join(__dirname, 'locale'), function (e, locales) {
    locales.forEach(function (locale) {
      buildlocale(locale);
    });
  });
}
fullbuild();

if (process.argv[2] === 'serve') {
  server();
}

function server () {
  /** Static file server **/
  const st = require('st');
  const http = require('http');
  const mount = st({
    path: path.join(__dirname, 'build'),
    cache: false,
    index: 'index.html'
  });
  http.createServer(
    function (req, res) { mount(req, res); }
  ).listen(8080,
    function () { console.log('http://localhost:8080/en/'); }
  );

  /** File Watches for Re-Builds **/
  const chokidar = require('chokidar');
  const opts = {
    persistent: true,
    ignoreInitial: true,
    followSymlinks: true,
    usePolling: true,
    alwaysStat: false,
    depth: undefined,
    interval: 100,
    ignorePermissionErrors: false,
    atomic: true
  };
  const locales = chokidar.watch(path.join(__dirname, 'locale'), opts);
  const layouts = chokidar.watch(path.join(__dirname, 'layouts'), opts);
  const staticf = chokidar.watch(path.join(__dirname, 'static'), opts);

  function getlocale (p) {
    const pre = path.join(__dirname, 'locale');
    return p.slice(pre.length + 1, p.indexOf('/', pre.length + 1));
  }
  locales.on('change', function (p) {
    buildlocale(getlocale(p));
  });
  locales.on('add', function (p) {
    buildlocale(getlocale(p));
    locales.add(p);
  });

  layouts.on('change', fullbuild);
  layouts.on('add', function (p) { layouts.add(p); fullbuild(); });

  staticf.on('change', copystatic);
  staticf.on('add', function (p) { staticf.add(p); copystatic(); });
}
<|endoftext|>


<commit_before>'use strict'

class Node {

    static idOfLast = 1;
    static idPrefix = 'n';

    /**
     * Depending on the number of nodes already created, the function will crea-
     * -te a new node identifier. This id includes the idPrefix specific to Node.
     * @returns {String} a unique node identifier
     */
    static createId() {

        return Node.idPrefix + Node.idOfLast++;

    };

    /**
     * Property of Node: counts the number of instanciated nodes
     * @returns {Number} the number of instanciated nodes
     */
    static get length() {

        return Object.keys(nodes).length;

    };

    /**
     * Getter for Node#label which gets the node's displayed label
     * @returns {String} the node's label
     */
    get label() {

        // gets the string label directly from the DOM element
        return this.labelElement.textContent;

    };

    /**
     * Setter for Node#label which sets the node's displayed label
     * @param {String} newLabel - the new label to set
     */
    set label(newLabel) {

        this.labelElement.textContent = newLabel;

    };

    /**
     * Getter for Node#position which gets the position of the node in the Canvas
     * @returns {Number[2]} - the x and y coordinates of the node's current position
     */
    get position() {

        // gets the position directly from inline-style as an array
        // of Strings and maps it into an array of Numbers
        return [this.nodeElement.style.left, this.nodeElement.style.top]
            .map(posString => parseInt(posString));

    };

    /**
     * Setter for Node#position which sets the position of the node in the Canvas
     * @param {Number[2]} [ x, y ] - the x and y coordinates to which it is moved
     */
    set position([ x, y ]) {

        // coerces the two coordinates into string applied to the node's style
        this.nodeElement.style.left = x + 'px';
        this.nodeElement.style.top = y + 'px';

    };

    /**
     * Getter for Node#headerColor to get the color of the node's header
     * this getter is needed when saving the nodes into a string format
     * @returns {String} - the CSS color of the node's header
     */
    get headerColor() {

        return this.headerElement.style.background;

    };

    /**
     * Setter for Node#headerColor to change the color of the node's header
     * @param {String} newColor - the color to change the node's header to
     */
    set headerColor(newColor) {

        this.headerElement.style.background = newColor;

    };

    /**
     * Getter for Node#size to get the size of the node container element
     * Might as well be a method because it is not explicit enough
     * @returns {Number[2]} - the width and height of the container element
     */
    get size() {

        const properties = this.nodeElement.getBoundingClientRect();
        return [ properties.width, properties.height ];

    };

    /**
     * Setter to add/remove a CSS class to node's container element
     * @param {Boolean} bool - determines whether to add or remove the class
     */
    set highlight(bool) {

        this.nodeElement.classList[ bool ? 'add' : 'remove' ]('selected');

    };

    /**
     * Toggles the class on the node's container element
     * @returns {Boolean} - whether the class has been added or removed
     */
    toggleHighlight() {

        return this.nodeElement.classList.toggle('selected');

    }

    /**
     * Node instance constructor which takes in an node object and:
     * 1) adds the properties to the Node's instance
     * 2) creates and renders the node's element on the canvas
     * 3) appends the instance to the node object
     * @param {Node | Object} - takes in an actual instance of Node OR an object
     * containing all the necessary properties to construct a node, i.e.: label
     * (String), position (Number[2]), exeDocks (Object), dataDocks (Object) and func
     * (function). Optional parameters are background (String) and headerColor (String)
     */
    constructor({ label, position, exeDocks, dataDocks, hideBody, func, stringFunc, background, headerColor, getter }) {

        // the following property assignments are happening first because
        // Node#createNode needs them to create the HTML elements properly
        Object.assign(this, {
            id: Node.createId(),
            background,
            docks: [],
            hideBody: !!hideBody,
            func,
            stringFunc,
        });

        // creating the actual HTML node element
        if (getter) this.getter = getter;
        this.createNode();

        // This second set of property assignments (styling) needs the HTML
        // elements to be created because they directly take effect on them
        Object.assign(this, {
            headerColor,
            label,
            position: position ? position : [0, 0],
        });

        // create and render all of the node's docks with their HTML elements
        this.createDocks({ exeDocks, dataDocks });

        // adds this Node instance to the object of instances, it can be
        // accessed with the unique node identifier provided previously
        nodes[ this.id ] = this;

        // attach the interpreter system to the node's instance
        const interpreter = new Interpreter(this);
        this.isExecutable = !![...exeDocks.in, ...exeDocks.out].length;
        this.calculate = interpreter.calculate.bind(interpreter);
        // <? could have a executor interpreter too for executable nodes, or
        // just have the interpreter logic in executable (=> true by nature)

    };

    /**
     * With all the docks properties, the method instanciates all the Dock objects
     * The method is instanciating them by side and by type by accessing the Dock's
     * attributes object. Then for each element in the provided dockDef it calls the
     * Dock constructor and adds the dock to the node's properties.
     * @param {Object} { exeDocks, dataDocks } - the dock properties provided by Node's constructor
     */
    createDocks(dockDef) {

        // the four arrays that will be filled with instances of Dock
        this.exeDocks = { in: [], out: [] };
        this.dataDocks = { in: [], out: [] };

        Dock.sideAttributes.forEach(({ direction, side, isRight, sidePrefix }) => {
        //                            'in'/'out', 'left'/'right', F/T, 'L'/'R'

            Dock.typeAttributes.forEach(({ isData, propertyName, typePrefix, blockName, otherBlockName }) => {
            //                            true/false, 'exeDocks'/'dataDocks', 'e'/'d', 'head'/'body'

                dockDef[ propertyName ][ direction ].forEach(({ label, editable, type, switchSection }, i) => {

                    // default position of the dock is determined by its type but the position
                    // can be switched by setting switchSection to true. In this case the dock
                    // will take the other position. Available positions are in body and head
                    const sectionName = (switchSection ? otherBlockName : blockName) + 'Section';

                    const newDock = new Dock({
                        id: this.id + typePrefix + sidePrefix + i,
                        label,
                        isRight,
                        isData,
                        editable: editable ? editable : false,
                        type,
                        node: this,                                  // @this is an instance of Node
                        switchSection,
                        blockElement: this[ sectionName ][ side ],   // the element where the dock will be appended
                    });

                    this[ propertyName ][ direction ].push(newDock); // append the dock to the side-type specific array
                    this.docks.push(newDock);                        // append the dock to the array containing all node's docks

                });

            });

        });

    }

    /**
     * Creates the node's HTML element and renders it on the canvas. Most HTMLElement
     * objects are saved as the node's properties: nodeElement, headerElement, labelElement,
     * headerSection.left, headerSection.right, bodySection.left and bodySection.right
     *
     * <? we might call in a class to deal with importing the html
     *    should we use templates, as they are visible in the DOM
     *    this method needs to know the structure: .container > .body > .block
     */
    createNode() { //

        let template = document.querySelector('template#node');
        template = document.importNode(template.content, true);

        Object.assign(this, {
            nodeElement: template.querySelector('.container'),
            headerElement: template.querySelector('.header'),
            labelElement: template.querySelector('.headerTitle'),
            headSection: {
                left: template.querySelector('.exeblock > .leftblock'),
                right: template.querySelector('.exeblock > .rightblock')
            },
            bodySection: {
                left: template.querySelector('.body > .leftblock'),
                right: template.querySelector('.body > .rightblock')
            }
        });

        if (this.hideBody) {

            this.nodeElement.classList.add('hideBody');

        } else {

            template.querySelector('.body > .bodybefore').textContent = this.background;

        }

        template.querySelector('.header').ref = this.id;

        this.nodeElement.id = this.id;

        Canvas.nodeArea.appendChild(this.nodeElement);

    };

    /**
     * This method updates all links connected to all docks of the node
     */
    update() {

        this.docks.forEach(dock => {

            dock.links.forEach(link => {

                // get the path expression from the static Curve.get and
                // change the link's path directly by utilising the Link#path
                // setter which updates the SVG element in the DOM
                link.path = Curve.get(link.startDock.position, link.endDock.position);

            });

        });

    };

    /**
     * This method removes the node and all its attached links
     */
    remove() {

        // remove all the attached links
        this.docks.forEach(dock => {

            dock.links.forEach(link => {

                link.remove();

            });

        });

        // removes the node instance from the nodes object
        delete nodes[ this.id ];

        // remove the HTML element from the DOM
        this.nodeElement.remove();

    };

    /**
     * This static method destructs the given node object into a non circular object.
     * Because node's have a property Node#docks which contains references to itself this
     * circular structure cannot be stringified by the saving mechanism. Thefore this method
     * has to modify the object by destructuring the node's dock instances into dock objects.
     * @param {Node} { exeDocks, dataDocks, docks, headerColor, label, position, ...rest } -
     * exeDocks, dataDocks and docks have circular structures. headerColor, label and position
     * are  getters (they are not iterable i.e not in rest which contains all other properties.
     * @returns {object} { exeDocks, dataDocks, headerColor, label and position, ...rest } -
     * the returned object doesn't contain dock: the array of Dock instances, as it is not
     * needed in the saved node object
     *
     * <? this static method could be a Node#destruct method instead
     */
    static destruct({ exeDocks, dataDocks, docks, headerColor, label, position, ...rest }) {

        // exeDocks and dataDocks are modified by Dock's own destruct method
        // to convert the Docks objects into non circular dock objects
    	exeDocks = Dock.destruct(exeDocks);
    	dataDocks = Dock.destruct(dataDocks);

    	return { exeDocks, dataDocks, headerColor, label, position, ...rest };

    };

}; const nodes = {};

/*Object.assign(Node, {

    idPrefix: 'n',

});*/
<commit_msg>If node is supposed to be executable, it calls Executable. constructor<commit_after>'use strict'

class Node {

    static idOfLast = 1;
    static idPrefix = 'n';

    /**
     * Depending on the number of nodes already created, the function will crea-
     * -te a new node identifier. This id includes the idPrefix specific to Node.
     * @returns {String} a unique node identifier
     */
    static createId() {

        return Node.idPrefix + Node.idOfLast++;

    };

    /**
     * Property of Node: counts the number of instanciated nodes
     * @returns {Number} the number of instanciated nodes
     */
    static get length() {

        return Object.keys(nodes).length;

    };

    /**
     * Getter for Node#label which gets the node's displayed label
     * @returns {String} the node's label
     */
    get label() {

        // gets the string label directly from the DOM element
        return this.labelElement.textContent;

    };

    /**
     * Setter for Node#label which sets the node's displayed label
     * @param {String} newLabel - the new label to set
     */
    set label(newLabel) {

        this.labelElement.textContent = newLabel;

    };

    /**
     * Getter for Node#position which gets the position of the node in the Canvas
     * @returns {Number[2]} - the x and y coordinates of the node's current position
     */
    get position() {

        // gets the position directly from inline-style as an array
        // of Strings and maps it into an array of Numbers
        return [this.nodeElement.style.left, this.nodeElement.style.top]
            .map(posString => parseInt(posString));

    };

    /**
     * Setter for Node#position which sets the position of the node in the Canvas
     * @param {Number[2]} [ x, y ] - the x and y coordinates to which it is moved
     */
    set position([ x, y ]) {

        // coerces the two coordinates into string applied to the node's style
        this.nodeElement.style.left = x + 'px';
        this.nodeElement.style.top = y + 'px';

    };

    /**
     * Getter for Node#headerColor to get the color of the node's header
     * this getter is needed when saving the nodes into a string format
     * @returns {String} - the CSS color of the node's header
     */
    get headerColor() {

        return this.headerElement.style.background;

    };

    /**
     * Setter for Node#headerColor to change the color of the node's header
     * @param {String} newColor - the color to change the node's header to
     */
    set headerColor(newColor) {

        this.headerElement.style.background = newColor;

    };

    /**
     * Getter for Node#size to get the size of the node container element
     * Might as well be a method because it is not explicit enough
     * @returns {Number[2]} - the width and height of the container element
     */
    get size() {

        const properties = this.nodeElement.getBoundingClientRect();
        return [ properties.width, properties.height ];

    };

    /**
     * Setter to add/remove a CSS class to node's container element
     * @param {Boolean} bool - determines whether to add or remove the class
     */
    set highlight(bool) {

        this.nodeElement.classList[ bool ? 'add' : 'remove' ]('selected');

    };

    /**
     * Toggles the class on the node's container element
     * @returns {Boolean} - whether the class has been added or removed
     */
    toggleHighlight() {

        return this.nodeElement.classList.toggle('selected');

    }

    /**
     * Node instance constructor which takes in an node object and:
     * 1) adds the properties to the Node's instance
     * 2) creates and renders the node's element on the canvas
     * 3) appends the instance to the node object
     * @param {Node | Object} - takes in an actual instance of Node OR an object
     * containing all the necessary properties to construct a node, i.e.: label
     * (String), position (Number[2]), exeDocks (Object), dataDocks (Object) and func
     * (function). Optional parameters are background (String) and headerColor (String)
     */
    constructor(parameters) {

        // destructure the parameters into seperate variable
        const { label, position, exeDocks, dataDocks, hideBody, func, stringFunc, background, headerColor, getter } = parameters;

        // if it's an Node of type executable but not yet an instance of Executable
        if (!(this instanceof Executable) && [...exeDocks.in, ...exeDocks.out].length) return new Executable(parameters);

        // the following property assignments are happening first because
        // Node#createNode needs them to create the HTML elements properly
        Object.assign(this, {
            id: Node.createId(),
            background,
            docks: [],
            hideBody: !!hideBody,
            func,
            stringFunc,
        });

        // creating the actual HTML node element
        if (getter) this.getter = getter;                                       // <? getter
        this.createNode();

        // This second set of property assignments (styling) needs the HTML
        // elements to be created because they directly take effect on them
        Object.assign(this, {
            headerColor,
            label,
            position: position ? position : [0, 0],
        });

        // create and render all of the node's docks with their HTML elements
        this.createDocks({ exeDocks, dataDocks });

        // adds this Node instance to the object of instances, it can be
        // accessed with the unique node identifier provided previously
        nodes[ this.id ] = this;

        // attach the interpreter system to the node's instance
        const interpreter = new Interpreter(this);
        this.calculate = interpreter.calculate.bind(interpreter);
        // <? could have a executor interpreter too for executable nodes, or
        // just have the interpreter logic in executable (=> true by nature)

    };

    /**
     * With all the docks properties, the method instanciates all the Dock objects
     * The method is instanciating them by side and by type by accessing the Dock's
     * attributes object. Then for each element in the provided dockDef it calls the
     * Dock constructor and adds the dock to the node's properties.
     * @param {Object} { exeDocks, dataDocks } - the dock properties provided by Node's constructor
     */
    createDocks(dockDef) {

        // the four arrays that will be filled with instances of Dock
        this.exeDocks = { in: [], out: [] };
        this.dataDocks = { in: [], out: [] };

        Dock.sideAttributes.forEach(({ direction, side, isRight, sidePrefix }) => {
        //                            'in'/'out', 'left'/'right', F/T, 'L'/'R'

            Dock.typeAttributes.forEach(({ isData, propertyName, typePrefix, blockName, otherBlockName }) => {
            //                            true/false, 'exeDocks'/'dataDocks', 'e'/'d', 'head'/'body'

                dockDef[ propertyName ][ direction ].forEach(({ label, editable, type, switchSection }, i) => {

                    // default position of the dock is determined by its type but the position
                    // can be switched by setting switchSection to true. In this case the dock
                    // will take the other position. Available positions are in body and head
                    const sectionName = (switchSection ? otherBlockName : blockName) + 'Section';

                    const newDock = new Dock({
                        id: this.id + typePrefix + sidePrefix + i,
                        label,
                        isRight,
                        isData,
                        editable: editable ? editable : false,
                        type,
                        node: this,                                  // @this is an instance of Node
                        switchSection,
                        blockElement: this[ sectionName ][ side ],   // the element where the dock will be appended
                    });

                    this[ propertyName ][ direction ].push(newDock); // append the dock to the side-type specific array
                    this.docks.push(newDock);                        // append the dock to the array containing all node's docks

                });

            });

        });

    }

    /**
     * Creates the node's HTML element and renders it on the canvas. Most HTMLElement
     * objects are saved as the node's properties: nodeElement, headerElement, labelElement,
     * headerSection.left, headerSection.right, bodySection.left and bodySection.right
     *
     * <? we might call in a class to deal with importing the html
     *    should we use templates, as they are visible in the DOM
     *    this method needs to know the structure: .container > .body > .block
     */
    createNode() { //

        let template = document.querySelector('template#node');
        template = document.importNode(template.content, true);

        Object.assign(this, {
            nodeElement: template.querySelector('.container'),
            headerElement: template.querySelector('.header'),
            labelElement: template.querySelector('.headerTitle'),
            headSection: {
                left: template.querySelector('.exeblock > .leftblock'),
                right: template.querySelector('.exeblock > .rightblock')
            },
            bodySection: {
                left: template.querySelector('.body > .leftblock'),
                right: template.querySelector('.body > .rightblock')
            }
        });

        if (this.hideBody) {

            this.nodeElement.classList.add('hideBody');

        } else {

            template.querySelector('.body > .bodybefore').textContent = this.background;

        }

        template.querySelector('.header').ref = this.id;

        this.nodeElement.id = this.id;

        Canvas.nodeArea.appendChild(this.nodeElement);

    };

    /**
     * This method updates all links connected to all docks of the node
     */
    update() {

        this.docks.forEach(dock => {

            dock.links.forEach(link => {

                // get the path expression from the static Curve.get and
                // change the link's path directly by utilising the Link#path
                // setter which updates the SVG element in the DOM
                link.path = Curve.get(link.startDock.position, link.endDock.position);

            });

        });

    };

    /**
     * This method removes the node and all its attached links
     */
    remove() {

        // remove all the attached links
        this.docks.forEach(dock => {

            dock.links.forEach(link => {

                link.remove();

            });

        });

        // removes the node instance from the nodes object
        delete nodes[ this.id ];

        // remove the HTML element from the DOM
        this.nodeElement.remove();

    };

    /**
     * This static method destructs the given node object into a non circular object.
     * Because node's have a property Node#docks which contains references to itself this
     * circular structure cannot be stringified by the saving mechanism. Thefore this method
     * has to modify the object by destructuring the node's dock instances into dock objects.
     * @param {Node} { exeDocks, dataDocks, docks, headerColor, label, position, ...rest } -
     * exeDocks, dataDocks and docks have circular structures. headerColor, label and position
     * are  getters (they are not iterable i.e not in rest which contains all other properties.
     * @returns {object} { exeDocks, dataDocks, headerColor, label and position, ...rest } -
     * the returned object doesn't contain dock: the array of Dock instances, as it is not
     * needed in the saved node object
     *
     * <? this static method could be a Node#destruct method instead
     */
    static destruct({ exeDocks, dataDocks, docks, headerColor, label, position, ...rest }) {

        // exeDocks and dataDocks are modified by Dock's own destruct method
        // to convert the Docks objects into non circular dock objects
    	exeDocks = Dock.destruct(exeDocks);
    	dataDocks = Dock.destruct(dataDocks);

    	return { exeDocks, dataDocks, headerColor, label, position, ...rest };

    };

}; const nodes = {};

/*Object.assign(Node, {

    idPrefix: 'n',

});*/
<|endoftext|>


<commit_before>const generateBlobLink = require('./generate-blob-link')

/**
 * @typedef config {object}
 * @prop {boolean|string|string[]} [autoAssign=true]
 * @prop {string} [keyword='@todo']
 * @prop {number|boolean} [blobLines=5]
 * @prop {boolean} [caseSensitive=false]
 *
 * Generate a body string for the new issue.
 * @param {object} context - Probot context object
 * @param {config} config - Config object
 * @param {string} title - Issue title
 * @param {string} file - File name
 * @param {string} contents - Contents of the file
 * @param {string} author - Author of the commit
 * @param {string} sha - Commit where this todo was introduced
 * @param {number} [pr] - PR number if applicable
 *
 * :TODO: Include code blob
 */
module.exports = function generateBody (context, config, title, file, contents, author, sha, pr) {
  const footer = `###### This issue was generated by [todo](https://github.com/jasonetco/todo) based on a \`@todo\` comment in ${sha}${pr ? ` in #${pr}` : ''}. It's been assigned to @${author} because they committed the code.`
  const re = new RegExp(`${title}\n.*@body (.*)`, 'gim')
  const bodyRe = re.exec(contents)
  const separator = '\n\n---\n\n'

  let blob = ''
  if (Number.isNaN(config.blobLines) && config.blobLines !== 0) {
    blob = generateBlobLink(context, file, contents, title, sha, config) + separator
  }

  if (bodyRe) {
    const body = bodyRe ? bodyRe[1] : ''
    return body + separator + blob + separator + footer
  } else {
    return blob + separator + footer
  }
}
<commit_msg>Improve blob detection<commit_after>const generateBlobLink = require('./generate-blob-link')

/**
 * @typedef config {object}
 * @prop {boolean|string|string[]} [autoAssign=true]
 * @prop {string} [keyword='@todo']
 * @prop {number|boolean} [blobLines=5]
 * @prop {boolean} [caseSensitive=false]
 *
 * Generate a body string for the new issue.
 * @param {object} context - Probot context object
 * @param {config} config - Config object
 * @param {string} title - Issue title
 * @param {string} file - File name
 * @param {string} contents - Contents of the file
 * @param {string} author - Author of the commit
 * @param {string} sha - Commit where this todo was introduced
 * @param {number} [pr] - PR number if applicable
 *
 * :TODO: Include code blob
 */
module.exports = function generateBody (context, config, title, file, contents, author, sha, pr) {
  const footer = `###### This issue was generated by [todo](https://github.com/jasonetco/todo) based on a \`@todo\` comment in ${sha}${pr ? ` in #${pr}` : ''}. It's been assigned to @${author} because they committed the code.`
  const re = new RegExp(`${title}\n.*@body (.*)`, 'gim')
  const bodyRe = re.exec(contents)
  const separator = '\n\n---\n\n'

  let blob = ''
  if (!Number.isNaN(config.blobLines) && config.blobLines !== 0) {
    blob = generateBlobLink(context, file, contents, title, sha, config) + separator
  }

  if (bodyRe) {
    const body = bodyRe ? bodyRe[1] : ''
    return body + separator + blob + footer
  } else {
    return blob + separator + footer
  }
}
<|endoftext|>


<commit_before>angular.module('orcid_app', ['ngSanitize'])
	.config(function($routeProvider){
		$routeProvider
			.when('/', {
				controller:IndexCtrl,
				template: $('#index').html()
			})
	})
	.factory('works', function($http){
		return {
			getWorks: function(data) {
				return $http.post(base_url+'/orcid/orcid_works', {data:data}).then(function(response) {return response.data});
			},
			search: function(filters) {
				return $http.post(base_url+'/services/registry/post_solr_search', {filters:filters}).then(function(response) {return response.data});
			},
			import_works: function(ro_ids) {
				return $http.post(base_url+'/orcid/import_to_orcid', {ro_ids:ro_ids}).then(function(response) {return response.data});
			}
		}
	})
;

function IndexCtrl($scope, works) {
	$scope.works = {};
	$scope.to_import = [];
	$scope.import_available = false;
	$scope.filters = {};
	$scope.search_results = {};
	$scope.imported_ids= [];
	$scope.import_stg = 'ready';

	$scope.orcid = {
		orcid_id:$('#orcid_id').text(),
		first_name:$('#first_name').text(),
		last_name:$('#last_name').text()
	};

	$('.import').click(function(e){
		e.preventDefault();
		if(!$(this).hasClass('disabled')){
			$('#myModal').modal();
		}
		return false;
	});

	$scope.refresh = function(){
		works.getWorks($scope.orcid).then(function(data){
			$scope.works = data.works;
			$.each($scope.works, function(){
				if(this.type=='imported'){
					$scope.imported_ids.push(this.id);
				}
			})
		});
	}
	$scope.refresh();

	$scope.$watch('works', function(){
		$scope.review();
	}, true);

	$scope.$watch('search_results', function() {
		$scope.review();
	}, true);

	$scope.review = function(){
		$scope.import_available = false;
		$scope.to_import = [];
		$.each($scope.works, function(){
			if(this.to_import) {
				$scope.to_import.push(this);
				$scope.import_available = true;
			}
		});
		if($scope.search_results && $scope.search_results.docs){
			$.each($scope.search_results.docs, function(){
				if(this.to_import) {
					$scope.to_import.push(this);
					$scope.import_available = true;
				}
			});
		}
		$scope.import_stg = 'ready';
	}

	$scope.search = function() {
		if($scope.filters.q!=''){
			$scope.filters.rows = 100;
			works.search($scope.filters).then(function(data){
				$scope.search_results = data.result;
			});
		}
	}

	$scope.already_imported = function(item) {
		$.each($scope.works, function(){
			if(this.type=="imported" && this.id===item.id){
				return true;
			}
		});
		return false;
	}

	$scope.import = function() {
		$scope.import_stg = 'importing';
		var ids = [];
		$.each($scope.to_import, function(){
			ids.push(this.id);
		});
		works.import_works(ids).then(function(data){
			if(data!=1){
				console.err(data);
				$scope.import_stg = 'error';
			} else {
				$scope.import_stg = 'complete';
				$scope.refresh();
			}
		});
	}
}<commit_msg>only search for collection<commit_after>angular.module('orcid_app', ['ngSanitize'])
	.config(function($routeProvider){
		$routeProvider
			.when('/', {
				controller:IndexCtrl,
				template: $('#index').html()
			})
	})
	.factory('works', function($http){
		return {
			getWorks: function(data) {
				return $http.post(base_url+'/orcid/orcid_works', {data:data}).then(function(response) {return response.data});
			},
			search: function(filters) {
				return $http.post(base_url+'/services/registry/post_solr_search', {filters:filters}).then(function(response) {return response.data});
			},
			import_works: function(ro_ids) {
				return $http.post(base_url+'/orcid/import_to_orcid', {ro_ids:ro_ids}).then(function(response) {return response.data});
			}
		}
	})
;

function IndexCtrl($scope, works) {
	$scope.works = {};
	$scope.to_import = [];
	$scope.import_available = false;
	$scope.filters = {};
	$scope.search_results = {};
	$scope.imported_ids= [];
	$scope.import_stg = 'ready';

	$scope.orcid = {
		orcid_id:$('#orcid_id').text(),
		first_name:$('#first_name').text(),
		last_name:$('#last_name').text()
	};

	$('.import').click(function(e){
		e.preventDefault();
		if(!$(this).hasClass('disabled')){
			$('#myModal').modal();
		}
		return false;
	});

	$scope.refresh = function(){
		works.getWorks($scope.orcid).then(function(data){
			$scope.works = data.works;
			$.each($scope.works, function(){
				if(this.type=='imported'){
					$scope.imported_ids.push(this.id);
				}
			})
		});
	}
	$scope.refresh();

	$scope.$watch('works', function(){
		$scope.review();
	}, true);

	$scope.$watch('search_results', function() {
		$scope.review();
	}, true);

	$scope.review = function(){
		$scope.import_available = false;
		$scope.to_import = [];
		$.each($scope.works, function(){
			if(this.to_import) {
				$scope.to_import.push(this);
				$scope.import_available = true;
			}
		});
		if($scope.search_results && $scope.search_results.docs){
			$.each($scope.search_results.docs, function(){
				if(this.to_import) {
					$scope.to_import.push(this);
					$scope.import_available = true;
				}
			});
		}
		$scope.import_stg = 'ready';
	}

	$scope.search = function() {
		if($scope.filters.q!=''){
			$scope.filters.rows = 100;
			$scope.filters.class = 'collection';
			works.search($scope.filters).then(function(data){
				$scope.search_results = data.result;
			});
		}
	}

	$scope.already_imported = function(item) {
		$.each($scope.works, function(){
			if(this.type=="imported" && this.id===item.id){
				return true;
			}
		});
		return false;
	}

	$scope.import = function() {
		$scope.import_stg = 'importing';
		var ids = [];
		$.each($scope.to_import, function(){
			ids.push(this.id);
		});
		works.import_works(ids).then(function(data){
			if(data!=1){
				console.err(data);
				$scope.import_stg = 'error';
			} else {
				$scope.import_stg = 'complete';
				$scope.refresh();
			}
		});
	}
}<|endoftext|>


<commit_before>const fs = require('fs').promises;
const minify = require('html-minifier').minify;
const puppeteer = require('puppeteer');

const server = require('./server.js');

function minifyHtml(html) {
  return minify(html, {
    collapseWhitespace: true,
    includeAutoGeneratedTags: false,
    minifyCSS: true,
    minifyJS: true,
    removeAttributeQuotes: true,
    removeOptionalTags: true,
  });
}

async function main() {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await server.start(9001);
  await page.goto('http://localhost:9001/');
  await page.waitForSelector('.passing');
  const html = await page.evaluate(() => {
    document.scripts[0].remove();
    return `<!DOCTYPE html>${ document.documentElement.outerHTML }`;
  });
  await fs.writeFile('dist/index.html', minifyHtml(html));
  await browser.close();
  await server.stop();
}

main();
<commit_msg>Leverage page.content()<commit_after>const fs = require('fs').promises;
const minify = require('html-minifier').minify;
const puppeteer = require('puppeteer');

const server = require('./server.js');

function minifyHtml(html) {
  return minify(html, {
    collapseWhitespace: true,
    includeAutoGeneratedTags: false,
    minifyCSS: true,
    minifyJS: true,
    removeAttributeQuotes: true,
    removeOptionalTags: true,
  });
}

async function main() {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await server.start(9001);
  await page.goto('http://localhost:9001/');
  await page.waitForSelector('.passing');
  await page.evaluate(() => {
    document.querySelectorAll('scripts').forEach(script => script.remove());
  });
  const html = await page.content();
  await fs.writeFile('dist/index.html', minifyHtml(html));
  await browser.close();
  await server.stop();
}

main();
<|endoftext|>


<commit_before>'use strict';

var keypress = require('keypress');
var Drone = require('../');

var ACTIVE = false;
var STEPS = 2;

function cooldown() {
  ACTIVE = false;
  setTimeout(function () {
    ACTIVE = true;
  }, STEPS * 12);
}

// make `process.stdin` begin emitting "keypress" events
keypress(process.stdin);

// listen for the "keypress" event

process.stdin.setRawMode(true);
process.stdin.resume();

if (process.env.UUID) {
  console.log("Searching for ", process.env.UUID);
}

var d = new Drone(process.env.UUID);

function launch() {
  d.connect(function () {
    d.setup(function () {
            console.log("Prepare for take off! ", d.name);
      d.flatTrim();
      d.startPing();
      d.flatTrim();

      d.on('battery', function () {
        console.log('Battery: '+d.status.battery+'%');
      });
      setTimeout(function () {
        d.takeOff();
        ACTIVE = true;
      }, 1000);

    });
  });

}

process.stdin.on('keypress', function (ch, key) {
  if (ACTIVE && key) {
    console.log(key);
    if (key.name === 'm') {
      d.emergency();
      setTimeout(function () {
        process.exit();
      }, 3000);
    } else if (key.name == 't') {
      d = new Drone(process.env.UUID);
      launch();
    } else if (key.name === 'w') {
      d.forward({ steps: STEPS });
      cooldown();
    } else if (key.name === 's') {
      d.backward({ steps: STEPS });
      cooldown();
    } else if (key.name === 'left') {
      d.turnLeft({ steps: STEPS });
      cooldown();
    } else if (key.name === 'a') {
      d.tiltLeft({ steps: STEPS });
      cooldown();
    } else if (key.name === 'd') {
      d.tiltRight({ steps: STEPS });
      cooldown();
    } else if (key.name === 'right') {
      d.turnRight({ steps: STEPS });
      cooldown();
    } else if (key.name === 'up') {
      d.up({ steps: STEPS * 2.5 });
      cooldown();
    } else if (key.name === 'down') {
      d.down({ steps: STEPS * 2.5 });
      cooldown();
    } else if (key.name === 'i' || key.name === 'f') {
      d.frontFlip({ steps: STEPS });
      cooldown();
    } else if (key.name === 'j') {
      d.leftFlip({ steps: STEPS });
      cooldown();
    } else if (key.name === 'l') {
      d.rightFlip({ steps: STEPS });
      cooldown();
    } else if (key.name === 'k') {
      d.backFlip({ steps: STEPS });
      cooldown();
    } else if (key.name === 'q') {
      console.log("Initiated Landing Sequence...");
      d.land();
      setTimeout(function () {
        process.exit();
      }, 3000);
    } else if (key.ctrl && key.name === 'c') {
      process.stdin.pause();
      process.exit();
    }
  }
});

launch();<commit_msg>Keyboard now dumps battery and signal, remove key console.<commit_after>'use strict';

var keypress = require('keypress');
var Drone = require('../');

var ACTIVE = false;
var STEPS = 2;

function cooldown() {
  ACTIVE = false;
  setTimeout(function () {
    ACTIVE = true;
  }, STEPS * 12);
}

// make `process.stdin` begin emitting "keypress" events
keypress(process.stdin);

// listen for the "keypress" event

process.stdin.setRawMode(true);
process.stdin.resume();

if (process.env.UUID) {
  console.log("Searching for ", process.env.UUID);
}

var d = new Drone(process.env.UUID);

function launch() {
  d.connect(function () {
    d.setup(function () {
      console.log("Prepare for take off! ", d.name);
      d.flatTrim();
      d.startPing();
      d.flatTrim();

      d.on('battery', function () {
        console.log('Battery: ' + d.status.battery + '%');
        d.signalStrength(function (err, val) {
          console.log('Signal: ' + d.status.battery + 'dBm');
        });

      });
      setTimeout(function () {
        d.takeOff();
        ACTIVE = true;
      }, 1000);

    });
  });

}

process.stdin.on('keypress', function (ch, key) {
  if (ACTIVE && key) {
    if (key.name === 'm') {
      d.emergency();
      setTimeout(function () {
        process.exit();
      }, 3000);
    } else if (key.name == 't') {
      d = new Drone(process.env.UUID);
      launch();
    } else if (key.name === 'w') {
      d.forward({ steps: STEPS });
      cooldown();
    } else if (key.name === 's') {
      d.backward({ steps: STEPS });
      cooldown();
    } else if (key.name === 'left') {
      d.turnLeft({ steps: STEPS });
      cooldown();
    } else if (key.name === 'a') {
      d.tiltLeft({ steps: STEPS });
      cooldown();
    } else if (key.name === 'd') {
      d.tiltRight({ steps: STEPS });
      cooldown();
    } else if (key.name === 'right') {
      d.turnRight({ steps: STEPS });
      cooldown();
    } else if (key.name === 'up') {
      d.up({ steps: STEPS * 2.5 });
      cooldown();
    } else if (key.name === 'down') {
      d.down({ steps: STEPS * 2.5 });
      cooldown();
    } else if (key.name === 'i' || key.name === 'f') {
      d.frontFlip({ steps: STEPS });
      cooldown();
    } else if (key.name === 'j') {
      d.leftFlip({ steps: STEPS });
      cooldown();
    } else if (key.name === 'l') {
      d.rightFlip({ steps: STEPS });
      cooldown();
    } else if (key.name === 'k') {
      d.backFlip({ steps: STEPS });
      cooldown();
    } else if (key.name === 'q') {
      console.log("Initiated Landing Sequence...");
      d.land();
      setTimeout(function () {
        process.exit();
      }, 3000);
    } else if (key.ctrl && key.name === 'c') {
      process.stdin.pause();
      process.exit();
    }
  }
});

launch();<|endoftext|>


<commit_before>'use strict';

import React from 'react';
import ReactDOM from 'react-dom';

System.import('./src/shared/components/Card/Card').then((content) => {
  console.log('loaded in browser');
  const Content = content.default;
  return ReactDOM.render(
    <Content title="Hello" />,
    document.getElementById('app')
  );
});
<commit_msg>Use ES6 import instead of System.import to make style bundling work<commit_after>'use strict';

import React from 'react';
import ReactDOM from 'react-dom';

import Card from '../shared/components/Card/Card';

export default ReactDOM.render(
  <Card title="Hello" />,
  document.getElementById('app')
);
<|endoftext|>


<commit_before>const x = 7;
const y = x + 1;<commit_msg>Generating a tamarin test<commit_after>#!/usr/bin/env node
const x = 7
const y = x + 1
console.log(y)
<|endoftext|>


<commit_before>import { find, propEq, reject, isNil, values } from "ramda"

import { isProduction } from "~/share/environment"

const store = {
  strict: !isProduction(),

  state: {
    send: () => { },

    universe: { },
    user: null,

    showNavigation: false,
    inverted: false,

    games: { },
    rotation: null
  },

  mutations: {
    setSend: (state, send) => state.send = send,

    hideNavigation: state => state.showNavigation = false,
    toggleNavigation: state => state.showNavigation = !state.showNavigation,

    logIn: (state, user) => state.user = user,
    logOut: state => state.user = null,

    universe: (state, universe) => state.universe = universe,
    games: (state, games) => state.games = games,

    position: ({ games }, { uuid, fen }) => {
      const game = find(propEq("uuid", uuid), reject(isNil, values(games)))

      game.currentPosition.fen = fen
    },

    rotateLeft: state => {
      if (!isNil(state.games.after)) {
        return
      }

      state.send({
        action: "subscribe",
        spec: {
          direction: "after",
          of: state.games.after.uuid
        }
      })
    },

    rotateRight: state => {
      if (!isNil(state.games.before)) {
        return
      }

      state.send({
        action: "subscribe",
        spec: {
          direction: "before",
          of: state.games.before.uuid
        }
      })
    }
  },

  actions: {
    async logout({ commit }) {
      commit("hideNavigation")

      const response = await fetch("/sessions", { method: "DELETE" })

      if (response.status === 205) {
        commit("logOut")
      }
    }
  }
}

export default store
<commit_msg>invert guard clause<commit_after>import { find, propEq, reject, isNil, values } from "ramda"

import { isProduction } from "~/share/environment"

const store = {
  strict: !isProduction(),

  state: {
    send: () => { },

    universe: { },
    user: null,

    showNavigation: false,
    inverted: false,

    games: { },
    rotation: null
  },

  mutations: {
    setSend: (state, send) => state.send = send,

    hideNavigation: state => state.showNavigation = false,
    toggleNavigation: state => state.showNavigation = !state.showNavigation,

    logIn: (state, user) => state.user = user,
    logOut: state => state.user = null,

    universe: (state, universe) => state.universe = universe,
    games: (state, games) => state.games = games,

    position: ({ games }, { uuid, fen }) => {
      const game = find(propEq("uuid", uuid), reject(isNil, values(games)))

      game.currentPosition.fen = fen
    },

    rotateLeft: state => {
      if (isNil(state.games.after)) {
        return
      }

      state.send({
        action: "subscribe",
        spec: {
          direction: "after",
          of: state.games.after.uuid
        }
      })
    },

    rotateRight: state => {
      if (isNil(state.games.before)) {
        return
      }

      state.send({
        action: "subscribe",
        spec: {
          direction: "before",
          of: state.games.before.uuid
        }
      })
    }
  },

  actions: {
    async logout({ commit }) {
      commit("hideNavigation")

      const response = await fetch("/sessions", { method: "DELETE" })

      if (response.status === 205) {
        commit("logOut")
      }
    }
  }
}

export default store
<|endoftext|>