<commit_before>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * String output engine.
 *
 * Ultra fast string rendering.
 * Ommits all dom specific stuffs, obviously doesn't produce DOM node, doesn't apply bindings, etc.
 * Only constructs directly the needed string result with minimal work.
 *
 * That allows really FAST execution of template server side.
 * (on my dev machine :  under nodejs, for a full page with 1250 nodes it takes approximatly 0.250 ms to output as string ;)
 *
 * Templates are kept as descriptive as needed
 * to have multiple output engines
 * that loop through arrays of descriptors
 * and execute associated pure dedicated functions.
 * Here pure string output functions.
 *
 * Async warning :
 * It does not wait for async stuffs while executing template. It uses provided context as if it's fully constructed.
 * In other words : this output engine needs stabilised context. (see context stabilisation in docs).
 * There is a third output engine that manage contexts tree loads and stabilisation before applying string output. (aka twopass engine)
 */
var utils = require('../utils'),
	openTags = require('../parsers/open-tags'),
	strictTags = /span|script|meta|div|i/,
	Context = require('../context').Context,
	Template = require('../template');

// String Output Descriptor
function SOD() {
	this.attributes = '';
	this.classes = '';
	this.children = '';
	this.style = '';
}

function tagOutput(descriptor, innerDescriptor, name) {
	var out = '<' + name + innerDescriptor.attributes;
	if (innerDescriptor.style)
		out += ' style="' + innerDescriptor.style + '"';
	if (innerDescriptor.classes)
		out += ' class="' + innerDescriptor.classes + '"';
	if (innerDescriptor.children)
		descriptor.children += out + '>' + innerDescriptor.children + '</' + name + '>';
	else if (openTags.test(name))
		descriptor.children += out + '>';
	else if (strictTags.test(name))
		descriptor.children += out + '></' + name + '>';
	else
		descriptor.children += out + '/>';
}
utils.tagOutput = tagOutput;

var methods = {
	SOD: SOD,
	//_________________________________ local context management
	newContext: function(context, descriptor, args) {
		var data = args[0],
			parent = args[1] || context,
			path = args[2];
		descriptor.context = new Context(data, parent, path);
	},
	//_________________________________________ EACH
	each: function(context, descriptor, args) {
		var path = args[0],
			values = (typeof path === 'string') ? context.get(path) : path;
		if (values && values.length) {
			var template = args[1];
			for (var i = 0, len = values.length; i < len; ++i)
				template.toHTMLString(new Context(values[i], context), descriptor);
		} else if (args[2])
			args[2].toHTMLString(context, descriptor);
	},
	eachTemplates: function(context, descriptor, args) {
		var templates = args[0],
			handler = args[1];
		templates.forEach(function(templ) {
			(handler ? handler(templ) : templ).toHTMLString(context, descriptor);
		});
	},
	// ____________________________________ WITH
	with: function(context, descriptor, args) {
		var path = args[0],
			template = args[1];
		var ctx = new Context(typeof path === 'string' ? context.get(path) : path, context, path);
		template.toHTMLString(ctx, descriptor);
	},
	//______________________________________________
	mountIf: function(context, descriptor, args) {
		var ok, condition = args[0],
			successTempl = args[1],
			failTempl = args[2];
		if (condition && condition.__interpolable__)
			ok = condition.output(context);
		else if (typeof condition === 'function')
			ok = condition.call(this, context);
		var sod = new SOD();
		if (ok)
			successTempl.toHTMLString(context, sod);
		else if (failTempl)
			failTempl.toHTMLString(context, sod);
		if (sod.children)
			descriptor.children += sod.children;
	},
	agoraView: function(context, args) {
		// var channel = args[0],
		// template = args[1];
		// console.warn('agoraView has not been implemented yet for string engine.');
	},
	//______________________________________________
	if: function(context, descriptor, args) {
		var ok, condition = args[0],
			successTempl = args[1],
			failTempl = args[2];
		if (condition && condition.__interpolable__)
			ok = condition.output(context);
		else if (typeof condition === 'function')
			ok = condition.call(this, context);
		if (ok)
			successTempl.toHTMLString(context, descriptor);
		else if (failTempl)
			failTempl.toHTMLString(context, descriptor);
	},
	switch: function(context, descriptor, args) {
		var xpr = args[0],
			dico = args[1],
			value = xpr.output(context),
			templ = dico[value] || dico['default'];
		if (templ) {
			var sod = new SOD();
			templ.toHTMLString(context, sod);
			if (sod.children)
				descriptor.children += sod.children;
		}
	},
	//________________________________ TAGS
	tag: function(context, descriptor, originalArgs) {
		var name = originalArgs[0],
			template = originalArgs[1];
		var newDescriptor = new SOD();
		template.toHTMLString(context, newDescriptor);
		tagOutput(descriptor, newDescriptor, name);
	},
	text: function(context, descriptor, args) {
		var value = args[0];
		descriptor.children += value.__interpolable__ ? value.output(context) : value;
	},
	raw: function(context, descriptor, args) {
		descriptor.children += args[0];
	},
	br: function(context, descriptor) {
		descriptor.children += '
';
	},
	//______________________________________________ ATTRIBUTES
	attr: function(context, descriptor, args) {
		var name = args[0],
			value = args[1];
		descriptor.attributes += ' ' + name + (value ? ('="' + (value.__interpolable__ ? value.output(context) : value) + '"') : '');
	},
	disabled: function(context, descriptor, args) {
		var value = args[0];
		if (value === undefined || context.get(value))
			descriptor.attributes += ' disabled';
	},
	val: function(context, descriptor, args) {
		var path = args[0],
			value = args[1];
		descriptor.attributes += ' value="' + (value.__interpolable__ ? value.output(context) : value) + '"';
	},
	contentEditable: function(context, descriptor, args) {
		var value = args[1];
		descriptor.attributes += ' contenteditable';
		descriptor.children = value.output(context);
	},
	setClass: function(context, descriptor, args) {
		var name = args[0],
			flag = args[1];
		if ((flag.__interpolable__ && flag.output(context)) || flag)
			descriptor.classes += (descriptor.classes ? ' ' : '') + (name.__interpolable__ ? name.output(context) : name);
	},
	css: function(context, descriptor, args) {
		var prop = args[0],
			value = args[1];
		descriptor.style += prop + ':' + (value.__interpolable__ ? value.output(context) : value);
	},
	visible: function(context, descriptor, args) {
		var flag = args[0],
			val = (flag && flag.__interpolable__) ? flag.output(context) : flag;
		if (!val)
			descriptor.style += 'display:none;';
	},
	//_________________________________ EVENTS
	on: function() {},
	once: function() {},
	off: function() {},
	//_________________________________ CLIENT/SERVER
	client: function(context, descriptor, args) {
		if (context.env.data.isServer)
			return;
		args[0].toHTMLString(context, descriptor);
	},
	server: function(context, descriptor, args) {
		if (!context.env.data.isServer)
			return;
		args[0].toHTMLString(context, descriptor);
	},
	//_______________________________ SUSPEND RENDER
	suspendUntil: function(context, descriptor, args) {
		var xpr = args[0],
			index = args[1],
			templ = args[2],
			val = xpr.__interpolable__ ? xpr.output(context) : xpr,
			rest = new Template(templ._queue.slice(index));
		if (val)
			rest.toHTMLString(context, descriptor);
	},
	container: function(context, descriptor, args) {
		var sod = new SOD(),
			opt = args[0],
			template = args[1];
		template.toHTMLString(context, sod);
		descriptor.children += sod.children;
	}
};

Template.prototype.toHTMLString = function(context, descriptor) {
	context = context || new Context();
	descriptor = descriptor ||  new SOD();
	var handler = this._queue[0],
		index = 0,
		f;
	while (handler) {
		f = null;
		switch (handler.type) {
			case '*':
				f = methods[handler.handler];
				break;
			case 'string':
			case 'context':
				f = handler.handler;
				break;
			case 'custom':
				f = handler.handler.string;
				break;
		}
		if (!f) {
			handler = this._queue[++index];
			continue;
		}
		if (f.__yTemplate__)
			f.toHTMLString(descriptor.context || context, descriptor);
		else
			f(descriptor.context || context, descriptor, handler.args);
		if (handler.suspendAfter)
			break;
		handler = this._queue[++index];
	}
	return descriptor.children;
};

module.exports = methods;
<commit_msg>work on comments<commit_after>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * String output engine.
 *
 * Ultra fast string rendering.
 * Ommits all dom specific stuffs, obviously doesn't produce DOM node, doesn't apply bindings, etc.
 * Only constructs directly the needed string result with minimal work.
 *
 * That allows really FAST execution of template server side.
 * (on my dev machine :  under nodejs, for a full page with 1250 nodes it takes approximatly 0.250 ms to output as string ;)
 *
 * Templates are kept as descriptive as needed
 * to have multiple output engines
 * that loop through arrays of descriptors
 * and execute associated pure dedicated functions.
 * Here pure string output functions.
 *
 * Async warning :
 * It does not wait for async stuffs while executing template. It uses provided context as if it's fully constructed.
 * In other words : this output engine needs stabilised context. (see context stabilisation in docs).
 * There is a third output engine that manage contexts tree loads and stabilisation before applying string output. (aka twopass engine)
 */
var utils = require('../utils'),
	openTags = require('../parsers/open-tags'),
	strictTags = /span|script|meta|div|i/,
	Context = require('../context').Context,
	Template = require('../template');

// String Output Descriptor (temporary minimal strings holder - only for internal job)
function SOD() {
	this.attributes = '';
	this.classes = '';
	this.children = '';
	this.style = '';
}

// produce final html tag representation
function tagOutput(descriptor, innerDescriptor, name) {
	var out = '<' + name + innerDescriptor.attributes;
	if (innerDescriptor.style)
		out += ' style="' + innerDescriptor.style + '"';
	if (innerDescriptor.classes)
		out += ' class="' + innerDescriptor.classes + '"';
	if (innerDescriptor.children)
		descriptor.children += out + '>' + innerDescriptor.children + '</' + name + '>';
	else if (openTags.test(name))
		descriptor.children += out + '>';
	else if (strictTags.test(name))
		descriptor.children += out + '></' + name + '>';
	else
		descriptor.children += out + '/>';
}
utils.tagOutput = tagOutput;

var methods = {
	SOD: SOD,
	//_________________________________ local context management
	newContext: function(context, descriptor, args) {
		var data = args[0],
			parent = args[1] || context,
			path = args[2];
		descriptor.context = new Context(data, parent, path);
	},
	//_________________________________________ EACH
	each: function(context, descriptor, args) {
		var path = args[0],
			values = (typeof path === 'string') ? context.get(path) : path;
		if (values && values.length) {
			var template = args[1];
			for (var i = 0, len = values.length; i < len; ++i)
				template.toHTMLString(new Context(values[i], context), descriptor);
		} else if (args[2])
			args[2].toHTMLString(context, descriptor);
	},
	eachTemplates: function(context, descriptor, args) {
		var templates = args[0],
			handler = args[1];
		templates.forEach(function(templ) {
			(handler ? handler(templ) : templ).toHTMLString(context, descriptor);
		});
	},
	// ____________________________________ WITH
	with: function(context, descriptor, args) {
		var path = args[0],
			template = args[1];
		var ctx = new Context(typeof path === 'string' ? context.get(path) : path, context, path);
		template.toHTMLString(ctx, descriptor);
	},
	//______________________________________________
	mountIf: function(context, descriptor, args) {
		var ok, condition = args[0],
			successTempl = args[1],
			failTempl = args[2];
		if (condition && condition.__interpolable__)
			ok = condition.output(context);
		else if (typeof condition === 'function')
			ok = condition.call(this, context);
		var sod = new SOD();
		if (ok)
			successTempl.toHTMLString(context, sod);
		else if (failTempl)
			failTempl.toHTMLString(context, sod);
		if (sod.children)
			descriptor.children += sod.children;
	},
	agoraView: function(context, args) {
		// var channel = args[0],
		// template = args[1];
		// console.warn('agoraView has not been implemented yet for string engine.');
	},
	//______________________________________________
	if: function(context, descriptor, args) {
		var ok, condition = args[0],
			successTempl = args[1],
			failTempl = args[2];
		if (condition && condition.__interpolable__)
			ok = condition.output(context);
		else if (typeof condition === 'function')
			ok = condition.call(this, context);
		if (ok)
			successTempl.toHTMLString(context, descriptor);
		else if (failTempl)
			failTempl.toHTMLString(context, descriptor);
	},
	switch: function(context, descriptor, args) {
		var xpr = args[0],
			dico = args[1],
			value = xpr.output(context),
			templ = dico[value] || dico['default'];
		if (templ) {
			var sod = new SOD();
			templ.toHTMLString(context, sod);
			if (sod.children)
				descriptor.children += sod.children;
		}
	},
	//________________________________ TAGS
	tag: function(context, descriptor, originalArgs) {
		var name = originalArgs[0],
			template = originalArgs[1];
		var newDescriptor = new SOD();
		template.toHTMLString(context, newDescriptor);
		tagOutput(descriptor, newDescriptor, name);
	},
	text: function(context, descriptor, args) {
		var value = args[0];
		descriptor.children += value.__interpolable__ ? value.output(context) : value;
	},
	raw: function(context, descriptor, args) {
		descriptor.children += args[0];
	},
	br: function(context, descriptor) {
		descriptor.children += '
';
	},
	//______________________________________________ ATTRIBUTES
	attr: function(context, descriptor, args) {
		var name = args[0],
			value = args[1];
		descriptor.attributes += ' ' + name + (value ? ('="' + (value.__interpolable__ ? value.output(context) : value) + '"') : '');
	},
	disabled: function(context, descriptor, args) {
		var value = args[0];
		if (value === undefined || context.get(value))
			descriptor.attributes += ' disabled';
	},
	val: function(context, descriptor, args) {
		var path = args[0],
			value = args[1];
		descriptor.attributes += ' value="' + (value.__interpolable__ ? value.output(context) : value) + '"';
	},
	contentEditable: function(context, descriptor, args) {
		var value = args[1];
		descriptor.attributes += ' contenteditable';
		descriptor.children = value.output(context);
	},
	setClass: function(context, descriptor, args) {
		var name = args[0],
			flag = args[1];
		if ((flag.__interpolable__ && flag.output(context)) || flag)
			descriptor.classes += (descriptor.classes ? ' ' : '') + (name.__interpolable__ ? name.output(context) : name);
	},
	css: function(context, descriptor, args) {
		var prop = args[0],
			value = args[1];
		descriptor.style += prop + ':' + (value.__interpolable__ ? value.output(context) : value);
	},
	visible: function(context, descriptor, args) {
		var flag = args[0],
			val = (flag && flag.__interpolable__) ? flag.output(context) : flag;
		if (!val)
			descriptor.style += 'display:none;';
	},
	//_________________________________ EVENTS
	on: function() {},
	once: function() {},
	off: function() {},
	//_________________________________ CLIENT/SERVER
	client: function(context, descriptor, args) {
		if (context.env.data.isServer)
			return;
		args[0].toHTMLString(context, descriptor);
	},
	server: function(context, descriptor, args) {
		if (!context.env.data.isServer)
			return;
		args[0].toHTMLString(context, descriptor);
	},
	//_______________________________ SUSPEND RENDER
	suspendUntil: function(context, descriptor, args) {
		var xpr = args[0],
			index = args[1],
			templ = args[2],
			val = xpr.__interpolable__ ? xpr.output(context) : xpr,
			rest = new Template(templ._queue.slice(index));
		if (val)
			rest.toHTMLString(context, descriptor);
	},
	container: function(context, descriptor, args) {
		var sod = new SOD(),
			opt = args[0],
			template = args[1];
		template.toHTMLString(context, sod);
		descriptor.children += sod.children;
	}
};

Template.prototype.toHTMLString = function(context, descriptor) {
	context = context || new Context();
	descriptor = descriptor ||  new SOD();
	var handler = this._queue[0],
		index = 0,
		f;
	while (handler) {
		f = null;
		switch (handler.type) {
			case '*':
				f = methods[handler.handler];
				break;
			case 'string':
			case 'context':
				f = handler.handler;
				break;
			case 'custom':
				f = handler.handler.string;
				break;
		}
		if (!f) {
			handler = this._queue[++index];
			continue;
		}
		if (f.__yTemplate__)
			f.toHTMLString(descriptor.context || context, descriptor);
		else
			f(descriptor.context || context, descriptor, handler.args);
		if (handler.suspendAfter)
			break;
		handler = this._queue[++index];
	}
	return descriptor.children;
};

module.exports = methods;
<|endoftext|>


<commit_before>const btcProof = require('../index'),
  assert = require('assert');

const BLOCK_100K = {
  txs: [
    '8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87',
    'fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4',
    '6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4',
    'e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d'
  ]
};

describe('getProof', function() {
  it('for block 100k tx[0]', function() {
    const txs = BLOCK_100K.txs;

    // >>> i = '6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4'.decode('hex')[::-1]
    // >>> j = 'e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d'.decode('hex')[::-1]
    // >>> dbl_sha256(i+j).decode('hex')[::-1].encode('hex')
    // '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49'
    const hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
      expProof = [
        { hash: txs[1], path: 2},
        { hash: hRight, path: 2}
      ];

    var proof = btcProof.getProof(txs, 0);
    assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
  });

  it('for block 106022 tx[0]', function() {
    const txs = [
      '3a459eab5f0cf8394a21e04d2ed3b2beeaa59795912e20b9c680e9db74dfb18c',
      'be38f46f0eccba72416aed715851fd07b881ffb7928b7622847314588e06a6b7',
      'd173f2a12b6ff63a77d9fe7bbb590bdb02b826d07739f90ebb016dc9297332be',
      '59d1e83e5268bbb491234ff23cbbf2a7c0aa87df553484afee9e82385fc7052f',
      'f1ce77a69d06efb79e3b08a0ff441fa3b1deaf71b358df55244d56dd797ac60c',
      '84053cba91fe659fd3afa1bf2fd0e3746b99215b50cd74e44bda507d8edf52e0'
    ],
      expProof = [
        { hash: txs[1], path: 2},
        { hash: 'f6ae335dc2d2aecb6a255ebd03caaf6820e6c0534531051066810080e0d822c8', path: 2},
        { hash: '15eca0aa3e2cc2b9b4fbe0629f1dda87f329500fcdcd6ef546d163211266b3b3', path: 2}
      ];

    var proof = btcProof.getProof(txs, 0);
    assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
  });
});

describe('getMerkleRoot', function() {
  it('should return merkle root of block 100k', function() {
    const txs = BLOCK_100K.txs,
      expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });

  it('should return merkle root of block 100k-1 (odd num of tx)', function() {
    const txs = [
      '110ed92f558a1e3a94976ddea5c32f030670b5c58c3cc4d857ac14d7a1547a90'
    ],
      expMerkle = '110ed92f558a1e3a94976ddea5c32f030670b5c58c3cc4d857ac14d7a1547a90';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });

  it('should return merkle root of block 106022', function() {
    const txs = [
      '3a459eab5f0cf8394a21e04d2ed3b2beeaa59795912e20b9c680e9db74dfb18c',
      'be38f46f0eccba72416aed715851fd07b881ffb7928b7622847314588e06a6b7',
      'd173f2a12b6ff63a77d9fe7bbb590bdb02b826d07739f90ebb016dc9297332be',
      '59d1e83e5268bbb491234ff23cbbf2a7c0aa87df553484afee9e82385fc7052f',
      'f1ce77a69d06efb79e3b08a0ff441fa3b1deaf71b358df55244d56dd797ac60c',
      '84053cba91fe659fd3afa1bf2fd0e3746b99215b50cd74e44bda507d8edf52e0'
    ],
      expMerkle = '9cdf7722eb64015731ba9794e32bdefd9cf69b42456d31f5e59aedb68c57ed52';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });
});

describe('getTxMerkle', function() {
  it('for block 100k tx[0]', function() {
    const txs = BLOCK_100K.txs,
      hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
      proof = [{ hash: txs[1], path: 2}, { hash: hRight, path: 2}],
      expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

    var merkle = btcProof.getTxMerkle(txs[0], proof);
    assert.strictEqual(merkle, expMerkle);
  });

  it('for block 106022 tx[0]', function() {
    const txs = [
      '3a459eab5f0cf8394a21e04d2ed3b2beeaa59795912e20b9c680e9db74dfb18c',
      'be38f46f0eccba72416aed715851fd07b881ffb7928b7622847314588e06a6b7',
      'd173f2a12b6ff63a77d9fe7bbb590bdb02b826d07739f90ebb016dc9297332be',
      '59d1e83e5268bbb491234ff23cbbf2a7c0aa87df553484afee9e82385fc7052f',
      'f1ce77a69d06efb79e3b08a0ff441fa3b1deaf71b358df55244d56dd797ac60c',
      '84053cba91fe659fd3afa1bf2fd0e3746b99215b50cd74e44bda507d8edf52e0'
    ],
      proof = [
        { hash: txs[1], path: 2},
        { hash: 'f6ae335dc2d2aecb6a255ebd03caaf6820e6c0534531051066810080e0d822c8', path: 2},
        { hash: '15eca0aa3e2cc2b9b4fbe0629f1dda87f329500fcdcd6ef546d163211266b3b3', path: 2}
      ],
      expMerkle = '9cdf7722eb64015731ba9794e32bdefd9cf69b42456d31f5e59aedb68c57ed52';

    var merkle = btcProof.getTxMerkle(txs[0], proof);
    assert.strictEqual(merkle, expMerkle);
  });
});
<commit_msg>dedupe txs<commit_after>const btcProof = require('../index'),
  assert = require('assert');

const BLOCK_100K = {
  txs: [
    '8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87',
    'fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4',
    '6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4',
    'e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d'
  ]
},
  BLOCK_106022 = {
    txs: [
      '3a459eab5f0cf8394a21e04d2ed3b2beeaa59795912e20b9c680e9db74dfb18c',
      'be38f46f0eccba72416aed715851fd07b881ffb7928b7622847314588e06a6b7',
      'd173f2a12b6ff63a77d9fe7bbb590bdb02b826d07739f90ebb016dc9297332be',
      '59d1e83e5268bbb491234ff23cbbf2a7c0aa87df553484afee9e82385fc7052f',
      'f1ce77a69d06efb79e3b08a0ff441fa3b1deaf71b358df55244d56dd797ac60c',
      '84053cba91fe659fd3afa1bf2fd0e3746b99215b50cd74e44bda507d8edf52e0'
    ]
  };

describe('getProof', function() {
  it('for block 100k tx[0]', function() {
    const txs = BLOCK_100K.txs;

    // >>> i = '6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4'.decode('hex')[::-1]
    // >>> j = 'e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d'.decode('hex')[::-1]
    // >>> dbl_sha256(i+j).decode('hex')[::-1].encode('hex')
    // '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49'
    const hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
      expProof = [
        { hash: txs[1], path: 2},
        { hash: hRight, path: 2}
      ];

    var proof = btcProof.getProof(txs, 0);
    assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
  });

  it('for block 106022 tx[0]', function() {
    const txs = BLOCK_106022.txs,
      expProof = [
        { hash: txs[1], path: 2},
        { hash: 'f6ae335dc2d2aecb6a255ebd03caaf6820e6c0534531051066810080e0d822c8', path: 2},
        { hash: '15eca0aa3e2cc2b9b4fbe0629f1dda87f329500fcdcd6ef546d163211266b3b3', path: 2}
      ];

    var proof = btcProof.getProof(txs, 0);
    assert.strictEqual(JSON.stringify(proof), JSON.stringify(expProof));
  });
});

describe('getMerkleRoot', function() {
  it('should return merkle root of block 100k', function() {
    const txs = BLOCK_100K.txs,
      expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });

  it('should return merkle root of block 100k-1 (odd num of tx)', function() {
    const txs = [
      '110ed92f558a1e3a94976ddea5c32f030670b5c58c3cc4d857ac14d7a1547a90'
    ],
      expMerkle = '110ed92f558a1e3a94976ddea5c32f030670b5c58c3cc4d857ac14d7a1547a90';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });

  it('should return merkle root of block 106022', function() {
    const txs = BLOCK_106022.txs,
      expMerkle = '9cdf7722eb64015731ba9794e32bdefd9cf69b42456d31f5e59aedb68c57ed52';

    var merkle = btcProof.getProof(txs);
    assert.strictEqual(merkle, expMerkle);
  });
});

describe('getTxMerkle', function() {
  it('for block 100k tx[0]', function() {
    const txs = BLOCK_100K.txs,
      hRight = '8e30899078ca1813be036a073bbf80b86cdddde1c96e9e9c99e9e3782df4ae49',
      proof = [{ hash: txs[1], path: 2}, { hash: hRight, path: 2}],
      expMerkle = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766';

    var merkle = btcProof.getTxMerkle(txs[0], proof);
    assert.strictEqual(merkle, expMerkle);
  });

  it('for block 106022 tx[0]', function() {
    const txs = BLOCK_106022.txs,
      proof = [
        { hash: txs[1], path: 2},
        { hash: 'f6ae335dc2d2aecb6a255ebd03caaf6820e6c0534531051066810080e0d822c8', path: 2},
        { hash: '15eca0aa3e2cc2b9b4fbe0629f1dda87f329500fcdcd6ef546d163211266b3b3', path: 2}
      ],
      expMerkle = '9cdf7722eb64015731ba9794e32bdefd9cf69b42456d31f5e59aedb68c57ed52';

    var merkle = btcProof.getTxMerkle(txs[0], proof);
    assert.strictEqual(merkle, expMerkle);
  });
});
<|endoftext|>


<commit_before>define(function (require, exports, moudle) {
    alifenxi.track("course_video_view", {
        "course_name": $('#course_name').html()
    });
    var Pager = require('js/widget/pager');
    var commentBtn = $("#comment-submit");
    var commentArea = $("#user-comment-editor");
    var user_avator = ($('#ne_user_avator').val() - 0) || 1;
    var nickname = commentBtn.attr("data-nickname") || $('#ne_user_name').val();
    var userId = $('#ne_user_id').val() ;
    var courseid =  commentBtn.attr("data-course-id");

    function addPage(){
        var page = new Pager({
          container : $('#video_pager'),
          sum : $('#comment_list').attr('data-num') - 0,
          count : 10,
          step : 10,
          showCount : false,
          start :0,
          onChange : function(num, count){
            drawComment(num + 1 ,count)
          }
        });
      page.init();
    };

    addPage();

    function drawComment(num,count){
        var tpl =
            ['<% comments.forEach(function(val){%>',
                '
',
                    '
',
                        '<div class="user-head-icon user-head-<%=val.avator||1%>">
',
                    '
',
                    '
',
                        '<%=val.nickname%>',
                        '

<%=val.comment%>

',
                        '<% var d = new Date(val.updatetime).toLocaleDateString();%>',
                        '<time class="comment-time"><%=val.updatetime%></time>',
                    '
',
                '
',
            '<%})%>'].join("");
        $.get('/course/getcomment',{id: courseid ,page:num ,limit:count},function(result){
            if(result.errno == 0){
                $('#comment_list').html(_.template(tpl ,{comments : result.data}))
            }
        },'json')
    };

    commentBtn.unbind("click").on("click", function (e) {
        var data = {};
        var userId = commentBtn.attr("data-user-id");
        data.comment = commentArea.val();
        data.id = courseid;
        if(data.comment.trim()==''){
            return false;
        }

        $.post('/course/comment', data, 'json').done(function (res) {
            if (res.errno == 0) {
                var tmp = [
                    '
',
                    '
',
                    '

',
                    '
',
                    '
',
                    '', nickname, '',
                    '

', data.comment, '

',
                    '<time class="comment-time">刚刚</time>',
                    '
',
                    '
'
                ].join('');
                ALERT('提示','评论成功！');
                $(tmp).prependTo('#comment_list');
                commentArea.val('');
            }
        });

    });

})<commit_msg>remove right click on video page<commit_after>define(function (require, exports, moudle) {
    alifenxi.track("course_video_view", {
        "course_name": $('#course_name').html()
    });
    var Pager = require('js/widget/pager');
    var commentBtn = $("#comment-submit");
    var commentArea = $("#user-comment-editor");
    var user_avator = ($('#ne_user_avator').val() - 0) || 1;
    var nickname = commentBtn.attr("data-nickname") || $('#ne_user_name').val();
    var userId = $('#ne_user_id').val();
    var courseid = commentBtn.attr("data-course-id");

    function addPage() {
        var page = new Pager({
            container: $('#video_pager'),
            sum: $('#comment_list').attr('data-num') - 0,
            count: 10,
            step: 10,
            showCount: false,
            start: 0,
            onChange: function (num, count) {
                drawComment(num + 1, count)
            }
        });
        page.init();
    };

    addPage();

    function drawComment(num, count) {
        var tpl =
            ['<% comments.forEach(function(val){%>',
                '
',
                '
',
                '<div class="user-head-icon user-head-<%=val.avator||1%>">
',
                '
',
                '
',
                '<%=val.nickname%>',
                '

<%=val.comment%>

',
                '<% var d = new Date(val.updatetime).toLocaleDateString();%>',
                '<time class="comment-time"><%=val.updatetime%></time>',
                '
',
                '
',
                '<%})%>'].join("");
        $.get('/course/getcomment', {id: courseid, page: num, limit: count}, function (result) {
            if (result.errno == 0) {
                $('#comment_list').html(_.template(tpl, {comments: result.data}))
            }
        }, 'json')
    };

    commentBtn.unbind("click").on("click", function (e) {
        var data = {};
        var userId = commentBtn.attr("data-user-id");
        data.comment = commentArea.val();
        data.id = courseid;
        if (data.comment.trim() == '') {
            return false;
        }

        $.post('/course/comment', data, 'json').done(function (res) {
            if (res.errno == 0) {
                var tmp = [
                    '
',
                    '
',
                    '

',
                    '
',
                    '
',
                    '', nickname, '',
                    '

', data.comment, '

',
                    '<time class="comment-time">刚刚</time>',
                    '
',
                    '
'
                ].join('');
                ALERT('提示', '评论成功！');
                $(tmp).prependTo('#comment_list');
                commentArea.val('');
            }
        });

        document.oncontextmenu = function () {
            return false;
        }
    });

})<|endoftext|>


<commit_before>/*
 * index.js: Top-level include for the AWS module.
 *
 *  (C) Microsoft Open Technologies, Inc.   All rights reserved.
 *
 */

exports.compute = require('./compute');
exports.storage = require('./storage');
<commit_msg>changed AWS to Azure<commit_after>/*
 * index.js: Top-level include for the Azure module.
 *
 *  (C) Microsoft Open Technologies, Inc.   All rights reserved.
 *
 */

exports.compute = require('./compute');
exports.storage = require('./storage');
exports.database = require('./database');
<|endoftext|>


<commit_before>var assert = require('assert'),
    xmlparser = require('./../index.js');

describe('XmlParserMiddleware', function () {

    describe('#testMime', function () {

        var regexp = /^(text\/xml|application\/([\w!#\$%&\*`\-\.\^~]+\+)?xml)$/i;

        it('should detect common XML mime-types', function () {

            assert.equal(true, regexp.test('text/xml'));
            assert.equal(true, regexp.test('application/xml'));
            assert.equal(true, regexp.test('application/rss+xml'));
            assert.equal(true, regexp.test('application/atom+xml'));
            assert.equal(true, regexp.test('application/vnd.google-earth.kml+xml'));
            assert.equal(true, regexp.test('application/xhtml+xml'));
        });

        it('should not interfere with other body parsers', function () {

            assert.equal(false, regexp.test('application/json'));
            assert.equal(false, regexp.test('application/x-www-form-urlencoded'));
            assert.equal(false, regexp.test('multipart/form-data'));

        });
    });

});

<commit_msg>chore: use same regexp in tests as in module itself<commit_after>var assert = require('assert'),
    xmlparser = require('./../index.js');

describe('XmlParserMiddleware', function () {

    describe('#testMime', function () {

        var regexp = xmlparser.regexp;

        it('should detect common XML mime-types', function () {

            assert.equal(true, regexp.test('text/xml'));
            assert.equal(true, regexp.test('application/xml'));
            assert.equal(true, regexp.test('application/rss+xml'));
            assert.equal(true, regexp.test('application/atom+xml'));
            assert.equal(true, regexp.test('application/vnd.google-earth.kml+xml'));
            assert.equal(true, regexp.test('application/xhtml+xml'));
        });

        it('should not interfere with other body parsers', function () {

            assert.equal(false, regexp.test('application/json'));
            assert.equal(false, regexp.test('application/x-www-form-urlencoded'));
            assert.equal(false, regexp.test('multipart/form-data'));

        });
    });

});

<|endoftext|>


<commit_before>sjs({

required:[
	{'SpliceJS.UI':'../splice.ui.js'},
	{'SpliceJS.Controls':'splice.controls.scrollpanel.js'},
	{'Doc':'{sjshome}/modules/splice.document.js'},
	'splice.controls.listbox.css',
	'splice.controls.listbox.html'
],

definition:function(sjs){

	var Class = this.sjs.Class
	,		event = sjs.event
	,		exports = sjs.exports
	,		debug = this.sjs.debug
	, 	components = this.scope.components;

	var	UIControl = this.scope.SpliceJS.UI.UIControl
	,		dom = this.scope.Doc.dom;

	var ListBoxController = Class(function ListBoxController(){
			this.super();
			this.listItems = [];

			event(this).attach({
				onListItem : event.multicast,
				onDataItem : event.multicast,
				onResize   : event.multicast
			});

			if(!this.itemTemplate) this.itemTemplate = DefaultListItem;

	}).extend(UIControl);

	ListBoxController.prototype.initialize = function(){
			event(this.views.root).attach({	onclick	:	event.unicast	})
			.onclick.subscribe(this.click,this);

			if(this.ref.contentClient) {
				this.dom = this.ref.contentClient.views.root;
			}
			else {
				this.dom = this.views.root;
			}
	};

	ListBoxController.prototype.click = function(args){
		var parent = args.source;
		while(parent){
			if(parent.__sjs_item_index__ != null) break;
			parent = parent.parentNode;
		}
		//no data item index found
		if(parent == null) return;

		var idx = parent.__sjs_item_index__;
		console.log(this.dataItem[idx]);

		//notify list items listener
		this.onListItem(this.listItems[idx]);

		//notify on data item
		this.onDataItem(this.dataItem[idx]);
	};

	ListBoxController.prototype.dataIn = function(dataItem){
		this.dataItem = dataItem;
		//this.dom.clear();

		var item = null;

		// update existing items if any
		for(var i=0; i<this.listItems.length; i++){
			var item = this.listItems[i];

			if(this.dataPath){
				item.dataIn(sjs.propvalue(this.dataItem[i])(this.dataPath).value);
			} else {
				item.dataIn(this.dataItem[i]);
			}
		}

		// add new items
		for(var i= this.listItems.length; i<dataItem.length; i++) {
			if(this.itemTemplate) {
				item = new this.itemTemplate({parent:this});
				this.listItems.push(item);

				if(this.dataPath){
					item.dataIn(sjs.propvalue(this.dataItem[i])(this.dataPath).value);
				} else {
					item.dataIn(this.dataItem[i]);
				}

				item.concrete.dom.__sjs_item_index__ = i;

				this.dom.content(sjs.view(item.concrete.dom)).add();
				if(typeof item.onAttached == 'function')
					item.onAttached();
			}
		}

		this.reflow();
		if(!this.ref.scrollPanel) this.onResize(this);
	};

	ListBoxController.prototype.reflow = function(){
		if(!this.ref.scrollPanel) return;

		this.ref.scrollPanel.reflow();

	};

	var DefaultListItem = Class(function DefaultListItem(){
			this.concrete =  {
				dom : document.createElement('div')
			};

			this.concrete.dom.className = '-sjs-listbox-item';
	});

	DefaultListItem.prototype.dataIn = function(dataItem){
		if(!dataItem) return;
		this.dataItem = dataItem;
		this.concrete.dom.innerHTML = dataItem.toString();
	};

	var ListItemController = Class(function ListItemController(args){
		this.super(args);

		var self = this;
		this.concrete.dom.onclick = function(){
			if(typeof self.onClick === 'function' )
				self.onClick(self.dataItem);
		};

	}).extend(UIControl);

	ListItemController.prototype.dataIn = function(dataItem){
		this.dataItem = dataItem;
		this.concrete.applyContent(dataItem);
		this.dataOut(dataItem);
	};

	var GroupedListItem = Class(function GroupedListItem(args){
		this.groupInstance = null;
		this.itemInstances = [];
	});

	GroupedListItem.prototype.dataIn = function(dataItem){

		if(!this.groupInstance) {
			if(this.groupTemplate) {
				this.groupInstance = new this.groupTemplate({parent:this});
				Doc.$(this.elements.root).embed(this.groupInstance);
			}
		}

		if(this.groupInstance) this.groupInstance.dataIn(dataItem);

		if(this.itemInstances.length < 1) {
			if(dataItem.children) {
			for(var i=0; i<dataItem.children.length; i++){
				var item = new this.groupItemTemplate({parent:this});
				item.dataIn(dataItem.children[i]);
				this.itemInstances.push(item);
				this.elements.root.appendChild(item.concrete.dom);
			}}
		}

	};

	// list factory
	var ListBox = Class(function ListBox(args){

		if(args.isScrollable)
			return new components.ScrollableListBox(args);
		else
			return new components.StretchListBox(args);
	});

	exports.scope(
		ListBoxController
	)

	//exporting objects
	exports.module(
		ListItemController, ListBoxController, ListBox
	)

}

});
<commit_msg>hide _itemClick method in listbox control<commit_after>sjs({

required:[
	{'SpliceJS.UI':'../splice.ui.js'},
	{'SpliceJS.Controls':'splice.controls.scrollpanel.js'},
	{'Doc':'{sjshome}/modules/splice.document.js'},
	'splice.controls.listbox.css',
	'splice.controls.listbox.html'
],

definition:function(sjs){

	var Class = this.sjs.Class
	,		event = sjs.event
	,		exports = sjs.exports
	,		debug = this.sjs.debug
	, 	components = this.scope.components;

	var	UIControl = this.scope.SpliceJS.UI.UIControl
	,		dom = this.scope.Doc.dom;

	var ListBoxController = Class(function ListBoxController(){
			this.super();
			this.listItems = [];

			event(this).attach({
				onListItem : event.multicast,
				onDataItem : event.multicast,
				onResize   : event.multicast
			});

			if(!this.itemTemplate) this.itemTemplate = DefaultListItem;

	}).extend(UIControl);

	ListBoxController.prototype.initialize = function(){
			event(this.views.root).attach({	onclick	:	event.unicast	})
			.onclick.subscribe(_itemClick,this);

			if(this.ref.contentClient) {
				this.dom = this.ref.contentClient.views.root;
			}
			else {
				this.dom = this.views.root;
			}
	};

	/**
		Private
	*/
	function _itemClick(args){
		var parent = args.source;
		while(parent){
			if(parent.__sjs_item_index__ != null) break;
			parent = parent.parentNode;
		}
		//no data item index found
		if(parent == null) return;

		var idx = parent.__sjs_item_index__;
		console.log(this.dataItem[idx]);

		//notify list items listener
		this.onListItem(this.listItems[idx]);

		//notify on data item
		this.onDataItem(this.dataItem[idx]);
	};

	ListBoxController.prototype.dataIn = function(dataItem){
		this.dataItem = dataItem;
		//this.dom.clear();

		var item = null;

		// update existing items if any
		for(var i=0; i<this.listItems.length; i++){
			var item = this.listItems[i];

			if(this.dataPath){
				item.dataIn(sjs.propvalue(this.dataItem[i])(this.dataPath).value);
			} else {
				item.dataIn(this.dataItem[i]);
			}
		}

		// add new items
		for(var i= this.listItems.length; i<dataItem.length; i++) {
			if(this.itemTemplate) {
				item = new this.itemTemplate({parent:this});
				this.listItems.push(item);

				if(this.dataPath){
					item.dataIn(sjs.propvalue(this.dataItem[i])(this.dataPath).value);
				} else {
					item.dataIn(this.dataItem[i]);
				}

				item.concrete.dom.__sjs_item_index__ = i;

				this.dom.content(sjs.view(item.concrete.dom)).add();
				if(typeof item.onAttached == 'function')
					item.onAttached();
			}
		}

		this.reflow();
		if(!this.ref.scrollPanel) this.onResize(this);
	};

	ListBoxController.prototype.reflow = function(){
		if(!this.ref.scrollPanel) return;

		this.ref.scrollPanel.reflow();

	};

	var DefaultListItem = Class(function DefaultListItem(){
			this.concrete =  {
				dom : document.createElement('div')
			};

			this.concrete.dom.className = '-sjs-listbox-item';
	});

	DefaultListItem.prototype.dataIn = function(dataItem){
		if(!dataItem) return;
		this.dataItem = dataItem;
		this.concrete.dom.innerHTML = dataItem.toString();
	};

	var ListItemController = Class(function ListItemController(args){
		this.super(args);

		var self = this;
		this.concrete.dom.onclick = function(){
			if(typeof self.onClick === 'function' )
				self.onClick(self.dataItem);
		};

	}).extend(UIControl);

	ListItemController.prototype.dataIn = function(dataItem){
		this.dataItem = dataItem;
		this.concrete.applyContent(dataItem);
		this.dataOut(dataItem);
	};

	var GroupedListItem = Class(function GroupedListItem(args){
		this.groupInstance = null;
		this.itemInstances = [];
	});

	GroupedListItem.prototype.dataIn = function(dataItem){

		if(!this.groupInstance) {
			if(this.groupTemplate) {
				this.groupInstance = new this.groupTemplate({parent:this});
				Doc.$(this.elements.root).embed(this.groupInstance);
			}
		}

		if(this.groupInstance) this.groupInstance.dataIn(dataItem);

		if(this.itemInstances.length < 1) {
			if(dataItem.children) {
			for(var i=0; i<dataItem.children.length; i++){
				var item = new this.groupItemTemplate({parent:this});
				item.dataIn(dataItem.children[i]);
				this.itemInstances.push(item);
				this.elements.root.appendChild(item.concrete.dom);
			}}
		}

	};

	// list factory
	var ListBox = Class(function ListBox(args){

		if(args.isScrollable)
			return new components.ScrollableListBox(args);
		else
			return new components.StretchListBox(args);
	});

	exports.scope(
		ListBoxController
	)

	//exporting objects
	exports.module(
		ListItemController, ListBoxController, ListBox
	)

}

});
<|endoftext|>


<commit_before>/* global atom */
'use strict'
module.exports = PlantumlViewerView

var CompositeDisposable = require('atom').CompositeDisposable
var ScrollView = require('atom-space-pen-views').ScrollView
var plantuml = require('node-plantuml')
var inherits = require('./cs-inherits')
var fs = require('fs')
var svgPanZoom = require('svg-pan-zoom/src/svg-pan-zoom')

PlantumlViewerView.content = function () {
  PlantumlViewerView.div({
    class: 'plantuml-viewer native-key-bindings',
    tabindex: -1
  })
}

inherits(PlantumlViewerView, ScrollView)
function PlantumlViewerView (editor) {
  ScrollView.call(this)

  this.attached = attached
  this.detached = detached

  var self = this
  var disposables
  var loading = false
  var waitingToLoad = false

  var panZoom
  var centerPan
  var interval
  var width
  var height

  self.on('click', function () {
    atom.workspace.paneForURI(editor.getURI()).activate()
  })

  function attached () {
    disposables = new CompositeDisposable()
    updateImage()
    if (atom.config.get('plantuml-viewer.liveUpdate')) {
      disposables.add(editor.getBuffer().onDidChange(function () {
        if (loading) {
          waitingToLoad = true
          return
        }
        updateImage()
      }))

      interval = setInterval(function () {
        if (panZoom && self.is(':visible')) {
          if (width !== self.width() || height !== self.height()) {
            updateImage()
            width = self.width()
            height = self.height()
          }
        }
      }, 500)
    }

    atom.commands.add(self.element, 'core:save-as', function (event) {
      event.stopPropagation()
      saveAs()
    })
    atom.commands.add(self.element, 'core:save', function (event) {
      event.stopPropagation()
      saveAs()
    })
  }

  function detached () {
    disposables.dispose()
    if (panZoom) panZoom.destroy()
    panZoom = undefined

    clearInterval(interval)
  }

  function updateImage () {
    loading = true

    var options = {
      format: 'svg',
      dot: atom.config.get('plantuml-viewer.graphvizDotExecutable'),
      config: atom.config.get('plantuml-viewer.configFile')
    }

    var gen = plantuml.generate(editor.getText(), options)

    var chunks = []
    gen.out.on('data', function (chunk) { chunks.push(chunk) })
    gen.out.on('end', function () {
      var data = Buffer.concat(chunks)
      self.html(data.toString())

      var newPanZoom = svgPanZoom(self.find('svg')[0])

      newPanZoom.center()
      var oldCenter = centerPan
      centerPan = newPanZoom.getPan()

      if (panZoom) {
        var oldPanZoom = panZoom

        var oldZoom = oldPanZoom.getZoom()
        oldPanZoom.resetZoom()
        var x = oldPanZoom.getPan().x - oldCenter.x
        var y = oldPanZoom.getPan().y - oldCenter.y

        newPanZoom.panBy({ x: x, y: y })
        newPanZoom.zoom(oldZoom)

        oldPanZoom.destroy()
        oldPanZoom = undefined
      }

      panZoom = newPanZoom

      if (waitingToLoad) {
        waitingToLoad = false
        updateImage()
      }
      loading = false
    })
  }

  function saveAs () {
    var filters = [
      { name: 'Encapsulated PostScript (.eps)', extensions: ['eps'] },
      { name: 'Scalable Vector Graphics (.svg)', extensions: ['svg'] },
      { name: 'Portable Network Graphics (.png)', extensions: ['png'] }
    ]
    var filePath = editor.getPath().replace(/\.[^/.]+$/, '')
    var options = { defaultPath: filePath, filters: filters }
    var savePath = atom.showSaveDialogSync(options)

    if (savePath) {
      var extension = savePath.substr(savePath.lastIndexOf('.') + 1)
      var fileStream = fs.createWriteStream(savePath)

      var plantumlOptions = {
        format: extension,
        dot: atom.config.get('plantuml-viewer.graphvizDotExecutable'),
        config: atom.config.get('plantuml-viewer.configFile')
      }

      var gen = plantuml.generate(editor.getText(), plantumlOptions)
      gen.out.pipe(fileStream)
    }
  }
}
<commit_msg>Fix problem of updating the diagram while it is not visible<commit_after>/* global atom */
'use strict'
module.exports = PlantumlViewerView

var CompositeDisposable = require('atom').CompositeDisposable
var ScrollView = require('atom-space-pen-views').ScrollView
var plantuml = require('node-plantuml')
var inherits = require('./cs-inherits')
var fs = require('fs')
var svgPanZoom = require('svg-pan-zoom/src/svg-pan-zoom')

PlantumlViewerView.content = function () {
  PlantumlViewerView.div({
    class: 'plantuml-viewer native-key-bindings',
    tabindex: -1
  })
}

inherits(PlantumlViewerView, ScrollView)
function PlantumlViewerView (editor) {
  ScrollView.call(this)

  this.attached = attached
  this.detached = detached

  var self = this
  var disposables
  var loading = false
  var waitingToLoad = false

  var panZoom
  var centerPan
  var interval
  var width
  var height

  self.on('click', function () {
    atom.workspace.paneForURI(editor.getURI()).activate()
  })

  atom.workspace.onDidChangeActivePaneItem(function () {
    // The DOM and visibility is not yet updated
    var wasVisible = self.is(':visible')
    if (wasVisible) return
    // wait until update is complete
    setTimeout(function () {
      updatePanZoom()
    }, 0)
  })

  function attached () {
    disposables = new CompositeDisposable()
    updateImage()
    if (atom.config.get('plantuml-viewer.liveUpdate')) {
      disposables.add(editor.getBuffer().onDidChange(function () {
        if (loading) {
          waitingToLoad = true
          return
        }
        updateImage()
      }))

      interval = setInterval(function () {
        if (panZoom) {
          if (width !== self.width() || height !== self.height()) {
            updateImage()
            width = self.width()
            height = self.height()
          }
        }
      }, 500)
    }

    atom.commands.add(self.element, 'core:save-as', function (event) {
      event.stopPropagation()
      saveAs()
    })
    atom.commands.add(self.element, 'core:save', function (event) {
      event.stopPropagation()
      saveAs()
    })
  }

  function detached () {
    disposables.dispose()
    if (panZoom) panZoom.destroy()
    panZoom = undefined

    clearInterval(interval)
  }

  function updatePanZoom () {
    if (!self.is(':visible')) return

    var svgElement = self.find('svg')[0]
    if (!svgElement) return

    var newPanZoom = svgPanZoom(svgElement)

    newPanZoom.center()
    var oldCenter = centerPan
    centerPan = newPanZoom.getPan()

    if (panZoom) {
      var oldPanZoom = panZoom

      var oldZoom = oldPanZoom.getZoom()
      oldPanZoom.resetZoom()
      var x = oldPanZoom.getPan().x - oldCenter.x
      var y = oldPanZoom.getPan().y - oldCenter.y

      newPanZoom.panBy({ x: x, y: y })
      newPanZoom.zoom(oldZoom)

      oldPanZoom.destroy()
      oldPanZoom = undefined
    }

    panZoom = newPanZoom
  }

  function updateImage () {
    loading = true

    var options = {
      format: 'svg',
      dot: atom.config.get('plantuml-viewer.graphvizDotExecutable'),
      config: atom.config.get('plantuml-viewer.configFile')
    }

    var gen = plantuml.generate(editor.getText(), options)

    var chunks = []
    gen.out.on('data', function (chunk) { chunks.push(chunk) })
    gen.out.on('end', function () {
      var data = Buffer.concat(chunks)
      self.html(data.toString())

      updatePanZoom()

      if (waitingToLoad) {
        waitingToLoad = false
        updateImage()
      }
      loading = false
    })
  }

  function saveAs () {
    var filters = [
      { name: 'Encapsulated PostScript (.eps)', extensions: ['eps'] },
      { name: 'Scalable Vector Graphics (.svg)', extensions: ['svg'] },
      { name: 'Portable Network Graphics (.png)', extensions: ['png'] }
    ]
    var filePath = editor.getPath().replace(/\.[^/.]+$/, '')
    var options = { defaultPath: filePath, filters: filters }
    var savePath = atom.showSaveDialogSync(options)

    if (savePath) {
      var extension = savePath.substr(savePath.lastIndexOf('.') + 1)
      var fileStream = fs.createWriteStream(savePath)

      var plantumlOptions = {
        format: extension,
        dot: atom.config.get('plantuml-viewer.graphvizDotExecutable'),
        config: atom.config.get('plantuml-viewer.configFile')
      }

      var gen = plantuml.generate(editor.getText(), plantumlOptions)
      gen.out.pipe(fileStream)
    }
  }
}
<|endoftext|>


<commit_before>let regExp = /(?:https?:\/\/(?:www\.)?)?((?:casemates|mediocre|mediocritee|meh|morningsave|pastadrop|sidedeal|stellacarmina)\.com)?\/(deals|polls)\/([-\w]+)/;
if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'staging') {
    // Make iframes for any localhost deal/poll links on debug
    regExp = /(?:https?:\/\/)?((?:127\.0\.0\.1|localhost):\d{4})?\/(deals|polls)\/([-\w]+)/;
}

module.exports = function(md) {
    var defaultRender = md.renderer.rules.link_open || function(tokens, idx, options, env, self) {
        return self.renderToken(tokens, idx, options);
    };

    md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
        var openToken = tokens[idx];
        var hrefIndex = openToken.attrIndex('href');

        // Ensure we have an "href" attribute
        if (hrefIndex !== -1) {
            var href = openToken.attrs[hrefIndex][1];

            // Ensure we have an "href" attribute value
            if (href) {
                var textToken = tokens[idx + 1];

                // Ensure we have a text token and the text matches the URL pattern instead of [text](http://example.com/)
                if (textToken && textToken.content && regExp.test(textToken.content)) {
                    var matches = href.match(regExp);

                    var embedUrl = `/${matches.slice(2).join('/')}/embed`;

                    if (matches[1]) {
                        embedUrl = `https://${matches[1]}${embedUrl}`;
                    }

                    textToken.content = '';
                    tokens[idx + 2].hidden = true;

                    return `<iframe class="${matches[2]}" frameborder="0" scrolling="no" src="${embedUrl}"></iframe>`;
                }
            }
        }

        return defaultRender(tokens, idx, options, env, self);
    };
};<commit_msg>Fix tests and allow local iframes in debug<commit_after>const productionSites = '(?:https?:\\/\\/(?:www\\.)?)?(?<site>(?:casemates|mediocre|mediocritee|meh|morningsave|pastadrop|sidedeal|stellacarmina)\\.com)?';
const debugSites = '(?:https?:\\/\\/)?(?<siteLocal>(?:127\\.0\\.0\\.1|localhost):\\d{4})?';
const path = '\\/(?<path>(?<type>deals|polls)\\/(?:[-\\w]+))';
let regExp = new RegExp(`${productionSites}${path}`);
if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'staging') {
    // Allow iframes for any localhost deal/poll links on debug, but also make sure tests pass...
    regExp = new RegExp(`(?:(?:${productionSites})|(?:${debugSites}))${path}`);
}

module.exports = function(md) {
    var defaultRender = md.renderer.rules.link_open || function(tokens, idx, options, env, self) {
        return self.renderToken(tokens, idx, options);
    };

    md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
        var openToken = tokens[idx];
        var hrefIndex = openToken.attrIndex('href');

        // Ensure we have an "href" attribute
        if (hrefIndex !== -1) {
            var href = openToken.attrs[hrefIndex][1];

            // Ensure we have an "href" attribute value
            if (href) {
                var textToken = tokens[idx + 1];

                // Ensure we have a text token and the text matches the URL pattern instead of [text](http://example.com/)
                if (textToken && textToken.content && regExp.test(textToken.content)) {
                    var matches = href.match(regExp);

                    var embedUrl = `/${matches.groups.path}/embed`;

                    var site = matches.groups.site || matches.groups.siteLocal;
                    if (site) {
                        embedUrl = `https://${site}${embedUrl}`;
                    }

                    textToken.content = '';
                    tokens[idx + 2].hidden = true;

                    return `<iframe class="${matches.groups.type}" frameborder="0" scrolling="no" src="${embedUrl}"></iframe>`;
                }
            }
        }

        return defaultRender(tokens, idx, options, env, self);
    };
};<|endoftext|>


<commit_before>/*!
 * Copyright 2015 mifort.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author Andrew Voitov
 */

var ObjectID = require('mongodb').ObjectID;
var moment = require('moment');
var reqParams = require('./req_params');

var dateFormat = 'MM/DD/YYYY';

exports.getStartDate = function(req) {
    return getDateParam(req, reqParams.startDateParam);
};

exports.getEndDate = function(req) {
    return getDateParam(req, reqParams.endDateParam);
};

exports.getProjectId = function(req) {
    return getObjectIdParam(req, reqParams.projectIdParam)
};

exports.getUserId = function(req) {
    return getObjectIdParam(req, reqParams.userIdParam);
};

exports.getCompanyId = function(req) {
    return getObjectIdParam(req, reqParams.companyIdParam);
};

exports.getTimelogId = function(req) {
    return getObjectIdParam(req, reqParams.timelogIdParam);
};

exports.getFileName = function(req) {
    return getParameter(req, reqParams.fileNameParam);
};

exports.getEmailParam = function(req) {
    return getParameter(req, reqParams.emailParam);
};

//parse json. Date and ObjectId
exports.jsonParse = function(key, value) {
    if (typeof value === 'string') {
        var isDateField = key.toLowerCase().indexOf('date') > -1
                          || key === 'start'
                          || key === 'end';
        if (isDateField
                && moment.utc(value, dateFormat).isValid()) {
            return moment.utc(value, dateFormat).toDate();
        }
        var isIdField = key === '_id' //maybe should be some prefix/postfix ???
                        || key === 'userId'
                        || key === 'projectId'
                        || key === 'companyId';
        if(isIdField && ObjectID.isValid(value)) {
            return new ObjectID(value);
        }
    }
    return value;
};

exports.jsonStringify = function(key, value) {
    var keyName = key.toLowerCase();
    var isDateField = /date$/.test(keyName)
        || keyName === 'start'
        || keyName === 'end';
    if (isDateField && !isNaN(Date.parse(value))) {
        return moment.utc(Date.parse(value)).format(dateFormat);
    }
    return value;
};

exports.formatDate = function(date) {
    return moment(date).format(dateFormat);
};

exports.convertToMongoId = function(str) {
    var mongoId = str;
    if(str && ObjectID.isValid(str)) {
        mongoId = new ObjectID(str);
    }
    return mongoId;
};

//private section
function getObjectIdParam(req, name) {
    var entityObjectId = getParameter(req, name);
    if(entityObjectId && ObjectID.isValid(entityObjectId)) {
        entityObjectId = new ObjectID(entityObjectId);
    }
    return entityObjectId;
}

function getDateParam(req, name) {
    var date = getParameter(req, name);
    if(date) {
        return moment.utc(date, dateFormat).toDate();
    }
};

function getParameter(req, name) {
    return req.params[name] || req.query[name];
}
<commit_msg>Get New Object ID Util finction<commit_after>/*!
 * Copyright 2015 mifort.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author Andrew Voitov
 */

var ObjectID = require('mongodb').ObjectID;
var moment = require('moment');
var reqParams = require('./req_params');

var dateFormat = 'MM/DD/YYYY';

exports.getStartDate = function(req) {
    return getDateParam(req, reqParams.startDateParam);
};

exports.getEndDate = function(req) {
    return getDateParam(req, reqParams.endDateParam);
};

exports.getProjectId = function(req) {
    return getObjectIdParam(req, reqParams.projectIdParam)
};

exports.getUserId = function(req) {
    return getObjectIdParam(req, reqParams.userIdParam);
};

exports.getCompanyId = function(req) {
    return getObjectIdParam(req, reqParams.companyIdParam);
};

exports.getTimelogId = function(req) {
    return getObjectIdParam(req, reqParams.timelogIdParam);
};

exports.getFileName = function(req) {
    return getParameter(req, reqParams.fileNameParam);
};

exports.getEmailParam = function(req) {
    return getParameter(req, reqParams.emailParam);
};

//parse json. Date and ObjectId
exports.jsonParse = function(key, value) {
    if (typeof value === 'string') {
        var isDateField = key.toLowerCase().indexOf('date') > -1
                          || key === 'start'
                          || key === 'end';
        if (isDateField
                && moment.utc(value, dateFormat).isValid()) {
            return moment.utc(value, dateFormat).toDate();
        }
        var isIdField = key === '_id' //maybe should be some prefix/postfix ???
                        || key === 'userId'
                        || key === 'projectId'
                        || key === 'companyId';
        if(isIdField && ObjectID.isValid(value)) {
            return new ObjectID(value);
        }
    }
    return value;
};

exports.jsonStringify = function(key, value) {
    var keyName = key.toLowerCase();
    var isDateField = /date$/.test(keyName)
        || keyName === 'start'
        || keyName === 'end';
    if (isDateField && !isNaN(Date.parse(value))) {
        return moment.utc(Date.parse(value)).format(dateFormat);
    }
    return value;
};

exports.formatDate = function(date) {
    return moment(date).format(dateFormat);
};

exports.convertToMongoId = function(str) {
    var mongoId = str;
    if(str && ObjectID.isValid(str)) {
        mongoId = new ObjectID(str);
    }
    return mongoId;
};

exports.getNewObjectID = function(num) {
    if(!num) {
        return [new ObjectID()];
    }
    var ids = [];
    for (var i = 0; i < num; i++) {
        ids.push(new ObjectID());
    }
    return ids;
}

//private section
function getObjectIdParam(req, name) {
    var entityObjectId = getParameter(req, name);
    if(entityObjectId && ObjectID.isValid(entityObjectId)) {
        entityObjectId = new ObjectID(entityObjectId);
    }
    return entityObjectId;
}

function getDateParam(req, name) {
    var date = getParameter(req, name);
    if(date) {
        return moment.utc(date, dateFormat).toDate();
    }
};

function getParameter(req, name) {
    return req.params[name] || req.query[name];
}
<|endoftext|>


<commit_before>'use strict';

//global namespace object
var g = g || {};

// set to true to fake the api call
g.fakeApiCall = true

Date.prototype.yyyymmdd = function() {
   var yyyy = this.getFullYear().toString();
   var mm = (this.getMonth()+1).toString(); // getMonth() is zero-based
   var dd  = this.getDate().toString();
   return yyyy + '-' + (mm[1]?mm:"0"+mm[0]) + '-' + (dd[1]?dd:"0"+dd[0]); // padding
  };

g.main = function() {
	$('#seeTweets').hide();
	$("#submitParams").on('click', g.graphAJAX);
	$("#seeTweets").on('click', g.tweetsAJAX);
}

g.graphAJAX = function(e){
	//stop default form submission
	e.preventDefault();
	//clear any previous graphs (this should be improved I guess)
	$('#graph').html('');
	//show loading gif cos the api call takes a while
	$('#loadingGif').show()
	//get parameters from form
	var hashtag = $('#hashtag').val();
	var date = $('#date').val();
	////'http://localhost:3000/api/generate_time_series/'+ hashtag + '/' + date;
	var url = g.fakeApiCall ? null : 'http://localhost:3000/api/generate/'+ hashtag;
	//make the call
	$.ajax({
		url: url,
		type: 'GET'
	})
	.done(g.presentGraph)
	.fail(g.failedAjax);
};

g.presentGraph = function(filename) {
	$('#loadingGif').hide();
	g.plotGraph(filename);
	//show option to see tweets
	$('#seeTweets').show();
}

g.tweetsAJAX = function() {
	//console.log(g.dateRange);
	//var url = 'http://localhost:5000/api/get_tweets/' + g.dateRange[0].yyyymmdd() + '/' + g.dateRange[1].yyyymmdd();
	//hack to local data for test
	var url = 'testData.json';
	$.ajax({
		url: url,
		type: 'GET'
	})
	.done(g.addTweets)
}

g.failedAjax = function() {
	console.log('ajax failed')
}

g.addTweets = function(tweets) {
	//if there are no tweets, tell the console
	if(!tweets.length) {
		console.log("No tweets returned");
		return false;
	}
	//tweets = $.parseJSON(tweets)
	tweets.forEach(function(t, i) {
		console.log(t.coordinates, i)
		$('#tweets').append("
" +
													"
"+
														"" +
															t.user.name +
														"" +
													"
" +
													"
" + t.text + "
" +
													"Go to Tweet" +
												"
");
	})
}

$(document).ready(g.main);
<commit_msg>javascript now follows the three states<commit_after>'use strict';

//global namespace object
var g = g || {};

// set to true to fake the api call
g.fakeApiCall = true

Date.prototype.yyyymmdd = function() {
   var yyyy = this.getFullYear().toString();
   var mm = (this.getMonth()+1).toString(); // getMonth() is zero-based
   var dd  = this.getDate().toString();
   return yyyy + '-' + (mm[1]?mm:"0"+mm[0]) + '-' + (dd[1]?dd:"0"+dd[0]); // padding
  };

g.main = function() {
	$('body').addClass('landing');
	$('#seeTweets').hide();
	$("#initial-search").on('submit', g.initRefine);
	$("#seeTweets").on('click', g.initRetrieve);
}

g.initRefine = function(e) {
	//stop default form submission
	e.preventDefault();
	//change view state
	$('body').removeClass('landing').addClass('refine');

	//add filter event listener
	$('#filterParameters li').on('click', function() {
		$('#filterParameters li').removeClass('active');
		$(this).addClass('active');
	});
	//
	g.graphAJAX();
}

g.initRetrieve = function() {
	$('body').removeClass('refine').addClass('retrieve');

	g.tweetsAJAX();
}

g.graphAJAX = function(e) {
	//clear any previous graphs (this should be improved I guess)
	$('#graph').html('');
	//show loading gif cos the api call takes a while
	$('#loadingGif').show()
	//get parameters from form
	var hashtag = $('#hashtag').val();
	var date = $('#date').val();
	////'http://localhost:3000/api/generate_time_series/'+ hashtag + '/' + date;
	var url = g.fakeApiCall ? null : 'http://localhost:3000/api/generate/'+ hashtag;
	//make the call
	$.ajax({
		url: url,
		type: 'GET'
	})
	.done(g.presentGraph)
	.fail(g.failedAjax);
};

g.presentGraph = function(filename) {
	if(g.fakeApiCall) filename = 'data.tsv';
	$('#loadingGif').hide();
	g.plotGraph(filename);
	//show option to see tweets
	$('#seeTweets').show();
}

g.tweetsAJAX = function() {
	//console.log(g.dateRange);
	//var url = 'http://localhost:5000/api/get_tweets/' + g.dateRange[0].yyyymmdd() + '/' + g.dateRange[1].yyyymmdd();
	//hack to local data for test
	var url = 'testData.json';
	$.ajax({
		url: url,
		type: 'GET'
	})
	.done(g.addTweets)
}

g.failedAjax = function() {
	console.log('ajax failed')
}

g.addTweets = function(tweets) {
	//if there are no tweets, tell the console
	if(!tweets.length) {
		console.log("No tweets returned");
		return false;
	}
	//tweets = $.parseJSON(tweets)
	tweets.forEach(function(t, i) {
		console.log(t)
		//scan tweet for media
		//make tweet

		$('#tweets').append("
" +
														"" +
															"" +
												    "" +
												    "
" +
												      "
" +
												      	t.user.name +
												      "
" +
												      "
" +
																"
" + t.text + "
" +
																"" +
															"
" +
															"
" +
																"Go to Tweet" +
															"
" +
												"
");
	})
}

$(document).ready(g.main);
<|endoftext|>


<commit_before>console.log('chrodic loaded!');

function getWord(event, n) {
  var range = document.caretRangeFromPoint(event.clientX, event.clientY);
  if (!range.startContainer.nodeValue) return '';
  // Expand left.
  while (range.startOffset > 0) {
    range.setStart(range.startContainer, range.startOffset - 1);
    if (!/^[a-zA-Z0-9]/.test(range.toString())) {
      range.setStart(range.startContainer, range.startOffset + 1);
      break;
    }
  }
  // Expand right.
  while (range.endOffset < range.endContainer.nodeValue.length) {
    range.setEnd(range.endContainer, range.endOffset + 1);
    if (!/[a-zA-Z0-9]$/.test(range.toString())) {
      range.setEnd(range.endContainer, range.endOffset - 1);
      break;
    }
  }
  for (var i = 1; i < n; ++i) {
    while (range.endOffset < range.endContainer.nodeValue.length) {
      range.setEnd(range.endContainer, range.endOffset + 1);
      if (/[a-zA-Z0-9]$/.test(range.toString())) {
        range.setEnd(range.endContainer, range.endOffset - 1);
        break;
      }
    }
    while (range.endOffset < range.endContainer.nodeValue.length) {
      range.setEnd(range.endContainer, range.endOffset + 1);
      if (!/[a-zA-Z0-9]$/.test(range.toString())) {
        range.setEnd(range.endContainer, range.endOffset - 1);
        break;
      }
    }
  }
  while (range.endOffset > range.startOffset &&
         !/[a-zA-Z0-9]$/.test(range.toString())) {
    range.setEnd(range.endContainer, range.endOffset - 1);
  }
  return range.toString().toLowerCase();
}

var previous_word = '';

var translation_box = document.createElement('div');
with (translation_box.style) {
  zIndex = 2147483647;
  position = 'absolute';
  background = '#000000';
  color = '#ffffff';
  fontSize = '10px';
  opacity = '0.75';
  textAlign = 'left';
  display = 'none';
}
document.body.appendChild(translation_box);

var mouseMoveEvent;

var st;

document.addEventListener('mousedown', function(event) {
  translation_box.style.display = 'none';
  st = setTimeout(function() {
    redrawTranslationBox();
    translation_box.style.display = 'block';
  }, 500);
}, false);

document.addEventListener('mouseup', function(event) {
  clearTimeout(st);
});

var REWRITE_RULES = [
  [/s$/, ''],  // Plural (cats -> cat)
  [/ies$/, 'y'],  // Plural (categories -> category)
  [/ing$/, ''],  // Present participle (doing -> do)
  [/ing$/, 'e'],  // Present participle (rating -> rate)
  [/(.)\1ing$/, '$1'], // Present participle (getting -> get)
  [/ed$/, 'e'],  // Past participle (rated -> rate)
  [/ed$/, ''],  // Past participle (started -> start)
  [/(.)\1ed$/, '$1'],  // Past participle (submitted -> submit)
  [/ied$/, 'y']  // Past participle (fried -> fry)
];

// Test REWRITE_RULES
(function() {
   function expand(word) {
     return REWRITE_RULES.map(function(r) { return word.replace(r[0], r[1]); }).
       filter(function(s) { return s != word; });
   }
   [
     'categories|category',
     'cats|cat',
     'derived|derive',
     'dogged|dog',
     'doing|do',
     'fried|fry',
     'getting|get',
     'giving|give',
     'rated|rate',
     'rating|rate',
     'saved|save',
     'started|start',
     'submitted|submit',
     'writes|write'
   ].map(function(w) { return w.split('|'); }).forEach(function(word) {
     var expanded = expand(word[0]);
     var found = expanded.some(function(e) { return e == word[1]; });
     //console.log(found, word[0], expanded);
   });
})();

function translate(word) {
  chrome.runtime.sendMessage(
    {'action' : 'translateWord', 'word' : word},
    function (translation) {
      var match = translation.match(/<→(.*)>/);
      if (match &&  // Found a link to the canonical spelling.
          word != match[1]) {  // Check if we don't do infinite loop.
        translate(match[1]);
//        return;
      }
      if (translation != '') {
        translation_box.innerHTML +=
        ('' + word + '\n
' + translation + '
').
            replace(/\n/g, '
');
      }
    });
}

function redrawTranslationBox() {
  // Redraw translation box.
  var box_width = Math.min(400, window.innerWidth);
  var box_left =
      Math.min(window.innerWidth - box_width, mouseMoveEvent.clientX)
          + mouseMoveEvent.pageX - mouseMoveEvent.clientX;
  var box_top = mouseMoveEvent.pageY + 10;
  with (translation_box.style) {
    width = box_width + 'px';
    left = box_left + 'px';
    top = box_top + 'px';
  }

  var word = getWord(mouseMoveEvent, 1);
  if (word == previous_word) return;
  previous_word = word;
  translation_box.innerHTML = '';

  var words = [];
  words.push(word);
  REWRITE_RULES.forEach(function(r) {
    if (r[0].test(word)) {
      words.push(word.replace(r[0], r[1]));
    }
  });

  for (var i = 2; i <= 5; ++i) {
    var new_word = getWord(mouseMoveEvent, i);
    if (new_word == word) break;
    word = new_word;
    words.push(word);
  }

  for (var i = words.length - 1; i >= 0; --i) {
    translate(words[i]);
  }
}

document.addEventListener('mousemove', function(event) {
  mouseMoveEvent = event;
  if (translation_box.style.display == 'none') return;
  redrawTranslationBox();
}, false);
<commit_msg>Do not mix multiple translation results in the translation box.<commit_after>console.log('chrodic loaded!');

function getWord(event, n) {
  var range = document.caretRangeFromPoint(event.clientX, event.clientY);
  if (!range.startContainer.nodeValue) return '';
  // Expand left.
  while (range.startOffset > 0) {
    range.setStart(range.startContainer, range.startOffset - 1);
    if (!/^[a-zA-Z0-9]/.test(range.toString())) {
      range.setStart(range.startContainer, range.startOffset + 1);
      break;
    }
  }
  // Expand right.
  while (range.endOffset < range.endContainer.nodeValue.length) {
    range.setEnd(range.endContainer, range.endOffset + 1);
    if (!/[a-zA-Z0-9]$/.test(range.toString())) {
      range.setEnd(range.endContainer, range.endOffset - 1);
      break;
    }
  }
  for (var i = 1; i < n; ++i) {
    while (range.endOffset < range.endContainer.nodeValue.length) {
      range.setEnd(range.endContainer, range.endOffset + 1);
      if (/[a-zA-Z0-9]$/.test(range.toString())) {
        range.setEnd(range.endContainer, range.endOffset - 1);
        break;
      }
    }
    while (range.endOffset < range.endContainer.nodeValue.length) {
      range.setEnd(range.endContainer, range.endOffset + 1);
      if (!/[a-zA-Z0-9]$/.test(range.toString())) {
        range.setEnd(range.endContainer, range.endOffset - 1);
        break;
      }
    }
  }
  while (range.endOffset > range.startOffset &&
         !/[a-zA-Z0-9]$/.test(range.toString())) {
    range.setEnd(range.endContainer, range.endOffset - 1);
  }
  return range.toString().toLowerCase();
}

var previous_word = '';

var translation_box = document.createElement('div');
with (translation_box.style) {
  zIndex = 2147483647;
  position = 'absolute';
  background = '#000000';
  color = '#ffffff';
  fontSize = '10px';
  opacity = '0.75';
  textAlign = 'left';
  display = 'none';
}
document.body.appendChild(translation_box);

var mouseMoveEvent;

var st;

document.addEventListener('mousedown', function(event) {
  translation_box.style.display = 'none';
  st = setTimeout(function() {
    redrawTranslationBox();
    translation_box.style.display = 'block';
  }, 500);
}, false);

document.addEventListener('mouseup', function(event) {
  clearTimeout(st);
});

var REWRITE_RULES = [
  [/s$/, ''],  // Plural (cats -> cat)
  [/ies$/, 'y'],  // Plural (categories -> category)
  [/ing$/, ''],  // Present participle (doing -> do)
  [/ing$/, 'e'],  // Present participle (rating -> rate)
  [/(.)\1ing$/, '$1'], // Present participle (getting -> get)
  [/ed$/, 'e'],  // Past participle (rated -> rate)
  [/ed$/, ''],  // Past participle (started -> start)
  [/(.)\1ed$/, '$1'],  // Past participle (submitted -> submit)
  [/ied$/, 'y']  // Past participle (fried -> fry)
];

// Test REWRITE_RULES
(function() {
   function expand(word) {
     return REWRITE_RULES.map(function(r) { return word.replace(r[0], r[1]); }).
       filter(function(s) { return s != word; });
   }
   [
     'categories|category',
     'cats|cat',
     'derived|derive',
     'dogged|dog',
     'doing|do',
     'fried|fry',
     'getting|get',
     'giving|give',
     'rated|rate',
     'rating|rate',
     'saved|save',
     'started|start',
     'submitted|submit',
     'writes|write'
   ].map(function(w) { return w.split('|'); }).forEach(function(word) {
     var expanded = expand(word[0]);
     var found = expanded.some(function(e) { return e == word[1]; });
     //console.log(found, word[0], expanded);
   });
})();

function translationTask(words) {
  this.cancelled = false;
  this.words = words;
  this.remaining = 0;

  if (translationTask.activeTask != null) {
    translationTask.activeTask.cancel();
    translationTask.activeTask = null;
  }
  translationTask.activeTask = this;
}

translationTask.prototype.cancel = function() {
  this.cancelled = true;
};

translationTask.prototype.run = function() {
  for (var i = 0; i < this.words.length; i++) {
    this.translate(this.words[i]);
  }
};

translationTask.prototype.translate = function(word) {
  var self = this;
  ++self.remaining;
  chrome.runtime.sendMessage(
      {'action' : 'translateWord', 'word' : word},
      function (translation) {
        if (self.cancelled) return;
        var match = translation.match(/<→(.*)>/);
        if (match &&  // Found a link to the canonical spelling.
            word != match[1]) {  // Check if we don't do infinite loop.
          self.translate(match[1]);
//        return;
        }
        if (translation != '') {
          translation_box.innerHTML +=
          ('' + word + '\n
' + translation + '
').
              replace(/\n/g, '
');
        }
        --self.remaining;
        if (self.remaining == 0) {
          translationTask.activeTask = null;
        }
      });
};

function redrawTranslationBox() {
  // Redraw translation box.
  var box_width = Math.min(400, window.innerWidth);
  var box_left =
      Math.min(window.innerWidth - box_width, mouseMoveEvent.clientX)
          + mouseMoveEvent.pageX - mouseMoveEvent.clientX;
  var box_top = mouseMoveEvent.pageY + 10;
  with (translation_box.style) {
    width = box_width + 'px';
    left = box_left + 'px';
    top = box_top + 'px';
  }

  var word = getWord(mouseMoveEvent, 1);
  if (word == previous_word) return;
  previous_word = word;
  translation_box.innerHTML = '';

  var words = [];
  words.push(word);
  REWRITE_RULES.forEach(function(r) {
    if (r[0].test(word)) {
      words.push(word.replace(r[0], r[1]));
    }
  });

  for (var i = 2; i <= 5; ++i) {
    var new_word = getWord(mouseMoveEvent, i);
    if (new_word == word) break;
    word = new_word;
    words.push(word);
  }

  (new translationTask(words)).run();
}

document.addEventListener('mousemove', function(event) {
  mouseMoveEvent = event;
  if (translation_box.style.display == 'none') return;
  redrawTranslationBox();
}, false);
<|endoftext|>


<commit_before>'use strict';
var assert = require('assert');
var les = require("local-echoserver");
var zaif = require('..');

describe('test', function () {
    var constant = zaif.Constant;
    var apiv1 = zaif.PublicApi;
    it('depth', function () {
        return les(function(url){
            constant.OPT_APIV1_URL = url + '/api/1'
            return apiv1.depth('btc_jpy').then(function(v){
                assert(v.asks[0][0] === 1000);
                assert(v.asks[0][1] == 1.0);
                assert(v.asks[1][0] === 1001);
                assert(v.asks[1][1] == 0.9);
                assert(v.bids[0][0] === 999);
                assert(v.bids[0][1] == 1.5);
                assert(v.bids[1][0] === 998);
                assert(v.bids[1][1] == 2.2);
            })
        }, function(res, headers, method, url, body){
            assert(url === '/api/1/depth/btc_jpy');
            var result = JSON.stringify({
                asks:[[1000, 1.0],[1001,0.9]], bids:[[999,1.5],[998,2.2]]
            });
            res.end(result);
        })
    })
    it('lastPrice', function () {
        return les(function(url){
            constant.OPT_APIV1_URL = url + '/api/1'
            return apiv1.lastPrice('btc_jpy').then(function(v){
                assert(v.last_price === 75555.0);
            })
        }, function(res, headers, method, url, body){
            assert(url === '/api/1/last_price/btc_jpy');
            var result = JSON.stringify({"last_price": 75555.0});
            res.end(result);
        })
    })
    it('ticker', function () {
        return les(function(url){
            constant.OPT_APIV1_URL = url + '/api/1'
            return apiv1.ticker('btc_jpy').then(function(v){
                assert(v.last === 75630.0);
                assert(v.high === 75900.0);
                assert(v.low === 73930.0);
                assert(v.vwap === 75048.3677);
                assert(v.volume === 11725.0985);
                assert(v.bid === 75630.0);
                assert(v.ask === 75635.0);
            })
        }, function(res, headers, method, url, body){
            assert(url === '/api/1/ticker/btc_jpy');
            var result = JSON.stringify({
                "last": 75630.0, "high": 75900.0, "low": 73930.0, "vwap": 75048.3677, "volume": 11725.0985, "bid": 75630.0, "ask": 75635.0
            });
            res.end(result);
        })
    })
    it('trades', function () {
        return les(function(url){
            constant.OPT_APIV1_URL = url + '/api/1'
            return apiv1.trades('btc_jpy').then(function(v){
                assert(v instanceof Array)
                assert(v.length === 3)
                assert(v[0].currency_pair === 'btc_jpy')
            })
        }, function(res, headers, method, url, body){
            assert(url === '/api/1/trades/btc_jpy');
            var result = JSON.stringify([
                { date: 1477977267,
                  price: 75695,
                  amount: 0.1,
                  tid: 16301201,
                  currency_pair: 'btc_jpy',
                  trade_type: 'ask' },
                { date: 1477977264,
                  price: 75695,
                  amount: 0.1,
                  tid: 16301200,
                  currency_pair: 'btc_jpy',
                  trade_type: 'ask' },
                { date: 1477977262,
                  price: 75690,
                  amount: 0.6561,
                  tid: 16301199,
                  currency_pair: 'btc_jpy',
                  trade_type: 'ask' }
                ]);
            res.end(result);
        })
    })
})
<commit_msg>update test<commit_after>'use strict';
var assert = require('assert');
var les = require("local-echoserver");
var verify = require("@you21979/simple-verify");
var qstring = require("querystring");
var zaif = require('..');

describe('test', function () {
    describe('private api test', function () {
        var constant = zaif.Constant;
        var config = {apikey : "",secretkey : "", useragent : "tradebot"}
        before(function() {
            return verify.createKeyPair().then(function(res){
                config.apikey = res.key
                config.secretkey = res.secret
            })
        })
        it('getInfo and auth', function () {
            return les(function(url){
                constant.OPT_TAPI_URL = url + '/tapi'
                var papi = zaif.createPrivateApi(config.apikey, config.secretkey, config.useragent);
                return papi.getInfo().then(function(res){
                    assert(res.funds.jpy === 15320)
                    assert(res.deposit.jpy === 20440)
                })
            }, function(res, headers, method, url, body){
                var param = qstring.parse(body)
                assert(url === '/tapi');
                assert(headers['key'] === config.apikey)
                assert(headers['user-agent'] === config.useragent)
                assert(headers['sign'])
                assert(param.method === 'get_info');
                assert(param.nonce);
                var result = JSON.stringify({
                    success:1,
                    return:{
                        funds:{
                            jpy:15320,
                            btc:1.389,
                            xem:100.2,
                            mona:2600
                        },
                        deposit:{
                            jpy:20440,
                            btc:1.479,
                            xem:100.2,
                            mona:3200
                        },
                        rights:{
                            info:1,
                            trade:1,
                            withdraw:1
                        },
                        trade_count:18,
                        open_orders:3,
                        server_time:1401950833,
                    },
                });
                res.end(result);
            })
        })
    })
    describe('public api test', function () {
        var constant = zaif.Constant;
        var apiv1 = zaif.PublicApi;
        it('depth', function () {
            return les(function(url){
                constant.OPT_APIV1_URL = url + '/api/1'
                return apiv1.depth('btc_jpy').then(function(v){
                    assert(v.asks[0][0] === 1000);
                    assert(v.asks[0][1] == 1.0);
                    assert(v.asks[1][0] === 1001);
                    assert(v.asks[1][1] == 0.9);
                    assert(v.bids[0][0] === 999);
                    assert(v.bids[0][1] == 1.5);
                    assert(v.bids[1][0] === 998);
                    assert(v.bids[1][1] == 2.2);
                })
            }, function(res, headers, method, url, body){
                assert(url === '/api/1/depth/btc_jpy');
                var result = JSON.stringify({
                    asks:[[1000, 1.0],[1001,0.9]], bids:[[999,1.5],[998,2.2]]
                });
                res.end(result);
            })
        })
        it('lastPrice', function () {
            return les(function(url){
                constant.OPT_APIV1_URL = url + '/api/1'
                return apiv1.lastPrice('btc_jpy').then(function(v){
                    assert(v.last_price === 75555.0);
                })
            }, function(res, headers, method, url, body){
                assert(url === '/api/1/last_price/btc_jpy');
                var result = JSON.stringify({"last_price": 75555.0});
                res.end(result);
            })
        })
        it('ticker', function () {
            return les(function(url){
                constant.OPT_APIV1_URL = url + '/api/1'
                return apiv1.ticker('btc_jpy').then(function(v){
                    assert(v.last === 75630.0);
                    assert(v.high === 75900.0);
                    assert(v.low === 73930.0);
                    assert(v.vwap === 75048.3677);
                    assert(v.volume === 11725.0985);
                    assert(v.bid === 75630.0);
                    assert(v.ask === 75635.0);
                })
            }, function(res, headers, method, url, body){
                assert(url === '/api/1/ticker/btc_jpy');
                var result = JSON.stringify({
                    "last": 75630.0, "high": 75900.0, "low": 73930.0, "vwap": 75048.3677, "volume": 11725.0985, "bid": 75630.0, "ask": 75635.0
                });
                res.end(result);
            })
        })
        it('trades', function () {
            return les(function(url){
                constant.OPT_APIV1_URL = url + '/api/1'
                return apiv1.trades('btc_jpy').then(function(v){
                    assert(v instanceof Array)
                    assert(v.length === 3)
                    assert(v[0].currency_pair === 'btc_jpy')
                })
            }, function(res, headers, method, url, body){
                assert(url === '/api/1/trades/btc_jpy');
                var result = JSON.stringify([
                    { date: 1477977267,
                      price: 75695,
                      amount: 0.1,
                      tid: 16301201,
                      currency_pair: 'btc_jpy',
                      trade_type: 'ask' },
                    { date: 1477977264,
                      price: 75695,
                      amount: 0.1,
                      tid: 16301200,
                      currency_pair: 'btc_jpy',
                      trade_type: 'ask' },
                    { date: 1477977262,
                      price: 75690,
                      amount: 0.6561,
                      tid: 16301199,
                      currency_pair: 'btc_jpy',
                      trade_type: 'ask' }
                    ]);
                res.end(result);
            })
        })
    })
})
<|endoftext|>