<commit_before>// ==UserScript==
// @name WIP Limiter
// @namespace http://github.com/apiology/
// @description Add Kanban-style visual WIP limit indicators
// @match https://app.asana.com/*
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==

console.log('starting script');

((css) => {
  const head = document.getElementsByTagName('head')[0];
  if (!head) { return; }
  const style = document.createElement('style');
  style.type = 'text/css';
  style.innerHTML = css;
  head.appendChild(style);
})(`
  .wip-limit-under { }
  .wip-limit-over {
    background-color: rgb(214, 65, 65);
  }
  .wip-limit-on-edge {
    background-color: rgb(239, 190, 67);
  }
  div.task-row-overlay {
    background-color: rgb(214, 65, 65);
  }
`);

class Header {
  constructor(header) {
    this.header = header;
  }

  // header.classList.contains("bar-row")
  title() {
    const textareas = this.header.getElementsByClassName('task-row-text-input');
    if (textareas.length !== 1) {
      return null;
    }

    return textareas[0].value;
  }

  wipLimit() {
    const headerTitle = this.title();
    const wipFinder = /.*\[(\d*)\]:$/;
    const results = wipFinder.exec(headerTitle);
    if (results !== null) {
      return parseInt(results[1], 10);
    }
    return null;
  }

  countChildren() {
    const count = this.children().length;
    console.log(`Size of ${this.title()} is ${count}`);
    return count;
  }

  static isHeader(element) {
    return element.classList.contains('bar-row');
  }

  children() {
    let curNode = this.header.nextSibling;
    const childList = [];
    while (curNode != null) {
      if (Header.isHeader(curNode)) {
        curNode = null;
      } else {
        childList.push(curNode);
        curNode = curNode.nextSibling;
      }
    }
    return childList;
  }

  headerAndChildren() {
    // shallow copy
    const all = this.children().slice();
    all.unshift(this.header);
    return all;
  }

  markBackgroundColor() {
    const wipLimit = this.wipLimit();
    if (wipLimit === null) {
      this.markAsUnderLimit();
    } else {
      const childCount = this.countChildren();
      if (wipLimit === childCount) {
        this.markAsOnEdge();
      } else if (wipLimit < childCount) {
        this.markAsOverLimit();
      } else {
        this.markAsUnderLimit();
      }
    }
  }

  markAsOnEdge() {
    console.log(`Marking ${this.title()} as on edge`);
    for (const child of this.headerAndChildren()) {
      child.classList.remove('wip-limit-under');
      child.classList.remove('wip-limit-over');
      child.classList.add('wip-limit-on-edge');
    }
  }

  markAsOverLimit() {
    console.log(`Marking ${this.title()} as over limit`);
    for (const child of this.headerAndChildren()) {
      child.classList.remove('wip-limit-under');
      child.classList.add('wip-limit-over');
      child.classList.remove('wip-limit-on-edge');
    }
  }

  markAsUnderLimit() {
    console.log(`Marking ${this.title()} as under limit`);
    for (const child of this.headerAndChildren()) {
      child.classList.add('wip-limit-under');
      child.classList.remove('wip-limit-over');
      child.classList.remove('wip-limit-on-edge');
    }
  }
}

setInterval(() => {
  console.log('starting to mark whole document');
  const headers = document.getElementsByClassName('bar-row');
  for (const headerElement of headers) {
    const header = new Header(headerElement);
    header.markBackgroundColor();
  }
}, 1000);
console.log('setInterval run');

// if (document.body) {
//   console.log('already loaded; running now');
//   markWholeDocument();
//   console.log('ran!');
// } else {
//   console.log('registering listener');
//   document.addEventListener('DOMContentLoaded', markWholeDocument, false);
//   console.log('registered listener');
// }

// // const textareas = header.getElementsByClassName('task-row-text-input');
// // let headerTitle = textareas[0].value;
<commit_msg>Mark as important<commit_after>// ==UserScript==
// @name WIP Limiter
// @namespace http://github.com/apiology/
// @description Add Kanban-style visual WIP limit indicators
// @match https://app.asana.com/*
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==

console.log('starting script');

((css) => {
  const head = document.getElementsByTagName('head')[0];
  if (!head) { return; }
  const style = document.createElement('style');
  style.type = 'text/css';
  style.innerHTML = css;
  head.appendChild(style);
})(`
  .wip-limit-under { }
  .wip-limit-over {
    background-color: rgb(214, 65, 65) !important;
  }
  .wip-limit-on-edge {
    background-color: rgb(239, 190, 67) !important;
  }
  div.task-row-overlay {
    background-color: rgb(214, 65, 65);
  }
`);

class Header {
  constructor(header) {
    this.header = header;
  }

  // header.classList.contains("bar-row")
  title() {
    const textareas = this.header.getElementsByClassName('task-row-text-input');
    if (textareas.length !== 1) {
      return null;
    }

    return textareas[0].value;
  }

  wipLimit() {
    const headerTitle = this.title();
    const wipFinder = /.*\[(\d*)\]:$/;
    const results = wipFinder.exec(headerTitle);
    if (results !== null) {
      return parseInt(results[1], 10);
    }
    return null;
  }

  countChildren() {
    const count = this.children().length;
    console.log(`Size of ${this.title()} is ${count}`);
    return count;
  }

  static isHeader(element) {
    return element.classList.contains('bar-row');
  }

  children() {
    let curNode = this.header.nextSibling;
    const childList = [];
    while (curNode != null) {
      if (Header.isHeader(curNode)) {
        curNode = null;
      } else {
        childList.push(curNode);
        curNode = curNode.nextSibling;
      }
    }
    return childList;
  }

  headerAndChildren() {
    // shallow copy
    const all = this.children().slice();
    all.unshift(this.header);
    return all;
  }

  markBackgroundColor() {
    const wipLimit = this.wipLimit();
    if (wipLimit === null) {
      this.markAsUnderLimit();
    } else {
      const childCount = this.countChildren();
      if (wipLimit === childCount) {
        this.markAsOnEdge();
      } else if (wipLimit < childCount) {
        this.markAsOverLimit();
      } else {
        this.markAsUnderLimit();
      }
    }
  }

  markAsOnEdge() {
    console.log(`Marking ${this.title()} as on edge`);
    for (const child of this.headerAndChildren()) {
      child.classList.remove('wip-limit-under');
      child.classList.remove('wip-limit-over');
      child.classList.add('wip-limit-on-edge');
    }
  }

  markAsOverLimit() {
    console.log(`Marking ${this.title()} as over limit`);
    for (const child of this.headerAndChildren()) {
      child.classList.remove('wip-limit-under');
      child.classList.add('wip-limit-over');
      child.classList.remove('wip-limit-on-edge');
    }
  }

  markAsUnderLimit() {
    console.log(`Marking ${this.title()} as under limit`);
    for (const child of this.headerAndChildren()) {
      child.classList.add('wip-limit-under');
      child.classList.remove('wip-limit-over');
      child.classList.remove('wip-limit-on-edge');
    }
  }
}

setInterval(() => {
  console.log('starting to mark whole document');
  const headers = document.getElementsByClassName('bar-row');
  for (const headerElement of headers) {
    const header = new Header(headerElement);
    header.markBackgroundColor();
  }
}, 1000);
console.log('setInterval run');

// if (document.body) {
//   console.log('already loaded; running now');
//   markWholeDocument();
//   console.log('ran!');
// } else {
//   console.log('registering listener');
//   document.addEventListener('DOMContentLoaded', markWholeDocument, false);
//   console.log('registered listener');
// }

// // const textareas = header.getElementsByClassName('task-row-text-input');
// // let headerTitle = textareas[0].value;
<|endoftext|>


<commit_before>// ==UserScript==
// @name WIP Limiter
// @namespace http://github.com/apiology/
// @description Add Kanban-style visual WIP limit indicators
// @match https://app.asana.com/*
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==

console.log('starting script');

class Header {
  constructor(header) {
    this.header = header;
  }

  // header.classList.contains("bar-row")
  title() {
    const textareas = this.header.getElementsByClassName('task-row-text-input');
    if (textareas.length !== 1) {
      return null;
    }

    return textareas[0].value;
  }

  wipLimit() {
    const headerTitle = this.title();
    console.log(`title is ${headerTitle}`);
    const wipFinder = /.*\[(\d*)\]:$/;
    const results = wipFinder.exec(headerTitle);
    if (results !== null) {
      return parseInt(results[1], 10);
    }
    return null;
  }

  countChildren() {
    const count = this.children().length;
    console.log(`Size of ${this.title()} is ${count}`);
    return count;
  }

  static isHeader(element) {
    return element.classList.contains('bar-row');
  }

  children() {
    let curNode = this.header.nextSibling;
    const childList = [];
    while (curNode != null) {
      if (Header.isHeader(curNode)) {
        curNode = null;
      } else {
        childList.push(curNode);
        curNode = curNode.nextSibling;
      }
    }
    return childList;
  }

  markBackgroundColor() {
    const wipLimit = this.wipLimit();
    if (wipLimit === null) {
      this.markAsUnderLimit();
    } else {
      const childCount = this.countChildren();
      if (wipLimit === childCount) {
        this.markAsOnEdge();
      } else if (wipLimit < childCount) {
        this.markAsOverLimit();
      } else {
        this.markAsUnderLimit();
      }
    }
  }

  markAsOnEdge() {
    console.log(`Marking ${this.title()} as on edge`);
  }

  markAsOverLimit() {
    console.log(`Marking ${this.title()} as over limit`);
  }

  markAsUnderLimit() {
    console.log(`Marking ${this.title()} as under limit`);
  }
}

setInterval(() => {
  console.log('starting to mark whole document');
  const headers = document.getElementsByClassName('bar-row');
  for (const headerElement of headers) {
    const header = new Header(headerElement);
    header.markBackgroundColor();
  }
}, 1000);
console.log('setInterval run');

// if (document.body) {
//   console.log('already loaded; running now');
//   markWholeDocument();
//   console.log('ran!');
// } else {
//   console.log('registering listener');
//   document.addEventListener('DOMContentLoaded', markWholeDocument, false);
//   console.log('registered listener');
// }

// // const textareas = header.getElementsByClassName('task-row-text-input');
// // let headerTitle = textareas[0].value;
<commit_msg>Add CSS classes to nodes<commit_after>// ==UserScript==
// @name WIP Limiter
// @namespace http://github.com/apiology/
// @description Add Kanban-style visual WIP limit indicators
// @match https://app.asana.com/*
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==

console.log('starting script');

class Header {
  constructor(header) {
    this.header = header;
  }

  // header.classList.contains("bar-row")
  title() {
    const textareas = this.header.getElementsByClassName('task-row-text-input');
    if (textareas.length !== 1) {
      return null;
    }

    return textareas[0].value;
  }

  wipLimit() {
    const headerTitle = this.title();
    const wipFinder = /.*\[(\d*)\]:$/;
    const results = wipFinder.exec(headerTitle);
    if (results !== null) {
      return parseInt(results[1], 10);
    }
    return null;
  }

  countChildren() {
    const count = this.children().length;
    console.log(`Size of ${this.title()} is ${count}`);
    return count;
  }

  static isHeader(element) {
    return element.classList.contains('bar-row');
  }

  children() {
    let curNode = this.header.nextSibling;
    const childList = [];
    while (curNode != null) {
      if (Header.isHeader(curNode)) {
        curNode = null;
      } else {
        childList.push(curNode);
        curNode = curNode.nextSibling;
      }
    }
    return childList;
  }

  markBackgroundColor() {
    const wipLimit = this.wipLimit();
    if (wipLimit === null) {
      this.markAsUnderLimit();
    } else {
      const childCount = this.countChildren();
      if (wipLimit === childCount) {
        this.markAsOnEdge();
      } else if (wipLimit < childCount) {
        this.markAsOverLimit();
      } else {
        this.markAsUnderLimit();
      }
    }
  }

  markAsOnEdge() {
    console.log(`Marking ${this.title()} as on edge`);
    for (const child of this.children()) {
      child.classList.remove('wip-limit-under');
      child.classList.remove('wip-limit-over');
      child.classList.add('wip-limit-on-edge');
    }
  }

  markAsOverLimit() {
    console.log(`Marking ${this.title()} as over limit`);
    for (const child of this.children()) {
      child.classList.remove('wip-limit-under');
      child.classList.add('wip-limit-over');
      child.classList.remove('wip-limit-on-edge');
    }
  }

  markAsUnderLimit() {
    console.log(`Marking ${this.title()} as under limit`);
    for (const child of this.children()) {
      child.classList.add('wip-limit-under');
      child.classList.remove('wip-limit-over');
      child.classList.remove('wip-limit-on-edge');
    }
  }
}

setInterval(() => {
  console.log('starting to mark whole document');
  const headers = document.getElementsByClassName('bar-row');
  for (const headerElement of headers) {
    const header = new Header(headerElement);
    header.markBackgroundColor();
  }
}, 1000);
console.log('setInterval run');

// if (document.body) {
//   console.log('already loaded; running now');
//   markWholeDocument();
//   console.log('ran!');
// } else {
//   console.log('registering listener');
//   document.addEventListener('DOMContentLoaded', markWholeDocument, false);
//   console.log('registered listener');
// }

// // const textareas = header.getElementsByClassName('task-row-text-input');
// // let headerTitle = textareas[0].value;
<|endoftext|>


<commit_before>/**
 * @license Copyright (c) 2010 Brian Cavalier
 * LICENSE: see the LICENSE.txt file. If file is missing, this file is subject
 * to the MIT License at: http://www.opensource.org/licenses/mit-license.php.
 */

/*
	File: events.js
	wire plugin that sets up subscriptions and topics to be published after
	functions are invoked.  ,
	and disconnect them when an object is destroyed.  This implementation uses
	dojo.connect and dojo.disconnect to do the work of connecting and disconnecting
	event handlers.
*/
define(['dojo'], function(pubsub) {

	var destroyHandlers = [];

	/*
		Function: proxyPublish
		Proxies methods on target so that they publish topics after being
		invoked.  The payload of a topic will be the return value of the method
		that triggered it.

		Parameters:
			target - object whose methods should be proxied
			publish - hash of method names to topics each should publish
	*/
	function proxyPublish(target, publish) {
		var originals = {};

		for(var f in publish) {
			if(typeof target[f] == 'function') {
				var orig = originals[f] = target[f],
					topic = publish[f];

				target[f] = function publishProxy() {
					var result = orig.apply(target, arguments);
					pubsub.publish(topic, [result]);
				};
			}
		}

		destroyHandlers.push(function() {
			unproxyPublish(target, originals);
		});
	}

	/*
		Function: unproxyPublish
		Restores the original functions on object after they've been proxied
		by <proxyPublish> to publish topics.

		Parameters:
			object - object whose methods should be restored
			originals - hash of method names to original methods to restore
	*/
	function unproxyPublish(object, originals) {
		for(var p in originals) {
			object[p] = originals[p];
		}
	}

	function subscribeTarget(target, subscriptions) {
		var subscribeHandles = [];
		for(var topic in subscriptions) {
			var f = subscriptions[topic];
			if(typeof target[f] == 'function') {
				// TODO: How to unsubscribe?
				subscribeHandles.push(pubsub.subscribe(topic, target, f));
			}
		}

		if(subscribeHandles.length > 0) {
			destroyHandlers.push(function() {
				unsubscribeTarget();
			});
		}
	}

    function unsubscribeTarget(handles) {
        for (var i = handles.length - 1; i >= 0; i--){
			pubsub.unsubscribe(handles[i]);
		}
	}

	return {
		wire$wire: function onWire(ready, destroy) {
			ready.then(null, null,
				function onObject(progress) {
					if(progress.status === 'init') {
						var spec = progress.spec;

						if(typeof spec.publish == 'object') {
							proxyPublish(progress.target, spec.publish);
						}

						if(typeof spec.subscribe == 'object') {
							subscribeTarget(progress.target, spec.subscribe);
						}
					}
				}
			);

			destroy.then(function onContextDestroy() {
				for (var i = destroyHandlers.length - 1; i >= 0; i--){
					destroyHandlers[i]();
                }
            });
		}
	};
});<commit_msg>Scoped pubsub plugin properly to one context, and fixed a bug in unsubscribe on destroy<commit_after>/**
 * @license Copyright (c) 2010 Brian Cavalier
 * LICENSE: see the LICENSE.txt file. If file is missing, this file is subject
 * to the MIT License at: http://www.opensource.org/licenses/mit-license.php.
 */

/*
	File: events.js
	wire plugin that sets up subscriptions and topics to be published after
	functions are invoked.  ,
	and disconnect them when an object is destroyed.  This implementation uses
	dojo.connect and dojo.disconnect to do the work of connecting and disconnecting
	event handlers.
*/
define(['dojo'], function(pubsub) {

	return {
		wire$wire: function onWire(ready, destroy) {

			var destroyHandlers = [];

			/*
				Function: proxyPublish
				Proxies methods on target so that they publish topics after being
				invoked.  The payload of a topic will be the return value of the method
				that triggered it.

				Parameters:
					target - object whose methods should be proxied
					publish - hash of method names to topics each should publish
			*/
			function proxyPublish(target, publish) {
				var originals = {};

				for(var f in publish) {
					if(typeof target[f] == 'function') {
						var orig = originals[f] = target[f],
							topic = publish[f];

						target[f] = function publishProxy() {
							var result = orig.apply(target, arguments);
							pubsub.publish(topic, [result]);
						};
					}
				}

				destroyHandlers.push(function() {
					unproxyPublish(target, originals);
				});
			}

			/*
				Function: unproxyPublish
				Restores the original functions on object after they've been proxied
				by <proxyPublish> to publish topics.

				Parameters:
					object - object whose methods should be restored
					originals - hash of method names to original methods to restore
			*/
			function unproxyPublish(object, originals) {
				for(var p in originals) {
					object[p] = originals[p];
				}
			}

			function subscribeTarget(target, subscriptions) {
				var subscribeHandles = [];
				for(var topic in subscriptions) {
					var f = subscriptions[topic];
					if(typeof target[f] == 'function') {
						// TODO: How to unsubscribe?
						subscribeHandles.push(pubsub.subscribe(topic, target, f));
					}
				}

				if(subscribeHandles.length > 0) {
					destroyHandlers.push(function() {
						unsubscribeTarget(subscribeHandles);
					});
				}
			}

		    function unsubscribeTarget(handles) {
		        for (var i = handles.length - 1; i >= 0; i--){
					pubsub.unsubscribe(handles[i]);
				}
			}

			ready.then(null, null,
				function onObject(progress) {
					if(progress.status === 'init') {
						var spec = progress.spec;

						if(typeof spec.publish == 'object') {
							proxyPublish(progress.target, spec.publish);
						}

						if(typeof spec.subscribe == 'object') {
							subscribeTarget(progress.target, spec.subscribe);
						}
					}
				}
			);

			destroy.then(function onContextDestroy() {
				for (var i = destroyHandlers.length - 1; i >= 0; i--){
					destroyHandlers[i]();
                }
            });
		}
	};
});<|endoftext|>


<commit_before>// Options: --free-variable-checker --require --validate
/*global module require*/

module.exports = (function() {
  "use strict";

  const {def} = require('../../src/sesshim.es6');
  const {bnf} = require('../../src/bootbnf.es6');

  const binary = (left,rights) => rights.reduce((prev,[op,right]) => [op,prev,right], left);

  const qunpack = (h,ms,t) => {
    const result = [h];
    if (ms.length === 1) {
      const [[m,pairs]] = ms;
      result.push(m);
      for (let [q,e] of pairs) {
        result.push(q,e);
      }
    }
    result.push(t);
    return result;
  };

  const {FAIL, Packratter} = require('../../src/scanner.es6');
  // Packratter._debug = true;

  // Whereas SES is a maximal ocap-secure subset of ES6 (EcmaScript
  // 2015), microses is a minimal "better parts"
  // (http://www.infoq.com/presentations/efficient-programming-language-es6)
  // subset of SES-strict. SES is a semantic, not a syntactic, subset
  // of ES6. Microses is mostly defined as a syntactic subset of
  // SES-strict. The following microses grammar is based on
  // http://www.ecma-international.org/ecma-262/6.0/#sec-grammar-summary
  // Unlike that page, lexical productions are named in all upper
  // case. The intention is that microses be a true subset of SES in
  // the sense that every valid microses program is a valid SES
  // program of the same meaning.

  // Unlike ES6 and SES, microses has no semicolon insertion, and so
  // does not need a parser able to handle that. However, microses
  // must impose the NO_NEWLINE constraints from ES6, so that every
  // non-rejected microses program is accepted as the same SES
  // program. NO_NEWLINE is a lexical-level placeholder that must
  // never consume anything. It should fail if the whitespace to skip
  // over contains a newline. TODO: Currently this placeholder always
  // succeeds.

  // Microses excludes the RegularExpressionLiteral, instead including
  // the RegExp.make https://github.com/mikesamuel/regexp-make-js
  // template string tag. By omitting this and automatic semicolon
  // insertion, our lexical grammar avoids the context dependence that
  // plague JavaScript lexers.

  // In microses, all reserved words are unconditionally reserved. By
  // contrast, in ES6 and SES, "yield", "await", "implements", etc are
  // conditionally reserved. Thus we avoid the need for parameterized
  // lexical-level productions.

  // Microses excludes both the "in" expression and the for/in loop,
  // and thus avoid the need for parameterized parser-level
  // productions.

  // QUASI_* are lexical-level placeholders. QUASI_ALL should match a
  // self-contained template literal string that has no holes " `...`
  // ". QUASI_HEAD should match the initial literal part of a template
  // literal with holes " `...${ ". QUASI_MID should match the middle
  // " }...${ ", and QUASI_TAIL the end " }...` ". The reason these
  // are difficult is that a "}" during a hole only terminates the
  // hole if it is balanced.  TODO: All these placeholders currently
  // fail.

  // Ouside the lexical grammar, other differences from
  // http://www.ecma-international.org/ecma-262/6.0/#sec-grammar-summary
  // are noted as comments within the grammar below.
  // That page uses a cover grammar do avoid unbounded
  // lookahead. Because the grammar here is defined using a PEG
  // (parsing expression grammar) which supports unbounded lookahead,
  // we avoid the need for a cover grammar.

  // Microses array literals exclude elision (i.e., nothing between
  // commas).

  // Beyond subsetting ES6, this grammar also includes the infix "!"
  // (eventually) operator from
  // http://research.google.com/pubs/pub40673.html

  const microses = bnf`
    # TODO: module syntax
    start ::= body EOF                                     ${(b,_) => (..._) => ['script', b]};

    NO_NEWLINE ::= ;

    QUASI_ALL ::= ${() => FAIL};
    QUASI_HEAD ::= ${() => FAIL};
    QUASI_MID ::= ${() => FAIL};
    QUASI_TAIL ::= ${() => FAIL};

    # Exclude "arguments" and "eval" from IDENT in microses.
    RESERVED_WORD ::=
      KEYWORD / ES6_ONLY_KEYWORD / FUTURE_RESERVED_WORD
    / "arguments" / "eval";

    KEYWORD ::=
      "false" / "true"
    / "break" / "case" / "catch" / "const"
    / "debugger" / "default" / "delete"
    / "else" / "export" / "finally"
    / "for" / "if" / "import"
    / "return" / "switch" / "throw" / "try"
    / "typeof" / "void" / "while";

    # We enumerate these anyway, in order to exclude them from the
    # IDENT token.
    ES6_ONLY_KEYWORD ::=
      "null" / "class" / "continue" / "do" / "extends"
    / "function" / "in" / "instanceof" / "new" / "super"
    / "this" / "var" / "with" / "yield";

    FUTURE_RESERVED_WORD ::=
      "enum" / "await"
    / "implements" / "interface" / "package"
    / "private" / "protected" / "public";

    # Microses primaryExpr does not include "this", ClassExpression,
    # GeneratorExpression, or RegularExpressionLiteral.
    # No "null". No "function" functions.
    primaryExpr ::=
      (NUMBER / STRING / "true" / "false")                 ${n => ['data',JSON.parse(n)]}
    / "[" arg ** "," "]"                                   ${(_,es,_2) => ['array',es]}
    / "{" prop ** "," "}"                                  ${(_,ps,_2) => ['object',ps]}
    / quasiExpr
    / "(" expr ")"                                         ${(_,e,_2) => e}
    / IDENT
    / HOLE                                                 ${h => ['exprHole',h]};

    pattern ::=
      (NUMBER / STRING / "true" / "false")                 ${n => ['matchData',JSON.parse(n)]}
    / "[" param ** "," "]"                                 ${(_,ps,_2) => ['matchArray',ps]}
    / "{" propParam ** "," "}"                             ${(_,ps,_2) => ['matchObj',ps]}
    / IDENT
    / HOLE                                                 ${h => ['patternHole',h]};

    arg ::=
      "..." expr                                           ${(_,e) => ['spread',e]}
    / expr;

    param ::=
      "..." pattern                                        ${(_,p) => ['rest',p]}
    / IDENT "=" expr                                       ${(id,_,e) => ['optional',id,e]}
    / pattern;

    # No method definition.
    prop ::=
      "..." expr                                           ${(_,e) => ['spreadObj',e]}
    / key ":" expr                                         ${(k,_,e) => ['prop',k,e]}
    / IDENT                                                ${id => ['prop',id,id]};

    propParam ::=
      "..." pattern                                        ${(_,p) => ['restObj',p]}
    / key ":" pattern                                      ${(k,_,p) => ['matchProp',k,p]}
    / IDENT "=" expr                                       ${(id,_,e) => ['optionalProp',id,id,e]}
    / IDENT                                                ${id => ['matchProp',id,id]};

    key ::=
      IDENT / RESERVED_WORD / STRING / NUMBER
    / "[" expr "]"                                         ${(_,k) => ['computed', k]};

    quasiExpr ::=
      QUASI_ALL                                            ${q => ['quasi',[q]]}
    / QUASI_HEAD (expr (QUASI_MID expr)*)? QUASI_TAIL      ${(h,ms,t) => ['quasi',qunpack(h,ms,t)]};

    later ::= NO_NEWLINE "!";

    # No "new", "super", or MetaProperty. Without "new" we don't need
    # separate MemberExpr and CallExpr productions.
    postExpr ::= primaryExpr postOp*                       ${binary};
    postOp ::=
      "." IDENT                                            ${(_,id) => ['get',id]}
    / "[" expr "]"                                         ${(_,e,_2) => ['index',e]}
    / "(" arg ** "," ")"                                   ${(_,args,_2) => ['call',args]}
    / quasiExpr                                            ${q => ['tag',q]}

    / later IDENT                                          ${(_,id) => ['getLater',id]}
    / later "[" expr "]"                                   ${(_,_2,e,_3) => ['indexLater',e]}
    / later "(" arg ** "," ")"                             ${(_,_2,args,_3) => ['callLater',args]}
    / later quasiExpr                                      ${(_,q) => ['tagLater',q]};

    preExpr ::=
      "delete" fieldExpr                                   ${(_,fe) => ['delete', fe]}
    / preOp preExpr                                        ${(op,e) => [op,e]}
    / postExpr;

    # No prefix or postfix "++" or "--".
    preOp ::= "void" / "typeof" / "+" / "-" / "!";

    # No bitwise operators, "instanceof", or "in".  Unlike ES6, none
    # of the relational operators associate. To help readers, mixing
    # relational operators always requires explicit parens.
    multExpr ::= preExpr (("*" / "/" / "%") preExpr)*      ${binary};
    addExpr ::= multExpr (("+" / "-") multExpr)*           ${binary};
    relExpr ::= addExpr (relOp addExpr)?                   ${binary};
    relOp ::= "<" / ">" / "<=" / ">=" / "===" / "!==";
    andThenExpr ::= relExpr ("&&" relExpr)*                ${binary};
    orElseExpr ::= andThenExpr ("||" andThenExpr)*         ${binary};

    # No trinary ("?:") expression
    # No comma expression, so assignment expression is expr.
    expr ::=
      lValue assignOp expr                                 ${(lv,op,rv) => [op,lv,rv]}
    / arrow
    / orElseExpr;

    # lValue is divided into IDENT and fieldExpr because microses
    # syntactically disallows "delete" IDENT.
    # No pseudo-pattern lValues.
    lValue ::= IDENT / fieldExpr;

    fieldExpr ::=
      primaryExpr "." IDENT                                ${(pe,_,id) => ['get',pe,id]}
    / primaryExpr "[" expr "]"                             ${(pe,_,e,_2) => ['index',pe,e]}
    / primaryExpr later IDENT                              ${(pe,_,_2,id) => ['getLater',pe,id]}
    / primaryExpr later "[" expr "]"                       ${(pe,_,_2,e,_3) => ['indexLater',pe,e]};

    # No bitwise operators
    assignOp ::= "=" / "*=" / "/=" / "%=" / "+=" / "-=";

    arrow ::=
      params NO_NEWLINE "=>" block                         ${(ps,_,_2,b) => ['arrow',ps,b]}
    / params NO_NEWLINE "=>" expr                          ${(ps,_,_2,e) => ['lambda',ps,e]};
    params ::=
      IDENT                                                ${id => [id]}
    / "(" param ** "," ")"                                 ${(_,ps,_2) => ps};

    # No "var", empty statement, "continue", "with", "do/while",
    # "for/in", or labelled statement. None of the insane variations
    # of "for". Only blocks are accepted for flow-of-control
    # statements.
    statement ::=
      block
    / "if" "(" expr ")" block "else" block                 ${(_,_2,c,_3,t,_4,e) => ['if',c,t,e]}
    / "if" "(" expr ")" block                              ${(_,_2,c,_3,t) => ['if',c,t]}
    / "for" "(" declaration expr? ";" expr? ")" block      ${(_,_2,d,c,_3,i,_4,b) => ['for',d,c,i,b]}
    / "for" "(" declOp binding "of" expr ")" block         ${(_,_2,d,_3,e,_4,b) => ['forOf',d,e,b]}
    / "while" "(" expr ")" block                           ${(_,_2,c,_3,b) => ['while',c,b]}
    / "try" block catcher finalizer                        ${(_,b,c,f) => ['try',b,c,f]}
    / "try" block finalizer                                ${(_,b,f) => ['try',b,f]}
    / "try" block catcher                                  ${(_,b,c) => ['try',b,c]}
    / "switch" "(" expr ")" "{" branch* "}"                ${(_,_2,e,_3,_4,bs,_5) => ['switch',e,bs]}
    / terminator
    / "debugger" ";"                                       ${(_,_2) => ['debugger']}
    / expr ";"                                             ${(e,_) => e};

    # Each case branch must end in a terminating statement. No
    # labelled break.
    terminator ::=
      "return" NO_NEWLINE expr ";"                         ${(_,_2,e,_3) => ['return',e]}
    / "return" ";"                                         ${(_,_2) => ['return']}
    / "break" ";"                                          ${(_,_2) => ['break']}
    / "throw" expr ";"                                     ${(_,e,_2) => ['throw',e]};

    # no "function", generator, or "class" declaration.
    declaration ::= declOp binding ** "," ";"              ${(op,decls,_) => [op, decls]};
    declOp ::= "const" / "let";
    # Initializer is mandatory
    binding ::= pattern "=" expr                           ${(p,_,e) => ['bind', p, e]};

    catcher ::= "catch" "(" pattern ")" block              ${(_,_2,p,_3,b) => ['catch',p,b]};
    finalizer ::= "finally" block                          ${(_,b) => ['finally',b]};

    branch ::= caseLabel+ "{" body terminator "}"          ${(cs,_,b,t,_2) => ['branch',cs,[...b,t]]};
    caseLabel ::=
      "case" expr ":"                                      ${(_,e) => ['case', e]}
    / "default" ":"                                        ${(_,_2) => ['default']};

    block ::= "{" body "}"                                 ${(_,b,_2) => ['block', b]};
    body ::= (statement / declaration)*;
  `;

  return def({microses});
}());
<commit_msg>Update microses.es6<commit_after>// Options: --free-variable-checker --require --validate
/*global module require*/

module.exports = (function() {
  "use strict";

  const {def} = require('../../src/sesshim.es6');
  const {bnf} = require('../../src/bootbnf.es6');

  const binary = (left,rights) => rights.reduce((prev,[op,right]) => [op,prev,right], left);

  const qunpack = (h,ms,t) => {
    const result = [h];
    if (ms.length === 1) {
      const [[m,pairs]] = ms;
      result.push(m);
      for (let [q,e] of pairs) {
        result.push(q,e);
      }
    }
    result.push(t);
    return result;
  };

  const {FAIL, Packratter} = require('../../src/scanner.es6');
  // Packratter._debug = true;

  // Whereas SES is a maximal ocap-secure subset of ES6 (EcmaScript
  // 2015), microses is a minimal "better parts"
  // (http://www.infoq.com/presentations/efficient-programming-language-es6)
  // subset of SES-strict. SES is a semantic, not a syntactic, subset
  // of ES6. Microses is mostly defined as a syntactic subset of
  // SES-strict. The following microses grammar is based on
  // http://www.ecma-international.org/ecma-262/6.0/#sec-grammar-summary
  // Unlike that page, lexical productions are named in all upper
  // case. The intention is that microses be a true subset of SES in
  // the sense that every valid microses program is a valid SES
  // program of the same meaning.

  // Unlike ES6 and SES, microses has no semicolon insertion, and so
  // does not need a parser able to handle that. However, microses
  // must impose the NO_NEWLINE constraints from ES6, so that every
  // non-rejected microses program is accepted as the same SES
  // program. NO_NEWLINE is a lexical-level placeholder that must
  // never consume anything. It should fail if the whitespace to skip
  // over contains a newline. TODO: Currently this placeholder always
  // succeeds.

  // Microses excludes the RegularExpressionLiteral, instead including
  // the RegExp.make https://github.com/mikesamuel/regexp-make-js
  // template string tag. By omitting this and automatic semicolon
  // insertion, our lexical grammar avoids the context dependence that
  // plague JavaScript lexers.

  // In microses, all reserved words are unconditionally reserved. By
  // contrast, in ES6 and SES, "yield", "await", "implements", etc are
  // conditionally reserved. Thus we avoid the need for parameterized
  // lexical-level productions.

  // Microses excludes both the "in" expression and the for/in loop,
  // and thus avoid the need for parameterized parser-level
  // productions.

  // QUASI_* are lexical-level placeholders. QUASI_ALL should match a
  // self-contained template literal string that has no holes " `...`
  // ". QUASI_HEAD should match the initial literal part of a template
  // literal with holes " `...${ ". QUASI_MID should match the middle
  // " }...${ ", and QUASI_TAIL the end " }...` ". The reason these
  // are difficult is that a "}" during a hole only terminates the
  // hole if it is balanced.  TODO: All these placeholders currently
  // fail.

  // Ouside the lexical grammar, other differences from
  // http://www.ecma-international.org/ecma-262/6.0/#sec-grammar-summary
  // are noted as comments within the grammar below.
  // That page uses a cover grammar do avoid unbounded
  // lookahead. Because the grammar here is defined using a PEG
  // (parsing expression grammar) which supports unbounded lookahead,
  // we avoid the need for a cover grammar.

  // Microses array literals exclude elision (i.e., nothing between
  // commas).

  // Beyond subsetting ES6, this grammar also includes the infix "!"
  // (eventually) operator from
  // http://research.google.com/pubs/pub40673.html

  const microses = bnf`
    # TODO: module syntax
    start ::= body EOF                                     ${(b,_) => (..._) => ['script', b]};

    NO_NEWLINE ::= ;

    QUASI_ALL ::= ${() => FAIL};
    QUASI_HEAD ::= ${() => FAIL};
    QUASI_MID ::= ${() => FAIL};
    QUASI_TAIL ::= ${() => FAIL};

    # Exclude "arguments" and "eval" from IDENT in microses.
    RESERVED_WORD ::=
      KEYWORD / ES6_ONLY_KEYWORD / FUTURE_RESERVED_WORD
    / "arguments" / "eval";

    KEYWORD ::=
      "false" / "true"
    / "break" / "case" / "catch" / "const"
    / "debugger" / "default" / "delete"
    / "else" / "export" / "finally"
    / "for" / "if" / "import"
    / "return" / "switch" / "throw" / "try"
    / "typeof" / "void" / "while";

    # We enumerate these anyway, in order to exclude them from the
    # IDENT token.
    ES6_ONLY_KEYWORD ::=
      "null" / "class" / "continue" / "do" / "extends"
    / "function" / "in" / "instanceof" / "new" / "super"
    / "this" / "var" / "with" / "yield";

    FUTURE_RESERVED_WORD ::=
      "enum" / "await"
    / "implements" / "interface" / "package"
    / "private" / "protected" / "public";

    # Microses primaryExpr does not include "this", ClassExpression,
    # GeneratorExpression, or RegularExpressionLiteral.
    # No "null". No "function" functions.
    primaryExpr ::=
      (NUMBER / STRING / "true" / "false")                 ${n => ['data',JSON.parse(n)]}
    / "[" arg ** "," "]"                                   ${(_,es,_2) => ['array',es]}
    / "{" prop ** "," "}"                                  ${(_,ps,_2) => ['object',ps]}
    / quasiExpr
    / "(" expr ")"                                         ${(_,e,_2) => e}
    / IDENT
    / HOLE                                                 ${h => ['exprHole',h]};

    pattern ::=
      (NUMBER / STRING / "true" / "false")                 ${n => ['matchData',JSON.parse(n)]}
    / "[" param ** "," "]"                                 ${(_,ps,_2) => ['matchArray',ps]}
    / "{" propParam ** "," "}"                             ${(_,ps,_2) => ['matchObj',ps]}
    / IDENT
    / HOLE                                                 ${h => ['patternHole',h]};

    arg ::=
      "..." expr                                           ${(_,e) => ['spread',e]}
    / expr;

    param ::=
      "..." pattern                                        ${(_,p) => ['rest',p]}
    / IDENT "=" expr                                       ${(id,_,e) => ['optional',id,e]}
    / pattern;

    # No method definition.
    prop ::=
      "..." expr                                           ${(_,e) => ['spreadObj',e]}
    / key ":" expr                                         ${(k,_,e) => ['prop',k,e]}
    / IDENT                                                ${id => ['prop',id,id]};

    propParam ::=
      "..." pattern                                        ${(_,p) => ['restObj',p]}
    / key ":" pattern                                      ${(k,_,p) => ['matchProp',k,p]}
    / IDENT "=" expr                                       ${(id,_,e) => ['optionalProp',id,id,e]}
    / IDENT                                                ${id => ['matchProp',id,id]};

    key ::=
      IDENT / RESERVED_WORD / STRING / NUMBER
    / "[" expr "]"                                         ${(_,k) => ['computed', k]};

    quasiExpr ::=
      QUASI_ALL                                            ${q => ['quasi',[q]]}
    / QUASI_HEAD (expr (QUASI_MID expr)*)? QUASI_TAIL      ${(h,ms,t) => ['quasi',qunpack(h,ms,t)]};

    later ::= NO_NEWLINE "!";

    # No "new", "super", or MetaProperty. Without "new" we don't need
    # separate MemberExpr and CallExpr productions.
    postExpr ::= primaryExpr postOp*                       ${binary};
    postOp ::=
      "." IDENT                                            ${(_,id) => ['get',id]}
    / "[" expr "]"                                         ${(_,e,_2) => ['index',e]}
    / "(" arg ** "," ")"                                   ${(_,args,_2) => ['call',args]}
    / quasiExpr                                            ${q => ['tag',q]}

    / later IDENT                                          ${(_,id) => ['getLater',id]}
    / later "[" expr "]"                                   ${(_,_2,e,_3) => ['indexLater',e]}
    / later "(" arg ** "," ")"                             ${(_,_2,args,_3) => ['callLater',args]}
    / later quasiExpr                                      ${(_,q) => ['tagLater',q]};

    preExpr ::=
      "delete" fieldExpr                                   ${(_,fe) => ['delete', fe]}
    / preOp preExpr                                        ${(op,e) => [op,e]}
    / postExpr;

    # No prefix or postfix "++" or "--".
    preOp ::= "void" / "typeof" / "+" / "-" / "!";

    # No bitwise operators, "instanceof", or "in".  Unlike ES6, none
    # of the relational operators associate. To help readers, mixing
    # relational operators always requires explicit parens.
    multExpr ::= preExpr (("*" / "/" / "%") preExpr)*      ${binary};
    addExpr ::= multExpr (("+" / "-") multExpr)*           ${binary};
    relExpr ::= addExpr (relOp addExpr)?                   ${binary};
    relOp ::= "<" / ">" / "<=" / ">=" / "===" / "!==";
    andThenExpr ::= relExpr ("&&" relExpr)*                ${binary};
    orElseExpr ::= andThenExpr ("||" andThenExpr)*         ${binary};

    # No trinary ("?:") expression
    # No comma expression, so assignment expression is expr.
    expr ::=
      lValue assignOp expr                                 ${(lv,op,rv) => [op,lv,rv]}
    / arrow
    / orElseExpr;

    # lValue is divided into IDENT and fieldExpr because microses
    # syntactically disallows "delete" IDENT.
    # No pseudo-pattern lValues.
    lValue ::= IDENT / fieldExpr;

    fieldExpr ::=
      primaryExpr "." IDENT                                ${(pe,_,id) => ['get',pe,id]}
    / primaryExpr "[" expr "]"                             ${(pe,_,e,_2) => ['index',pe,e]}
    / primaryExpr later IDENT                              ${(pe,_,id) => ['getLater',pe,id]}
    / primaryExpr later "[" expr "]"                       ${(pe,_,_2,e,_3) => ['indexLater',pe,e]};

    # No bitwise operators
    assignOp ::= "=" / "*=" / "/=" / "%=" / "+=" / "-=";

    arrow ::=
      params NO_NEWLINE "=>" block                         ${(ps,_,_2,b) => ['arrow',ps,b]}
    / params NO_NEWLINE "=>" expr                          ${(ps,_,_2,e) => ['lambda',ps,e]};
    params ::=
      IDENT                                                ${id => [id]}
    / "(" param ** "," ")"                                 ${(_,ps,_2) => ps};

    # No "var", empty statement, "continue", "with", "do/while",
    # "for/in", or labelled statement. None of the insane variations
    # of "for". Only blocks are accepted for flow-of-control
    # statements.
    statement ::=
      block
    / "if" "(" expr ")" block "else" block                 ${(_,_2,c,_3,t,_4,e) => ['if',c,t,e]}
    / "if" "(" expr ")" block                              ${(_,_2,c,_3,t) => ['if',c,t]}
    / "for" "(" declaration expr? ";" expr? ")" block      ${(_,_2,d,c,_3,i,_4,b) => ['for',d,c,i,b]}
    / "for" "(" declOp binding "of" expr ")" block         ${(_,_2,d,_3,e,_4,b) => ['forOf',d,e,b]}
    / "while" "(" expr ")" block                           ${(_,_2,c,_3,b) => ['while',c,b]}
    / "try" block catcher finalizer                        ${(_,b,c,f) => ['try',b,c,f]}
    / "try" block finalizer                                ${(_,b,f) => ['try',b,f]}
    / "try" block catcher                                  ${(_,b,c) => ['try',b,c]}
    / "switch" "(" expr ")" "{" branch* "}"                ${(_,_2,e,_3,_4,bs,_5) => ['switch',e,bs]}
    / terminator
    / "debugger" ";"                                       ${(_,_2) => ['debugger']}
    / expr ";"                                             ${(e,_) => e};

    # Each case branch must end in a terminating statement. No
    # labelled break.
    terminator ::=
      "return" NO_NEWLINE expr ";"                         ${(_,_2,e,_3) => ['return',e]}
    / "return" ";"                                         ${(_,_2) => ['return']}
    / "break" ";"                                          ${(_,_2) => ['break']}
    / "throw" expr ";"                                     ${(_,e,_2) => ['throw',e]};

    # no "function", generator, or "class" declaration.
    declaration ::= declOp binding ** "," ";"              ${(op,decls,_) => [op, decls]};
    declOp ::= "const" / "let";
    # Initializer is mandatory
    binding ::= pattern "=" expr                           ${(p,_,e) => ['bind', p, e]};

    catcher ::= "catch" "(" pattern ")" block              ${(_,_2,p,_3,b) => ['catch',p,b]};
    finalizer ::= "finally" block                          ${(_,b) => ['finally',b]};

    branch ::= caseLabel+ "{" body terminator "}"          ${(cs,_,b,t,_2) => ['branch',cs,[...b,t]]};
    caseLabel ::=
      "case" expr ":"                                      ${(_,e) => ['case', e]}
    / "default" ":"                                        ${(_,_2) => ['default']};

    block ::= "{" body "}"                                 ${(_,b,_2) => ['block', b]};
    body ::= (statement / declaration)*;
  `;

  return def({microses});
}());
<|endoftext|>


<commit_before>let twitter = require('./Twitter.mock')

// dbのmock/stub
let db = {
  createUser: (user) => user,
  getUser: (id) => Promise.resolve(twitter.userMock(id)),
  setNickname: (id, nickname) => Promise.resolve([id, nickname]),
  setBirthday: (id, m, d) => Promise.resolve([id, m, d]),
  increaseLovelity: (id, lovelity) => Promise.resolve([id, lovelity]),
  addDonateLog: (name, amount) => Promise.resolve(name, amount),
  userIsDonated: () => Promise.resolve(false),
  sumDonation: () => Promise.resolve(1000),
  stashDonation: () => Promise.resolve()
}

module.exports = db<commit_msg>user tableのmockを追加<commit_after>let twitter = require('./Twitter.mock')

let createUserDBMock = (id) => {
  return {
    id: id,
    nickname: ':NAME:さん',
    birth_m: 1,
    birth_d: 1,
    lovelity: 20
  }
}

// dbのmock/stub
let db = {
  createUser: (user) => user,
  getUser: (id) => Promise.resolve(createUserDBMock(id)),
  setNickname: (id, nickname) => Promise.resolve([id, nickname]),
  setBirthday: (id, m, d) => Promise.resolve([id, m, d]),
  increaseLovelity: (id, lovelity) => Promise.resolve([id, lovelity]),
  addDonateLog: (name, amount) => Promise.resolve(name, amount),
  userIsDonated: () => Promise.resolve(false),
  sumDonation: () => Promise.resolve(1000),
  stashDonation: () => Promise.resolve()
}

module.exports = db<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const sinon = require('sinon');
const expect = require('chai').expect;
const Storage = require('storj-service-storage-models');
const ComplexClient = require('storj-complex').createClient;
const storj = require('storj-lib');
const Monitor = require('../../lib/monitor');
const MonitorConfig = require('../../lib/monitor/config');
const log = require('../../lib/logger');

/* jshint maxstatements: 100 */

describe('Monitor', function() {

  const sandbox = sinon.sandbox.create();
  beforeEach(() => {
    sandbox.stub(fs, 'existsSync').returns(true);
    sandbox.stub(fs, 'writeFileSync');
    sandbox.stub(fs, 'readFileSync').returns('{}');
  });
  afterEach(() => sandbox.restore());

  const config = new MonitorConfig('/tmp/storj-monitor-test.json');

  describe('@constructor', function() {

    it('will contruct with new', function() {
      const monitor = new Monitor(config);
      expect(monitor._config).to.equal(config);
      expect(monitor._timeout).to.equal(null);
      expect(monitor._running).to.equal(false);
    });

    it('will contruct without new', function() {
      const monitor = Monitor(config);
      expect(monitor._config).to.equal(config);
      expect(monitor._timeout).to.equal(null);
      expect(monitor._running).to.equal(false);
    });

  });

  describe('#start', function() {

    it('will init storage, network, contracts, and schedule run', function(done) {
      const monitor = new Monitor(config);
      monitor.wait = sandbox.stub();
      monitor.start(function(err) {
        if (err) {
          return done(err);
        }
        expect(monitor.storage).to.be.instanceOf(Storage);
        expect(monitor.network).to.be.instanceOf(ComplexClient);
        expect(monitor.contracts).to.be.instanceOf(storj.StorageManager);
        expect(monitor.wait.callCount).to.equal(1);
        done();
      });
    });

  });

  describe('#run', function() {

    it('will call wait if already running', function() {
      const monitor = new Monitor(config);
      monitor._running = true;
      monitor.wait = sandbox.stub();
      monitor.run();
      expect(monitor.wait.callCount).to.equal(1);
    });

    it('will log error when querying contacts', function() {
      const monitor = new Monitor(config);

      sandbox.stub(log, 'error');
      sandbox.stub(log, 'info');

      const exec = sandbox.stub().callsArgWith(0, new Error('Mongo error'));
      const sort = sandbox.stub().returns({
        exec: exec
      });
      const limit = sandbox.stub().returns({
        sort: sort
      });
      const find = sandbox.stub().returns({
        limit: limit
      });

      monitor.storage = {
        models: {
          Contact: {
            find: find
          }
        }
      };

      monitor.wait = sandbox.stub();
      monitor.run();
      expect(monitor.wait.callCount).to.equal(1);
      expect(monitor._running).to.equal(false);
      expect(log.error.callCount).to.equal(1);
      expect(log.info.callCount).to.equal(2);
    });

    it('will log error when missing contacts', function() {
      const monitor = new Monitor(config);

      sandbox.stub(log, 'error');
      sandbox.stub(log, 'info');

      const exec = sandbox.stub().callsArgWith(0, null, null);
      const sort = sandbox.stub().returns({
        exec: exec
      });
      const limit = sandbox.stub().returns({
        sort: sort
      });
      const find = sandbox.stub().returns({
        limit: limit
      });

      monitor.storage = {
        models: {
          Contact: {
            find: find
          }
        }
      };

      monitor.wait = sandbox.stub();
      monitor.run();
      expect(monitor.wait.callCount).to.equal(1);
      expect(monitor._running).to.equal(false);
      expect(log.error.callCount).to.equal(1);
      expect(log.info.callCount).to.equal(2);
    });

    it('query least seen contacts, log and record status', function() {
      const monitor = new Monitor(config);

      sandbox.stub(log, 'error');
      sandbox.stub(log, 'info');
      sandbox.stub(log, 'warn');

      monitor.network = {
        ping: sandbox.stub().callsArgWith(1, new Error('Farmer offline'))
      };
      monitor.network.ping.onThirdCall().callsArgWith(1, null);

      const save = sandbox.stub().callsArg(0);
      save.onSecondCall().callsArgWith(0, new Error('Mongo error'));

      const recordTimeoutFailure = sandbox.stub().returns({
        save: save
      });

      const contacts = [{
        nodeID: '7b8b30132e930c7827ee47efebfb197d6a3246d4',
        address: '127.0.0.1',
        port: 1337,
        recordTimeoutFailure: recordTimeoutFailure,
        timeoutRate: 0.05
      }, {
        nodeID: 'dd985ca22f19858257b3328a56f8f4aabee1d4a1',
        address: '127.0.0.1',
        port: 1337,
        recordTimeoutFailure: recordTimeoutFailure,
        timeoutRate: 0.02
      }, {
        nodeID: '6ae62b18fc9d20139c933e66f3b2fd2f8d04c20d',
        address: '127.0.0.1',
        port: 1337,
        recordTimeoutFailure: recordTimeoutFailure,
        timeoutRate: 0.03
      }];

      const exec = sandbox.stub().callsArgWith(0, null, contacts);
      const sort = sandbox.stub().returns({
        exec: exec
      });
      const limit = sandbox.stub().returns({
        sort: sort
      });
      const find = sandbox.stub().returns({
        limit: limit
      });
      monitor.storage = {
        models: {
          Contact: {
            find: find
          }
        }
      };
      monitor.wait = sandbox.stub();
      monitor._replicateFarmer = sinon.stub();
      monitor.run();

      expect(find.callCount).to.equal(1);
      expect(find.args[0][0]).to.eql({
        $or: [
          { timeoutRate: { $lt: 0.04 } },
          { timeoutRate: { $exists: false } }
        ]
      });

      expect(sort.callCount).to.equal(1);
      expect(sort.args[0][0]).to.eql({lastSeen: 1});
      expect(monitor.wait.callCount).to.equal(1);
      expect(exec.callCount).to.equal(1);
      expect(limit.callCount).to.equal(1);
      expect(limit.args[0][0]).to.equal(100);

      expect(log.error.callCount).to.equal(3);

      expect(log.error.args[0][1])
        .to.equal('7b8b30132e930c7827ee47efebfb197d6a3246d4');
      expect(log.error.args[0][2])
        .to.equal('Farmer offline');

      expect(log.error.args[1][1])
        .to.equal('dd985ca22f19858257b3328a56f8f4aabee1d4a1');
      expect(log.error.args[1][2])
        .to.equal('Farmer offline');

      expect(log.error.args[2][1])
        .to.equal('dd985ca22f19858257b3328a56f8f4aabee1d4a1');
      expect(log.error.args[2][2])
        .to.equal('Mongo error');

      expect(recordTimeoutFailure.callCount).to.equal(2);
      expect(save.callCount).to.equal(2);

      expect(log.info.callCount).to.equal(2);
      expect(log.warn.callCount).to.equal(1);
      expect(log.warn.args[0][1])
        .to.equal('7b8b30132e930c7827ee47efebfb197d6a3246d4');
      expect(log.warn.args[0][2])
        .to.equal(0.05);
      expect(monitor._replicateFarmer.callCount).to.equal(1);
      expect(monitor._replicateFarmer.args[0][0])
        .to.be.instanceOf(storj.Contact);

      expect(monitor.network.ping.callCount).to.equal(3);
      expect(monitor.network.ping.args[0][0]).to.be.instanceOf(storj.Contact);
    });

  });

  describe('_randomTime', function() {

    it('will select a random number between min and max', function() {
      const monitor = new Monitor(config);
      const time = monitor._randomTime(600000, 300000);
      expect(time).to.be.above(299999); // 5min
      expect(time).to.be.below(600001); // 10min
    });

    it('will throw with invalid options', function() {
      const monitor = new Monitor(config);
      expect(function() {
        monitor._randomTime(300000, 600000);
      }).to.throw('Assertion');
    });

  });

  describe('#wait', function() {

    it('will set a timeout, and call run', function() {
      const time = sandbox.useFakeTimers();

      const monitor = new Monitor(config);
      monitor.run = sandbox.stub();
      monitor._randomTime = sandbox.stub().returns(1000);
      monitor._timeout = setTimeout(() => {
        throw new Error('This should not happen');
      }, 5);
      monitor.wait();
      time.tick(1001);
      expect(monitor.run.callCount).to.equal(1);
    });

  });

});
<commit_msg>Include test for replicateFarmer<commit_after>'use strict';

const fs = require('fs');
const sinon = require('sinon');
const expect = require('chai').expect;
const EventEmitter = require('events').EventEmitter;
const Storage = require('storj-service-storage-models');
const ComplexClient = require('storj-complex').createClient;
const storj = require('storj-lib');
const Monitor = require('../../lib/monitor');
const MonitorConfig = require('../../lib/monitor/config');
const log = require('../../lib/logger');

/* jshint maxstatements: 100 */

describe('Monitor', function() {

  const sandbox = sinon.sandbox.create();
  beforeEach(() => {
    sandbox.stub(fs, 'existsSync').returns(true);
    sandbox.stub(fs, 'writeFileSync');
    sandbox.stub(fs, 'readFileSync').returns('{}');
  });
  afterEach(() => sandbox.restore());

  const config = new MonitorConfig('/tmp/storj-monitor-test.json');

  describe('@constructor', function() {

    it('will contruct with new', function() {
      const monitor = new Monitor(config);
      expect(monitor._config).to.equal(config);
      expect(monitor._timeout).to.equal(null);
      expect(monitor._running).to.equal(false);
    });

    it('will contruct without new', function() {
      const monitor = Monitor(config);
      expect(monitor._config).to.equal(config);
      expect(monitor._timeout).to.equal(null);
      expect(monitor._running).to.equal(false);
    });

  });

  describe('#start', function() {

    it('will init storage, network, contracts, and schedule run', function(done) {
      const monitor = new Monitor(config);
      monitor.wait = sandbox.stub();
      monitor.start(function(err) {
        if (err) {
          return done(err);
        }
        expect(monitor.storage).to.be.instanceOf(Storage);
        expect(monitor.network).to.be.instanceOf(ComplexClient);
        expect(monitor.contracts).to.be.instanceOf(storj.StorageManager);
        expect(monitor.wait.callCount).to.equal(1);
        done();
      });
    });

  });

  describe('#_replicateFarmer', function() {
    const sandbox = sinon.sandbox.create();
    afterEach(() => sandbox.restore());

    it('it will log on error', function(done) {
      sandbox.stub(log, 'info');
      sandbox.stub(log, 'error');
      const monitor = new Monitor(config);
      const cursor = new EventEmitter();
      const nodeID = '353ba728e2d74826c2fcbf5ada2fe1c402e3eda1';
      monitor.storage = {
        models: {
          Shard: {
            find: sinon.stub().returns(cursor)
          }
        }
      };
      const contact = {
        nodeID: nodeID
      };
      monitor._replicateFarmer(contact);
      cursor.on('error', () => {
        expect(log.info.callCount).to.equal(1);
        expect(log.error.callCount).to.equal(1);
        expect(log.error.args[0][1]).to.equal(nodeID);
        expect(log.error.args[0][2]).to.equal('test');
        done();
      });
      cursor.emit('error', new Error('test'));
    });

    it('will call replicateShard for each data item', function(done) {
      sandbox.stub(log, 'info');
      const monitor = new Monitor(config);
      const cursor = new EventEmitter();
      monitor.storage = {
        models: {
          Shard: {
            find: sinon.stub().returns(cursor)
          }
        }
      };
      const data = {};
      const contact = {
        nodeID: '353ba728e2d74826c2fcbf5ada2fe1c402e3eda1'
      };
      monitor._replicateShard = sinon.stub();
      monitor._replicateFarmer(contact);
      cursor.on('data', () => {
        expect(log.info.callCount).to.equal(2);
        expect(monitor._replicateShard.callCount).to.equal(1);
        expect(monitor._replicateShard.args[0][0]).to.equal(data);
        done();
      });
      cursor.emit('data', data);
    });

    it('it will log on close', function(done) {
      sandbox.stub(log, 'info');
      const monitor = new Monitor(config);
      const cursor = new EventEmitter();
      monitor.storage = {
        models: {
          Shard: {
            find: sinon.stub().returns(cursor)
          }
        }
      };
      const contact = {
        nodeID: '353ba728e2d74826c2fcbf5ada2fe1c402e3eda1'
      };
      monitor._replicateFarmer(contact);
      cursor.on('close', () => {
        expect(log.info.callCount).to.equal(2);
        done();
      });
      cursor.emit('close');
    });
  });

  describe('#run', function() {

    it('will call wait if already running', function() {
      const monitor = new Monitor(config);
      monitor._running = true;
      monitor.wait = sandbox.stub();
      monitor.run();
      expect(monitor.wait.callCount).to.equal(1);
    });

    it('will log error when querying contacts', function() {
      const monitor = new Monitor(config);

      sandbox.stub(log, 'error');
      sandbox.stub(log, 'info');

      const exec = sandbox.stub().callsArgWith(0, new Error('Mongo error'));
      const sort = sandbox.stub().returns({
        exec: exec
      });
      const limit = sandbox.stub().returns({
        sort: sort
      });
      const find = sandbox.stub().returns({
        limit: limit
      });

      monitor.storage = {
        models: {
          Contact: {
            find: find
          }
        }
      };

      monitor.wait = sandbox.stub();
      monitor.run();
      expect(monitor.wait.callCount).to.equal(1);
      expect(monitor._running).to.equal(false);
      expect(log.error.callCount).to.equal(1);
      expect(log.info.callCount).to.equal(2);
    });

    it('will log error when missing contacts', function() {
      const monitor = new Monitor(config);

      sandbox.stub(log, 'error');
      sandbox.stub(log, 'info');

      const exec = sandbox.stub().callsArgWith(0, null, null);
      const sort = sandbox.stub().returns({
        exec: exec
      });
      const limit = sandbox.stub().returns({
        sort: sort
      });
      const find = sandbox.stub().returns({
        limit: limit
      });

      monitor.storage = {
        models: {
          Contact: {
            find: find
          }
        }
      };

      monitor.wait = sandbox.stub();
      monitor.run();
      expect(monitor.wait.callCount).to.equal(1);
      expect(monitor._running).to.equal(false);
      expect(log.error.callCount).to.equal(1);
      expect(log.info.callCount).to.equal(2);
    });

    it('query least seen contacts, log and record status', function() {
      const monitor = new Monitor(config);

      sandbox.stub(log, 'error');
      sandbox.stub(log, 'info');
      sandbox.stub(log, 'warn');

      monitor.network = {
        ping: sandbox.stub().callsArgWith(1, new Error('Farmer offline'))
      };
      monitor.network.ping.onThirdCall().callsArgWith(1, null);

      const save = sandbox.stub().callsArg(0);
      save.onSecondCall().callsArgWith(0, new Error('Mongo error'));

      const recordTimeoutFailure = sandbox.stub().returns({
        save: save
      });

      const contacts = [{
        nodeID: '7b8b30132e930c7827ee47efebfb197d6a3246d4',
        address: '127.0.0.1',
        port: 1337,
        recordTimeoutFailure: recordTimeoutFailure,
        timeoutRate: 0.05
      }, {
        nodeID: 'dd985ca22f19858257b3328a56f8f4aabee1d4a1',
        address: '127.0.0.1',
        port: 1337,
        recordTimeoutFailure: recordTimeoutFailure,
        timeoutRate: 0.02
      }, {
        nodeID: '6ae62b18fc9d20139c933e66f3b2fd2f8d04c20d',
        address: '127.0.0.1',
        port: 1337,
        recordTimeoutFailure: recordTimeoutFailure,
        timeoutRate: 0.03
      }];

      const exec = sandbox.stub().callsArgWith(0, null, contacts);
      const sort = sandbox.stub().returns({
        exec: exec
      });
      const limit = sandbox.stub().returns({
        sort: sort
      });
      const find = sandbox.stub().returns({
        limit: limit
      });
      monitor.storage = {
        models: {
          Contact: {
            find: find
          }
        }
      };
      monitor.wait = sandbox.stub();
      monitor._replicateFarmer = sinon.stub();
      monitor.run();

      expect(find.callCount).to.equal(1);
      expect(find.args[0][0]).to.eql({
        $or: [
          { timeoutRate: { $lt: 0.04 } },
          { timeoutRate: { $exists: false } }
        ]
      });

      expect(sort.callCount).to.equal(1);
      expect(sort.args[0][0]).to.eql({lastSeen: 1});
      expect(monitor.wait.callCount).to.equal(1);
      expect(exec.callCount).to.equal(1);
      expect(limit.callCount).to.equal(1);
      expect(limit.args[0][0]).to.equal(100);

      expect(log.error.callCount).to.equal(3);

      expect(log.error.args[0][1])
        .to.equal('7b8b30132e930c7827ee47efebfb197d6a3246d4');
      expect(log.error.args[0][2])
        .to.equal('Farmer offline');

      expect(log.error.args[1][1])
        .to.equal('dd985ca22f19858257b3328a56f8f4aabee1d4a1');
      expect(log.error.args[1][2])
        .to.equal('Farmer offline');

      expect(log.error.args[2][1])
        .to.equal('dd985ca22f19858257b3328a56f8f4aabee1d4a1');
      expect(log.error.args[2][2])
        .to.equal('Mongo error');

      expect(recordTimeoutFailure.callCount).to.equal(2);
      expect(save.callCount).to.equal(2);

      expect(log.info.callCount).to.equal(2);
      expect(log.warn.callCount).to.equal(1);
      expect(log.warn.args[0][1])
        .to.equal('7b8b30132e930c7827ee47efebfb197d6a3246d4');
      expect(log.warn.args[0][2])
        .to.equal(0.05);
      expect(monitor._replicateFarmer.callCount).to.equal(1);
      expect(monitor._replicateFarmer.args[0][0])
        .to.be.instanceOf(storj.Contact);

      expect(monitor.network.ping.callCount).to.equal(3);
      expect(monitor.network.ping.args[0][0]).to.be.instanceOf(storj.Contact);
    });

  });

  describe('_randomTime', function() {

    it('will select a random number between min and max', function() {
      const monitor = new Monitor(config);
      const time = monitor._randomTime(600000, 300000);
      expect(time).to.be.above(299999); // 5min
      expect(time).to.be.below(600001); // 10min
    });

    it('will throw with invalid options', function() {
      const monitor = new Monitor(config);
      expect(function() {
        monitor._randomTime(300000, 600000);
      }).to.throw('Assertion');
    });

  });

  describe('#wait', function() {

    it('will set a timeout, and call run', function() {
      const time = sandbox.useFakeTimers();

      const monitor = new Monitor(config);
      monitor.run = sandbox.stub();
      monitor._randomTime = sandbox.stub().returns(1000);
      monitor._timeout = setTimeout(() => {
        throw new Error('This should not happen');
      }, 5);
      monitor.wait();
      time.tick(1001);
      expect(monitor.run.callCount).to.equal(1);
    });

  });

});
<|endoftext|>


<commit_before>function SiriWave(opt){
	this.opt = opt || {};

	this.K = 2;
	this.F = 6;
	this.speed = 0.1;
	this.noise = 0;
	this.phase = 0;

	if (!devicePixelRatio) devicePixelRatio = 1;
	this.width = devicePixelRatio * (this.opt.width || 320);
	this.height = devicePixelRatio * (this.opt.height || 100);
	this.MAX = (this.height/2)-4;

	this.canvas = document.createElement('canvas');
	this.canvas.width = this.width;
	this.canvas.height = this.height;
	this.canvas.style.width = (this.width/devicePixelRatio)+'px';
	this.canvas.style.height = (this.height/devicePixelRatio)+'px';
	(this.opt.container || document.body).appendChild(this.canvas);
	this.ctx = this.canvas.getContext('2d');

	this.run = false;
}

SiriWave.prototype = {

	_globalAttenuationFn: function(x){
		return Math.pow(this.K*4/(this.K*4+Math.pow(x,4)),this.K*2);
	},

	_drawLine: function(attenuation, color, width){
		this.ctx.moveTo(0,0);
		this.ctx.beginPath();
		this.ctx.strokeStyle = color;
		this.ctx.lineWidth = width || 1;
		var x, y;
		for (var i=-this.K; i<=this.K; i+=0.01) {
			x = this.width*((i+this.K)/(this.K*2));
			y = this.height/2 + this.noise * this._globalAttenuationFn(i) * (1/attenuation) * Math.sin(this.F*i-this.phase);
			this.ctx.lineTo(x, y);
		}
		this.ctx.stroke();
	},

	_clear: function(){
		this.ctx.globalCompositeOperation = 'destination-out';
		this.ctx.fillRect(0, 0, this.width, this.height);
		this.ctx.globalCompositeOperation = 'source-over';
	},

	_draw: function(){
		if (!this.run) return;

		this.phase = (this.phase+this.speed)%(Math.PI*64);
		this._clear();
		this._drawLine(-2, 'rgba(255,255,255,0.1)');
		this._drawLine(-6, 'rgba(255,255,255,0.2)');
		this._drawLine(4, 'rgba(255,255,255,0.4)');
		this._drawLine(2, 'rgba(255,255,255,0.6)');
		this._drawLine(1, 'rgba(255,255,255,1)', 1.5);

		requestAnimationFrame(this._draw.bind(this), 1000);
	},

	start: function(){
		this.phase = 0;
		this.run = true;
		this._draw();
	},

	stop: function(){
		this.speed = 0;
		this.phase = 0;
		this.noise = 0;
		this.run = false;
	},

	setNoise: function(v){
		this.noise = Math.min(v, 1)*this.MAX;
	},

	setSpeed: function(v){
		this.speed = v;
	},

	set: function(noise, speed) {
		this.setNoise(noise);
		this.setSpeed(speed);
	}

};
<commit_msg>Fixes<commit_after>/*

SiriWave JS
Have you ever thought on how to get the Siri wave effect on your website or mobile app? SiriWaveJS is a library that easily allows you to get this effect.

https://github.com/CaffeinaLab/SiriWaveJS

*/

function SiriWave(opt){
	this.opt = opt || {};

	this.K = 2;
	this.F = 6;
	this.speed = 0.1;
	this.noise = 0;
	this.phase = 0;

	var ratio = opt.ratio ? opt.ratio : ( window.devicePixelRatio ? window.devicePixelRatio : 1 );
	this.width = ratio * (this.opt.width || 320);
	this.height = ratio * (this.opt.height || 100);
	this.MAX = (this.height/2)-4;

	this.canvas = document.createElement('canvas');
	this.canvas.width = this.width;
	this.canvas.height = this.height;
	this.canvas.style.width = (this.width/ratio)+'px';
	this.canvas.style.height = (this.height/ratio)+'px';

	(this.opt.container || document.body).appendChild(this.canvas);
	this.ctx = this.canvas.getContext('2d');

	this.run = false;
}

SiriWave.prototype = {

	_globalAttenuationFn: function(x){
		return Math.pow(this.K*4/(this.K*4+Math.pow(x,4)),this.K*2);
	},

	_drawLine: function(attenuation, color, width){
		this.ctx.moveTo(0,0);
		this.ctx.beginPath();
		this.ctx.strokeStyle = color;
		this.ctx.lineWidth = width || 1;
		var x, y;
		for (var i=-this.K; i<=this.K; i+=0.01) {
			x = this.width*((i+this.K)/(this.K*2));
			y = this.height/2 + this.noise * this._globalAttenuationFn(i) * (1/attenuation) * Math.sin(this.F*i-this.phase);
			this.ctx.lineTo(x, y);
		}
		this.ctx.stroke();
	},

	_clear: function(){
		this.ctx.globalCompositeOperation = 'destination-out';
		this.ctx.fillRect(0, 0, this.width, this.height);
		this.ctx.globalCompositeOperation = 'source-over';
	},

	_draw: function(){
		if (!this.run) return;

		this.phase = (this.phase+this.speed)%(Math.PI*64);
		this._clear();
		this._drawLine(-2, 'rgba(255,255,255,0.1)');
		this._drawLine(-6, 'rgba(255,255,255,0.2)');
		this._drawLine(4, 'rgba(255,255,255,0.4)');
		this._drawLine(2, 'rgba(255,255,255,0.6)');
		this._drawLine(1, 'rgba(255,255,255,1)', 1.5);

		window.requestAnimationFrame(this._draw.bind(this), 1000);
	},

	start: function(){
		this.phase = 0;
		this.run = true;
		this._draw();
	},

	stop: function(){
		this.speed = 0;
		this.phase = 0;
		this.noise = 0;
		this.run = false;
	},

	setNoise: function(v){
		this.noise = Math.min(v, 1)*this.MAX;
	},

	setSpeed: function(v){
		this.speed = v;
	},

	set: function(noise, speed) {
		this.setNoise(noise);
		this.setSpeed(speed);
	}

};<|endoftext|>


<commit_before>/**
Oreon is developped with GPL Licence 2.0 :
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
Developped by : Julien Mathis - Romain Le Merlus

The Software is provided to you AS IS and WITH ALL FAULTS.
OREON makes no representation and gives no warranty whatsoever,
whether express or implied, and without limitation, with regard to the quality,
safety, contents, performance, merchantability, non-infringement or suitability for
any particular or intended purpose of the Software found on the OREON web site.
In no event will OREON be liable for any direct, indirect, punitive, special,
incidental or consequential damages however they may arise and even if OREON has
been previously advised of the possibility of such damages.

For information : contact@centreon.com
*/
<commit_msg>remove empty file<commit_after><|endoftext|>


<commit_before>// Generated by CoffeeScript 1.6.3
(function() {
  angular.module('app', ['CoolForm', 'CoolFormServices', 'ngRoute'], function($routeProvider, $locationProvider) {
    $locationProvider.html5Mode(false);
    return $routeProvider.when('/', {
      templateUrl: 'home.html'
    }).when('/demo/simple', {
      templateUrl: 'demo/simple.html'
    }).when('/demo/post', {
      templateUrl: 'demo/post.html'
    }).when('/demo/wizard', {
      templateUrl: 'demo/wizard.html'
    });
  });

  angular.module('app').directive('demo', function(networkService) {
    var l;
    l = function(scope) {
      scope.definition = networkService().getJSON(scope.url).then(function(def) {
        scope.form = def;
        return scope.jsonString = JSON.stringify(def, null, 2);
      });
      scope.showCode = function() {
        if ((scope.code != null) && scope.code.display === false) {
          return scope.code = {
            display: true,
            title: 'Hide Code'
          };
        } else {
          return scope.code = {
            display: false,
            title: 'Show Code'
          };
        }
      };
      return scope.showCode();
    };
    return {
      restrict: 'E',
      scope: {
        url: '@',
        name: '@'
      },
      templateUrl: 'demo.html',
      link: l,
      replace: true,
      transclude: true
    };
  });

}).call(this);
<commit_msg>recompiled<commit_after>// Generated by CoffeeScript 1.6.3
(function() {
  angular.module('app', ['CoolForm', 'CoolFormServices', 'ngRoute'], function($routeProvider, $locationProvider) {
    $locationProvider.html5Mode(false);
    return $routeProvider.when('/', {
      templateUrl: 'home.html'
    }).when('/demo/simple', {
      templateUrl: 'demo/simple.html'
    }).when('/demo/post', {
      templateUrl: 'demo/post.html'
    }).when('/demo/wizard', {
      templateUrl: 'demo/wizard.html'
    }).when('/demo/show', {
      templateUrl: 'demo/show.html'
    });
  });

  angular.module('app').directive('demo', function(networkService) {
    var l;
    l = function(scope) {
      scope.definition = networkService().getJSON(scope.url).then(function(def) {
        scope.form = def;
        return scope.jsonString = JSON.stringify(def, null, 2);
      });
      scope.showCode = function() {
        if ((scope.code != null) && scope.code.display === false) {
          return scope.code = {
            display: true,
            title: 'Hide Code'
          };
        } else {
          return scope.code = {
            display: false,
            title: 'Show Code'
          };
        }
      };
      return scope.showCode();
    };
    return {
      restrict: 'E',
      scope: {
        url: '@',
        name: '@'
      },
      templateUrl: 'demo.html',
      link: l,
      replace: true,
      transclude: true
    };
  });

}).call(this);
<|endoftext|>