<commit_before>/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import { $C } from '../deps/collection';
import { IS_NODE } from '../consts/hacks';
import { ws } from '../helpers/string';

/**
 * The class for parsing SS templates
 *
 * @constructor
 * @implements {$$SnakeskinParser}
 */
export class Parser {
	/**
	 * @param {string} src - the source text of templates
	 * @param {$$SnakeskinParserParams} params - additional parameters
	 */
	constructor(src, params) {
		$C(this).forEach((el, key) => {
			if (el && el.init) {
				this[key] = el.init();
			}

		}, {notOwn: true});

		/** @type {Parser} */
		this.parent = params.parent || null;

		/** @type {boolean} */
		this.throws = params.throws;

		/** @type {boolean} */
		this.useStrict = params.useStrict;

		/** @type {?function(!Error)} */
		this.onError = params.onError || null;

		/** @type {!Array} */
		this.scope = params.scope || [];

		/** @type {Object} */
		this.proto = params.proto || null;

		/** @type {!Object} */
		this.info = params.info;

		/** @type {boolean} */
		this.needPrfx = params.needPrfx || false;

		/** @type {!Array} */
		this.lines = params.lines || [''];

		/** @type {string} */
		this.eol = params.eol;

		/** @type {string} */
		this.renderMode = params.renderMode;

		/** @type {boolean} */
		this.tolerateWhitespace = params.tolerateWhitespace;

		/** @type {boolean} */
		this.inlineIterators = params.inlineIterators;

		/** @type {(string|boolean)} */
		this.doctype = params.doctype;

		/** @type {boolean} */
		this.replaceUndef = params.replaceUndef;

		/** @type {boolean} */
		this.escapeOutput = params.escapeOutput;

		/** @type {(?string|undefined)} */
		this.renderAs = params.renderAs;

		/** @type {string} */
		this.exports = params.exports;

		/** @type {boolean} */
		this.autoReplace = params.autoReplace !== false;

		/** @type {(Object|undefined)} */
		this.macros = params.macros;

		/** @type {string} */
		this.bemFilter = params.bemFilter;

		/** @type {boolean} */
		this.localization = params.localization;

		/** @type {string} */
		this.i18nFn = params.i18nFn;

		/** @type {(Object|undefined)} */
		this.language = params.language;

		/** @type {(RegExp|undefined)} */
		this.ignore = params.ignore;

		/**
		 * Stack parameters that can be changed in a code
		 * @type {!Array}
		 */
		this.params = [
			{
				'@root': true,
				renderMode: this.renderMode,
				inlineIterators: this.inlineIterators,
				doctype: this.doctype,
				escapeOutput: this.escapeOutput,
				renderAs: this.renderAs,
				replaceUndef: this.replaceUndef,
				autoReplace: this.autoReplace,
				macros: this.macros,
				localization: this.localization,
				i18nFn: this.i18nFn,
				bemFilter: this.bemFilter,
				language: this.language,
				ignore: this.ignore,
				tolerateWhitespace: this.tolerateWhitespace
			}
		];

		if (params.consts) {
			/** @type {(Array|undefined)} */
			this.consts = params.consts;
		}

		/**
		 * If is true, then compiling will be broken
		 * @type {boolean}
		 */
		this.brk = false;

		/**
		 * The array of errors
		 * @type {!Array}
		 */
		this.errors = [];

		/**
		 * The name of the active directive
		 * @type {?string}
		 */
		this.name = null;

		/**
		 * The name of the active template
		 * @type {?string}
		 */
		this.tplName = null;

		/**
		 * The map of directives, which can go after the active
		 * @type {Object}
		 */
		this.after = null;

		/**
		 * If is false, then template can't be inserted into the resulting JS string
		 * @type {boolean}
		 */
		this.canWrite = true;

		// Whitespace
		// >>>

		/** @type {boolean} */
		this.space = false;

		/** @type {boolean} */
		this.skipSpace = false;

		/** @type {boolean} */
		this.prevSpace = false;

		/** @type {boolean} */
		this.chainSpace = false;

		/** @type {number} */
		this.strongSpace = 0;

		/** @type {boolean} */
		this.sysSpace = false;

		/** @type {number} */
		this.freezeLine = 0;

		/** @type {boolean} */
		this.attr = false;

		/** @type {boolean} */
		this.attrEscape = false;

		// <<<

		/**
		 * The number of the active iteration
		 * @type {number}
		 */
		this.i = -1;

		/**
		 * The tree of blocks: proto, block, const
		 * @type {Object}
		 */
		this.blockStructure = null;

		/**
		 * The map for blocks: proto, block, const
		 * @type {Object}
		 */
		this.blockTable = null;

		/**
		 * The cache of outer prototypes / blocks
		 * @type {!Object}
		 */
		this.preDefs = {};

		/**
		 * The name of the active outer prototype / block
		 * @type {?string}
		 */
		this.outerLink = null;

		/**
		 * The template structure
		 * @type {!Object}
		 */
		this.structure = {
			name: 'root',

			/**
			 * @type {?{
			 *   name:
			 *   string,
			 *   parent: Object,
			 *   params: !Object,
			 *   stack: !Array,
			 *   vars: Object,
			 *   children: Array,
			 *   sys: boolean,
			 *   strong: boolean
			 * }}
			 */
			parent: null,

			params: {},
			stack: [],

			vars: params.vars || {},
			children: [],

			sys: false,
			strong: false
		};

		/**
		 * If is true, then the active directive is inline
		 * @type {?boolean}
		 */
		this.inline = null;

		/**
		 * If is true, then the active directive has a text type
		 * @type {boolean}
		 */
		this.text = false;

		/**
		 * The content of Escaper blocks
		 * @type {!Array}
		 */
		this.quotContent = [];

		/**
		 * The content of directives (for replaceTplVars)
		 * @type {!Array}
		 */
		this.dirContent = [];

		/**
		 * The content of CDATA blocks
		 * @type {!Array}
		 */
		this.cDataContent = [];

		/**
		 * The map of included files
		 * @type {!Object}
		 */
		this.files = {};

		/**
		 * The module environment
		 * @type {{exports, require, id, key, root, filename, parent, children, loaded}}
		 */
		this.environment = {
			exports: {},
			require: IS_NODE ?
				require : null,

			id: 0,
			key: [],

			root: null,
			filename: this.info.file,
			parent: IS_NODE ?
				module : null,

			children: [],
			loaded: true
		};

		/**
		 * The source text of templates
		 * @type {string}
		 */
		this.source = this.replaceCData(String(src));

		/**
		 * The final JS string
		 * @type {string}
		 */
		this.res = '';

		if (!this.proto) {
			this.res += ws`
				This code is generated automatically, don\'t alter it. */
				(function () {
					${this.useStrict ? '\'use strict\';' : ''}

					var
						__IS_NODE__ = false,
						__AMD__ = typeof define === 'function' && define.amd,
						__HAS_EXPORTS__ = typeof exports !== 'undefined',
						__EXPORTS__ = __HAS_EXPORTS__ ? exports : __AMD__ ? {} : this;

					try {
						__IS_NODE__ = typeof process === 'object' && Object().toString.call(process) === '[object process]';

					} catch (ignore) {}

					var Snakeskin = (__IS_NODE__ ? global : this).Snakeskin;

					function __INIT__(obj) {
						Snakeskin = Snakeskin ||
							(obj instanceof Object ? obj : void 0);

						if (__HAS_EXPORTS__) {
							delete __EXPORTS__.init;
						}

						if (__AMD__) {
							define(['Snakeskin'], function (ss) {
								Snakeskin = Snakeskin || ss;
								__EXEC__.call(__EXPORTS__);
								return __EXPORTS__;
							});

						} else {
							if (__IS_NODE__) {
								Snakeskin = Snakeskin || require(obj);
							}

							__EXEC__.call(__EXPORTS__);
							return __EXPORTS__;
						}
					}

					if (__HAS_EXPORTS__) {
						__EXPORTS__.init = __INIT__;
					}

					function __EXEC__() {
						var
							__ROOT__ = this,
							self = this;

						var
							__APPEND__ = Snakeskin.appendChild,
							__FILTERS__ = Snakeskin.Filters,
							__VARS__ = Snakeskin.Vars,
							__LOCAL__ = Snakeskin.LocalVars;

						${this.declVars('$_')}
			`;
		}
	};
}
<commit_msg>https://github.com/SnakeskinTpl/Snakeskin/commit/908001a5de08b48d6410f649dd3ff279c61ab418<commit_after>/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import { $C } from '../deps/collection';
import { IS_NODE } from '../consts/hacks';
import { ws } from '../helpers/string';

/**
 * The class for parsing SS templates
 *
 * @constructor
 * @implements {$$SnakeskinParser}
 */
export class Parser {
	/**
	 * @param {string} src - the source text of templates
	 * @param {$$SnakeskinParserParams} params - additional parameters
	 */
	constructor(src, params) {
		$C(this).forEach((el, key) => {
			if (el && el.init) {
				this[key] = el.init();
			}

		}, {notOwn: true});

		/** @type {Parser} */
		this.parent = params.parent || null;

		/** @type {boolean} */
		this.throws = params.throws;

		/** @type {boolean} */
		this.useStrict = params.useStrict;

		/** @type {?function(!Error)} */
		this.onError = params.onError || null;

		/** @type {!Array} */
		this.scope = params.scope || [];

		/** @type {Object} */
		this.proto = params.proto || null;

		/** @type {!Object} */
		this.info = params.info;

		/** @type {boolean} */
		this.needPrfx = params.needPrfx || false;

		/** @type {!Array} */
		this.lines = params.lines || [''];

		/** @type {string} */
		this.eol = params.eol;

		/** @type {string} */
		this.renderMode = params.renderMode;

		/** @type {boolean} */
		this.tolerateWhitespace = params.tolerateWhitespace;

		/** @type {boolean} */
		this.inlineIterators = params.inlineIterators;

		/** @type {(string|boolean)} */
		this.doctype = params.doctype;

		/** @type {boolean} */
		this.replaceUndef = params.replaceUndef;

		/** @type {boolean} */
		this.escapeOutput = params.escapeOutput;

		/** @type {(?string|undefined)} */
		this.renderAs = params.renderAs;

		/** @type {string} */
		this.exports = params.exports;

		/** @type {boolean} */
		this.autoReplace = params.autoReplace !== false;

		/** @type {(Object|undefined)} */
		this.macros = params.macros;

		/** @type {string} */
		this.bemFilter = params.bemFilter;

		/** @type {boolean} */
		this.localization = params.localization;

		/** @type {string} */
		this.i18nFn = params.i18nFn;

		/** @type {(Object|undefined)} */
		this.language = params.language;

		/** @type {(RegExp|undefined)} */
		this.ignore = params.ignore;

		/**
		 * Stack parameters that can be changed in a code
		 * @type {!Array}
		 */
		this.params = [
			{
				'@root': true,
				renderMode: this.renderMode,
				inlineIterators: this.inlineIterators,
				doctype: this.doctype,
				escapeOutput: this.escapeOutput,
				renderAs: this.renderAs,
				replaceUndef: this.replaceUndef,
				autoReplace: this.autoReplace,
				macros: this.macros,
				localization: this.localization,
				i18nFn: this.i18nFn,
				bemFilter: this.bemFilter,
				language: this.language,
				ignore: this.ignore,
				tolerateWhitespace: this.tolerateWhitespace
			}
		];

		if (params.consts) {
			/** @type {(Array|undefined)} */
			this.consts = params.consts;
		}

		/**
		 * If is true, then compiling will be broken
		 * @type {boolean}
		 */
		this.brk = false;

		/**
		 * The array of errors
		 * @type {!Array}
		 */
		this.errors = [];

		/**
		 * The name of the active directive
		 * @type {?string}
		 */
		this.name = null;

		/**
		 * The name of the active template
		 * @type {?string}
		 */
		this.tplName = null;

		/**
		 * The map of directives, which can go after the active
		 * @type {Object}
		 */
		this.after = null;

		/**
		 * If is false, then template can't be inserted into the resulting JS string
		 * @type {boolean}
		 */
		this.canWrite = true;

		// Whitespace
		// >>>

		/** @type {boolean} */
		this.space = false;

		/** @type {boolean} */
		this.skipSpace = false;

		/** @type {boolean} */
		this.prevSpace = false;

		/** @type {boolean} */
		this.chainSpace = false;

		/** @type {number} */
		this.strongSpace = 0;

		/** @type {boolean} */
		this.sysSpace = false;

		/** @type {number} */
		this.freezeLine = 0;

		/** @type {boolean} */
		this.attr = false;

		/** @type {boolean} */
		this.attrEscape = false;

		// <<<

		/**
		 * The number of the active iteration
		 * @type {number}
		 */
		this.i = -1;

		/**
		 * The tree of blocks: proto, block, const
		 * @type {Object}
		 */
		this.blockStructure = null;

		/**
		 * The map for blocks: proto, block, const
		 * @type {Object}
		 */
		this.blockTable = null;

		/**
		 * The cache of outer prototypes / blocks
		 * @type {!Object}
		 */
		this.preDefs = {};

		/**
		 * The name of the active outer prototype / block
		 * @type {?string}
		 */
		this.outerLink = null;

		/**
		 * The template structure
		 * @type {!Object}
		 */
		this.structure = {
			name: 'root',

			/**
			 * @type {?{
			 *   name:
			 *   string,
			 *   parent: Object,
			 *   params: !Object,
			 *   stack: !Array,
			 *   vars: Object,
			 *   children: Array,
			 *   sys: boolean,
			 *   strong: boolean
			 * }}
			 */
			parent: null,

			params: {},
			stack: [],

			vars: params.vars || {},
			children: [],

			sys: false,
			strong: false
		};

		/**
		 * If is true, then the active directive is inline
		 * @type {?boolean}
		 */
		this.inline = null;

		/**
		 * If is true, then the active directive has a text type
		 * @type {boolean}
		 */
		this.text = false;

		/**
		 * The content of Escaper blocks
		 * @type {!Array}
		 */
		this.quotContent = [];

		/**
		 * The content of directives (for replaceTplVars)
		 * @type {!Array}
		 */
		this.dirContent = [];

		/**
		 * The content of CDATA blocks
		 * @type {!Array}
		 */
		this.cDataContent = [];

		/**
		 * The map of included files
		 * @type {!Object}
		 */
		this.files = {};

		/**
		 * The module environment
		 * @type {{exports, require, id, key, root, filename, parent, children, loaded}}
		 */
		this.environment = {
			exports: {},
			require: IS_NODE ?
				require : null,

			id: 0,
			key: [],

			root: null,
			filename: this.info.file,
			parent: IS_NODE ?
				module : null,

			children: [],
			loaded: true
		};

		/**
		 * The source text of templates
		 * @type {string}
		 */
		this.source = this.replaceCData(String(src));

		/**
		 * The final JS string
		 * @type {string}
		 */
		this.res = '';

		if (!this.proto) {
			this.res += ws`
				This code is generated automatically, don\'t alter it. */
				(function () {
					${this.useStrict ? '\'use strict\';' : ''}

					var
						__IS_NODE__ = false,
						__AMD__ = typeof define === 'function' && define.amd,
						__HAS_EXPORTS__ = typeof exports !== 'undefined',
						__EXPORTS__ = __HAS_EXPORTS__ ? exports : __AMD__ ? {} : this;

					try {
						__IS_NODE__ = typeof process === 'object' && Object().toString.call(process) === '[object process]';

					} catch (ignore) {}

					var Snakeskin = (__IS_NODE__ ? global : this).Snakeskin;

					function __INIT__(obj) {
						Snakeskin = Snakeskin ||
							(obj instanceof Object ? obj : void 0);

						if (__AMD__) {
							define(['Snakeskin'], function (ss) {
								Snakeskin = Snakeskin || ss;
								__EXEC__.call(__EXPORTS__);
								return __EXPORTS__;
							});

						} else {
							if (__IS_NODE__) {
								Snakeskin = Snakeskin || require(obj);
							}

							__EXEC__.call(__EXPORTS__);
							return __EXPORTS__;
						}
					}

					if (__HAS_EXPORTS__) {
						__EXPORTS__.init = __INIT__;
					}

					function __EXEC__() {
						var
							__ROOT__ = this,
							self = this;

						var
							__APPEND__ = Snakeskin.appendChild,
							__FILTERS__ = Snakeskin.Filters,
							__VARS__ = Snakeskin.Vars,
							__LOCAL__ = Snakeskin.LocalVars;

						${this.declVars('$_')}
			`;
		}
	};
}
<|endoftext|>


<commit_before>/*global require:true*/
(function(){
	"use strict";
	var path = require( 'path' );
	var Constructor = require( path.join('..', 'lib', 'data-uri-encoder'));
	var SvgURIEncoder = require( path.join('..', 'lib', 'svg-uri-encoder'));
	var PngURIEncoder = require( path.join('..', 'lib', 'png-uri-encoder'));
	var _ = require( 'lodash' );

	exports['Constructor'] = {
		setUp: function( done ) {
			this.encoder = new Constructor( "test/files/bear.svg" );
			done();
		},

		path: function( test ) {
			test.equal( this.encoder.path, "test/files/bear.svg" );
			test.done();
		},

		extension: function( test ) {
			test.equal( this.encoder.extension, "svg" );
			test.done();
		}
	};

	function testEncoded( test, str ) {
		str.split('').forEach(function( c ) {
			test.ok( /[a-zA-Z0-9+\/=]+/.test(c) );
		});
	}

	exports['encode'] = {
		setUp: function( done ) {
			this.encoder = new Constructor( "test/files/cat.png" );
			done();
		},

		output: function( test ) {
			testEncoded( test, this.encoder.encode());
			test.done();
		},

		callback: function( test ) {
			this.encoder.encode(function( prefix, fileData ) {
				test.equal( prefix, this.encoder.prefix );
				test.ok( fileData );
			});

			test.done();
		}
	};

	exports['stats'] = {
		setUp: function( done ) {
			this.encoder = new Constructor( "test/files/cat.png" );
			this.encoder2 = new Constructor( "test/files/bear.svg" );
			done();
		},

		stats: function( test ) {
			test.equal( this.encoder.stats().width, '100px', "Width should match" );
			test.equal( this.encoder.stats().height, '100px', "Height should match on png" );
			test.equal( this.encoder2.stats().width, '100px', "Width should match" );
			test.equal( this.encoder2.stats().height, '62.905px', "Height should match on svg" );
			test.done();
		}
	};

	exports['SvgURIEncoder'] = {
		setUp: function( done ) {
			this.encoder = new SvgURIEncoder( "test/files/bear.svg" );
			done();
		},

		encode: function( test ) {
			var datauri = this.encoder.encode();

			test.ok( datauri.indexOf(SvgURIEncoder.prefix) >= 0 );
			test.ok( datauri.indexOf( '%' ) >= 0 );
			test.done();
		}
	};

	/**
	 * Test encoding brackets '(' and ')' to generate a valid encoded SVG
	 * in case of <g> element with functions in the 'transformation' attribute
	 */
	exports['SvgURIEncoder_brackets'] = {
		setUp: function( done ) {
			this.encoder = new SvgURIEncoder( "test/files/bear.svg" );
			done();
		},

		encode: function( test ) {
			var datauri = this.encoder.encode();

			test.ok( datauri.indexOf(SvgURIEncoder.prefix) >= 0 );
			test.ok( datauri.indexOf( '%' ) >= 0 );
			test.ok( datauri.indexOf( '(' ) === -1 );
			test.ok( datauri.indexOf( ')' ) === -1 );
			test.done();
		}
	};

	exports['PngURIEncoder'] = {
		setUp: function( done ) {
			this.encoder = new PngURIEncoder( "test/files/cat.png" );
			this.encode = _.clone( Constructor.prototype.encode );
			done();
		},

		tearDown: function( done ) {
			Constructor.prototype.encode = this.encode;
			done();
		},

		encode: function( test ) {
			testEncoded( test, this.encoder.encode().replace(PngURIEncoder.prefix, "") );
			test.done();
		},

		pathSwitch: function( test ) {
			Constructor.prototype.encode = function(){
				var i = 32768, datauri = "";

				while( i >= 0 ) {
					datauri += "a";
					i--;
				}

				return datauri;
			};

			test.equal( this.encoder.encode({ pngfolder: "foo" }), 'foo/cat.png' );
			test.done();
		}
	};
	exports['PngURIEncoder2'] = {
		setUp: function( done ) {
			this.encoder = new PngURIEncoder( "test/files/cat.png" );
			done();
		},
		tearDown: function( done ){
			done();
		},
		noencode: function( test ){
			var options = {
				noencodepng: true,
				pngfolder: "bar"
			};

			test.equal( this.encoder.encode(options), 'bar/cat.png' );
			test.done();
		}
	};
	exports['PngURIEncoder3'] = {
		setUp: function( done ) {
			this.encoder = new PngURIEncoder( "test/files/cat.png" );
			done();
		},
		tearDown: function( done ){
			done();
		},
		noencode_custompath: function( test ){
			var options = {
				noencodepng: true,
				pngfolder: "foo",
				pngpath: "bar"
			};

			test.equal( this.encoder.encode(options), 'bar/cat.png' );
			test.done();
		}
	};
}());
<commit_msg>Add tests for URL as pngpath<commit_after>/*global require:true*/
(function(){
	"use strict";
	var path = require( 'path' );
	var Constructor = require( path.join('..', 'lib', 'data-uri-encoder'));
	var SvgURIEncoder = require( path.join('..', 'lib', 'svg-uri-encoder'));
	var PngURIEncoder = require( path.join('..', 'lib', 'png-uri-encoder'));
	var _ = require( 'lodash' );

	exports['Constructor'] = {
		setUp: function( done ) {
			this.encoder = new Constructor( "test/files/bear.svg" );
			done();
		},

		path: function( test ) {
			test.equal( this.encoder.path, "test/files/bear.svg" );
			test.done();
		},

		extension: function( test ) {
			test.equal( this.encoder.extension, "svg" );
			test.done();
		}
	};

	function testEncoded( test, str ) {
		str.split('').forEach(function( c ) {
			test.ok( /[a-zA-Z0-9+\/=]+/.test(c) );
		});
	}

	exports['encode'] = {
		setUp: function( done ) {
			this.encoder = new Constructor( "test/files/cat.png" );
			done();
		},

		output: function( test ) {
			testEncoded( test, this.encoder.encode());
			test.done();
		},

		callback: function( test ) {
			this.encoder.encode(function( prefix, fileData ) {
				test.equal( prefix, this.encoder.prefix );
				test.ok( fileData );
			});

			test.done();
		}
	};

	exports['stats'] = {
		setUp: function( done ) {
			this.encoder = new Constructor( "test/files/cat.png" );
			this.encoder2 = new Constructor( "test/files/bear.svg" );
			done();
		},

		stats: function( test ) {
			test.equal( this.encoder.stats().width, '100px', "Width should match" );
			test.equal( this.encoder.stats().height, '100px', "Height should match on png" );
			test.equal( this.encoder2.stats().width, '100px', "Width should match" );
			test.equal( this.encoder2.stats().height, '62.905px', "Height should match on svg" );
			test.done();
		}
	};

	exports['SvgURIEncoder'] = {
		setUp: function( done ) {
			this.encoder = new SvgURIEncoder( "test/files/bear.svg" );
			done();
		},

		encode: function( test ) {
			var datauri = this.encoder.encode();

			test.ok( datauri.indexOf(SvgURIEncoder.prefix) >= 0 );
			test.ok( datauri.indexOf( '%' ) >= 0 );
			test.done();
		}
	};

	/**
	 * Test encoding brackets '(' and ')' to generate a valid encoded SVG
	 * in case of <g> element with functions in the 'transformation' attribute
	 */
	exports['SvgURIEncoder_brackets'] = {
		setUp: function( done ) {
			this.encoder = new SvgURIEncoder( "test/files/bear.svg" );
			done();
		},

		encode: function( test ) {
			var datauri = this.encoder.encode();

			test.ok( datauri.indexOf(SvgURIEncoder.prefix) >= 0 );
			test.ok( datauri.indexOf( '%' ) >= 0 );
			test.ok( datauri.indexOf( '(' ) === -1 );
			test.ok( datauri.indexOf( ')' ) === -1 );
			test.done();
		}
	};

	exports['PngURIEncoder'] = {
		setUp: function( done ) {
			this.encoder = new PngURIEncoder( "test/files/cat.png" );
			this.encode = _.clone( Constructor.prototype.encode );
			done();
		},

		tearDown: function( done ) {
			Constructor.prototype.encode = this.encode;
			done();
		},

		encode: function( test ) {
			testEncoded( test, this.encoder.encode().replace(PngURIEncoder.prefix, "") );
			test.done();
		},

		pathSwitch: function( test ) {
			Constructor.prototype.encode = function(){
				var i = 32768, datauri = "";

				while( i >= 0 ) {
					datauri += "a";
					i--;
				}

				return datauri;
			};

			test.equal( this.encoder.encode({ pngfolder: "foo" }), 'foo/cat.png' );
			test.done();
		}
	};
	exports['PngURIEncoder2'] = {
		setUp: function( done ) {
			this.encoder = new PngURIEncoder( "test/files/cat.png" );
			done();
		},
		tearDown: function( done ){
			done();
		},
		noencode: function( test ){
			var options = {
				noencodepng: true,
				pngfolder: "bar"
			};

			test.equal( this.encoder.encode(options), 'bar/cat.png' );
			test.done();
		}
	};
	exports['PngURIEncoder3'] = {
		setUp: function( done ) {
			this.encoder = new PngURIEncoder( "test/files/cat.png" );
			done();
		},
		tearDown: function( done ){
			done();
		},
		noencode_custompath: function( test ){
			var options = {
				noencodepng: true,
				pngfolder: "foo",
				pngpath: "bar"
			};

			test.equal( this.encoder.encode(options), 'bar/cat.png' );
			test.done();
		}
	};
	exports['PngURIEncoder4'] = {
        setUp: function( done ) {
        	this.encoder = new PngURIEncoder( "test/files/cat.png" );
            	done();
        },
        tearDown: function( done ){
        	done();
        },
        noencode_url_pngpath_http: function( test ){
        	var options = {
			noencodepng: true,
			pngpath: "http://myhost.com/images/"
		};

		test.equal( this.encoder.encode(options), 'http://myhost.com/images/cat.png' );
		test.done();
        },
        noencode_url_pngpath_https: function( test ){
		var options = {
			noencodepng: true,
			pngpath: "https://myhost.com/images/"
		};

		test.equal( this.encoder.encode(options), 'https://myhost.com/images/cat.png' );
		test.done();
        },
        noencode_url_pngpath_schemaless: function( test ){
		var options = {
			noencodepng: true,
			pngpath: "//mycdn.com/images/"
		};

		test.equal( this.encoder.encode(options), '//mycdn.com/images/cat.png' );
		test.done();
        }
    };
}());
<|endoftext|>


<commit_before>const path = require('path')

const {
  hyphenate,
  isComponent
} = require('./util')

const {
  removeExt
} = require('@dcloudio/uni-cli-shared/lib/util')

const {
  getAutoComponents
} = require('@dcloudio/uni-cli-shared/lib/pages')

const {
  updateUsingAutoImportComponents
} = require('@dcloudio/uni-cli-shared/lib/cache')

function formatSource (source) {
  if (source.indexOf('@/') === 0) { // 根目录
    source = source.replace('@/', '')
  } else { // node_modules
    if (process.env.UNI_PLATFORM === 'mp-alipay') {
      if (source.indexOf('@') === 0) {
        source = source.replace('@', 'npm-scope-')
      }
    }
    source = 'node-modules/' + source
  }
  return removeExt(source)
}

function getWebpackChunkName (source) {
  return formatSource(source)
}

function updateMPUsingAutoImportComponents (autoComponents, options) {
  if (!options.resourcePath) {
    return
  }
  const resourcePath = options.resourcePath.replace(path.extname(options.resourcePath), '')
  if (resourcePath === 'App') {
    return
  }
  const usingAutoImportComponents = Object.create(null)
  autoComponents.forEach(({
    name,
    source
  }) => {
    // 自定义组件统一格式化为 kebab-case
    usingAutoImportComponents[hyphenate(name)] = '/' + formatSource(source)
  })
  updateUsingAutoImportComponents(resourcePath, usingAutoImportComponents) // 更新json
}

function generateAutoComponentsCode (autoComponents, dynamic = false) {
  const components = []
  autoComponents.forEach(({
    name,
    source
  }) => {
    // 统一转换为驼峰命名
    name = name.replace(/-(\w)/g, (_, str) => str.toUpperCase())
    if (dynamic) {
      components.push(`'${name}': function(){return import(/* webpackChunkName: "${getWebpackChunkName(source)}" */'${source}')}`)
    } else {
      components.push(`'${name}': require('${source}').default`)
    }
  })
  return `var components;
try{
  components = {${components.join(',')}}
}catch(e){
  if(e.message.indexOf('Cannot find module') !== -1 && e.message.indexOf('.vue') !== -1){
    console.error(e.message)
    console.error('1. 排查组件名称拼写是否正确')
    console.error('2. 排查组件是否符合 easycom 规范，文档：https://uniapp.dcloud.net.cn/collocation/pages?id=easycom')
    console.error('3. 若组件不符合 easycom 规范，需手动引入，并在 components 中注册该组件')
  } else {
    throw e
  }
}`
}

function compileTemplate (source, options, compile) {
  const res = compile(source, options)
  const autoComponents = getAutoComponents([...(options.isUnaryTag.autoComponents || [])])
  if (autoComponents.length) {
    // console.log('检测到的自定义组件:' + JSON.stringify(autoComponents))
    res.components = generateAutoComponentsCode(autoComponents, options.mp)
  } else {
    res.components = 'var components;'
  }
  if (options.mp) { // 小程序 更新 json 每次编译都要调整,保证热更新时增减组件一致
    updateMPUsingAutoImportComponents(autoComponents || [], options)
  }
  return res
}

const compilerModule = {
  preTransformNode (el, options) {
    if (el.tag === 'match-media' && process.env.UNI_PLATFORM !== 'mp-weixin') {
      el.tag = 'uni-match-media'
    }
    if (process.env.UNI_PLATFORM === 'quickapp-native') {
      // 排查所有标签
      (options.isUnaryTag.autoComponents || (options.isUnaryTag.autoComponents = new Set())).add(el.tag)
    } else if (isComponent(el.tag) && el.tag !== 'App') { // App.vue
      // 挂在 isUnaryTag 上边,可以保证外部访问到
      (options.isUnaryTag.autoComponents || (options.isUnaryTag.autoComponents = new Set())).add(el.tag)
    }
  }
}
module.exports = {
  compileTemplate,
  module: compilerModule
}
<commit_msg>chore(cli): remove tips with production<commit_after>const path = require('path')

const {
  hyphenate,
  isComponent
} = require('./util')

const {
  removeExt
} = require('@dcloudio/uni-cli-shared/lib/util')

const {
  getAutoComponents
} = require('@dcloudio/uni-cli-shared/lib/pages')

const {
  updateUsingAutoImportComponents
} = require('@dcloudio/uni-cli-shared/lib/cache')

function formatSource (source) {
  if (source.indexOf('@/') === 0) { // 根目录
    source = source.replace('@/', '')
  } else { // node_modules
    if (process.env.UNI_PLATFORM === 'mp-alipay') {
      if (source.indexOf('@') === 0) {
        source = source.replace('@', 'npm-scope-')
      }
    }
    source = 'node-modules/' + source
  }
  return removeExt(source)
}

function getWebpackChunkName (source) {
  return formatSource(source)
}

function updateMPUsingAutoImportComponents (autoComponents, options) {
  if (!options.resourcePath) {
    return
  }
  const resourcePath = options.resourcePath.replace(path.extname(options.resourcePath), '')
  if (resourcePath === 'App') {
    return
  }
  const usingAutoImportComponents = Object.create(null)
  autoComponents.forEach(({
    name,
    source
  }) => {
    // 自定义组件统一格式化为 kebab-case
    usingAutoImportComponents[hyphenate(name)] = '/' + formatSource(source)
  })
  updateUsingAutoImportComponents(resourcePath, usingAutoImportComponents) // 更新json
}

function generateAutoComponentsCode (autoComponents, dynamic = false) {
  const components = []
  autoComponents.forEach(({
    name,
    source
  }) => {
    // 统一转换为驼峰命名
    name = name.replace(/-(\w)/g, (_, str) => str.toUpperCase())
    if (dynamic) {
      components.push(
        `'${name}': function(){return import(/* webpackChunkName: "${getWebpackChunkName(source)}" */'${source}')}`
      )
    } else {
      components.push(`'${name}': require('${source}').default`)
    }
  })
  if (process.env.NODE_ENV === 'production') {
    return `var components = {${components.join(',')}}`
  }
  return `var components;
try{
  components = {${components.join(',')}}
}catch(e){
  if(e.message.indexOf('Cannot find module') !== -1 && e.message.indexOf('.vue') !== -1){
    console.error(e.message)
    console.error('1. 排查组件名称拼写是否正确')
    console.error('2. 排查组件是否符合 easycom 规范，文档：https://uniapp.dcloud.net.cn/collocation/pages?id=easycom')
    console.error('3. 若组件不符合 easycom 规范，需手动引入，并在 components 中注册该组件')
  } else {
    throw e
  }
}`
}

function compileTemplate (source, options, compile) {
  const res = compile(source, options)
  const autoComponents = getAutoComponents([...(options.isUnaryTag.autoComponents || [])])
  if (autoComponents.length) {
    // console.log('检测到的自定义组件:' + JSON.stringify(autoComponents))
    res.components = generateAutoComponentsCode(autoComponents, options.mp)
  } else {
    res.components = 'var components;'
  }
  if (options.mp) { // 小程序 更新 json 每次编译都要调整,保证热更新时增减组件一致
    updateMPUsingAutoImportComponents(autoComponents || [], options)
  }
  return res
}

const compilerModule = {
  preTransformNode (el, options) {
    if (el.tag === 'match-media' && process.env.UNI_PLATFORM !== 'mp-weixin') {
      el.tag = 'uni-match-media'
    }
    if (process.env.UNI_PLATFORM === 'quickapp-native') {
      // 排查所有标签
      (options.isUnaryTag.autoComponents || (options.isUnaryTag.autoComponents = new Set())).add(el.tag)
    } else if (isComponent(el.tag) && el.tag !== 'App') { // App.vue
      // 挂在 isUnaryTag 上边,可以保证外部访问到
      (options.isUnaryTag.autoComponents || (options.isUnaryTag.autoComponents = new Set())).add(el.tag)
    }
  }
}
module.exports = {
  compileTemplate,
  module: compilerModule
}
<|endoftext|>


<commit_before>load('lib/monarch/api.js');
var Parser = require('ringo/args').Parser;
var system = require('system');
var httpclient = require('ringo/httpclient');

function main(args) {
    var script = args.shift();
    var parser = new Parser(system.args);

    parser.addOption("d","datatype","Datatype", "E.g. disease");
    parser.addOption("q","query","QueryTerm", "ID or name for a disease");
    parser.addOption("x", "extract", "DocumentPart", "E.g. phenotype_associations");
    parser.addOption('h', 'help', null, 'Display help');
    parser.addOption('c', 'context', null, 'Add JSON-LD context');
    parser.addOption('t', 'target', 'Format', 'Target format. E.g. nt, rdf-xml');
    //parser.addOption('', 'no-context', null, 'Hide JSON-LD context');
    //parser.addOption('p', 'prettyprint', null, 'Pretty print JSON');

    var options = parser.parse(args);

    if (options.help) {
	print(parser.help());
	system.exit('-1');
    }

    var engine = new bbop.monarch.Engine();

    var q = options.query;
    var func = "fetchDiseaseInfo";
    var dt = options.datatype;

    if (dt == 'disease') {
        func = "fetchDiseaseInfo";
    }
    else if (dt == 'genotype') {
        func = "fetchGenotypeInfo";
    }
    else {
        print("Unknown datatype: "+dt);
        system.exit(1);
    }

    var info = engine[func](q);

    if (options.extract != null) {
        info = info[options.extract];
    }

    if (options.context || options.target != null) {
        engine.addJsonLdContext(info);
    }
    else {
        info['@context'] = null;
    }

    var out = JSON.stringify(info, null, "    ");

    if (options.target != null) {
        var tgt = options.target;
        if (tgt == 'rdf' || tgt == 'rdf-xml') {
            tgt = 'xml';
        }
        var url = "http://rdf-translator.appspot.com/convert/json-ld/"+tgt+"/content";
        out = httpclient.post(url, {content:out}).content;
    }

    print(out);
}

// call the main method; ringo specific
if (require.main == module.id) {
    main(system.args);
}
<commit_msg>added fetching script flag for fetching similar stuff<commit_after>load('lib/monarch/api.js');
var Parser = require('ringo/args').Parser;
var system = require('system');
var httpclient = require('ringo/httpclient');

function main(args) {
    var script = args.shift();
    var parser = new Parser(system.args);

    parser.addOption("d","datatype","Datatype", "E.g. disease");
    parser.addOption("q","query","QueryTerm", "ID or name for a disease");
    parser.addOption("x", "extract", "DocumentPart", "E.g. phenotype_associations");
    parser.addOption('h', 'help', null, 'Display help');
    parser.addOption('c', 'context', null, 'Add JSON-LD context');
    parser.addOption('t', 'target', 'Format', 'Target format. E.g. nt, rdf-xml');
    //parser.addOption('', 'no-context', null, 'Hide JSON-LD context');
    //parser.addOption('p', 'prettyprint', null, 'Pretty print JSON');

    var options = parser.parse(args);

    if (options.help) {
	print(parser.help());
	system.exit('-1');
    }

    var engine = new bbop.monarch.Engine();

    var q = options.query;
    var func = "fetchDiseaseInfo";
    var dt = options.datatype;

    if (dt == 'disease') {
        func = "fetchDiseaseInfo";
    }
    else if (dt == 'genotype') {
        func = "fetchGenotypeInfo";
    }
    else if (dt == 'similarity') {
	func = "fetchThingsSimilarToADisease";
    }
    else {
        print("Unknown datatype: "+dt);
        system.exit(1);
    }

    var info = engine[func](q);

    if (options.extract != null) {
        info = info[options.extract];
    }

    if (options.context || options.target != null) {
        engine.addJsonLdContext(info);
    }
    else {
        info['@context'] = null;
    }

    var out = JSON.stringify(info, null, "    ");

    if (options.target != null) {
        var tgt = options.target;
        if (tgt == 'rdf' || tgt == 'rdf-xml') {
            tgt = 'xml';
        }
        var url = "http://rdf-translator.appspot.com/convert/json-ld/"+tgt+"/content";
        out = httpclient.post(url, {content:out}).content;
    }

    print(out);
}

// call the main method; ringo specific
if (require.main == module.id) {
    main(system.args);
}
<|endoftext|>


<commit_before>var fs = require("fs-extra");
var semver = require("semver");
var exec = require("child_process").exec;

var prefix = "[iobeam-client] ";

function log(msg) {
    console.log(prefix + msg);
}

var forceBabel;
// if dependency, check the package.json
try {
    var pjson = require(__dirname + "/../../package.json");
    var iobeamClient = pjson.iobeam;
    forceBabel = iobeamClient.babel || iobeamClient.es5 || false;
} catch (Exception) {
    forceBabel = false;
}

log("Determining whether to use ES5 or not...");
if (!forceBabel && semver.gt(process.version, "4.0.0")) {
    log("ES5 not needed, using original files.");

    try {
        fs.copySync("./src", "./lib", {clobber: true});
    } catch (err) {
            return console.error(err);
    }
} else {
    if (forceBabel) {
        log("Library requested that es5 be used.");
    } else {
        log("Node version too old, using es5.");
    }
    try {
        fs.copySync("./es5", "./lib", {clobber: true});
    } catch (err) {
            return console.error(err);
    }
}
<commit_msg>build: simplify compile script<commit_after>var fs = require("fs-extra");
var semver = require("semver");
var exec = require("child_process").exec;

function log(msg) {
    console.log("[iobeam-client] " + msg);
}

var forceBabel;
// if dependency, check the package.json
try {
    var pjson = require(__dirname + "/../../package.json");
    var iobeamClient = pjson.iobeam;
    forceBabel = iobeamClient.babel || iobeamClient.es5 || false;
} catch (Exception) {
    forceBabel = false;
}

var src;
log("Determining whether to use ES5 or not...");
if (!forceBabel && semver.gt(process.version, "4.0.0")) {
    log("ES5 not needed, using original files.");
    src = "./src";
} else {
    if (forceBabel) {
        log("Library requested that ES5 be used.");
    } else {
        log("Node version too old, using ES5.");
    }
    src = "./es5";
}

try {
    fs.copySync(src, "./lib", {clobber: true});
} catch (err) {
        return console.error(err);
}
<|endoftext|>


<commit_before>import { expect } from 'chai';
import { describe, it } from 'mocha';
import currencies from '../../js/data/cryptoCurrencies';

describe('the crypto currencies data module', () => {
  describe('has a config array of crypto currency configuration objects', () => {
    it('that requires a code to be provided as a string', () => {
      currencies.forEach(cur => {
        expect(typeof cur.code).to.equal('string');
      });
    });

    it('that, if provided, requires the testnetCode to be a string', () => {
      currencies.forEach(cur => {
        if (cur.testnetCode !== undefined) {
          expect(typeof cur.testnetCode).to.equal('string');
        }
      });
    });

    it('that, if provided, requires the symbol to be a string', () => {
      currencies.forEach(cur => {
        if (cur.symbol !== undefined) {
          expect(typeof cur.symbol).to.equal('string');
        }
      });
    });

    it('that requires the baseUnit to be a number > 0', () => {
      currencies.forEach(cur => {
        expect(typeof cur.baseUnit === 'number' && cur.baseUnit > 0).to.equal(true);
      });
    });

    it('that requires the minDisplayDecimals to be a number >= 0', () => {
      currencies.forEach(cur => {
        expect(typeof cur.minDisplayDecimals === 'number' && cur.minDisplayDecimals >= 0)
          .to.equal(true);
      });
    });

    it('that requires the maxDisplayDecimals to be a number > 0', () => {
      currencies.forEach(cur => {
        expect(typeof cur.maxDisplayDecimals === 'number' && cur.maxDisplayDecimals > 0)
          .to.equal(true);
      });
    });

    it('that requires the maxDisplayDecimals to be greater than or equal to the minDisplayDecimals',
      () => {
        currencies.forEach(cur => {
          expect(cur.maxDisplayDecimals >= cur.minDisplayDecimals).to.equal(true);
        });
      });

    it('that requires the averageModeratedTransactionSize to be a number > 0', () => {
      currencies.forEach(cur => {
        expect(typeof cur.averageModeratedTransactionSize === 'number' &&
          cur.averageModeratedTransactionSize > 0).to.equal(true);
      });
    });

    it('that requires the feeBumpTransactionSize to be a number > 0', () => {
      currencies.forEach(cur => {
        expect(typeof cur.feeBumpTransactionSize === 'number' &&
          cur.feeBumpTransactionSize > 0).to.equal(true);
      });
    });

    it('that requires the qrCodeText to be a function', () => {
      currencies.forEach(cur => {
        expect(typeof cur.qrCodeText).to.equal('function');
      });
    });

    it('that, if provided, requires the icon to be a string', () => {
      currencies.forEach(cur => {
        if (cur.icon !== undefined) {
          expect(typeof cur.icon).to.equal('string');
        }
      });
    });

    it('that, if provided, requires the needCoinLink to be a string', () => {
      currencies.forEach(cur => {
        if (cur.needCoinLink !== undefined) {
          expect(typeof cur.needCoinLink).to.equal('string');
        }
      });
    });

    it('that requires the getBlockChainAddressUrl to be a function', () => {
      currencies.forEach(cur => {
        expect(typeof cur.getBlockChainAddressUrl).to.equal('function');
      });
    });

    it('that requires the getBlockChainTxUrl to be a function', () => {
      currencies.forEach(cur => {
        expect(typeof cur.getBlockChainTxUrl).to.equal('function');
      });
    });

    it('that requires the getBlockChainTxUrl to be a function', () => {
      currencies.forEach(cur => {
        expect(typeof cur.getBlockChainTxUrl).to.equal('function');
      });
    });

    it('that requires the canShapeShiftInto to be a boolean', () => {
      currencies.forEach(cur => {
        expect(typeof cur.canShapeShiftInto).to.equal('boolean');
      });
    });
  });
});
<commit_msg>added a unit test for isValidAddress of the crypto currencies module<commit_after>import { expect } from 'chai';
import { describe, it } from 'mocha';
import currencies from '../../js/data/cryptoCurrencies';

describe('the crypto currencies data module', () => {
  describe('has a config array of crypto currency configuration objects', () => {
    it('that requires a code to be provided as a string', () => {
      currencies.forEach(cur => {
        expect(typeof cur.code).to.equal('string');
      });
    });

    it('that, if provided, requires the testnetCode to be a string', () => {
      currencies.forEach(cur => {
        if (cur.testnetCode !== undefined) {
          expect(typeof cur.testnetCode).to.equal('string');
        }
      });
    });

    it('that, if provided, requires the symbol to be a string', () => {
      currencies.forEach(cur => {
        if (cur.symbol !== undefined) {
          expect(typeof cur.symbol).to.equal('string');
        }
      });
    });

    it('that requires the baseUnit to be a number > 0', () => {
      currencies.forEach(cur => {
        expect(typeof cur.baseUnit === 'number' && cur.baseUnit > 0).to.equal(true);
      });
    });

    it('that requires the minDisplayDecimals to be a number >= 0', () => {
      currencies.forEach(cur => {
        expect(typeof cur.minDisplayDecimals === 'number' && cur.minDisplayDecimals >= 0)
          .to.equal(true);
      });
    });

    it('that requires the maxDisplayDecimals to be a number > 0', () => {
      currencies.forEach(cur => {
        expect(typeof cur.maxDisplayDecimals === 'number' && cur.maxDisplayDecimals > 0)
          .to.equal(true);
      });
    });

    it('that requires the maxDisplayDecimals to be greater than or equal to the minDisplayDecimals',
      () => {
        currencies.forEach(cur => {
          expect(cur.maxDisplayDecimals >= cur.minDisplayDecimals).to.equal(true);
        });
      });

    it('that requires the averageModeratedTransactionSize to be a number > 0', () => {
      currencies.forEach(cur => {
        expect(typeof cur.averageModeratedTransactionSize === 'number' &&
          cur.averageModeratedTransactionSize > 0).to.equal(true);
      });
    });

    it('that requires the feeBumpTransactionSize to be a number > 0', () => {
      currencies.forEach(cur => {
        expect(typeof cur.feeBumpTransactionSize === 'number' &&
          cur.feeBumpTransactionSize > 0).to.equal(true);
      });
    });

    it('that requires the qrCodeText to be a function', () => {
      currencies.forEach(cur => {
        expect(typeof cur.qrCodeText).to.equal('function');
      });
    });

    it('that, if provided, requires the icon to be a string', () => {
      currencies.forEach(cur => {
        if (cur.icon !== undefined) {
          expect(typeof cur.icon).to.equal('string');
        }
      });
    });

    it('that, if provided, requires the needCoinLink to be a string', () => {
      currencies.forEach(cur => {
        if (cur.needCoinLink !== undefined) {
          expect(typeof cur.needCoinLink).to.equal('string');
        }
      });
    });

    it('that requires the getBlockChainAddressUrl to be a function', () => {
      currencies.forEach(cur => {
        expect(typeof cur.getBlockChainAddressUrl).to.equal('function');
      });
    });

    it('that requires the getBlockChainTxUrl to be a function', () => {
      currencies.forEach(cur => {
        expect(typeof cur.getBlockChainTxUrl).to.equal('function');
      });
    });

    it('that requires the getBlockChainTxUrl to be a function', () => {
      currencies.forEach(cur => {
        expect(typeof cur.getBlockChainTxUrl).to.equal('function');
      });
    });

    it('that requires the canShapeShiftInto to be a boolean', () => {
      currencies.forEach(cur => {
        expect(typeof cur.canShapeShiftInto).to.equal('boolean');
      });
    });

    // isValidAddress
    it('that, if provided, requires isValidAddress to be a function', () => {
      currencies.forEach(cur => {
        if (cur.isValidAddress !== undefined) {
          expect(typeof cur.isValidAddress).to.equal('function');
        }
      });
    });

    it('that, if provided, requires isValidAddress to be a function that returns a boolean ' +
      'or throws an exception', () => {
      currencies.forEach(cur => {
        if (cur.isValidAddress !== undefined) {
          let isValid;
          let exceptionThrown = false;

          try {
            isValid = cur.isValidAddress('abcdefghijklmnop');
          } catch (e) {
            exceptionThrown = true;
          }

          expect(typeof isValid === 'boolean' || exceptionThrown).to.equal(true);
        }
      });
    });
  });
});
<|endoftext|>


<commit_before>#!/usr/bin/env node
var metaMarked =    require("meta-marked"),
    fs =            require("fs-extra"),
    yamljs =        require("yamljs"),
    fswf =          require("safe-write-file");

var SOURCE_PATH = "src/",
    SOURCE_INFO_FILE = "info.yml",
    SOURCE_EXTENSION = "md",
    SOURCE_COVER_FILE = "cover.png",
    DIST_PATH = "dist/",
    DIST_INFO_FILE = "info.json",
    DIST_COVER_FILE = "cover.png",
    DIST_EXTENSION = "json";

var crypto = require("crypto");

function createChecksum(str){
  return crypto
    .createHash("sha256")
    .update(str, "utf8")
    .digest("hex")
}

var processLang = function(path){
  var quarterlies = fs.readdirSync(path).reverse(),
      lang_info = { "quarterlies": [] };

  for (var i = 0; i < quarterlies.length; i++){
    var quarterly_path = path + "/" + quarterlies[i];
    if (!fs.lstatSync(quarterly_path).isDirectory()) continue;
    if (!fs.lstatSync(quarterly_path + "/" + SOURCE_INFO_FILE).isFile()) continue;
    if (!fs.lstatSync(quarterly_path + "/" + SOURCE_COVER_FILE).isFile()) continue;

    var quarterly = fs.readdirSync(quarterly_path);

    var quarterly_info = yamljs.load(quarterly_path + "/" + SOURCE_INFO_FILE);
    quarterly_info.id = quarterly_path.replace(SOURCE_PATH, "");
    quarterly_info.lessons = [];

    fs.copySync(quarterly_path + "/" + SOURCE_COVER_FILE, quarterly_path.replace(SOURCE_PATH, DIST_PATH) + "/" + DIST_COVER_FILE);
    quarterly_info.cover = quarterly_path.replace(SOURCE_PATH, "") + "/" + DIST_COVER_FILE;

    for (var j = 0; j < quarterly.length; j++){
      var lesson_dir = quarterly_path + "/" + quarterly[j];
      if (!fs.lstatSync(lesson_dir).isDirectory()) continue;

      var lessons = fs.readdirSync(lesson_dir);

      var lesson_md_info = yamljs.load(lesson_dir + "/" + SOURCE_INFO_FILE);
      lesson_md_info.days = [];

      for (var k = 0; k < lessons.length; k++){
        var extension = lessons[k].split(".").pop();
        if (extension != SOURCE_EXTENSION) continue;

        var day_path = lesson_dir.replace(SOURCE_PATH, DIST_PATH) + "/" + lessons[k].replace(SOURCE_EXTENSION, DIST_EXTENSION),
          lesson_md = metaMarked(fs.readFileSync(lesson_dir + "/" + lessons[k], "utf-8"));

        lesson_md.meta.path = day_path.replace(DIST_PATH, "");
        lesson_md_info.days.push(lesson_md.meta);

        var lesson_contents = {};
        lesson_contents = lesson_md.meta;
        lesson_contents.html = lesson_md.html;

        lesson_contents.checksum = createChecksum(JSON.stringify(lesson_contents));
        lesson_contents.last_modified = Date.now();
        fswf(day_path, JSON.stringify(lesson_contents));
        delete lesson_contents.html;

      }

      lesson_md_info.checksum = createChecksum(JSON.stringify(lesson_md_info));
      lesson_md_info.last_modified = Date.now();
      fswf(quarterly_path.replace(SOURCE_PATH, DIST_PATH) + "/" + "/" + quarterly[j] + "/" + DIST_INFO_FILE, JSON.stringify(lesson_md_info));
      delete lesson_md_info.days;
      lesson_md_info.path = quarterly_path.replace(SOURCE_PATH, "") + "/" + quarterly[j] + "/" + DIST_INFO_FILE;
      quarterly_info.lessons.push(lesson_md_info);
    }

    quarterly_info.path = quarterly_path.replace(SOURCE_PATH, "") + "/" + DIST_INFO_FILE;

    quarterly_info.checksum = createChecksum(JSON.stringify(quarterly_info));
    quarterly_info.last_modified = Date.now();
    fswf(quarterly_path.replace(SOURCE_PATH, DIST_PATH) + "/" + DIST_INFO_FILE, JSON.stringify(quarterly_info));
    delete quarterly_info.lessons;
    lang_info.quarterlies.push(quarterly_info);
  }

  lang_info.checksum = createChecksum(JSON.stringify(lang_info));
  lang_info.last_modified = Date.now();
  fswf(path.replace(SOURCE_PATH, DIST_PATH) + "/" + DIST_INFO_FILE, JSON.stringify(lang_info));
};

var languages = fs.readdirSync(SOURCE_PATH),
    api_info = {
      "languages": []
    };

for (var i = 0; i < languages.length; i++){
  if (!fs.lstatSync(SOURCE_PATH + languages[i]).isDirectory()) continue;
  processLang(SOURCE_PATH + languages[i]);
  api_info.languages.push(languages[i]);

}

api_info.checksum = createChecksum(JSON.stringify(api_info));
api_info.last_modified = Date.now();
fswf(DIST_PATH+ "/" + DIST_INFO_FILE, JSON.stringify(api_info));<commit_msg>Add ID value to weekly lesson and daily lesson<commit_after>#!/usr/bin/env node
var metaMarked =    require("meta-marked"),
    fs =            require("fs-extra"),
    yamljs =        require("yamljs"),
    fswf =          require("safe-write-file");

var SOURCE_PATH = "src/",
    SOURCE_INFO_FILE = "info.yml",
    SOURCE_EXTENSION = "md",
    SOURCE_COVER_FILE = "cover.png",
    DIST_PATH = "dist/",
    DIST_INFO_FILE = "info.json",
    DIST_COVER_FILE = "cover.png",
    DIST_EXTENSION = "json";

var crypto = require("crypto");

function createChecksum(str){
  return crypto
    .createHash("sha256")
    .update(str, "utf8")
    .digest("hex")
}

var processLang = function(path){
  var quarterlies = fs.readdirSync(path).reverse(),
      lang_info = { "quarterlies": [] };

  for (var i = 0; i < quarterlies.length; i++){
    var quarterly_path = path + "/" + quarterlies[i];
    if (!fs.lstatSync(quarterly_path).isDirectory()) continue;
    if (!fs.lstatSync(quarterly_path + "/" + SOURCE_INFO_FILE).isFile()) continue;
    if (!fs.lstatSync(quarterly_path + "/" + SOURCE_COVER_FILE).isFile()) continue;

    var quarterly = fs.readdirSync(quarterly_path);

    var quarterly_info = yamljs.load(quarterly_path + "/" + SOURCE_INFO_FILE);
    quarterly_info.id = quarterly_path.replace(SOURCE_PATH, "");
    quarterly_info.lessons = [];

    fs.copySync(quarterly_path + "/" + SOURCE_COVER_FILE, quarterly_path.replace(SOURCE_PATH, DIST_PATH) + "/" + DIST_COVER_FILE);
    quarterly_info.cover = quarterly_path.replace(SOURCE_PATH, "") + "/" + DIST_COVER_FILE;

    for (var j = 0; j < quarterly.length; j++){
      var lesson_dir = quarterly_path + "/" + quarterly[j];
      if (!fs.lstatSync(lesson_dir).isDirectory()) continue;

      var lessons = fs.readdirSync(lesson_dir);

      var lesson_md_info = yamljs.load(lesson_dir + "/" + SOURCE_INFO_FILE);
      lesson_md_info.id = lesson_dir.replace(SOURCE_PATH, "");
      lesson_md_info.days = [];

      for (var k = 0; k < lessons.length; k++){
        var extension = lessons[k].split(".").pop();
        if (extension != SOURCE_EXTENSION) continue;

        var day_path = lesson_dir.replace(SOURCE_PATH, DIST_PATH) + "/" + lessons[k].replace(SOURCE_EXTENSION, DIST_EXTENSION),
          lesson_md = metaMarked(fs.readFileSync(lesson_dir + "/" + lessons[k], "utf-8"));

        lesson_md.meta.path = day_path.replace(DIST_PATH, "");
        lesson_md_info.days.push(lesson_md.meta);

        var lesson_contents = {};

        lesson_contents = lesson_md.meta;
        lesson_contents.id = lesson_dir.replace(SOURCE_PATH, "") + "/" + lessons[k].replace("."+SOURCE_EXTENSION, "");
        lesson_contents.html = lesson_md.html;

        lesson_contents.checksum = createChecksum(JSON.stringify(lesson_contents));
        lesson_contents.last_modified = Date.now();
        fswf(day_path, JSON.stringify(lesson_contents));
        delete lesson_contents.html;

      }

      lesson_md_info.checksum = createChecksum(JSON.stringify(lesson_md_info));
      lesson_md_info.last_modified = Date.now();
      fswf(quarterly_path.replace(SOURCE_PATH, DIST_PATH) + "/" + "/" + quarterly[j] + "/" + DIST_INFO_FILE, JSON.stringify(lesson_md_info));
      delete lesson_md_info.days;
      lesson_md_info.path = quarterly_path.replace(SOURCE_PATH, "") + "/" + quarterly[j] + "/" + DIST_INFO_FILE;
      quarterly_info.lessons.push(lesson_md_info);
    }

    quarterly_info.path = quarterly_path.replace(SOURCE_PATH, "") + "/" + DIST_INFO_FILE;

    quarterly_info.checksum = createChecksum(JSON.stringify(quarterly_info));
    quarterly_info.last_modified = Date.now();
    fswf(quarterly_path.replace(SOURCE_PATH, DIST_PATH) + "/" + DIST_INFO_FILE, JSON.stringify(quarterly_info));
    delete quarterly_info.lessons;
    lang_info.quarterlies.push(quarterly_info);
  }

  lang_info.checksum = createChecksum(JSON.stringify(lang_info));
  lang_info.last_modified = Date.now();
  fswf(path.replace(SOURCE_PATH, DIST_PATH) + "/" + DIST_INFO_FILE, JSON.stringify(lang_info));
};

var languages = fs.readdirSync(SOURCE_PATH),
    api_info = {
      "languages": []
    };

for (var i = 0; i < languages.length; i++){
  if (!fs.lstatSync(SOURCE_PATH + languages[i]).isDirectory()) continue;
  processLang(SOURCE_PATH + languages[i]);
  api_info.languages.push(languages[i]);

}

api_info.checksum = createChecksum(JSON.stringify(api_info));
api_info.last_modified = Date.now();
fswf(DIST_PATH+ "/" + DIST_INFO_FILE, JSON.stringify(api_info));<|endoftext|>


<commit_before>/*
 * This file is part of the Spludo Framework.
 * Copyright (c) 2009 DracoBlue, http://dracoblue.net/
 *
 * Licensed under the terms of MIT License. For the full copyright and license
 * information, please see the LICENSE file in the root folder.
 */

/**
 * @class A toolkit for convenient functions to work on the context.
 *
 * @since 0.1
 * @author DracoBlue
 */
ContextToolkit = {

    setCookie: function(context, key, value, life_time, path) {
        context.cookies = context.cookies || {};
        context.cookies[key] = value;
        if (typeof life_time !== "undefined") {
            if (life_time !== null) {
                context.cookies_life_time = context.cookies_life_time || {};
                context.cookies_life_time[key] = life_time;
            }

            if (typeof path !== "undefined") {
                context.cookies_path = context.cookies_path || {};
                context.cookies_path[key] = path;
            }
        }
    },

    applyCookiesToHeaders: function(context) {
        if (!context || !context.cookies) {

            /*
             * Ok, we have nothing in the cookies, let's remove the
             * headers['Set-Cookie'] (if it exists)
             */
            if (context && context.headers) {
                delete context.headers["Set-Cookie"];
            }

            return;
        }

        context = context || {};
        context.headers = context.headers || {};

        context.headers["Set-Cookie"] = [];
        for (key in context.cookies) {
            context.headers["Set-Cookie"]
                    .push(encodeURIComponent(key) + "=" + encodeURIComponent(context.cookies[key]));
        }

    }

};<commit_msg>Externalized the headers.cookies into an extra variable.<commit_after>/*
 * This file is part of the Spludo Framework.
 * Copyright (c) 2009 DracoBlue, http://dracoblue.net/
 *
 * Licensed under the terms of MIT License. For the full copyright and license
 * information, please see the LICENSE file in the root folder.
 */

/**
 * @class A toolkit for convenient functions to work on the context.
 *
 * @since 0.1
 * @author DracoBlue
 */
ContextToolkit = {

    setCookie: function(context, key, value, life_time, path) {
        context.cookies = context.cookies || {};
        context.cookies[key] = value;
        if (typeof life_time !== "undefined") {
            if (life_time !== null) {
                context.cookies_life_time = context.cookies_life_time || {};
                context.cookies_life_time[key] = life_time;
            }

            if (typeof path !== "undefined") {
                context.cookies_path = context.cookies_path || {};
                context.cookies_path[key] = path;
            }
        }
    },

    applyCookiesToHeaders: function(context) {
        if (!context || !context.cookies) {

            /*
             * Ok, we have nothing in the cookies, let's remove the
             * headers['Set-Cookie'] (if it exists)
             */
            if (context && context.headers) {
                delete context.headers["Set-Cookie"];
            }

            return;
        }

        context = context || {};
        context.headers = context.headers || {};
        context.headers["Set-Cookie"] = [];

        var cookies = context.cookies;
        for (key in cookies) {
            context.headers["Set-Cookie"].push(encodeURIComponent(key) + "=" + encodeURIComponent(cookies[key]));
        }

    }

};<|endoftext|>


<commit_before>import { mount, createLocalVue } from '@vue/test-utils'
import Tree from '@/components/Tree'

let datasource = [
  {
    label: 'Infused',
    value: 'Infused',
    children: [
      {
        label: 'Filtered',
        value: 'Filtered'
      }
    ]
  },
  {
    label: 'Boiled',
    value: 'Boiled',
    children: [
      {
        label: 'Brewed',
        value: 'Brewed'
      }
    ]
  }
]

describe('components/Tree', () => {
  it('should render item slot', () => {
    let wrapper = mount(Tree, {
      localVue: createLocalVue(),
      propsData: {
        datasource,
        expanded: ['Infused']
      },
      scopedSlots: {
        item:
          '
{{props.item.label}}
'
      }
    })

    expect(wrapper.find('.test-item-slot').exists()).to.equal(true)

    wrapper.destroy()
  })

  it('should render item-label slot', () => {
    let wrapper = mount(Tree, {
      localVue: createLocalVue(),
      propsData: {
        datasource,
        expanded: ['Infused']
      },
      scopedSlots: {
        'item-label':
          '
{{props.item.label}}
'
      }
    })

    expect(wrapper.find('.test-item-label-slot').exists()).to.equal(true)

    wrapper.destroy()
  })

  it('should sync expanded status when click the item', async () => {
    let localVue = createLocalVue()
    let WrapperTree = {
      components: {
        'veui-tree': Tree
      },
      data () {
        return {
          expanded: ['Infused'],
          datasource
        }
      },
      template:
        '<veui-tree :datasource="datasource" :expanded.sync="expanded" />'
    }

    let wrapper = mount(WrapperTree, { localVue })
    expect(
      wrapper
        .findAll('.veui-tree-item')
        .at(0)
        .classes('veui-tree-item-expanded')
    ).to.equal(true)

    wrapper
      .findAll('.veui-tree-item')
      .at(2)
      .find('.veui-tree-item-expand-switcher')
      .trigger('click')

    await localVue.nextTick()

    expect(wrapper.vm.expanded.indexOf('Boiled') > -1).to.equal(true)
    expect(
      wrapper
        .findAll('.veui-tree-item')
        .at(2)
        .classes('veui-tree-item-expanded')
    ).to.equal(true)

    wrapper.destroy()
  })
})
<commit_msg>test: add test case for Tree (#464)<commit_after>import { mount } from '@vue/test-utils'
import Tree from '@/components/Tree'

let datasource = [
  {
    label: 'Infused',
    value: 'infused',
    children: [
      {
        label: 'Brewed',
        value: 'brewed',
        children: [
          {
            label: 'Drip brewed',
            value: 'drip-brewed'
          },
          {
            label: 'Filtered',
            value: 'filtered'
          },
          {
            label: 'Pour-over',
            value: 'pour-over'
          },
          {
            label: 'Immersion brewed',
            value: 'immersion-brewed'
          }
        ]
      },
      {
        label: 'French press',
        value: 'french-press'
      },
      {
        label: 'Cold brew',
        value: 'cold-brew'
      }
    ]
  },
  {
    label: 'Boiled',
    value: 'boiled',
    children: [
      {
        label: 'Percolated',
        value: 'percolated'
      },
      {
        label: 'Turkish',
        value: 'turkish'
      },
      {
        label: 'Moka',
        value: 'moka'
      }
    ]
  },
  {
    label: 'Espresso',
    value: 'espresso',
    children: [
      {
        label: 'Caffè Americano',
        value: 'caffe-americano'
      },
      {
        label: 'Cafe Lungo',
        value: 'cafe-lungo'
      },
      {
        label: 'Café Cubano',
        value: 'cafe-cubano'
      },
      {
        label: 'Caffè crema',
        value: 'caffe-crema'
      },
      {
        label: 'Cafe Zorro',
        value: 'cafe-zorro'
      },
      {
        label: 'Doppio',
        value: 'doppio'
      },
      {
        label: 'Espresso Romano',
        value: 'espresso-romano'
      },
      {
        label: 'Guillermo',
        value: 'guillermo'
      },
      {
        label: 'Ristretto',
        value: 'ristretto'
      }
    ]
  },
  {
    label: 'Milk coffee',
    value: 'milk-coffee',
    children: [
      {
        label: 'Flat white',
        value: 'flat-white'
      },
      {
        label: 'Latte',
        value: 'latte'
      },
      {
        label: 'Macchiato',
        value: 'macchiato'
      },
      {
        label: 'Cappuccino',
        value: 'cappuccino'
      },
      {
        label: 'White coffee',
        value: 'white-coffee'
      },
      {
        label: 'Flat white',
        value: 'flat-white'
      },
      {
        label: 'Flat white',
        value: 'flat-white'
      }
    ]
  }
]

describe('components/Tree', () => {
  it('should render datasource correctly when `expanded` was not set', () => {
    let wrapper = mount(Tree, {
      propsData: {
        datasource
      }
    })

    expect(wrapper.findAll('.veui-tree-item').length).to.equal(4)
    expect(wrapper.find('.veui-tree-item-group').exists()).to.equal(false)

    wrapper.destroy()
  })

  it('should render datasource correctly when `expanded` was set', () => {
    let wrapper = mount(Tree, {
      propsData: {
        datasource,
        expanded: ['infused', 'brewed']
      }
    })

    expect(wrapper.findAll('.veui-tree-item').length).to.equal(11)
    expect(wrapper.findAll('.veui-tree-item-expanded').length).to.equal(2)
    expect(wrapper.findAll('.veui-tree-item-group').length).to.equal(2)
    expect(
      wrapper
        .find('.veui-tree-item')
        .classes('veui-tree-item-expanded')
    ).to.equal(true)
    expect(
      wrapper
        .find('.veui-tree-item')
        .find('.veui-tree-item')
        .classes('veui-tree-item-expanded')
    ).to.equal(true)

    wrapper.destroy()
  })

  it('nodes can only be toggled by clicking toggle buttons when `item-click` was not set', async () => {
    let wrapper = mount(Tree, {
      propsData: {
        datasource
      }
    })
    let { vm } = wrapper

    expect(wrapper.findAll('.veui-tree-item').length).to.equal(4)

    let item = wrapper.find('.veui-tree-item')
    item.find('.veui-tree-item-label').trigger('click')
    await vm.$nextTick()

    expect(wrapper.findAll('.veui-tree-item').length).to.equal(4)
    expect(item.classes('veui-tree-item-expanded')).to.equal(false)

    item.find('.veui-tree-item-expand-switcher').trigger('click')
    await vm.$nextTick()

    expect(wrapper.findAll('.veui-tree-item').length).to.equal(7)
    expect(item.classes('veui-tree-item-expanded')).to.equal(true)

    wrapper.destroy()
  })

  it('nodes can be toggled by clicking any part of them when `item-click` was not set', async () => {
    let wrapper = mount(Tree, {
      propsData: {
        datasource,
        itemClick: 'toggle'
      }
    })
    let { vm } = wrapper

    expect(wrapper.findAll('.veui-tree-item').length).to.equal(4)

    let item = wrapper.find('.veui-tree-item')
    item.find('.veui-tree-item-label').trigger('click')
    await vm.$nextTick()

    expect(wrapper.findAll('.veui-tree-item').length).to.equal(7)
    expect(item.classes('veui-tree-item-expanded')).to.equal(true)

    item.find('.veui-tree-item-expand-switcher').trigger('click')
    await vm.$nextTick()

    expect(wrapper.findAll('.veui-tree-item').length).to.equal(4)
    expect(item.classes('veui-tree-item-expanded')).to.equal(false)

    wrapper.destroy()
  })

  it('should render item scoped-slot correctly', () => {
    let wrapper = mount(Tree, {
      propsData: {
        datasource
      },
      scopedSlots: {
        item:
          '
{{props.item.label}} item slot
'
      }
    })

    expect(wrapper.find('.test-item-slot').exists()).to.equal(true)
    expect(wrapper.find('.test-item-slot').text()).to.equal('Infused item slot')

    wrapper.destroy()
  })

  it('should render item-label scoped-slot correctly', () => {
    let wrapper = mount(Tree, {
      propsData: {
        datasource
      },
      scopedSlots: {
        'item-label':
          '
{{props.item.label}} item-label slot
'
      }
    })

    expect(wrapper.find('.test-item-label-slot').exists()).to.equal(true)
    expect(wrapper.find('.test-item-label-slot').text()).to.equal('Infused item-label slot')

    wrapper.destroy()
  })

  it('should sync expanded status correctly when toggling a node', async () => {
    let wrapper = mount({
      components: {
        'veui-tree': Tree
      },
      data () {
        return {
          expanded: ['infused'],
          datasource
        }
      },
      template:
        '<veui-tree :datasource="datasource" :expanded.sync="expanded" />'
    })
    let { vm } = wrapper

    expect(
      wrapper
        .find('.veui-tree-item')
        .classes('veui-tree-item-expanded')
    ).to.equal(true)

    wrapper
      .findAll('.veui-tree-item')
      .at(4)
      .find('.veui-tree-item-expand-switcher')
      .trigger('click')
    await vm.$nextTick()

    expect(vm.expanded.indexOf('boiled') > -1).to.equal(true)
    expect(
      wrapper
        .findAll('.veui-tree-item')
        .at(4)
        .classes('veui-tree-item-expanded')
    ).to.equal(true)

    wrapper
      .findAll('.veui-tree-item')
      .at(1)
      .find('.veui-tree-item-expand-switcher')
      .trigger('click')
    await vm.$nextTick()

    expect(vm.expanded.indexOf('brewed') > -1).to.equal(true)
    expect(
      wrapper
        .findAll('.veui-tree-item')
        .at(1)
        .classes('veui-tree-item-expanded')
    ).to.equal(true)

    wrapper
      .findAll('.veui-tree-item')
      .at(1)
      .find('.veui-tree-item-expand-switcher')
      .trigger('click')
    await vm.$nextTick()

    expect(vm.expanded.indexOf('brewed') > -1).to.equal(false)
    expect(
      wrapper
        .findAll('.veui-tree-item')
        .at(1)
        .classes('veui-tree-item-expanded')
    ).to.equal(false)

    wrapper
      .findAll('.veui-tree-item')
      .at(4)
      .find('.veui-tree-item-expand-switcher')
      .trigger('click')
    await vm.$nextTick()

    expect(vm.expanded.indexOf('boiled') > -1).to.equal(false)
    expect(
      wrapper
        .findAll('.veui-tree-item')
        .at(4)
        .classes('veui-tree-item-expanded')
    ).to.equal(false)

    wrapper.destroy()
  })

  it('should handle click event correctly', async () => {
    let wrapper = mount({
      components: {
        'veui-tree': Tree
      },
      data () {
        return {
          datasource
        }
      },
      methods: {
        handleClick (item, parents, index, depth) {
          expect(item.value).to.equal('infused')
          expect(parents).to.deep.equal([])
          expect(index).to.equal(0)
          expect(depth).to.equal(1)
        }
      },
      template:
        '<veui-tree :datasource="datasource" @click="handleClick" item-click="toggle" />'
    })
    let { vm } = wrapper

    wrapper.find('.veui-tree-item').trigger('click')
    await vm.$nextTick()

    wrapper.destroy()
  })

  it('should handle keyboard event correctly', async () => {
    let wrapper = mount(Tree, {
      propsData: {
        datasource
      },
      attachToDocument: true
    })
    let { vm } = wrapper

    wrapper.find('.veui-tree-item').trigger('keydown', { key: 'Enter' })
    await vm.$nextTick()

    expect(wrapper.find('.veui-tree-item').classes('focus-visible')).to.equal(true)
    expect(wrapper.find('.veui-tree-item').classes('veui-tree-item-expanded')).to.equal(true)

    wrapper.find('.veui-tree-item').trigger('keydown', { key: 'Left' })
    await vm.$nextTick()

    expect(wrapper.find('.veui-tree-item').classes('veui-tree-item-expanded')).to.equal(false)

    wrapper.find('.veui-tree-item').trigger('keydown', { key: 'Right' })
    await vm.$nextTick()

    expect(wrapper.find('.veui-tree-item').classes('veui-tree-item-expanded')).to.equal(true)

    wrapper.find('.veui-tree-item').trigger('keydown', { key: 'Enter' })
    await vm.$nextTick()

    expect(wrapper.find('.veui-tree-item').classes('veui-tree-item-expanded')).to.equal(false)

    wrapper.find('.veui-tree-item').trigger('blur')
    await vm.$nextTick()

    expect(
      wrapper
        .findAll('.veui-tree-item')
        .at(0)
        .classes('focus-visible')
    ).to.equal(false)

    wrapper.destroy()
  })
})
<|endoftext|>


<commit_before>import React from 'react';
import types from '@appbaseio/reactivecore/lib/utils/types';
import { getInternalComponentID } from '@appbaseio/reactivecore/lib/utils/transform';

import {
	pushToAndClause,
	checkPropChange,
	checkSomePropChange,
} from '@appbaseio/reactivecore/lib/utils/helper';

import {
	addComponent,
	removeComponent,
	watchComponent,
	setQueryListener,
	setComponentProps,
	updateComponentProps,
} from '@appbaseio/reactivecore/lib/actions';

import { connect, getValidPropsKeys, hasCustomRenderer, getComponent } from '../../utils';

/**
 * ComponentWrapper component is a wrapper component for each ReactiveSearch component
 * which is responsible for following tasks:
 * 1. Register a component on mount
 * 2. Set query listener
 * 3. Set react prop
 * 4. Follow the [1-3] for the internal component if needed
 * 5. Update component props in redux store
 * 6. Unregister the component on un-mount
 */
class ComponentWrapper extends React.Component {
	constructor(props) {
		super(props);
		// Register  component
		props.addComponent(props.componentId);
		props.setQueryListener(props.componentId, props.onQueryChange, props.onError);
		// Update props in store
		props.setComponentProps(props.componentId, props);

		if (props.internalComponent) {
			this.internalComponent = getInternalComponentID(props.componentId);
		}

		// Register internal component
		if (this.internalComponent) {
			props.addComponent(this.internalComponent);
			props.setComponentProps(this.internalComponent, props);
		}
	}

	get hasCustomRenderer() {
		return hasCustomRenderer(this.props);
	}

	setReact = (props) => {
		const { react } = props;
		if (this.internalComponent) {
			if (react) {
				const newReact = pushToAndClause(react, this.internalComponent);
				props.watchComponent(props.componentId, newReact);
			} else {
				props.watchComponent(props.componentId, {
					and: this.internalComponent,
				});
			}
		} else {
			props.watchComponent(props.componentId, react);
		}
	};

	componentDidUpdate(prevProps) {
		checkSomePropChange(this.props, prevProps, getValidPropsKeys(this.props), () => {
			this.props.updateComponentProps(
				this.props.componentId,
				this.props,
			);
			if (this.internalComponent) {
				this.props.updateComponentProps(
					this.internalComponent,
					this.props,
				);
			}
		});
		checkPropChange(this.props.react, prevProps.react, () => this.setReact(this.props));
	}

	componentWillUnmount() {
		// Unregister components
		const { componentId } = this.props;
		this.props.removeComponent(componentId);
		if (this.internalComponent) {
			this.props.removeComponent(this.internalComponent);
		}
	}

	componentDidMount() {
		// Register internal component
		if (this.internalComponent) {
			// Watch component after rendering the component to avoid the un-necessary calls
			this.setReact(this.props);
		}
	}

	render() {
		if (this.hasCustomRenderer) {
			return getComponent({}, this.props);
		}
		return null;
	}
}

ComponentWrapper.propTypes = {
	addComponent: types.funcRequired,
	removeComponent: types.funcRequired,
	setComponentProps: types.funcRequired,
	setQueryListener: types.funcRequired,
	updateComponentProps: types.funcRequired,
	watchComponent: types.funcRequired,
	// component props
	children: types.func,
	componentId: types.string.isRequired,
	componentType: types.componentType,
	internalComponent: types.bool,
	onError: types.func,
	onQueryChange: types.func,
	react: types.react,
	render: types.func,
};

const mapDispatchToProps = (dispatch, ownProps) => ({
	setComponentProps: (component, options) =>
		dispatch(setComponentProps(component, options, ownProps.componentType)),
	updateComponentProps: (component, options) =>
		dispatch(updateComponentProps(component, options, ownProps.componentType)),
	addComponent: component => dispatch(addComponent(component)),
	removeComponent: component => dispatch(removeComponent(component)),
	watchComponent: (component, react) => dispatch(watchComponent(component, react)),
	setQueryListener: (component, onQueryChange, beforeQueryChange) =>
		dispatch(setQueryListener(component, onQueryChange, beforeQueryChange)),
});

export default connect(null, mapDispatchToProps)(ComponentWrapper);
<commit_msg>fix: force re-render should not break components<commit_after>import React from 'react';
import types from '@appbaseio/reactivecore/lib/utils/types';
import { getInternalComponentID } from '@appbaseio/reactivecore/lib/utils/transform';

import {
	pushToAndClause,
	checkPropChange,
	checkSomePropChange,
} from '@appbaseio/reactivecore/lib/utils/helper';

import {
	addComponent,
	removeComponent,
	watchComponent,
	setQueryListener,
	setComponentProps,
	updateComponentProps,
} from '@appbaseio/reactivecore/lib/actions';

import {
	connect,
	ReactReduxContext,
	getValidPropsKeys,
	hasCustomRenderer,
	getComponent,
} from '../../utils';

/**
 * ComponentWrapper component is a wrapper component for each ReactiveSearch component
 * which is responsible for following tasks:
 * 1. Register a component on mount
 * 2. Set query listener
 * 3. Set react prop
 * 4. Follow the [1-3] for the internal component if needed
 * 5. Update component props in redux store
 * 6. Unregister the component on un-mount
 */
class ComponentWrapper extends React.Component {
	static contextType = ReactReduxContext;

	constructor(props, context) {
		super(props, context);
		// Register a component only when `destroyOnUnmount` is `true`
		// or component is not present in store
		let components = [];
		if (context.store) {
			({ components } = context.store.getState());
		}
		if (props.destroyOnUnmount || components.indexOf(props.componentId) === -1) {
			// Register  component
			props.addComponent(props.componentId);
			props.setQueryListener(props.componentId, props.onQueryChange, props.onError);
			// Update props in store
			props.setComponentProps(props.componentId, props);
		}

		if (props.internalComponent) {
			this.internalComponent = getInternalComponentID(props.componentId);
		}

		// Register internal component
		if (this.internalComponent && (props.destroyOnUnmount
			|| components.indexOf(this.internalComponent) === -1)) {
			props.addComponent(this.internalComponent);
			props.setComponentProps(this.internalComponent, props);
		}
	}

	get hasCustomRenderer() {
		return hasCustomRenderer(this.props);
	}

	setReact = (props) => {
		const { react } = props;
		if (this.internalComponent) {
			if (react) {
				const newReact = pushToAndClause(react, this.internalComponent);
				props.watchComponent(props.componentId, newReact);
			} else {
				props.watchComponent(props.componentId, {
					and: this.internalComponent,
				});
			}
		} else {
			props.watchComponent(props.componentId, react);
		}
	};

	componentDidUpdate(prevProps) {
		checkSomePropChange(this.props, prevProps, getValidPropsKeys(this.props), () => {
			this.props.updateComponentProps(this.props.componentId, this.props);
			if (this.internalComponent) {
				this.props.updateComponentProps(this.internalComponent, this.props);
			}
		});
		checkPropChange(this.props.react, prevProps.react, () => this.setReact(this.props));
	}

	componentWillUnmount() {
		// Unregister components
		const { componentId, destroyOnUnmount } = this.props;
		if (destroyOnUnmount) {
			this.props.removeComponent(componentId);
			if (this.internalComponent) {
				this.props.removeComponent(this.internalComponent);
			}
		}
	}

	componentDidMount() {
		// Register internal component
		if (this.internalComponent) {
			// Watch component after rendering the component to avoid the un-necessary calls
			this.setReact(this.props);
		}
	}

	render() {
		if (this.hasCustomRenderer) {
			return getComponent({}, this.props);
		}
		return null;
	}
}

ComponentWrapper.propTypes = {
	addComponent: types.funcRequired,
	removeComponent: types.funcRequired,
	setComponentProps: types.funcRequired,
	setQueryListener: types.funcRequired,
	updateComponentProps: types.funcRequired,
	watchComponent: types.funcRequired,
	// component props
	children: types.func,
	destroyOnUnmount: types.bool,
	componentId: types.string.isRequired,
	componentType: types.componentType,
	internalComponent: types.bool,
	onError: types.func,
	onQueryChange: types.func,
	react: types.react,
	render: types.func,
};

const mapDispatchToProps = (dispatch, ownProps) => ({
	setComponentProps: (component, options) =>
		dispatch(setComponentProps(component, options, ownProps.componentType)),
	updateComponentProps: (component, options) =>
		dispatch(updateComponentProps(component, options, ownProps.componentType)),
	addComponent: component => dispatch(addComponent(component)),
	removeComponent: component => dispatch(removeComponent(component)),
	watchComponent: (component, react) => dispatch(watchComponent(component, react)),
	setQueryListener: (component, onQueryChange, beforeQueryChange) =>
		dispatch(setQueryListener(component, onQueryChange, beforeQueryChange)),
});

export default connect(null, mapDispatchToProps)(ComponentWrapper);
<|endoftext|>


<commit_before>// Enable pooling of a specific class.
var ObjectPool = function(constructor) {
	this.objectClass = constructor;
	this.factoryFunction = constructor;
	this.objects = [];
	this.count = 0;
};

// Factory function: Creates an object of the given class, thereby tries to revive an existing one.
ObjectPool.prototype.createObject = function(/*arguments*/) {
	console.log(arguments);
	if(this.count > 0) {
		// can revive an existing  object
		this.count--;
		this.objectClass.prototype.Clear.apply(this.objects[this.count], arguments);
		return this.objects[this.count];
	} else {
		// have to create a new object
		var instance = Object.create(this.objectClass.prototype);
		this.objectClass.apply(instance, arguments);

		return instance;
	}
};

// Free an object of a given class for reuse.
ObjectPool.prototype.freeForUse = function(object) {
	this.objects[this.count] = object;
	this.count++;
};
<commit_msg>removed unnecessary log operation in ObjectPool<commit_after>// Enable pooling of a specific class.
var ObjectPool = function(constructor) {
	this.objectClass = constructor;
	this.factoryFunction = constructor;
	this.objects = [];
	this.count = 0;
};

// Factory function: Creates an object of the given class, thereby tries to revive an existing one.
ObjectPool.prototype.createObject = function(/*arguments*/) {
	if(this.count > 0) {
		// can revive an existing  object
		this.count--;
		this.objectClass.prototype.Clear.apply(this.objects[this.count], arguments);
		return this.objects[this.count];
	} else {
		// have to create a new object
		var instance = Object.create(this.objectClass.prototype);
		this.objectClass.apply(instance, arguments);

		return instance;
	}
};

// Free an object of a given class for reuse.
ObjectPool.prototype.freeForUse = function(object) {
	this.objects[this.count] = object;
	this.count++;
};
<|endoftext|>


<commit_before>'use strict';

const Promise = require('bluebird');
const path = require('path');
const messageMaker = require('../../support/messageMaker');
const aggregator = require('./aggregator');
const log = require('intel');
const filterRegistry = require('../../support/filterRegistry');
const analyzer = require('./analyzer');

const make = messageMaker('gpsi').make;
const DEFAULT_METRICS_PAGESUMMARY = ['ruleGroups.SPEED.score'];

module.exports = {
  name() {
    return path.basename(__dirname);
  },
  open(context, options) {
    this.options = options;
    filterRegistry.registerFilterForType(DEFAULT_METRICS_PAGESUMMARY, 'gpsi.pageSummary');
  },
  processMessage(message, queue) {
    switch (message.type) {
      case 'url':
        {
          const url = message.url;
          const group = message.group;
          const options = {
            gpsi: this.options.gpsi,
            mobile: this.options.mobile
          }
          return analyzer.analyzeUrl(url, options)
            .then((result) => {
              log.info('Got ' + url + ' analysed from Google Page Speed Insights');
              log.trace('Result from Google Page Speed Insights:%:2j', result);
              queue.postMessage(make('gpsi.pageSummary', result, {
                url,
                group
              }))
            });
        }

      case 'gpsi.data':
        return Promise.all([
          aggregator.speedAggregator.addToAggregate(message.data),
          aggregator.pageStatsAggregator.addToAggregate(message.data)
        ]);

      case 'summarize':
        {
          // TODO lets implement the summary later, most important is to
          // get the score per page
          // queue.postMessage(make('gpsi.speed', aggregator.speedAggregator.summarize()));
          // queue.postMessage(make('gpsi.summary', aggregator.pageStatsAggregator.summarize()));
        }
    }
  }
};
<commit_msg>Prefer to extract plugin options in ’open’ method.<commit_after>'use strict';

const Promise = require('bluebird');
const path = require('path');
const messageMaker = require('../../support/messageMaker');
const aggregator = require('./aggregator');
const log = require('intel');
const filterRegistry = require('../../support/filterRegistry');
const analyzer = require('./analyzer');

const make = messageMaker('gpsi').make;
const DEFAULT_METRICS_PAGESUMMARY = ['ruleGroups.SPEED.score'];

module.exports = {
  name() {
    return path.basename(__dirname);
  },
  open(context, options) {
    this.options = {
      gpsi: options.gpsi,
      mobile: options.mobile
    };
    filterRegistry.registerFilterForType(DEFAULT_METRICS_PAGESUMMARY, 'gpsi.pageSummary');
  },
  processMessage(message, queue) {
    switch (message.type) {
      case 'url':
        {
          const url = message.url;
          const group = message.group;
          return analyzer.analyzeUrl(url, this.options)
            .then((result) => {
              log.info('Got ' + url + ' analysed from Google Page Speed Insights');
              log.trace('Result from Google Page Speed Insights:%:2j', result);
              queue.postMessage(make('gpsi.pageSummary', result, {
                url,
                group
              }))
            });
        }

      case 'gpsi.data':
        return Promise.all([
          aggregator.speedAggregator.addToAggregate(message.data),
          aggregator.pageStatsAggregator.addToAggregate(message.data)
        ]);

      case 'summarize':
        {
          // TODO lets implement the summary later, most important is to
          // get the score per page
          // queue.postMessage(make('gpsi.speed', aggregator.speedAggregator.summarize()));
          // queue.postMessage(make('gpsi.summary', aggregator.pageStatsAggregator.summarize()));
        }
    }
  }
};
<|endoftext|>