<commit_before>/**
 * Created by Mihail on 9/24/2016.
 */

/*
 var Ball = function (point, vector) {
 if (!vector || vector.isZero()) {
 this.vector = Point.random() * 5;
 } else {
 this.vector = vector * 2;
 }

 this.point = point;
 this.dampen = 0.4;
 this.gravity = 3;
 this.bounce = -0.6;

 var color = {
 hue: Math.random() * 360,
 saturation: 1,
 brightness: 1
 };

 var gradient = new Gradient([color, 'black'], true);
 var radius = this.radius = 15;

 var ball = new Group({
 children: [
 new Path.Circle({
 radius: radius
 })
 ],
 fillColor: new Color(gradient, 0, radius, radius / 8)
 });

 var txt = new PointText(this.center);
 txt.style = {
 justification: 'center',
 fontWeight: 'bold',
 fillColor: 'white'
 };

 // Generate random random from 1 to 75 to attach it to a ball
 txt.content = Math.floor(Math.random() * (75)) + 1;

 ball.addChild(txt);

 this.item = new Group({
 children: [ball],
 transformContent: false,
 position: this.point
 });
 };

 Ball.prototype.iterate = function () {
 var size = view.size;
 this.vector.y += this.gravity;
 this.vector.x *= 0.99;
 var pre = this.point + this.vector;

 if (pre.x < this.radius || pre.x > size.width - this.radius)
 this.vector.x *= -this.dampen / 2;
 if (pre.y < this.radius || pre.y > size.height - this.radius) {
 if (Math.abs(this.vector.x) < 3)
 this.vector = Point.random() * [150, 100] + [-75, 20];
 this.vector.y *= this.bounce / 2;
 }

 var max = Point.max(this.radius, this.point + this.vector);
 this.item.position = this.point = Point.min(max, size - this.radius);
 this.item.rotate(this.vector.x);
 };

 Ball.prototype.putBallsOnBottom = function () {
 var size = view.size;
 this.vector.y += this.gravity;
 this.vector.x *= 0.99;
 var pre = this.point + this.vector;
 if (pre.x < this.radius || pre.x > size.width - this.radius)
 this.vector.x *= -this.dampen;
 if (pre.y < this.radius || pre.y > size.height - this.radius) {
 if (Math.abs(this.vector.x) < .3)
 this.vector = Point.random() * [150, 100] + [-75, 20];
 this.vector.y *= this.bounce;
 }

 var max = Point.max(this.radius, this.point + this.vector);
 this.item.position = this.point = Point.min(max, size - this.radius);
 this.item.rotate(this.vector.x);
 };

 var balls = [];
 for (var i = 0; i < 75; i++) {
 var position = {
 x: Math.random() * (view.size.width - 1) + 1,
 y: Math.random() * (330 - 300) + 300
 },
 vector = (Point.random() - [0.5, 0]) * [50, 100],
 ball = new Ball(position, vector);

 balls.push(ball);
 }

 var init = {
 play: false,
 isPlaying: false
 };

 function startAnimation() {
 for (var i = 0, l= balls.length; i < l; i++) {
 balls[i].point = Point.random() * view.size;
 }
 init.play = true;
 init.isPlaying = true;
 }

 function stopAnimation() {
 init.play = false;

 setTimeout(function () {
 init.isPlaying = false;
 }, 2000);
 }

 function onMouseUp(event) {
 if (!init.play) {
 startAnimation();
 } else {
 stopAnimation();
 }
 }

 function onFrame() {
 for (var i = 0, l = balls.length; i < l; i++) {
 if (init.play) {
 balls[i].iterate();
 } else if (init.play === false && init.isPlaying === true) {
 balls[i].putBallsOnBottom();
 }
 }
 }
 */

'use strict';

import { paper } from '../../node_modules/paper/dist/paper-full';

class Ball {
	constructor(point, vector) {
		this.vector = null;
		this.point = null;

		if (!vector || vector.isZero()) {
			//this.vector = paper.Point.random() * 5;
			this.vector = new paper.Point(Math.random() * 5, Math.random() * 5);
		} else {
			this.vector = vector * 2;
		}

		console.log('>>> vector: ', vector);

		this.point = point;
		this.dampen = 0.4;
		this.gravity = 3;
		this.bounce = -0.6;

		var color = {
			hue: Math.random() * 360,
			saturation: 1,
			brightness: 1
		};

		var gradient = new paper.Gradient([color, 'black'], true);
		var radius = this.radius = 15;

		var ball = new paper.CompoundPath({
			children: [
				new paper.Path.Circle({
					radius: radius
				})
			],
			fillColor: new paper.Color(gradient, 0, radius, radius / 8)
		});

		var txt = new paper.PointText(this.center);
		txt.style = {
			justification: 'center',
			fontWeight: 'bold',
			fillColor: 'white'
		};

		// Generate random random from 1 to 75 to attach it to a ball
		txt.content = Math.floor(Math.random() * (75)) + 1;

		ball.addChild(txt);

		this.item = new paper.Group({
			children: [ball],
			transformContent: false,
			position: this.point
		});
	}

	iterate() {
		var size = paper.view.size;
		this.vector.y += this.gravity;
		this.vector.x *= 0.99;
		//var pre = this.point + this.vector;
		var pre = {
			x: this.point.x + this.vector.x,
			y: this.point.y + this.vector.y
		};

		console.log('>>>> ', pre);

		if (pre.x < this.radius || pre.x > size.width - this.radius)
			this.vector.x *= -this.dampen / 2;

		if (pre.y < this.radius || pre.y > size.height - this.radius) {
			if (Math.abs(this.vector.x) < 3)
				// this.vector = paper.Point.random() * [150, 100] + [-75, 20];
				this.vector = paper.Point(Math.random() * 150,  Math.random() * 20);
			this.vector.y *= this.bounce / 2;
		}

		var max = paper.Point.max(this.radius, this.point + this.vector);

		console.log('>>> this.item.position: ', this.item.position);

		this.item.position = this.point = paper.Point.min(max, size - this.radius);

		this.item.rotate(this.vector.x);
	}

	putBallsOnBottom() {
		var size = paper.view.size;
		this.vector.y += this.gravity;
		this.vector.x *= 0.99;
		var pre = this.point + this.vector;

		if (pre.x < this.radius || pre.x > size.width - this.radius)
			this.vector.x *= -this.dampen;

		if (pre.y < this.radius || pre.y > size.height - this.radius) {
			if (Math.abs(this.vector.x) < .3)
				this.vector = Point.random() * [150, 100] + [-75, 20];
			this.vector.y *= this.bounce;
		}

		var max = Point.max(this.radius, this.point + this.vector);
		this.item.position = this.point = Point.min(max, size - this.radius);
		this.item.rotate(this.vector.x);
	}
}

class Blower {
	constructor() {
		this.balls = [];
		var canvas = document.getElementById('blower');
		if (canvas) {
			paper.setup(canvas);
		} else {
			throw new Error('There is no canvas element to draw the blower in.');
		}

		/*var canvas = document.getElementById('blower');
		 paper.setup(canvas);
		 paper.view.draw();*/

		for (var i = 0; i < 75; i++) {
			var position = {
					x: Math.random() * (paper.view.size.width - 1) + 1,
					y: Math.random() * paper.view.size.width
				},
				// vector = (paper.Point.random() - [0.5, 0]) * [50, 100],
				vector = new paper.Point((Math.random() - 0.5) * 50, Math.random() * 100),
				ball = new Ball(position, vector);

			this.balls.push(ball);
		}

		this.init = {
			play: false,
			isPlaying: false
		};

		paper.view.onFrame = (event) => {
			for (var i = 0, l = this.balls.length; i < l; i++) {
				if (this.init.play) {
					this.balls[i].iterate();
				} else if (this.init.play === false && this.init.isPlaying === true) {
					this.balls[i].putBallsOnBottom();
				}
			}
		};
	}

	startAnimation() {
		console.log('>>> Start');
		for (var i = 0, l = this.balls.length; i < l; i++) {
			//this.balls[i].point = paper.Point.random() * paper.view.size;
			this.balls[i].point = paper.Point(Math.random() * paper.view.size.width,
				Math.random() * paper.view.size.height);
		}
		this.init.play = true;
		this.init.isPlaying = true;
	}

	stopAnimation() {
		this.init.play = false;

		setTimeout(function () {
			this.init.isPlaying = false;
		}, 2000);
	}

	/*onMouseUp(event) {
		if (!this.init.play) {
			this.startAnimation();
		} else {
			this.stopAnimation();
		}
	}*/
}

export default Blower;<commit_msg>Convert blower.js to ES6 class  - work in progress.<commit_after>/**
 * Created by Mihail on 9/24/2016.
 */

/*
 var Ball = function (point, vector) {
 if (!vector || vector.isZero()) {
 this.vector = Point.random() * 5;
 } else {
 this.vector = vector * 2;
 }

 this.point = point;
 this.dampen = 0.4;
 this.gravity = 3;
 this.bounce = -0.6;

 var color = {
 hue: Math.random() * 360,
 saturation: 1,
 brightness: 1
 };

 var gradient = new Gradient([color, 'black'], true);
 var radius = this.radius = 15;

 var ball = new Group({
 children: [
 new Path.Circle({
 radius: radius
 })
 ],
 fillColor: new Color(gradient, 0, radius, radius / 8)
 });

 var txt = new PointText(this.center);
 txt.style = {
 justification: 'center',
 fontWeight: 'bold',
 fillColor: 'white'
 };

 // Generate random random from 1 to 75 to attach it to a ball
 txt.content = Math.floor(Math.random() * (75)) + 1;

 ball.addChild(txt);

 this.item = new Group({
 children: [ball],
 transformContent: false,
 position: this.point
 });
 };

 Ball.prototype.iterate = function () {
 var size = view.size;
 this.vector.y += this.gravity;
 this.vector.x *= 0.99;
 var pre = this.point + this.vector;

 if (pre.x < this.radius || pre.x > size.width - this.radius)
 this.vector.x *= -this.dampen / 2;
 if (pre.y < this.radius || pre.y > size.height - this.radius) {
 if (Math.abs(this.vector.x) < 3)
 this.vector = Point.random() * [150, 100] + [-75, 20];
 this.vector.y *= this.bounce / 2;
 }

 var max = Point.max(this.radius, this.point + this.vector);
 this.item.position = this.point = Point.min(max, size - this.radius);
 this.item.rotate(this.vector.x);
 };

 Ball.prototype.putBallsOnBottom = function () {
 var size = view.size;
 this.vector.y += this.gravity;
 this.vector.x *= 0.99;
 var pre = this.point + this.vector;
 if (pre.x < this.radius || pre.x > size.width - this.radius)
 this.vector.x *= -this.dampen;
 if (pre.y < this.radius || pre.y > size.height - this.radius) {
 if (Math.abs(this.vector.x) < .3)
 this.vector = Point.random() * [150, 100] + [-75, 20];
 this.vector.y *= this.bounce;
 }

 var max = Point.max(this.radius, this.point + this.vector);
 this.item.position = this.point = Point.min(max, size - this.radius);
 this.item.rotate(this.vector.x);
 };

 var balls = [];
 for (var i = 0; i < 75; i++) {
 var position = {
 x: Math.random() * (view.size.width - 1) + 1,
 y: Math.random() * (330 - 300) + 300
 },
 vector = (Point.random() - [0.5, 0]) * [50, 100],
 ball = new Ball(position, vector);

 balls.push(ball);
 }

 var init = {
 play: false,
 isPlaying: false
 };

 function startAnimation() {
 for (var i = 0, l= balls.length; i < l; i++) {
 balls[i].point = Point.random() * view.size;
 }
 init.play = true;
 init.isPlaying = true;
 }

 function stopAnimation() {
 init.play = false;

 setTimeout(function () {
 init.isPlaying = false;
 }, 2000);
 }

 function onMouseUp(event) {
 if (!init.play) {
 startAnimation();
 } else {
 stopAnimation();
 }
 }

 function onFrame() {
 for (var i = 0, l = balls.length; i < l; i++) {
 if (init.play) {
 balls[i].iterate();
 } else if (init.play === false && init.isPlaying === true) {
 balls[i].putBallsOnBottom();
 }
 }
 }
 */

'use strict';

import { paper } from '../../node_modules/paper/dist/paper-full';

class Ball {
	constructor(point, vector) {
		if (!vector || vector.isZero()) {
			//this.vector = paper.Point.random() * 5;
			this.vector = { x: Math.random() * 5, y: Math.random() * 5 };
		} else {
			//this.vector = vector * 2;
			this.vector = { x: vector.x * 2, y: vector.y * 2};
		}

		this.point = point;
		this.dampen = 0.4;
		this.gravity = 3;
		this.bounce = -0.6;

		var color = {
			hue: Math.random() * 360,
			saturation: 1,
			brightness: 1
		};

		var gradient = new paper.Gradient([color, 'black'], true);
		var radius = this.radius = 15;

		var ball = new paper.CompoundPath({
			children: [
				new paper.Path.Circle({
					radius: radius
				})
			],
			fillColor: new paper.Color(gradient, 0, radius, radius / 8)
		});

		var txt = new paper.PointText(this.center);
		txt.style = {
			justification: 'center',
			fontWeight: 'bold',
			fillColor: 'white'
		};

		// Generate random random from 1 to 75 to attach it to a ball
		txt.content = Math.floor(Math.random() * (75)) + 1;

		ball.addChild(txt);

		this.item = new paper.Group({
			children: [ball],
			transformContent: false,
			position: this.point
		});

		//console.log('>>> this.point: ', this.point);
	}

	iterate() {

		//console.log('>>>> this.point: ', this.point);

		var size = paper.view.size;
		this.vector.y += this.gravity;
		this.vector.x *= 0.99;
		//var pre = this.point + this.vector;
		var pre = {
			x: this.point.x + this.vector.x,
			y: this.point.y + this.vector.y
		};

		if (pre.x < this.radius || pre.x > size.width - this.radius)
			this.vector.x *= -this.dampen / 2;

		if (pre.y < this.radius || pre.y > size.height - this.radius) {
			if (Math.abs(this.vector.x) < 3)
				// this.vector = paper.Point.random() * [150, 100] + [-75, 20];
				this.vector = paper.Point(Math.random() * 150,  Math.random() * 20);
			this.vector.y *= this.bounce / 2;
		}

		var max = paper.Point.max(this.radius, this.point + this.vector);

		//console.log('>>> this.item.position: ', this.item.position);

		this.item.position = this.point = paper.Point.min(max, size - this.radius);

		this.item.rotate(this.vector.x);
	}

	putBallsOnBottom() {
		var size = paper.view.size;
		this.vector.y += this.gravity;
		this.vector.x *= 0.99;
		var pre = this.point + this.vector;

		if (pre.x < this.radius || pre.x > size.width - this.radius)
			this.vector.x *= -this.dampen;

		if (pre.y < this.radius || pre.y > size.height - this.radius) {
			if (Math.abs(this.vector.x) < .3)
				this.vector = Point.random() * [150, 100] + [-75, 20];
			this.vector.y *= this.bounce;
		}

		var max = Point.max(this.radius, this.point + this.vector);
		this.item.position = this.point = Point.min(max, size - this.radius);
		this.item.rotate(this.vector.x);
	}
}

class Blower {
	constructor() {
		this.balls = [];
		var canvas = document.getElementById('blower');
		if (canvas) {
			paper.setup(canvas);
		} else {
			throw new Error('There is no canvas element to draw the blower in.');
		}

		 //paper.view.draw();

		for (var i = 0; i < 75; i++) {
			var position = {
					x: Math.random() * (paper.view.size.width - 1) + 1,
					y: Math.random() * (paper.view.size.height - 300) + 300
				},
				// vector = (paper.Point.random() - [0.5, 0]) * [50, 100],
				vector = new paper.Point((Math.random() - 0.5) * 50, Math.random() * 100),
				ball = new Ball(position, vector);

			this.balls.push(ball);
		}

		this.init = {
			play: false,
			isPlaying: false
		};

		paper.view.onFrame = (event) => {
			for (var i = 0, l = this.balls.length; i < l; i++) {
				if (this.init.play) {
					this.balls[i].iterate();
				} else if (this.init.play === false && this.init.isPlaying === true) {
					this.balls[i].putBallsOnBottom();
				}
			}
		};
	}

	startAnimation() {
		console.log('>>> Start');
		for (var i = 0, l = this.balls.length; i < l; i++) {
			//this.balls[i].point = paper.Point.random() * paper.view.size;
			this.balls[i].point = new paper.Point(Math.random() * paper.view.size.width,
				Math.random() * paper.view.size.height);
		}
		//console.log(this.balls);
		this.init.play = true;
		this.init.isPlaying = true;
	}

	stopAnimation() {
		this.init.play = false;

		setTimeout(function () {
			this.init.isPlaying = false;
		}, 2000);
	}

	/*onMouseUp(event) {
		if (!this.init.play) {
			this.startAnimation();
		} else {
			this.stopAnimation();
		}
	}*/
}

export default Blower;<|endoftext|>


<commit_before>import {pretty, p, pp} from '../universal/base';

function isInlineScriptError(err) {
  return !!(
    err.sourceURL &&
    err.sourceURL === window.location.href
  );
}

function isTranspiledScriptError(err) {
  return !!(
    err.stack &&
    err.stack.match(/\nrun([^\n])+babel/m)
  );
}

function inlineScripts() {
  return Array.from(document.scripts).
    filter(script => !script.getAttribute('src')).
    map(script => ({
      source: script.textContent,
      sourceMap: null,
      originalErrorInfo: null
    }));
}

function transpiledInlineScripts(_inlineScripts) {
  return _inlineScripts.
    map(scriptInfo => {
      scriptInfo.sourceMap = embeddedSourceMap(
        sourceMappingURL(scriptInfo.source)
      );

      return scriptInfo;
    }).
    filter(scriptInfo => !!scriptInfo.sourceMap);
}

async function transpiledInlineScriptsWithOriginalErrorInfoAsync(
  _transpiledInlineScripts,
  err
) {
  return Promise.all(
    _transpiledInlineScripts.
      map(async scriptInfo => {
        scriptInfo.originalErrorInfo = await originalErrorInfoAsync(
          scriptInfo.sourceMap, err
        );

        return scriptInfo;
      })
  );
}

async function transpiledInlineScriptsSourceTracesAsync(err) {
  let scripts = transpiledInlineScripts(inlineScripts());

  try {
    return (await transpiledInlineScriptsWithOriginalErrorInfoAsync(
      scripts,
      err
    )).
      map(scriptInfo => sourceTrace(
        ...sourceTraceArgs(scriptInfo.originalErrorInfo)
      ));
  } catch (err1) {
    return scripts.
      map((scriptInfo, i) => sourceTrace(
        scriptInfo.source,
        `Transpiled inline script #${i + 1}`,
        err.line,
        err.column
      ));
  }
}

async function errorSourceAsync(err) {
  return new Promise(async (resolve, reject) => {
    if (!err.sourceURL) {
      return reject(Error('sourceURL unavailable'));
    }

    let url = err.sourceURL;

    try {
      let res = await fetch(url);

      if (!res.ok) {
        return reject(Error(`${res.status} (${res.statusText}) ${url}`));
      }

      resolve(await res.text());
    } catch (err) {
      reject(Error(`Cannot retrieve ${url}`));
    }
  });
}

function sourceMappingURL(source) {
  let reSourceMappingURL =
    /\/\/# sourceMappingURL=(.+)\s*$/m;

  return (source.match(reSourceMappingURL) || [])[1];
}

function embeddedSourceMap(_sourceMappingURL) {
  let reEmbeddedSourceMap =
    /^data:application\/json;(charset=[^;]+;)?base64,(.*)$/;
  let base64 = ((_sourceMappingURL || '').match(reEmbeddedSourceMap) || [])[2];

  return (base64) ? JSON.parse(atob(base64)) : null;
}

function originalErrorInfoAsync(_sourceMap, err) {
  const {SourceMapConsumer} = sourceMap;

  return SourceMapConsumer.with(_sourceMap, null, consumer => {
    let position = consumer.originalPositionFor({
      line: err.line || 1,
      // The sourceMap lib expects 0-based columns
      column: (err.column || 1) - 1
    }) || {};
    let source = consumer.sourceContentFor(position.source, true) || '';

    return {
      position,
      source
    };
  });
}

function sourceTraceArgs(_originalErrorInfo) {
  let {source, position} = _originalErrorInfo;

  return [
    source,
    position.source || '',
    position.line || 1,
    // The sourceTrace func expects 1-based columns
    // position.name is the erroneous token
    // Place the error marker after it for consistency with runtime errors
    (position.column || 0) + 1 + (position.name || '').length
  ];
}

function sourceTrace(source, location, line1, column1, {
  indent = '',
  peekLines = 2
} = {}) {
  let lines = (source || '').split('\n');
  let [, path = 'path n/a', name = 'code'] = (location || '').
    match(/^(.+\/)?([^\/]+)$/) || [];
  let iLine = (line1 || 1) - 1;
  let iColumn = (column1 || 1) - 1;
  let traceLines = [];
  let iTraceLineMax = Math.max(0, lines.length - 1);
  let iTraceLineBeg = Math.max(0, iLine - peekLines);
  let iTraceLineEnd = Math.min(iTraceLineMax, iLine + peekLines);
  let padMax = `${lines.length}`.length;
  let margin = '|';
  let linePointer = '>';
  let columnPointer = `${' '.repeat(iColumn)}^`;

  for (let i = iTraceLineBeg; i <= iTraceLineEnd; i++) {
    let pad = ' '.repeat(padMax - `${i + 1}`.length);
    let lineMarker = (i == iLine) ?
      linePointer :
      ' '.repeat(linePointer.length);
    let columnMarker = (i == iLine) ?
      `\n${indent}${' '.repeat(lineMarker.length + padMax)}${margin}${columnPointer}` :
      '';

    traceLines.push(`${indent}${lineMarker}${pad}${i + 1}${margin}${lines[i]}${columnMarker}`);
  }

  return `${indent}${name}:${line1}:${column1} (${path})\n${traceLines.join('\n')}`;
}

async function _formatErrorAsync(err) {
  let info;

  try {
    if (isInlineScriptError(err) && isTranspiledScriptError(err)) {
      info = (await transpiledInlineScriptsSourceTracesAsync(err)).
        join('\n');
    } else {
      info = sourceTrace(await errorSourceAsync(err),
        err.sourceURL, err.line, err.column);
    }
  } catch (err1) {
    err.sourceTraceNA = `${err1}`;

    info = pretty(err);
  }

  return `${info}\nstack:\n  ${
    (err &&
      err.stack &&
      err.stack.replace(/\n/gm, '\n  ')
    ) || 'n/a'
  }`;
}

function _reportError(err, note = 'error') {
  _formatErrorAsync(err).then(str => {
    p(str,
      `(${note}) ${err}`,
      {level: 'error'});
  });
}

export {
  _formatErrorAsync,
  _reportError
};
export default _reportError;
<commit_msg>Warn about missing/incomplete (not initialized) sourceMap library support<commit_after>import {pretty, p, pp} from '../universal/base';

function isInlineScriptError(err) {
  return !!(
    err.sourceURL &&
    err.sourceURL === window.location.href
  );
}

function isTranspiledScriptError(err) {
  return !!(
    err.stack &&
    err.stack.match(/\nrun([^\n])+babel/m)
  );
}

function inlineScripts() {
  return Array.from(document.scripts).
    filter(script => !script.getAttribute('src')).
    map(script => ({
      source: script.textContent,
      sourceMap: null,
      originalErrorInfo: null
    }));
}

function transpiledInlineScripts(_inlineScripts) {
  return _inlineScripts.
    map(scriptInfo => {
      scriptInfo.sourceMap = embeddedSourceMap(
        sourceMappingURL(scriptInfo.source)
      );

      return scriptInfo;
    }).
    filter(scriptInfo => !!scriptInfo.sourceMap);
}

async function transpiledInlineScriptsWithOriginalErrorInfoAsync(
  _transpiledInlineScripts,
  err
) {
  return Promise.all(
    _transpiledInlineScripts.
      map(async scriptInfo => {
        scriptInfo.originalErrorInfo = await originalErrorInfoAsync(
          scriptInfo.sourceMap, err
        );

        return scriptInfo;
      })
  );
}

async function transpiledInlineScriptsSourceTracesAsync(err) {
  let scripts = transpiledInlineScripts(inlineScripts());

  try {
    return (await transpiledInlineScriptsWithOriginalErrorInfoAsync(
      scripts,
      err
    )).
      map(scriptInfo => sourceTrace(
        ...sourceTraceArgs(scriptInfo.originalErrorInfo)
      ));
  } catch (err1) {
    console.warn(`sourceMap library support missing/incomplete\n${err1}`);

    return scripts.
      map((scriptInfo, i) => sourceTrace(
        scriptInfo.source,
        `Transpiled inline script #${i + 1}`,
        err.line,
        err.column
      ));
  }
}

async function errorSourceAsync(err) {
  return new Promise(async (resolve, reject) => {
    if (!err.sourceURL) {
      return reject(Error('sourceURL unavailable'));
    }

    let url = err.sourceURL;

    try {
      let res = await fetch(url);

      if (!res.ok) {
        return reject(Error(`${res.status} (${res.statusText}) ${url}`));
      }

      resolve(await res.text());
    } catch (err) {
      reject(Error(`Cannot retrieve ${url}`));
    }
  });
}

function sourceMappingURL(source) {
  let reSourceMappingURL =
    /\/\/# sourceMappingURL=(.+)\s*$/m;

  return (source.match(reSourceMappingURL) || [])[1];
}

function embeddedSourceMap(_sourceMappingURL) {
  let reEmbeddedSourceMap =
    /^data:application\/json;(charset=[^;]+;)?base64,(.*)$/;
  let base64 = ((_sourceMappingURL || '').match(reEmbeddedSourceMap) || [])[2];

  return (base64) ? JSON.parse(atob(base64)) : null;
}

function originalErrorInfoAsync(_sourceMap, err) {
  const {SourceMapConsumer} = sourceMap;

  return SourceMapConsumer.with(_sourceMap, null, consumer => {
    let position = consumer.originalPositionFor({
      line: err.line || 1,
      // The sourceMap lib expects 0-based columns
      column: (err.column || 1) - 1
    }) || {};
    let source = consumer.sourceContentFor(position.source, true) || '';

    return {
      position,
      source
    };
  });
}

function sourceTraceArgs(_originalErrorInfo) {
  let {source, position} = _originalErrorInfo;

  return [
    source,
    position.source || '',
    position.line || 1,
    // The sourceTrace func expects 1-based columns
    // position.name is the erroneous token
    // Place the error marker after it for consistency with runtime errors
    (position.column || 0) + 1 + (position.name || '').length
  ];
}

function sourceTrace(source, location, line1, column1, {
  indent = '',
  peekLines = 2
} = {}) {
  let lines = (source || '').split('\n');
  let [, path = 'path n/a', name = 'code'] = (location || '').
    match(/^(.+\/)?([^\/]+)$/) || [];
  let iLine = (line1 || 1) - 1;
  let iColumn = (column1 || 1) - 1;
  let traceLines = [];
  let iTraceLineMax = Math.max(0, lines.length - 1);
  let iTraceLineBeg = Math.max(0, iLine - peekLines);
  let iTraceLineEnd = Math.min(iTraceLineMax, iLine + peekLines);
  let padMax = `${lines.length}`.length;
  let margin = '|';
  let linePointer = '>';
  let columnPointer = `${' '.repeat(iColumn)}^`;

  for (let i = iTraceLineBeg; i <= iTraceLineEnd; i++) {
    let pad = ' '.repeat(padMax - `${i + 1}`.length);
    let lineMarker = (i == iLine) ?
      linePointer :
      ' '.repeat(linePointer.length);
    let columnMarker = (i == iLine) ?
      `\n${indent}${' '.repeat(lineMarker.length + padMax)}${margin}${columnPointer}` :
      '';

    traceLines.push(`${indent}${lineMarker}${pad}${i + 1}${margin}${lines[i]}${columnMarker}`);
  }

  return `${indent}${name}:${line1}:${column1} (${path})\n${traceLines.join('\n')}`;
}

async function _formatErrorAsync(err) {
  let info;

  try {
    if (isInlineScriptError(err) && isTranspiledScriptError(err)) {
      info = (await transpiledInlineScriptsSourceTracesAsync(err)).
        join('\n');
    } else {
      info = sourceTrace(await errorSourceAsync(err),
        err.sourceURL, err.line, err.column);
    }
  } catch (err1) {
    err.sourceTraceNA = `${err1}`;

    info = pretty(err);
  }

  return `${info}\nstack:\n  ${
    (err &&
      err.stack &&
      err.stack.replace(/\n/gm, '\n  ')
    ) || 'n/a'
  }`;
}

function _reportError(err, note = 'error') {
  _formatErrorAsync(err).then(str => {
    p(str,
      `(${note}) ${err}`,
      {level: 'error'});
  });
}

export {
  _formatErrorAsync,
  _reportError
};
export default _reportError;
<|endoftext|>


<commit_before>var Reflux = require('reflux');
var socket = require('./websocket');

// TODO MOVE TO TESTS!!!
if (process && !process.browser) {
  window = {};
  window.localStorage = { getItem: function () {}, setItem: function () {} };
}

var actions = Reflux.createActions({
    'join': {}, // Joining a game/room
    'chat': {},  // New chat-message
    'canvas': { children: [ 'crayon', 'point', 'clear' ] }
});

var store = Reflux.createStore({
  listenables: actions,

  init: function () {
    // Init canvas
    this.crayon = {
      color: window.localStorage.getItem('crayonColor') || 'red',
      size: +window.localStorage.getItem('crayonSize') || 5
    };
    this.points = [];
    socket.on('canvas', this.handlePointFromServer);
    socket.on('your turn', this.handleYourRound);
    socket.on('new round', this.handleNewRound);

    // Init websocket
    this.ready = false;

    socket.on('connect', this.handleConnect);
    socket.on('player', this.handlePlayer);
    socket.on('join', this.handleJoin);
    socket.on('disconnect', this.handleDisconnect);
    socket.on('error', function (err) { console.log('Socket.io-client ERROR: ', err); });

    socket.on('player joined', this.handlePlayerJoined);
    socket.on('player left', this.handlePlayerLeft);
    socket.on('chat', this.handleChat);
  },

  handleConnect: function () {
    this.ready = true;
    this.trigger({ event: 'connection', type: 'connected' });
  },

  handleDisconnect: function () {
    this.ready = false;
    this.trigger({ event: 'connection', type: 'disconnected' });
  },

  handlePlayer: function (data) {
    this.player = data;
    this.trigger({ event: 'player', type: 'update', data: data });
  },

  handleJoin: function (data) {
    this.room = data.data;
    this.trigger({ event: 'join', type: 'game', data: data.data });
    // Draw each point to the canvas
    data.points.forEach(this.handlePointFromServer);
  },

  handlePlayerJoined: function (data) {
    this.trigger({ event: 'otherPlayer', type: 'joined', data: data });
  },

  handlePlayerLeft: function (data) {
    this.trigger({ event: 'otherPlayer', type: 'left', data: data.player });
  },

  handleChat: function (data) {
    data.me = typeof data.player === 'undefined';
    if (typeof data.player === 'undefined') { data.player = this.player; }
    this.trigger({ event: 'chat', type: 'message', data: data });
  },

  onJoin: function (roomId) {
    socket.emit('join', { roomId: roomId });
  },

  // TODO Should probably save the messages when offline, to send them when
  // connected to socket.io
  onChat: function (message) {
    // TODO Do i need to send uuid, or do the server know how is sending the
    // message?
    socket.emit('chat', { player: this.player, message: message });
    this.handleChat({ message: message });
  },

  onSelectCrayon: function (crayon) {
    if (crayon.color) {
      this.crayon.color = crayon.color;
      window.localStorage.setItem('crayonColor', crayon.color);
    }

    if (crayon.size) {
      this.crayon.size = crayon.size;
      window.localStorage.setItem('crayonSize', crayon.size);
    }

    this.trigger({ event: 'crayon', type: 'update', data: this.crayon });
  },

  /*!
   * CANVAS
   */

  _addPoint: function (x, y, dragging, size, color) {
    if (typeof size === 'undefined') { size = this.crayon.size; }
    if (typeof color === 'undefined') { color = this.crayon.color; }

    var p = { x: x, y: y, color: color, size: size, dragging: !!dragging };
    this.points.push(p);

    this._triggerCanvas('point', {
      nrOfPoints: this.points.length,
      last: this._lastPoint
    });

    return p;
  },

  _lastPoint: function (fn) {
    fn(this.points[this.points.length - 2], this.points[this.points.length - 1]);
  },

  handlePointFromServer: function (point) {
    this._addPoint(point.x, point.y, point.dragging, point.size, point.color);
  },

  _triggerCanvas: function (type, data) {
    this.trigger({ event: 'canvas', type: type, data: data });
  },

  onCanvasCrayon: function (crayon) {
    if (crayon.color) {
      this.crayon.color = crayon.color;
      window.localStorage.setItem('crayonColor', crayon.color);
    }

    if (crayon.size) {
      this.crayon.size = crayon.size;
      window.localStorage.setItem('crayonSize', crayon.size);
    }

    this._triggerCanvas('crayon', this.crayon);
  },

  onCanvasPoint: function (x, y, dragging) {
    socket.emit('canvas', this._addPoint(x, y, dragging));
    //addArray: forEach.bind(null, add),
  },

  onCanvasClear: function (player) {
    this.points = [];
    this._triggerCanvas('clear', { playersTurn: player.UUID === this.player.UUID });
  },

  handleYourRound: function (word) {
    console.log('Your turn:', word);
    this._triggerCanvas('start', word);
  },

  handleNewRound: function (player) {
    actions.canvas.clear(player);
    console.log('This players turn:', player);
  }
});

module.exports = { actions: actions, store: store };
<commit_msg>Move functions around<commit_after>var Reflux = require('reflux');
var socket = require('./websocket');

// TODO MOVE TO TESTS!!!
if (process && !process.browser) {
  window = {};
  window.localStorage = { getItem: function () {}, setItem: function () {} };
}

var actions = Reflux.createActions({
    'join': {}, // Joining a game/room
    'chat': {},  // New chat-message
    'canvas': { children: [ 'crayon', 'point', 'clear' ] }
});

var store = Reflux.createStore({
  listenables: actions,

  init: function () {
    // Init canvas
    this.crayon = {
      color: window.localStorage.getItem('crayonColor') || 'red',
      size: +window.localStorage.getItem('crayonSize') || 5
    };
    this.points = [];
    socket.on('canvas', this.handlePointFromServer);
    socket.on('your turn', this.handleYourRound);
    socket.on('new round', this.handleNewRound);

    // Init websocket
    this.ready = false;

    socket.on('connect', this.handleConnect);
    socket.on('player', this.handlePlayer);
    socket.on('join', this.handleJoin);
    socket.on('disconnect', this.handleDisconnect);
    socket.on('error', function (err) { console.log('Socket.io-client ERROR: ', err); });

    socket.on('player joined', this.handlePlayerJoined);
    socket.on('player left', this.handlePlayerLeft);
    socket.on('chat', this.handleChat);
  },

  handleConnect: function () {
    this.ready = true;
    this.trigger({ event: 'connection', type: 'connected' });
  },

  handleDisconnect: function () {
    this.ready = false;
    this.trigger({ event: 'connection', type: 'disconnected' });
  },

  handlePlayer: function (data) {
    this.player = data;
    this.trigger({ event: 'player', type: 'update', data: data });
  },

  handleJoin: function (data) {
    this.room = data.data;
    this.trigger({ event: 'join', type: 'game', data: data.data });
    // Draw each point to the canvas
    data.points.forEach(this.handlePointFromServer);
  },

  handlePlayerJoined: function (data) {
    this.trigger({ event: 'otherPlayer', type: 'joined', data: data });
  },

  handlePlayerLeft: function (data) {
    this.trigger({ event: 'otherPlayer', type: 'left', data: data.player });
  },

  handleChat: function (data) {
    data.me = typeof data.player === 'undefined';
    if (typeof data.player === 'undefined') { data.player = this.player; }
    this.trigger({ event: 'chat', type: 'message', data: data });
  },

  onJoin: function (roomId) {
    socket.emit('join', { roomId: roomId });
  },

  // TODO Should probably save the messages when offline, to send them when
  // connected to socket.io
  onChat: function (message) {
    // TODO Do i need to send uuid, or do the server know how is sending the
    // message?
    socket.emit('chat', { player: this.player, message: message });
    this.handleChat({ message: message });
  },

  onSelectCrayon: function (crayon) {
    if (crayon.color) {
      this.crayon.color = crayon.color;
      window.localStorage.setItem('crayonColor', crayon.color);
    }

    if (crayon.size) {
      this.crayon.size = crayon.size;
      window.localStorage.setItem('crayonSize', crayon.size);
    }

    this.trigger({ event: 'crayon', type: 'update', data: this.crayon });
  },

  /*!
   * CANVAS
   */

  _addPoint: function (x, y, dragging, size, color) {
    if (typeof size === 'undefined') { size = this.crayon.size; }
    if (typeof color === 'undefined') { color = this.crayon.color; }

    var p = { x: x, y: y, color: color, size: size, dragging: !!dragging };
    this.points.push(p);

    this._triggerCanvas('point', {
      nrOfPoints: this.points.length,
      last: this._lastPoint
    });

    return p;
  },

  _lastPoint: function (fn) {
    fn(this.points[this.points.length - 2], this.points[this.points.length - 1]);
  },

  _triggerCanvas: function (type, data) {
    this.trigger({ event: 'canvas', type: type, data: data });
  },

  handlePointFromServer: function (point) {
    this._addPoint(point.x, point.y, point.dragging, point.size, point.color);
  },

  handleYourRound: function (word) {
    console.log('Your turn:', word);
    this._triggerCanvas('start', word);
  },

  handleNewRound: function (player) {
    actions.canvas.clear(player);
    console.log('This players turn:', player);
  },

  onCanvasCrayon: function (crayon) {
    if (crayon.color) {
      this.crayon.color = crayon.color;
      window.localStorage.setItem('crayonColor', crayon.color);
    }

    if (crayon.size) {
      this.crayon.size = crayon.size;
      window.localStorage.setItem('crayonSize', crayon.size);
    }

    this._triggerCanvas('crayon', this.crayon);
  },

  onCanvasPoint: function (x, y, dragging) {
    socket.emit('canvas', this._addPoint(x, y, dragging));
    //addArray: forEach.bind(null, add),
  },

  onCanvasClear: function (player) {
    this.points = [];
    this._triggerCanvas('clear', { playersTurn: player.UUID === this.player.UUID });
  }
});

module.exports = { actions: actions, store: store };
<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var stylesInDom = {},
	memoize = function(fn) {
		var memo;
		return function () {
			if (typeof memo === "undefined") memo = fn.apply(this, arguments);
			return memo;
		};
	},
	isIE9 = memoize(function() {
		return /msie 9\b/.test(window.navigator.userAgent.toLowerCase());
	}),
	getHeadElement = memoize(function () {
		return document.head || document.getElementsByTagName("head")[0];
	}),
	singletonElement = null,
	singletonCounter = 0;

module.exports = function(list, options) {
	if(typeof DEBUG !== "undefined" && DEBUG) {
		if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
	}

	options = options || {};
	// Force single-tag solution on IE9, which has a hard limit on the # of <style>
	// tags it will allow on a page
	if (typeof options.singleton === "undefined") options.singleton = isIE9();

	var styles = listToStyles(list);
	addStylesToDom(styles, options);

	return function update(newList) {
		var mayRemove = [];
		for(var i = 0; i < styles.length; i++) {
			var item = styles[i];
			var domStyle = stylesInDom[item.id];
			domStyle.refs--;
			mayRemove.push(domStyle);
		}
		if(newList) {
			var newStyles = listToStyles(newList);
			addStylesToDom(newStyles, options);
		}
		for(var i = 0; i < mayRemove.length; i++) {
			var domStyle = mayRemove[i];
			if(domStyle.refs === 0) {
				for(var j = 0; j < domStyle.parts.length; j++)
					domStyle.parts[j]();
				delete stylesInDom[domStyle.id];
			}
		}
	};
}

function addStylesToDom(styles, options) {
	for(var i = 0; i < styles.length; i++) {
		var item = styles[i];
		var domStyle = stylesInDom[item.id];
		if(domStyle) {
			domStyle.refs++;
			for(var j = 0; j < domStyle.parts.length; j++) {
				domStyle.parts[j](item.parts[j]);
			}
			for(; j < item.parts.length; j++) {
				domStyle.parts.push(addStyle(item.parts[j], options));
			}
		} else {
			var parts = [];
			for(var j = 0; j < item.parts.length; j++) {
				parts.push(addStyle(item.parts[j], options));
			}
			stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
		}
	}
}

function listToStyles(list) {
	var styles = [];
	var newStyles = {};
	for(var i = 0; i < list.length; i++) {
		var item = list[i];
		var id = item[0];
		var css = item[1];
		var media = item[2];
		// var sourceMap = item[3];
		var part = {css: css, media: media/*, sourceMap: sourceMap*/};
		if(!newStyles[id])
			styles.push(newStyles[id] = {id: id, parts: [part]});
		else
			newStyles[id].parts.push(part);
	}
	return styles;
}

function createStyleElement() {
	var styleElement = document.createElement("style");
	var head = getHeadElement();
	styleElement.type = "text/css";
	head.appendChild(styleElement);
	return styleElement;
}

function addStyle(obj, options) {
	var styleElement, update, remove;

	if (options.singleton) {
		var styleIndex = singletonCounter++;
		styleElement = singletonElement || (singletonElement = createStyleElement());
		update = applyToSingletonTag.bind(null, styleElement, styleIndex, false);
		remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true);
	} else {
		styleElement = createStyleElement();
		update = applyToTag.bind(null, styleElement);
		remove = function () {
			styleElement.parentNode.removeChild(styleElement);
		};
	}

	update(obj);

	return function updateStyle(newObj) {
		if(newObj) {
			if(newObj.css === obj.css && newObj.media === obj.media /*&& newObj.sourceMap === obj.sourceMap*/)
				return;
			update(obj = newObj);
		} else {
			remove();
		}
	};
}

function replaceText(source, id, replacement) {
	var boundaries = ['/** >>' + id + ' **/', '/** ' + id + '<< **/'];
	var start = source.lastIndexOf(boundaries[0]);
	var wrappedReplacement = boundaries[0] + replacement + boundaries[1];
	if (source.lastIndexOf(boundaries[0]) >= 0) {
		var end = source.lastIndexOf(boundaries[1]) + boundaries[1].length;
		return source.slice(0, start) + wrappedReplacement + source.slice(end);
	} else {
		return source + wrappedReplacement;
	}
}

function applyToSingletonTag(styleElement, index, remove, obj) {
	var css = remove ? '' : obj.css;

	if(styleElement.styleSheet) {
		styleElement.styleSheet.cssText = replaceText(styleElement.styleSheet.cssText, index, css);
	} else {
		var cssNode = document.createTextNode(css);
		var childNodes = styleElement.childNodes;
		if (childNodes[index]) styleElement.removeChild(childNodes[index]);
		if (childNodes.length) {
			styleElement.insertBefore(cssNode, childNodes[index]);
		} else {
			styleElement.appendChild(cssNode);
		}
	}
}

function applyToTag(styleElement, obj) {
	var css = obj.css;
	var media = obj.media;
	// var sourceMap = obj.sourceMap;
	// No browser support
	// if(sourceMap && typeof btoa === "function") {
		// try {
			// css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(JSON.stringify(sourceMap)) + " */";
		// } catch(e) {}
	// }

	if(media) {
		styleElement.setAttribute("media", media)
	}

	if(styleElement.styleSheet) {
		styleElement.styleSheet.cssText = css;
	} else {
		while(styleElement.firstChild) {
			styleElement.removeChild(styleElement.firstChild);
		}
		styleElement.appendChild(document.createTextNode(css));
	}
}
<commit_msg>Handle case of null/empty replacement<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var stylesInDom = {},
	memoize = function(fn) {
		var memo;
		return function () {
			if (typeof memo === "undefined") memo = fn.apply(this, arguments);
			return memo;
		};
	},
	isIE9 = memoize(function() {
		return /msie 9\b/.test(window.navigator.userAgent.toLowerCase());
	}),
	getHeadElement = memoize(function () {
		return document.head || document.getElementsByTagName("head")[0];
	}),
	singletonElement = null,
	singletonCounter = 0;

module.exports = function(list, options) {
	if(typeof DEBUG !== "undefined" && DEBUG) {
		if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
	}

	options = options || {};
	// Force single-tag solution on IE9, which has a hard limit on the # of <style>
	// tags it will allow on a page
	if (typeof options.singleton === "undefined") options.singleton = isIE9();

	var styles = listToStyles(list);
	addStylesToDom(styles, options);

	return function update(newList) {
		var mayRemove = [];
		for(var i = 0; i < styles.length; i++) {
			var item = styles[i];
			var domStyle = stylesInDom[item.id];
			domStyle.refs--;
			mayRemove.push(domStyle);
		}
		if(newList) {
			var newStyles = listToStyles(newList);
			addStylesToDom(newStyles, options);
		}
		for(var i = 0; i < mayRemove.length; i++) {
			var domStyle = mayRemove[i];
			if(domStyle.refs === 0) {
				for(var j = 0; j < domStyle.parts.length; j++)
					domStyle.parts[j]();
				delete stylesInDom[domStyle.id];
			}
		}
	};
}

function addStylesToDom(styles, options) {
	for(var i = 0; i < styles.length; i++) {
		var item = styles[i];
		var domStyle = stylesInDom[item.id];
		if(domStyle) {
			domStyle.refs++;
			for(var j = 0; j < domStyle.parts.length; j++) {
				domStyle.parts[j](item.parts[j]);
			}
			for(; j < item.parts.length; j++) {
				domStyle.parts.push(addStyle(item.parts[j], options));
			}
		} else {
			var parts = [];
			for(var j = 0; j < item.parts.length; j++) {
				parts.push(addStyle(item.parts[j], options));
			}
			stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
		}
	}
}

function listToStyles(list) {
	var styles = [];
	var newStyles = {};
	for(var i = 0; i < list.length; i++) {
		var item = list[i];
		var id = item[0];
		var css = item[1];
		var media = item[2];
		// var sourceMap = item[3];
		var part = {css: css, media: media/*, sourceMap: sourceMap*/};
		if(!newStyles[id])
			styles.push(newStyles[id] = {id: id, parts: [part]});
		else
			newStyles[id].parts.push(part);
	}
	return styles;
}

function createStyleElement() {
	var styleElement = document.createElement("style");
	var head = getHeadElement();
	styleElement.type = "text/css";
	head.appendChild(styleElement);
	return styleElement;
}

function addStyle(obj, options) {
	var styleElement, update, remove;

	if (options.singleton) {
		var styleIndex = singletonCounter++;
		styleElement = singletonElement || (singletonElement = createStyleElement());
		update = applyToSingletonTag.bind(null, styleElement, styleIndex, false);
		remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true);
	} else {
		styleElement = createStyleElement();
		update = applyToTag.bind(null, styleElement);
		remove = function () {
			styleElement.parentNode.removeChild(styleElement);
		};
	}

	update(obj);

	return function updateStyle(newObj) {
		if(newObj) {
			if(newObj.css === obj.css && newObj.media === obj.media /*&& newObj.sourceMap === obj.sourceMap*/)
				return;
			update(obj = newObj);
		} else {
			remove();
		}
	};
}

function replaceText(source, id, replacement) {
	var boundaries = ["/** >>" + id + " **/", "/** " + id + "<< **/"];
	var start = source.lastIndexOf(boundaries[0]);
	var wrappedReplacement = replacement
		? (boundaries[0] + replacement + boundaries[1])
		: "";
	if (source.lastIndexOf(boundaries[0]) >= 0) {
		var end = source.lastIndexOf(boundaries[1]) + boundaries[1].length;
		return source.slice(0, start) + wrappedReplacement + source.slice(end);
	} else {
		return source + wrappedReplacement;
	}
}

function applyToSingletonTag(styleElement, index, remove, obj) {
	var css = remove ? "" : obj.css;

	if(styleElement.styleSheet) {
		styleElement.styleSheet.cssText = replaceText(styleElement.styleSheet.cssText, index, css);
	} else {
		var cssNode = document.createTextNode(css);
		var childNodes = styleElement.childNodes;
		if (childNodes[index]) styleElement.removeChild(childNodes[index]);
		if (childNodes.length) {
			styleElement.insertBefore(cssNode, childNodes[index]);
		} else {
			styleElement.appendChild(cssNode);
		}
	}
}

function applyToTag(styleElement, obj) {
	var css = obj.css;
	var media = obj.media;
	// var sourceMap = obj.sourceMap;
	// No browser support
	// if(sourceMap && typeof btoa === "function") {
		// try {
			// css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(JSON.stringify(sourceMap)) + " */";
		// } catch(e) {}
	// }

	if(media) {
		styleElement.setAttribute("media", media)
	}

	if(styleElement.styleSheet) {
		styleElement.styleSheet.cssText = css;
	} else {
		while(styleElement.firstChild) {
			styleElement.removeChild(styleElement.firstChild);
		}
		styleElement.appendChild(document.createTextNode(css));
	}
}
<|endoftext|>


<commit_before>var Botkit = require('botkit'),
  BeepBoop = require('beepboop-botkit'),
  schedule = require('node-schedule'),
  request = require('request');

// var winsObj = require('./wins.json'); // json object of wins

var controller = Botkit.slackbot({
  debug: false,
  json_file_store: ''
});
var beepboop = BeepBoop.start(controller, {
  debug: true
});

// Get token when team adds bot
var accessToken, teamID, webhookURL;
beepboop.on('add_resource', function(message) {
  accessToken = message.resource.SlackBotAccessToken;
  teamID = message.resource.SlackTeamID;
  webhookURL = message.resource.SlackIncomingWebhookConfigURL;
  console.log(webhookURL);
});

// give the bot something to listen for
controller.on('direct_message,direct_mention,mention', function(bot, message) {
  var messageTxt = message.text;

  // if lucy dm's "show me wins", send her a printout of all wins
  if (messageTxt.indexOf('show me wins') >= 0) {
    if (message.user === 'U0G8TL9LJ' /* lucy */ || message.user === 'U0G6LRZ0F' /* robert */ ) {
      console.log('I showed the wins!');

      bot.reply(message, 'Ok!\n' + compileMsg());
    } else {
      bot.reply(message, 'Sorry, but you are not authorized to use that command.')
    }
  } else {
    console.log('Someone sent me a win, but i have not saved it yet');

    saveWin(bot, message);
  }
});

beepboop.on('botkit.rtm.started', function(bot, resource, meta) {
  // every friday at 2pm, send message to everybody room with all client wins. erase wins.
  var j = schedule.scheduleJob('0 55 18 * * *', function() { // adjusted for GMT time
    console.log('I \'m sending the wins to general!');

    bot.api.chat.postMessage({
      channel: '#general',
      text: 'Here are the wins from this week:\n' + compileMsg(),
      username: 'Team Wins'
    }, function(err, res) {
      if (err) {
        throw new Error('Could not postMessage to #general');
      }
    });

    console.log('Here are the wins from this week:\n' + compileMsg());

    // erase wins
    controller.storage.teams.get(teamID, function(err, team) {
      team.wins = []

      // save new user object
      controller.storage.teams.save(team, function(err) {
        if (!err) {
          console.log("I erased the wins.")
        }
      });
    });
  });
});

function saveWin(bot, message) {
  // send request to get username (whyyyyyy?!)
  request('https://slack.com/api/users.info?token=' + accessToken + '&user=' + message.user, function(error, response, body) {
    if (!error && response.statusCode == 200) {
      var str = body;
      var userObj = JSON.parse(str);
      var hours, minutes;
      var ts = Math.floor(message.ts);
      var d = new Date(ts * 1000);

      if (d.getHours() > 12) {
        hours = d.getHours() - 12;
      } else {
        hours = d.getHours() - 12;
      }

      if (d.getMinutes() < 9) {
        minutes = '0' + d.getMinutes();
      } else {
        minutes = d.getMinutes();
      }

      var timestamp = d.getMonth() + 1 + '-' + d.getDate() + '-' + d.getFullYear() + ' @ ' + (d.getHours() - 7) + ':' + d.getMinutes();

      controller.storage.teams.get(teamID, function(err, team) {
        if (!team.wins) {
          team.wins = []
        }

        // push data to user object
        team.wins.push({
          "timestamp": timestamp,
          "from": userObj.user.name,
          "text": message.text
        });

        // save new user object
        controller.storage.teams.save(team, function(err) {
          if (!err) {
            console.log("I saved the win!")
          }
        });
      });
    }
  });

  // optional reply
  bot.reply(message, "Thanks for submitting your team win!");
  // bot.reply(message, "I'm currently sick and not saving wins. I will let everybody know when I feel better!");
}

// function compileMsg(winsObj) {
function compileMsg() {
  var finalMessage = '';

  controller.storage.teams.get(teamID, function(err, team) {
    console.log(team);
    for (var i = 0; i < team.wins.length; i++) {
      finalMessage += '*From:* ' + team.wins[i].from + '\n' + '*Date:* ' + team.wins[i].timestamp + '\n' + team.wins[i].text + '\n------------\n';
    }
  });

  return finalMessage;
}
<commit_msg>Update time to Friday at 2pm<commit_after>var Botkit = require('botkit'),
  BeepBoop = require('beepboop-botkit'),
  schedule = require('node-schedule'),
  request = require('request');

// var winsObj = require('./wins.json'); // json object of wins

var controller = Botkit.slackbot({
  debug: false,
  json_file_store: ''
});
var beepboop = BeepBoop.start(controller, {
  debug: true
});

// Get token when team adds bot
var accessToken, teamID, webhookURL;
beepboop.on('add_resource', function(message) {
  accessToken = message.resource.SlackBotAccessToken;
  teamID = message.resource.SlackTeamID;
  webhookURL = message.resource.SlackIncomingWebhookConfigURL;
  console.log(webhookURL);
});

// give the bot something to listen for
controller.on('direct_message,direct_mention,mention', function(bot, message) {
  var messageTxt = message.text;

  // if lucy dm's "show me wins", send her a printout of all wins
  if (messageTxt.indexOf('show me wins') >= 0) {
    if (message.user === 'U0G8TL9LJ' /* lucy */ || message.user === 'U0G6LRZ0F' /* robert */ ) {
      console.log('I showed the wins!');

      bot.reply(message, 'Ok!\n' + compileMsg());
    } else {
      bot.reply(message, 'Sorry, but you are not authorized to use that command.')
    }
  } else {
    console.log('Someone sent me a win, but i have not saved it yet');

    saveWin(bot, message);
  }
});

beepboop.on('botkit.rtm.started', function(bot, resource, meta) {
  // every friday at 2pm, send message to everybody room with all client wins. erase wins.
  var j = schedule.scheduleJob('0 0 21 * * 5', function() { // adjusted for GMT time
    console.log('I \'m sending the wins to general!');

    bot.api.chat.postMessage({
      channel: '#general',
      text: 'Here are the wins from this week:\n' + compileMsg(),
      username: 'Team Wins'
    }, function(err, res) {
      if (err) {
        throw new Error('Could not postMessage to #general');
      }
    });

    console.log('Here are the wins from this week:\n' + compileMsg());

    // erase wins
    controller.storage.teams.get(teamID, function(err, team) {
      team.wins = []

      // save new user object
      controller.storage.teams.save(team, function(err) {
        if (!err) {
          console.log("I erased the wins.")
        }
      });
    });
  });
});

function saveWin(bot, message) {
  // send request to get username (whyyyyyy?!)
  request('https://slack.com/api/users.info?token=' + accessToken + '&user=' + message.user, function(error, response, body) {
    if (!error && response.statusCode == 200) {
      var str = body;
      var userObj = JSON.parse(str);
      var hours, minutes;
      var ts = Math.floor(message.ts);
      var d = new Date(ts * 1000);

      if (d.getHours() > 12) {
        hours = d.getHours() - 12;
      } else {
        hours = d.getHours() - 12;
      }

      if (d.getMinutes() < 9) {
        minutes = '0' + d.getMinutes();
      } else {
        minutes = d.getMinutes();
      }

      var timestamp = d.getMonth() + 1 + '-' + d.getDate() + '-' + d.getFullYear() + ' @ ' + (d.getHours() - 7) + ':' + d.getMinutes();

      controller.storage.teams.get(teamID, function(err, team) {
        if (!team.wins) {
          team.wins = []
        }

        // push data to user object
        team.wins.push({
          "timestamp": timestamp,
          "from": userObj.user.name,
          "text": message.text
        });

        // save new user object
        controller.storage.teams.save(team, function(err) {
          if (!err) {
            console.log("I saved the win!")
          }
        });
      });
    }
  });

  // optional reply
  bot.reply(message, "Thanks for submitting your team win!");
  // bot.reply(message, "I'm currently sick and not saving wins. I will let everybody know when I feel better!");
}

// function compileMsg(winsObj) {
function compileMsg() {
  var finalMessage = '';

  controller.storage.teams.get(teamID, function(err, team) {
    console.log(team);
    for (var i = 0; i < team.wins.length; i++) {
      finalMessage += '*From:* ' + team.wins[i].from + '\n' + '*Date:* ' + team.wins[i].timestamp + '\n' + team.wins[i].text + '\n------------\n';
    }
  });

  return finalMessage;
}
<|endoftext|>


<commit_before>module.exports = function(grunt) {

	grunt.config('clean', {
		options: {
			force: true,
		},
		styles: {
			src: [
				'<%= project.styles_dev %>/*.concat.css',
				'<%= project.styles_dev %>/*.map',
				'<%= project.styles_min %>/*.css',
			],
		},
		scripts: {
			src: [
				'<%= project.scripts_dev %>/*.hint.js',
				'<%= project.scripts_min %>/*.js',
			],
		},
		grunticon: {
			src: [
				'<%= project.styles_scss %>/grunticon/grunticon.loader.js',
				'<%= project.styles_scss %>/grunticon/preview.html',
				'<%= project.styles_scss %>/grunticon/tmp',
			],
		},
	});

};
<commit_msg>Add comment.<commit_after>module.exports = function(grunt) {

	grunt.config('clean', {
		options: {
			force: true, // overrides this task from blocking deletion of folders outside current working dir
		},
		styles: {
			src: [
				'<%= project.styles_dev %>/*.concat.css',
				'<%= project.styles_dev %>/*.map',
				'<%= project.styles_min %>/*.css',
			],
		},
		scripts: {
			src: [
				'<%= project.scripts_dev %>/*.hint.js',
				'<%= project.scripts_min %>/*.js',
			],
		},
		grunticon: {
			src: [
				'<%= project.styles_scss %>/grunticon/grunticon.loader.js',
				'<%= project.styles_scss %>/grunticon/preview.html',
				'<%= project.styles_scss %>/grunticon/tmp',
			],
		},
	});

};
<|endoftext|>


<commit_before>import React from 'react';
import {
  Collapse,
  Navbar,
  NavbarToggler,
  NavbarBrand,
  Nav,
  NavItem,
  NavLink,
  UncontrolledDropdown,
  DropdownToggle,
  DropdownMenu,
  DropdownItem } from 'reactstrap';

export default class Example extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = this.toggle.bind(this);
    this.state = {
      isOpen: false
    };
  }
  toggle() {
    this.setState({
      isOpen: !this.state.isOpen
    });
  }
  render() {
    return (

        <Navbar color="faded" light expand="md">
          <NavbarBrand href="/">reactstrap</NavbarBrand>
          <NavbarToggler onClick={this.toggle} />
          <Collapse isOpen={this.state.isOpen} navbar>

              <NavItem>
                <NavLink href="/components/">Components</NavLink>
              </NavItem>
              <NavItem>
                <NavLink href="https://github.com/reactstrap/reactstrap">Github</NavLink>
              </NavItem>
              <UncontrolledDropdown nav inNavbar>
                <DropdownToggle nav caret>
                  Options
                </DropdownToggle>
                <DropdownMenu >
                  <DropdownItem>
                    Option 1
                  </DropdownItem>
                  <DropdownItem>
                    Option 2
                  </DropdownItem>
                  <DropdownItem divider />
                  <DropdownItem>
                    Reset
                  </DropdownItem>
                </DropdownMenu>
              </UncontrolledDropdown>

          </Collapse>
        </Navbar>

    );
  }
}
<commit_msg>align the dropdown menu for NavbarExampleSource to the right (#922)<commit_after>import React from 'react';
import {
  Collapse,
  Navbar,
  NavbarToggler,
  NavbarBrand,
  Nav,
  NavItem,
  NavLink,
  UncontrolledDropdown,
  DropdownToggle,
  DropdownMenu,
  DropdownItem } from 'reactstrap';

export default class Example extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = this.toggle.bind(this);
    this.state = {
      isOpen: false
    };
  }
  toggle() {
    this.setState({
      isOpen: !this.state.isOpen
    });
  }
  render() {
    return (

        <Navbar color="faded" light expand="md">
          <NavbarBrand href="/">reactstrap</NavbarBrand>
          <NavbarToggler onClick={this.toggle} />
          <Collapse isOpen={this.state.isOpen} navbar>

              <NavItem>
                <NavLink href="/components/">Components</NavLink>
              </NavItem>
              <NavItem>
                <NavLink href="https://github.com/reactstrap/reactstrap">Github</NavLink>
              </NavItem>
              <UncontrolledDropdown nav inNavbar>
                <DropdownToggle nav caret>
                  Options
                </DropdownToggle>
                <DropdownMenu right>
                  <DropdownItem>
                    Option 1
                  </DropdownItem>
                  <DropdownItem>
                    Option 2
                  </DropdownItem>
                  <DropdownItem divider />
                  <DropdownItem>
                    Reset
                  </DropdownItem>
                </DropdownMenu>
              </UncontrolledDropdown>

          </Collapse>
        </Navbar>

    );
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2021 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import {DISCUSSION_QUERY} from '../graphql/Queries'
import {DiscussionThreadsContainer} from './containers/DiscussionThreadsContainer/DiscussionThreadsContainer'
import {DiscussionTopicContainer} from './containers/DiscussionTopicContainer/DiscussionTopicContainer'
import errorShipUrl from '@canvas/images/ErrorShip.svg'
import GenericErrorPage from '@canvas/generic-error-page'
import I18n from 'i18n!discussion_topics_post'
import LoadingIndicator from '@canvas/loading-indicator'
import {NoResultsFound} from './components/NoResultsFound/NoResultsFound'
import {PER_PAGE, SearchContext} from './utils/constants'
import PropTypes from 'prop-types'
import React, {useContext, useState} from 'react'
import {useMutation, useQuery} from 'react-apollo'
import {CREATE_DISCUSSION_ENTRY} from '../graphql/Mutations'
import {AlertManagerContext} from '@canvas/alerts/react/AlertManager'

const DiscussionTopicManager = props => {
  const [searchTerm, setSearchTerm] = useState('')
  const value = {searchTerm, setSearchTerm}

  const {setOnFailure, setOnSuccess} = useContext(AlertManagerContext)
  const variables = {
    discussionID: props.discussionTopicId,
    perPage: PER_PAGE,
    page: btoa(0),
    searchTerm,
    rootEntries: !searchTerm
  }
  const discussionTopicQuery = useQuery(DISCUSSION_QUERY, {variables})

  const updateCache = (cache, result) => {
    try {
      const lastPage = discussionTopicQuery.data.legacyNode.entriesTotalPages - 1
      const options = {
        query: DISCUSSION_QUERY,
        variables: {...variables, page: btoa(lastPage * PER_PAGE)}
      }
      const newDiscussionEntry = result.data.createDiscussionEntry.discussionEntry
      const currentDiscussion = JSON.parse(JSON.stringify(cache.readQuery(options)))

      if (currentDiscussion && newDiscussionEntry) {
        currentDiscussion.legacyNode.discussionEntriesConnection.nodes.push(newDiscussionEntry)

        // TODO: Handle sorting.
        cache.writeQuery({...options, data: currentDiscussion})
      }
      // eslint-disable-next-line no-empty
    } catch (e) {}
  }

  const [createDiscussionEntry] = useMutation(CREATE_DISCUSSION_ENTRY, {
    update: updateCache,
    onCompleted: () => {
      setOnSuccess(I18n.t('The discussion entry was successfully created.'))
    },
    onError: () => {
      setOnFailure(I18n.t('There was an unexpected error creating the discussion entry.'))
    }
  })

  if (discussionTopicQuery.loading && !searchTerm) {
    return <LoadingIndicator />
  }

  if (discussionTopicQuery.error || !discussionTopicQuery?.data?.legacyNode) {
    return (
      <GenericErrorPage
        imageUrl={errorShipUrl}
        errorSubject={I18n.t('Discussion Topic initial query error')}
        errorCategory={I18n.t('Discussion Topic Post Error Page')}
      />
    )
  }

  return (
    <>
      <SearchContext.Provider value={value}>
        <DiscussionTopicContainer
          discussionTopic={discussionTopicQuery.data.legacyNode}
          createDiscussionEntry={text => {
            createDiscussionEntry({
              variables: {
                discussionTopicId: ENV.discussion_topic_id,
                message: text
              }
            })
          }}
        />
        {discussionTopicQuery.data.legacyNode.discussionEntriesConnection.nodes.length === 0 ? (
          <NoResultsFound />
        ) : (
          <DiscussionThreadsContainer
            discussionTopic={discussionTopicQuery.data.legacyNode}
            discussionTopicId={props.discussionTopicId}
            threads={discussionTopicQuery.data.legacyNode.discussionEntriesConnection.nodes}
            pageInfo={discussionTopicQuery.data.legacyNode.discussionEntriesConnection.pageInfo}
            totalPages={discussionTopicQuery.data.legacyNode.entriesTotalPages}
          />
        )}
      </SearchContext.Provider>
    </>
  )
}

DiscussionTopicManager.propTypes = {
  discussionTopicId: PropTypes.string.isRequired
}

export default DiscussionTopicManager
<commit_msg>Doesn't display NoResultsComponent if no search performed<commit_after>/*
 * Copyright (C) 2021 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import {DISCUSSION_QUERY} from '../graphql/Queries'
import {DiscussionThreadsContainer} from './containers/DiscussionThreadsContainer/DiscussionThreadsContainer'
import {DiscussionTopicContainer} from './containers/DiscussionTopicContainer/DiscussionTopicContainer'
import errorShipUrl from '@canvas/images/ErrorShip.svg'
import GenericErrorPage from '@canvas/generic-error-page'
import I18n from 'i18n!discussion_topics_post'
import LoadingIndicator from '@canvas/loading-indicator'
import {NoResultsFound} from './components/NoResultsFound/NoResultsFound'
import {PER_PAGE, SearchContext} from './utils/constants'
import PropTypes from 'prop-types'
import React, {useContext, useState} from 'react'
import {useMutation, useQuery} from 'react-apollo'
import {CREATE_DISCUSSION_ENTRY} from '../graphql/Mutations'
import {AlertManagerContext} from '@canvas/alerts/react/AlertManager'

const DiscussionTopicManager = props => {
  const [searchTerm, setSearchTerm] = useState('')
  const value = {searchTerm, setSearchTerm}

  const {setOnFailure, setOnSuccess} = useContext(AlertManagerContext)
  const variables = {
    discussionID: props.discussionTopicId,
    perPage: PER_PAGE,
    page: btoa(0),
    searchTerm,
    rootEntries: !searchTerm
  }
  const discussionTopicQuery = useQuery(DISCUSSION_QUERY, {variables})

  const updateCache = (cache, result) => {
    try {
      const lastPage = discussionTopicQuery.data.legacyNode.entriesTotalPages - 1
      const options = {
        query: DISCUSSION_QUERY,
        variables: {...variables, page: btoa(lastPage * PER_PAGE)}
      }
      const newDiscussionEntry = result.data.createDiscussionEntry.discussionEntry
      const currentDiscussion = JSON.parse(JSON.stringify(cache.readQuery(options)))

      if (currentDiscussion && newDiscussionEntry) {
        currentDiscussion.legacyNode.discussionEntriesConnection.nodes.push(newDiscussionEntry)

        // TODO: Handle sorting.
        cache.writeQuery({...options, data: currentDiscussion})
      }
      // eslint-disable-next-line no-empty
    } catch (e) {}
  }

  const [createDiscussionEntry] = useMutation(CREATE_DISCUSSION_ENTRY, {
    update: updateCache,
    onCompleted: () => {
      setOnSuccess(I18n.t('The discussion entry was successfully created.'))
    },
    onError: () => {
      setOnFailure(I18n.t('There was an unexpected error creating the discussion entry.'))
    }
  })

  if (discussionTopicQuery.loading && !searchTerm) {
    return <LoadingIndicator />
  }

  if (discussionTopicQuery.error || !discussionTopicQuery?.data?.legacyNode) {
    return (
      <GenericErrorPage
        imageUrl={errorShipUrl}
        errorSubject={I18n.t('Discussion Topic initial query error')}
        errorCategory={I18n.t('Discussion Topic Post Error Page')}
      />
    )
  }

  return (
    <>
      <SearchContext.Provider value={value}>
        <DiscussionTopicContainer
          discussionTopic={discussionTopicQuery.data.legacyNode}
          createDiscussionEntry={text => {
            createDiscussionEntry({
              variables: {
                discussionTopicId: ENV.discussion_topic_id,
                message: text
              }
            })
          }}
        />
        {discussionTopicQuery.data.legacyNode.discussionEntriesConnection.nodes.length === 0 &&
        searchTerm ? (
          <NoResultsFound />
        ) : (
          <DiscussionThreadsContainer
            discussionTopic={discussionTopicQuery.data.legacyNode}
            discussionTopicId={props.discussionTopicId}
            threads={discussionTopicQuery.data.legacyNode.discussionEntriesConnection.nodes}
            pageInfo={discussionTopicQuery.data.legacyNode.discussionEntriesConnection.pageInfo}
            totalPages={discussionTopicQuery.data.legacyNode.entriesTotalPages}
          />
        )}
      </SearchContext.Provider>
    </>
  )
}

DiscussionTopicManager.propTypes = {
  discussionTopicId: PropTypes.string.isRequired
}

export default DiscussionTopicManager
<|endoftext|>


<commit_before>(function(global, factory) {
  if(typeof define === 'function' && define.amd) {
    define(factory);
  } else {
    global.analytics = factory();
  }
}(this, function() {

  // Use hostname for GA Category
  var _category = location.hostname,
      _redacted = "REDACTED (Potential Email Address)";

  /**
   * To Title Case 2.1 - http://individed.com/code/to-title-case/
   * Copyright 2008-2013 David Gouch. Licensed under the MIT License.
   * https://github.com/gouch/to-title-case
   */
  function toTitleCase(s){
    var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs?\.?|via)$/i;
    s = trim(s);

    return s.replace(/[A-Za-z0-9\u00C0-\u00FF]+[^\s-]*/g, function(match, index, title){
      if (index > 0 &&
          index + match.length !== title.length &&
          match.search(smallWords) > -1 &&
          title.charAt(index - 2) !== ":" &&
          (title.charAt(index + match.length) !== '-' || title.charAt(index - 1) === '-') &&
          title.charAt(index - 1).search(/[^\s-]/) < 0) {
        return match.toLowerCase();
      }

      if (match.substr(1).search(/[A-Z]|\../) > -1) {
        return match;
      }

      return match.charAt(0).toUpperCase() + match.substr(1);
    });
  }

  // GA strings need to have leading/trailing whitespace trimmed, and not all
  // browsers have String.prototoype.trim().
  function trim(s) {
    return s.replace(/^\s+|\s+$/g, '');
  }

  // See if s could be an email address. We don't want to send personal data like email.
  function mightBeEmail(s) {
    // There's no point trying to validate rfc822 fully, just look for ...@...
    return (/[^@]+@[^@]+/).test(s);
  }

  function warn(msg) {
    console.warn("[analytics] " + msg);
  }

  // Support both types of Google Analytics Event Tracking, see:
  // ga.js - https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide
  // analytics.js - https://developers.google.com/analytics/devguides/collection/analyticsjs/events
  function _ga(options) {
    // If the new analytics.js API is present, fire this event using ga().
    if(typeof this.ga === "function") {
      // Transform the argument array to match the expected call signature for ga(), see:
      // https://developers.google.com/analytics/devguides/collection/analyticsjs/events#overview
      var fieldObject = {
        'hitType': 'event',
        'eventCategory': _category,
        'eventAction': options.action
      };
      if(options.label) {
        fieldObject['eventLabel'] = options.label;
      }
      if(options.value) {
        fieldObject['eventValue'] = options.value;
      }
      if(options.nonInteraction === true) {
        fieldObject['nonInteraction'] = 1;
      }
      this.ga('send', fieldObject);
    }

    // Also support the old API. Google suggests firing data at both to be the right thing.
    _gaq = _gaq || [];
    var eventArgs = ['_trackEvent', _category, options.action];
    if(options.label) {
      eventArgs.push(options.label);
    }
    if(options.value) {
      eventArgs.push(options.value);
    }
    if(options.nonInteraction === true) {
      eventArgs.push(true);
    }
    _gaq.push(eventArgs);
  }

  function event(action, options) {
    options = options || {};
    var eventOptions = {},
        label = options.label,
        value = options.value,
        // Support both forms to deal with typos between the 2 APIs
        nonInteraction = options.noninteraction || options.nonInteraction;

    if(!action) {
      warn("Expected `action` arg.");
      return;
    }
    if(mightBeEmail(action)) {
      warn("`action` arg looks like an email address, redacting.");
      action = _redacted;
    }
    eventOptions.action = toTitleCase(action);

    // label: An optional string to provide additional dimensions to the event data.
    if(label) {
      if(typeof label !== "string") {
        warn("Expected `label` arg to be a String.");
      } else {
        if(mightBeEmail(label)) {
          warn("`label` arg looks like an email address, redacting.");
          label = _redacted;
        }
        eventOptions.label = trim(label);
      }
    }

    // value: An optional integer that you can use to provide numerical data about
    // the user event.
    if(value) {
      if(typeof value !== "number") {
        warn("Expected `value` arg to be a Number.");
      } else {
        // Force value to int
        eventOptions.value = value|0;
      }
    }

    // noninteraction: An optional boolean that when set to true, indicates that
    // the event hit will not be used in bounce-rate calculation.
    if(nonInteraction) {
      if(typeof nonInteraction !== "boolean") {
        warn("Expected `noninteraction` arg to be a Boolean.");
      } else {
        eventOptions.nonInteraction = nonInteraction === true;
      }
    }

    _ga(eventOptions);
  }

  return {
    event: event
  };

}));
<commit_msg>Add var to _gaq = ... to stop undefined refernece error.<commit_after>(function(global, factory) {
  if(typeof define === 'function' && define.amd) {
    define(factory);
  } else {
    global.analytics = factory();
  }
}(this, function() {

  // Use hostname for GA Category
  var _category = location.hostname,
      _redacted = "REDACTED (Potential Email Address)";

  /**
   * To Title Case 2.1 - http://individed.com/code/to-title-case/
   * Copyright 2008-2013 David Gouch. Licensed under the MIT License.
   * https://github.com/gouch/to-title-case
   */
  function toTitleCase(s){
    var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs?\.?|via)$/i;
    s = trim(s);

    return s.replace(/[A-Za-z0-9\u00C0-\u00FF]+[^\s-]*/g, function(match, index, title){
      if (index > 0 &&
          index + match.length !== title.length &&
          match.search(smallWords) > -1 &&
          title.charAt(index - 2) !== ":" &&
          (title.charAt(index + match.length) !== '-' || title.charAt(index - 1) === '-') &&
          title.charAt(index - 1).search(/[^\s-]/) < 0) {
        return match.toLowerCase();
      }

      if (match.substr(1).search(/[A-Z]|\../) > -1) {
        return match;
      }

      return match.charAt(0).toUpperCase() + match.substr(1);
    });
  }

  // GA strings need to have leading/trailing whitespace trimmed, and not all
  // browsers have String.prototoype.trim().
  function trim(s) {
    return s.replace(/^\s+|\s+$/g, '');
  }

  // See if s could be an email address. We don't want to send personal data like email.
  function mightBeEmail(s) {
    // There's no point trying to validate rfc822 fully, just look for ...@...
    return (/[^@]+@[^@]+/).test(s);
  }

  function warn(msg) {
    console.warn("[analytics] " + msg);
  }

  // Support both types of Google Analytics Event Tracking, see:
  // ga.js - https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide
  // analytics.js - https://developers.google.com/analytics/devguides/collection/analyticsjs/events
  function _ga(options) {
    // If the new analytics.js API is present, fire this event using ga().
    if(typeof this.ga === "function") {
      // Transform the argument array to match the expected call signature for ga(), see:
      // https://developers.google.com/analytics/devguides/collection/analyticsjs/events#overview
      var fieldObject = {
        'hitType': 'event',
        'eventCategory': _category,
        'eventAction': options.action
      };
      if(options.label) {
        fieldObject['eventLabel'] = options.label;
      }
      if(options.value) {
        fieldObject['eventValue'] = options.value;
      }
      if(options.nonInteraction === true) {
        fieldObject['nonInteraction'] = 1;
      }
      this.ga('send', fieldObject);
    }

    // Also support the old API. Google suggests firing data at both to be the right thing.
    var _gaq = _gaq || [];
    var eventArgs = ['_trackEvent', _category, options.action];
    if(options.label) {
      eventArgs.push(options.label);
    }
    if(options.value) {
      eventArgs.push(options.value);
    }
    if(options.nonInteraction === true) {
      eventArgs.push(true);
    }
    _gaq.push(eventArgs);
  }

  function event(action, options) {
    options = options || {};
    var eventOptions = {},
        label = options.label,
        value = options.value,
        // Support both forms to deal with typos between the 2 APIs
        nonInteraction = options.noninteraction || options.nonInteraction;

    if(!action) {
      warn("Expected `action` arg.");
      return;
    }
    if(mightBeEmail(action)) {
      warn("`action` arg looks like an email address, redacting.");
      action = _redacted;
    }
    eventOptions.action = toTitleCase(action);

    // label: An optional string to provide additional dimensions to the event data.
    if(label) {
      if(typeof label !== "string") {
        warn("Expected `label` arg to be a String.");
      } else {
        if(mightBeEmail(label)) {
          warn("`label` arg looks like an email address, redacting.");
          label = _redacted;
        }
        eventOptions.label = trim(label);
      }
    }

    // value: An optional integer that you can use to provide numerical data about
    // the user event.
    if(value) {
      if(typeof value !== "number") {
        warn("Expected `value` arg to be a Number.");
      } else {
        // Force value to int
        eventOptions.value = value|0;
      }
    }

    // noninteraction: An optional boolean that when set to true, indicates that
    // the event hit will not be used in bounce-rate calculation.
    if(nonInteraction) {
      if(typeof nonInteraction !== "boolean") {
        warn("Expected `noninteraction` arg to be a Boolean.");
      } else {
        eventOptions.nonInteraction = nonInteraction === true;
      }
    }

    _ga(eventOptions);
  }

  return {
    event: event
  };

}));
<|endoftext|>


<commit_before>import path from "path";
import { fileURLToPath } from "url";
import TestStream from "test262-stream";
import TestRunner from "../utils/parser-test-runner.js";

const dirname = path.dirname(fileURLToPath(import.meta.url));

const ignoredFeatures = [
  "__getter__",
  "__setter__",
  "AggregateError",
  "Array.prototype.at",
  "Array.prototype.flat",
  "Array.prototype.flatMap",
  "Array.prototype.item",
  "Array.prototype.values",
  "ArrayBuffer",
  "align-detached-buffer-semantics-with-web-reality",
  "arbitrary-module-namespace-names",
  "async-functions",
  "async-iteration",
  "arrow-function",
  "Atomics",
  "Atomics.waitAsync",
  "BigInt",
  "caller",
  "class",
  "class-fields-private",
  "class-fields-public",
  "class-methods-private",
  "class-static-fields-private",
  "class-static-fields-public",
  "class-static-methods-private",
  "cleanupSome",
  "coalesce-expression",
  "computed-property-names",
  "const",
  "cross-realm",
  "DataView",
  "DataView.prototype.getFloat32",
  "DataView.prototype.getFloat64",
  "DataView.prototype.getInt8",
  "DataView.prototype.getInt16",
  "DataView.prototype.getInt32",
  "DataView.prototype.getUint16",
  "DataView.prototype.getUint32",
  "DataView.prototype.setUint8",
  "default-parameters",
  "destructuring-assignment",
  "destructuring-binding",
  "dynamic-import",
  "export-star-as-namespace-from-module",
  "FinalizationGroup",
  "FinalizationRegistry",
  "FinalizationRegistry.prototype.cleanupSome",
  "Float32Array",
  "Float64Array",
  "for-in-order",
  "for-of",
  "generators",
  "globalThis",
  "hashbang",
  "host-gc-required",
  "Int8Array",
  "Int16Array",
  "Int32Array",
  "Intl.DateTimeFormat-datetimestyle",
  "Intl.DateTimeFormat-dayPeriod",
  "Intl.DateTimeFormat-fractionalSecondDigits",
  "Intl.DateTimeFormat-formatRange",
  "Intl.DisplayNames",
  "Intl.ListFormat",
  "Intl.Locale",
  "Intl.NumberFormat-unified",
  "Intl.RelativeTimeFormat",
  "Intl.Segmenter",
  "IsHTMLDDA",
  "import.meta",
  "intl-normative-optional",
  "json-superset",
  "legacy-regexp",
  "let",
  "logical-assignment-operators",
  "Map",
  "new.target",
  "numeric-separator-literal",
  "Object.fromEntries",
  "Object.is",
  "object-rest",
  "object-spread",
  "optional-catch-binding",
  "optional-chaining",
  "Promise",
  "Promise.allSettled",
  "Promise.any",
  "Promise.prototype.finally",
  "Proxy",
  "proxy-missing-checks",
  "Reflect",
  "Reflect.construct",
  "Reflect.set",
  "Reflect.setPrototypeOf",
  "regexp-dotall",
  "regexp-lookbehind",
  "regexp-named-groups",
  "regexp-unicode-property-escapes",
  "rest-parameters",
  "SharedArrayBuffer",
  "Set",
  "String.fromCodePoint",
  "String.prototype.at",
  "String.prototype.endsWith",
  "String.prototype.includes",
  "String.prototype.item",
  "String.prototype.matchAll",
  "String.prototype.replaceAll",
  "String.prototype.trimEnd",
  "String.prototype.trimStart",
  "string-trimming",
  "super",
  "Symbol",
  "Symbol.asyncIterator",
  "Symbol.hasInstance",
  "Symbol.isConcatSpreadable",
  "Symbol.iterator",
  "Symbol.match",
  "Symbol.matchAll",
  "Symbol.prototype.description",
  "Symbol.replace",
  "Symbol.search",
  "Symbol.split",
  "Symbol.species",
  "Symbol.toPrimitive",
  "Symbol.toStringTag",
  "Symbol.unscopables",
  "tail-call-optimization",
  "template",
  "top-level-await",
  "TypedArray",
  "TypedArray.prototype.at",
  "TypedArray.prototype.item",
  "u180e",
  "Uint8Array",
  "Uint8ClampedArray",
  "Uint16Array",
  "Uint32Array",
  "WeakMap",
  "WeakSet",
  "WeakRef",
  "well-formed-json-stringify",
];

const ignoredTests = ["built-ins/RegExp/", "language/literals/regexp/"];

const featuresToPlugins = {
  __proto__: null,
  "import-assertions": "importAssertions",
};

const unmappedFeatures = new Set();

function* getPlugins(features) {
  if (!features) return;

  for (const f of features) {
    if (featuresToPlugins[f]) {
      yield featuresToPlugins[f];
    } else if (!ignoredFeatures.includes(f)) {
      unmappedFeatures.add(f);
    }
  }
}

const runner = new TestRunner({
  testDir: path.join(dirname, "../../../build/test262"),
  allowlist: path.join(dirname, "allowlist.txt"),
  logInterval: 500,
  shouldUpdate: process.argv.includes("--update-allowlist"),

  async *getTests() {
    const stream = new TestStream(this.testDir, {
      omitRuntime: true,
    });

    for await (const test of stream) {
      // strip test/
      const fileName = test.file.substr(5);

      if (ignoredTests.some(start => fileName.startsWith(start))) continue;

      yield {
        contents: test.contents,
        fileName,
        id: `${fileName}(${test.scenario})`,
        sourceType: test.attrs.flags.module ? "module" : "script",
        plugins: Array.from(getPlugins(test.attrs.features)),
        expectedError:
          !!test.attrs.negative &&
          (test.attrs.negative.phase === "parse" ||
            test.attrs.negative.phase === "early"),
      };
    }
  },
});

runner
  .run()
  .then(() => {
    if (unmappedFeatures.size) {
      console.log("");
      console.log(
        "The following Features are not currently mapped or ignored:"
      );
      console.log(
        Array.from(unmappedFeatures).join("\n").replace(/^/gm, "   ")
      );
    }
  })
  .catch(err => {
    console.error(err);
    process.exitCode = 1;
  });
<commit_msg>Update `test262` parser tests `ignoredFeatures` list (#14019)<commit_after>import path from "path";
import { fileURLToPath } from "url";
import TestStream from "test262-stream";
import TestRunner from "../utils/parser-test-runner.js";

const dirname = path.dirname(fileURLToPath(import.meta.url));

const ignoredFeatures = new Set([
  "__getter__",
  "__proto__",
  "__setter__",
  "AggregateError",
  "Array.prototype.at",
  "Array.prototype.flat",
  "Array.prototype.flatMap",
  "Array.prototype.item",
  "Array.prototype.values",
  "ArrayBuffer",
  "align-detached-buffer-semantics-with-web-reality",
  "arbitrary-module-namespace-names",
  "array-find-from-last",
  "async-functions",
  "async-iteration",
  "arrow-function",
  "Atomics",
  "Atomics.waitAsync",
  "BigInt",
  "caller",
  "class",
  "class-fields-private",
  "class-fields-private-in",
  "class-fields-public",
  "class-methods-private",
  "class-static-block",
  "class-static-fields-private",
  "class-static-fields-public",
  "class-static-methods-private",
  "cleanupSome",
  "coalesce-expression",
  "computed-property-names",
  "const",
  "cross-realm",
  "DataView",
  "DataView.prototype.getFloat32",
  "DataView.prototype.getFloat64",
  "DataView.prototype.getInt8",
  "DataView.prototype.getInt16",
  "DataView.prototype.getInt32",
  "DataView.prototype.getUint16",
  "DataView.prototype.getUint32",
  "DataView.prototype.setUint8",
  "default-parameters",
  "destructuring-assignment",
  "destructuring-binding",
  "dynamic-import",
  "error-cause",
  "export-star-as-namespace-from-module",
  "FinalizationGroup",
  "FinalizationRegistry",
  "FinalizationRegistry.prototype.cleanupSome",
  "Float32Array",
  "Float64Array",
  "for-in-order",
  "for-of",
  "generators",
  "globalThis",
  "hashbang",
  "host-gc-required",
  "Int8Array",
  "Int16Array",
  "Int32Array",
  "Intl-enumeration",
  "Intl.DateTimeFormat-datetimestyle",
  "Intl.DateTimeFormat-dayPeriod",
  "Intl.DateTimeFormat-extend-timezonename",
  "Intl.DateTimeFormat-fractionalSecondDigits",
  "Intl.DateTimeFormat-formatRange",
  "Intl.DisplayNames",
  "Intl.DisplayNames-v2",
  "Intl.ListFormat",
  "Intl.Locale",
  "Intl.Locale-info",
  "Intl.NumberFormat-unified",
  "Intl.NumberFormat-v3",
  "Intl.RelativeTimeFormat",
  "Intl.Segmenter",
  "IsHTMLDDA",
  "import.meta",
  "intl-normative-optional",
  "json-modules",
  "json-superset",
  "legacy-regexp",
  "let",
  "logical-assignment-operators",
  "Map",
  "new.target",
  "numeric-separator-literal",
  "Object.fromEntries",
  "Object.hasOwn",
  "Object.is",
  "object-rest",
  "object-spread",
  "optional-catch-binding",
  "optional-chaining",
  "Promise",
  "Promise.allSettled",
  "Promise.any",
  "Promise.prototype.finally",
  "Proxy",
  "proxy-missing-checks",
  "Reflect",
  "Reflect.construct",
  "Reflect.set",
  "Reflect.setPrototypeOf",
  "regexp-dotall",
  "regexp-lookbehind",
  "regexp-named-groups",
  "regexp-unicode-property-escapes",
  "resizable-arraybuffer",
  "rest-parameters",
  "ShadowRealm",
  "SharedArrayBuffer",
  "Set",
  "String.fromCodePoint",
  "String.prototype.at",
  "String.prototype.endsWith",
  "String.prototype.includes",
  "String.prototype.item",
  "String.prototype.matchAll",
  "String.prototype.replaceAll",
  "String.prototype.trimEnd",
  "String.prototype.trimStart",
  "string-trimming",
  "super",
  "Symbol",
  "Symbol.asyncIterator",
  "Symbol.hasInstance",
  "Symbol.isConcatSpreadable",
  "Symbol.iterator",
  "Symbol.match",
  "Symbol.matchAll",
  "Symbol.prototype.description",
  "Symbol.replace",
  "Symbol.search",
  "Symbol.split",
  "Symbol.species",
  "Symbol.toPrimitive",
  "Symbol.toStringTag",
  "Symbol.unscopables",
  "tail-call-optimization",
  "template",
  "top-level-await",
  "Temporal",
  "TypedArray",
  "TypedArray.prototype.at",
  "TypedArray.prototype.item",
  "u180e",
  "Uint8Array",
  "Uint8ClampedArray",
  "Uint16Array",
  "Uint32Array",
  "WeakMap",
  "WeakSet",
  "WeakRef",
  "well-formed-json-stringify",
]);

const ignoredTests = ["built-ins/RegExp/", "language/literals/regexp/"];

const featuresToPlugins = new Map([["import-assertions", "importAssertions"]]);

const unmappedFeatures = new Set();

function* getPlugins(features) {
  if (!features) return;

  for (const f of features) {
    if (featuresToPlugins.has(f)) {
      yield featuresToPlugins.get(f);
    } else if (!ignoredFeatures.has(f)) {
      unmappedFeatures.add(f);
    }
  }
}

const runner = new TestRunner({
  testDir: path.join(dirname, "../../../build/test262"),
  allowlist: path.join(dirname, "allowlist.txt"),
  logInterval: 500,
  shouldUpdate: process.argv.includes("--update-allowlist"),

  async *getTests() {
    const stream = new TestStream(this.testDir, {
      omitRuntime: true,
    });

    for await (const test of stream) {
      // strip test/
      const fileName = test.file.substr(5);

      if (ignoredTests.some(start => fileName.startsWith(start))) continue;

      yield {
        contents: test.contents,
        fileName,
        id: `${fileName}(${test.scenario})`,
        sourceType: test.attrs.flags.module ? "module" : "script",
        plugins: Array.from(getPlugins(test.attrs.features)),
        expectedError:
          !!test.attrs.negative &&
          (test.attrs.negative.phase === "parse" ||
            test.attrs.negative.phase === "early"),
      };
    }
  },
});

runner
  .run()
  .then(() => {
    if (unmappedFeatures.size) {
      console.warn("");
      console.warn(
        "The following Features are not currently mapped or ignored:"
      );
      console.warn(
        Array.from(unmappedFeatures).join("\n").replace(/^/gm, "   ")
      );

      process.exitCode = 1;
    }
  })
  .catch(err => {
    console.error(err);
    process.exitCode = 1;
  });
<|endoftext|>


<commit_before>(function(){
"use strict";
angular.module("uk.ac.soton.ecs.videogular.plugins.analytics", [])
	.directive(
		"vgAnalytics", ["VG_STATES", "$http", "$timeout",
			function(VG_STATES, $http, $timeout) {
				return {
					restrict: "E",
					require: "^videogular",
					scope: {
						servers: "=vgAnalyticsServers",
					},
					link: function($scope, elem, attr, API) {

						$scope.$parent.$on("analytics", function(event, name, details) {
							sendEvent(name, details);
						});

						function onUpdateState(newState, videoTime) {
							switch (newState) {
								case VG_STATES.PLAY:
									sendEvent("play", {
										time: videoTime
									});
									break;
								case VG_STATES.STOP:
									sendEvent("stop", {
										time: videoTime
									});
									break;
								case VG_STATES.PAUSE:
									sendEvent("pause", {
										time: videoTime
									});
									break;
							}
						}

						function sendEvent(name, details) {
							var now = new Date();

							var content = {
								time: now.toISOString(),
								name: name,
							};

							if (typeof(details) !== "undefined") {
								content.details = details;
							}

							$scope.servers.forEach(function(server) {
								$http.post(server + 'log', content)
									.success(function(data, status, headers, config) {
									// this callback will be called asynchronously
									// when the response is available
								}).error(function(data, status, headers, config) {
									console.error("error reporting event to the server");
									// called asynchronously if an error occurs
									// or server returns response with an error status.
								});
							});
						}

						$scope.$watch(
							function () {
								return API.currentState;
							},
							function (newVal, oldVal) {
								if (newVal !== oldVal) {
									onUpdateState(newVal, API.currentTime);
								}
							}
						);
					},
				};
			}
		]
	);
})();
<commit_msg>Use HTMLMediaElement events instead of a watch<commit_after>(function(){
"use strict";
angular.module("uk.ac.soton.ecs.videogular.plugins.analytics", [])
	.directive(
		"vgAnalytics", ["VG_STATES", "$http", "$timeout",
			function(VG_STATES, $http, $timeout) {
				return {
					restrict: "E",
					require: "^videogular",
					scope: {
						servers: "=vgAnalyticsServers",
					},
					link: function($scope, elem, attr, API) {

						$scope.$parent.$on("analytics", function(event, name, details) {
							sendEvent(name, details);
						});

						function sendEvent(name, details) {
							var now = new Date();

							var content = {
								time: now.toISOString(),
								name: name,
							};

							if (typeof(details) !== "undefined") {
								content.details = details;
							}

							$scope.servers.forEach(function(server) {
								$http.post(server + 'log', content)
									.success(function(data, status, headers, config) {
									// this callback will be called asynchronously
									// when the response is available
								}).error(function(data, status, headers, config) {
									console.error("error reporting event to the server");
									// called asynchronously if an error occurs
									// or server returns response with an error status.
								});
							});
						}

						function reportMediaElementEvent(event) {
							sendEvent(event.type, { time: API.currentTime });
						}

						var eventsToReport = ['play', 'pause', 'stop'];

						for (var i in eventsToReport) {
							API.mediaElement[0].addEventListener(eventsToReport[i], reportMediaElementEvent);
						}
					},
				};
			}
		]
	);
})();
<|endoftext|>


<commit_before>describe('Testing the first D3.js function drawKaryo', function() {
  var c;

  beforeEach(function() {
    c = drawKaryo();
    c.render();
  });

  afterEach(function() {
    d3.selectAll('svg').remove();
  });

  describe('the svg' ,function() {
    it('should be created', function() {
        expect(getSvg()).not.toBeNull();
    });

    it('should have the correct height', function() {
      expect(getSvg().attr('height')).toBe('3000');
    });

    it('should have the correct width', function() {
      expect(getSvg().attr('width')).toBe('1200');
    });
  });

  function getSvg() {
    return d3.select('svg');
  }

  describe('testing the data' ,function() {
	    it('should be null if no data has been specified', function() {
	        expect(c.getData()).not.toBeNull();
	    });

//	    it('should be able to update the data', function() {
//	      var testData =  [{ date: '2014-01', value: 100}, {date: '2014-02', value: 215}];
//	      c.setData(testData);
//	      expect(c.getData()).toBe(testData);
//	    });
  	});

});
<commit_msg>Und jetzt ist der Test auch schon erfolgreich. Wenn keine Daten festgelegt werden, bekommen die Daten einfach den Wert null, das funktioniert<commit_after>describe('Testing the first D3.js function drawKaryo', function() {
  var c;

  beforeEach(function() {
    c = drawKaryo();
    c.render();
  });

  afterEach(function() {
    d3.selectAll('svg').remove();
  });

  describe('the svg' ,function() {
    it('should be created', function() {
        expect(getSvg()).not.toBeNull();
    });

    it('should have the correct height', function() {
      expect(getSvg().attr('height')).toBe('3000');
    });

    it('should have the correct width', function() {
      expect(getSvg().attr('width')).toBe('1200');
    });
  });

  function getSvg() {
    return d3.select('svg');
  }

  describe('testing the data' ,function() {
	    it('should be null if no data has been specified', function() {
	        expect(c.getData()).toBeNull();
	    });

//	    it('should be able to update the data', function() {
//	      var testData =  [{ date: '2014-01', value: 100}, {date: '2014-02', value: 215}];
//	      c.setData(testData);
//	      expect(c.getData()).toBe(testData);
//	    });
  	});

});
<|endoftext|>