<commit_before>'use strict';

var _ = require('lodash');
var assert = require('assert');
var normalize = require('json-normalizer').sync;
var regulate = require('json-regulator');
var globsJoin = require('../helpers/globs').join;
var from = require('../helpers/dataflow');
var PluginError = require('gulp-util').PluginError;

var INTERPOLATE = /{{([\s\S]+?)}}/g;

/*
 * NOTE:
 * According to [gulp API](https://github.com/gulpjs/gulp/blob/master/docs/API.md)
 * and [gulp 4.0 API](https://github.com/gulpjs/gulp/blob/4.0/docs/API.md):
 * gulp supports all options supported by node-glob and glob-stream except ignore and adds the following options.
 *
 * @see
 * [node-glob](https://github.com/isaacs/node-glob)
 * [glob-stream](https://github.com/gulpjs/glob-stream)
 *
 */
var SCHEMA_SRC = require('../schema/src.json');
var SCHEMA_DEST = require('../schema/dest.json');

var SCHEMA_DEFAULTS = {
	type: 'object',
	properties: {
		src: SCHEMA_SRC,
		dest: SCHEMA_DEST,
		configs: {
			description: 'Any property insides "configs" property considered a configuration property.',
			type: 'object'
		},
		options: {
			type: 'object'
		}
	},
	patternProperties: {
		'^\\$.+$': {
			description: 'Any property prefix with $ considered a configuration property and can be accessed both with or without $ prefix.'
		}
	},
	additionalProperties: false
};

var PATTERN_PROPERTY_REGEX = /^\$(.+)$/;

var SCHEMA_TASK = require('../schema/task.json');
var TASK_SCHEMA_MAPPINGS = {
	title: 'name',
	description: 'description'
};
var TASK_METADATAS = Object.keys(SCHEMA_TASK.properties);

var REGEX_RUNTIME_OPTIONS = /^([.#]?)([_\w][-_:\s\w]*)([!?]?)$/;

var CONSTANT = {
	VISIBILITY: {
		/** hidden configurable task can't be run from cli, but still functional */
		HIDDEN: '.',
		/** disabled configurable task is not processed and not functional, including all it's descendants */
		DISABLED: '#',
		/** normal configurable task can be run from cli */
		NORMAL: ''
	},
	RUNTIME: {
		/** configurable task can only run in production mode */
		PRODUCTION: '!',
		/** configurable task can only run in development mode */
		DEVELOPMENT: '?',
		/** configurable task can run in both production and development mode */
		ALL: ''
	}
};

// TODO: remove temp hack for _.defaultsDeep() when bug fix public available:
// defaultsDeep() try to mix string characters into array
// https://github.com/lodash/lodash/issues/1560
_.defaultsDeep = defaultsDeep;

function defaultsDeep(object) {
	var sources = Array.prototype.splice.call(arguments, 1);

	sources.forEach(function (source) {
		_defaults(object, source);
	});
	return object;

	function _defaults(target, source) {
		_.forIn(source, function (value, key) {
			if (_.isPlainObject(target[key]) && _.isPlainObject(value)) {
				_defaults(target[key], value);
			} else if (!(key in target)) {
				target[key] = typeof value === 'function' ? value : _.cloneDeep(value);
			}
		});
	}
}

function getTaskRuntimeInfo(rawConfig) {
	var match, name, taskInfo;

	taskInfo = from(rawConfig).to({}).move(TASK_METADATAS);

	if (taskInfo.name) {
		name = _.trim(taskInfo.name);
		match = REGEX_RUNTIME_OPTIONS.exec(name);
		if (!match) {
			throw new PluginError(__filename, 'invalid task name: ' + name);
		}

		taskInfo.name = match[2] || name;

		if (match[1]) {
			taskInfo.visibility = match[1];
		}
		if (match[3]) {
			taskInfo.runtime = match[3];
		}
	}

	return taskInfo;
}

function realize(original, additional) {
	var values;

	values = _.defaultsDeep({}, original, additional);
	return realizeAll({}, values);

	function realizeAll(target, source) {
		_.each(source, function (value, name) {
			target[name] = _realize(value);
		});
		return target;
	}

	function _realize(source) {
		if (typeof source === 'string') {
			return source.replace(INTERPOLATE, function (match, path) {
				var value;

				value = _.get(values, path) || path;
				if (typeof value === 'function') {
					value = value(values);
				}
				return value;
			});
		}
		if (typeof source === 'function') {
			return source(values);
		}
		if (_.isArray(source)) {
			return realizeAll([], source);
		}
		if (_.isPlainObject(source)) {
			return realizeAll({}, source);
		}
		return source;
	}
}

function src(values) {
	return normalize(SCHEMA_SRC, values);
}

function dest(values) {
	return normalize(SCHEMA_DEST, values);
}

// TODO: make sure path separator works in all operating systems (especially windows that use "\\").
function resolveSrc(child, parent) {
	var value;

	if (child.src) {
		value = src(child.src);
		if (parent.src && !(value.options && value.options.override)) {
			value.globs = globsJoin(parent.src.globs, value.globs);
		}
		return value;
	}
	return parent.src;
}

function resolveDest(child, parent) {
	var value;

	if (child.dest) {
		value = dest(child.dest);
		if (parent.dest && !(value.options && value.options.override)) {
			value.path = globsJoin(parent.dest.path, value.path);
		}
		return value;
	}
	return parent.dest;
}

/**
 * If both parentConfig and taskConfig specified src property
 * then try to join paths.
 */
function sort(taskInfo, rawConfig, parentConfig, optionalSchema) {
	var inheritedConfig, schema, subTaskConfigs, taskConfig, value;

	assert(_.isPlainObject(rawConfig));

	schema = optionalSchema || {};
	from(schema).to(taskInfo).imply(TASK_SCHEMA_MAPPINGS);
	schema = _.defaultsDeep({}, schema, SCHEMA_DEFAULTS);

	taskConfig = {};

	if (parentConfig.src && !Array.isArray(parentConfig.src.globs)) {
		throw new TypeError('parentConfig.src not normalized');
	}

	value = resolveSrc(rawConfig, parentConfig);
	if (value) {
		taskConfig.src = value;
	}

	if (parentConfig.dest && typeof parentConfig.dest.path !== 'string') {
		throw new TypeError('parentConfig.dest not normalized');
	}

	value = resolveDest(rawConfig, parentConfig);
	if (value) {
		taskConfig.dest = value;
	}

	inheritedConfig = _.defaultsDeep(taskConfig, rawConfig, parentConfig);

	taskConfig = normalize(schema, inheritedConfig);
	taskConfig = addPatternProperties(taskConfig);
	taskConfig = regulate(taskConfig, ['configs']);
	assert(_.isPlainObject(taskConfig));

	subTaskConfigs = _.omit(inheritedConfig, Object.keys(taskConfig));

	return {
		taskInfo: taskInfo,
		taskConfig: taskConfig,
		subTaskConfigs: subTaskConfigs
	};
}

function addPatternProperties(target) {
	Object.keys(target).forEach(function (key) {
		var match;

		match = PATTERN_PROPERTY_REGEX.exec(key);
		if (match) {
			target[match[1]] = target[key];
		}
	});
	return target;
}

module.exports = {
	CONSTANT: CONSTANT,
	getTaskRuntimeInfo: getTaskRuntimeInfo,
	dest: dest,
	normalize: normalize,
	realize: realize,
	resolveSrc: resolveSrc,
	resolveDest: resolveDest,
	sort: sort,
	src: src
};
<commit_msg>Configuration: add additionalProperties to configs and options<commit_after>'use strict';

var _ = require('lodash');
var assert = require('assert');
var PluginError = require('gulp-util').PluginError;
var normalize = require('json-normalizer').sync;
var regulate = require('json-regulator');
var globsJoin = require('../helpers/globs').join;
var from = require('../helpers/dataflow');

var INTERPOLATE = /{{([\s\S]+?)}}/g;

/*
 * NOTE:
 * According to [gulp API](https://github.com/gulpjs/gulp/blob/master/docs/API.md)
 * and [gulp 4.0 API](https://github.com/gulpjs/gulp/blob/4.0/docs/API.md):
 * gulp supports all options supported by node-glob and glob-stream except ignore and adds the following options.
 *
 * @see
 * [node-glob](https://github.com/isaacs/node-glob)
 * [glob-stream](https://github.com/gulpjs/glob-stream)
 *
 */
var SCHEMA_SRC = require('../schema/src.json');
var SCHEMA_DEST = require('../schema/dest.json');

var SCHEMA_DEFAULTS = {
	type: 'object',
	properties: {
		src: SCHEMA_SRC,
		dest: SCHEMA_DEST,
		configs: {
			description: 'Any property insides "configs" property considered a configuration property.',
			type: 'object',
			additionalProperties: true
		},
		options: {
			type: 'object',
			additionalProperties: true
		}
	},
	patternProperties: {
		'^\\$.+$': {
			description: 'Any property prefix with $ considered a configuration property and can be accessed both with or without $ prefix.'
		}
	},
	additionalProperties: false
};

var PATTERN_PROPERTY_REGEX = /^\$(.+)$/;

var SCHEMA_TASK = require('../schema/task.json');
var TASK_SCHEMA_MAPPINGS = {
	title: 'name',
	description: 'description'
};
var TASK_METADATAS = Object.keys(SCHEMA_TASK.properties);

var REGEX_RUNTIME_OPTIONS = /^([.#]?)([_\w][-_:\s\w]*)([!?]?)$/;

var CONSTANT = {
	VISIBILITY: {
		/** hidden configurable task can't be run from cli, but still functional */
		HIDDEN: '.',
		/** disabled configurable task is not processed and not functional, including all it's descendants */
		DISABLED: '#',
		/** normal configurable task can be run from cli */
		NORMAL: ''
	},
	RUNTIME: {
		/** configurable task can only run in production mode */
		PRODUCTION: '!',
		/** configurable task can only run in development mode */
		DEVELOPMENT: '?',
		/** configurable task can run in both production and development mode */
		ALL: ''
	}
};

// TODO: remove temp hack for _.defaultsDeep() when bug fix public available:
// defaultsDeep() try to mix string characters into array
// https://github.com/lodash/lodash/issues/1560
_.defaultsDeep = defaultsDeep;

function defaultsDeep(object) {
	var sources = Array.prototype.splice.call(arguments, 1);

	sources.forEach(function (source) {
		_defaults(object, source);
	});
	return object;

	function _defaults(target, source) {
		_.forIn(source, function (value, key) {
			if (_.isPlainObject(target[key]) && _.isPlainObject(value)) {
				_defaults(target[key], value);
			} else if (!(key in target)) {
				target[key] = typeof value === 'function' ? value : _.cloneDeep(value);
			}
		});
	}
}

function getTaskRuntimeInfo(rawConfig) {
	var match, name, taskInfo;

	taskInfo = from(rawConfig).to({}).move(TASK_METADATAS);

	if (taskInfo.name) {
		name = _.trim(taskInfo.name);
		match = REGEX_RUNTIME_OPTIONS.exec(name);
		if (!match) {
			throw new PluginError(__filename, 'invalid task name: ' + name);
		}

		taskInfo.name = match[2] || name;

		if (match[1]) {
			taskInfo.visibility = match[1];
		}
		if (match[3]) {
			taskInfo.runtime = match[3];
		}
	}

	return taskInfo;
}

function realize(original, additional) {
	var values;

	values = _.defaultsDeep({}, original, additional);
	return realizeAll({}, values);

	function realizeAll(target, source) {
		_.each(source, function (value, name) {
			target[name] = _realize(value);
		});
		return target;
	}

	function _realize(source) {
		if (typeof source === 'string') {
			return source.replace(INTERPOLATE, function (match, path) {
				var value;

				value = _.get(values, path) || path;
				if (typeof value === 'function') {
					value = value(values);
				}
				return value;
			});
		}
		if (typeof source === 'function') {
			return source(values);
		}
		if (_.isArray(source)) {
			return realizeAll([], source);
		}
		if (_.isPlainObject(source)) {
			return realizeAll({}, source);
		}
		return source;
	}
}

function src(values) {
	return normalize(SCHEMA_SRC, values);
}

function dest(values) {
	return normalize(SCHEMA_DEST, values);
}

// TODO: make sure path separator works in all operating systems (especially windows that use "\\").
function resolveSrc(child, parent) {
	var value;

	if (child.src) {
		value = src(child.src);
		if (parent.src && !(value.options && value.options.override)) {
			value.globs = globsJoin(parent.src.globs, value.globs);
		}
		return value;
	}
	return parent.src;
}

function resolveDest(child, parent) {
	var value;

	if (child.dest) {
		value = dest(child.dest);
		if (parent.dest && !(value.options && value.options.override)) {
			value.path = globsJoin(parent.dest.path, value.path);
		}
		return value;
	}
	return parent.dest;
}

/**
 * If both parentConfig and taskConfig specified src property
 * then try to join paths.
 */
function sort(taskInfo, rawConfig, parentConfig, optionalSchema) {
	var inheritedConfig, schema, subTaskConfigs, taskConfig, value;

	assert(_.isPlainObject(rawConfig));

	schema = optionalSchema || {};
	from(schema).to(taskInfo).imply(TASK_SCHEMA_MAPPINGS);
	schema = _.defaultsDeep({}, schema, SCHEMA_DEFAULTS);

	taskConfig = {};

	if (parentConfig.src && !Array.isArray(parentConfig.src.globs)) {
		throw new TypeError('parentConfig.src not normalized');
	}

	value = resolveSrc(rawConfig, parentConfig);
	if (value) {
		taskConfig.src = value;
	}

	if (parentConfig.dest && typeof parentConfig.dest.path !== 'string') {
		throw new TypeError('parentConfig.dest not normalized');
	}

	value = resolveDest(rawConfig, parentConfig);
	if (value) {
		taskConfig.dest = value;
	}

	inheritedConfig = _.defaultsDeep(taskConfig, rawConfig, parentConfig);

	taskConfig = normalize(schema, inheritedConfig);
	taskConfig = addPatternProperties(taskConfig);
	taskConfig = regulate(taskConfig, ['configs']);
	assert(_.isPlainObject(taskConfig));

	subTaskConfigs = _.omit(inheritedConfig, Object.keys(taskConfig));

	return {
		taskInfo: taskInfo,
		taskConfig: taskConfig,
		subTaskConfigs: subTaskConfigs
	};
}

function addPatternProperties(target) {
	Object.keys(target).forEach(function (key) {
		var match;

		match = PATTERN_PROPERTY_REGEX.exec(key);
		if (match) {
			target[match[1]] = target[key];
		}
	});
	return target;
}

module.exports = {
	CONSTANT: CONSTANT,
	getTaskRuntimeInfo: getTaskRuntimeInfo,
	dest: dest,
	normalize: normalize,
	realize: realize,
	resolveSrc: resolveSrc,
	resolveDest: resolveDest,
	sort: sort,
	src: src
};
<|endoftext|>


<commit_before>/**
Oreon is developped with Apache Licence 2.0 :
http://www.apache.org/licenses/LICENSE-2.0.txt
Developped by : Cedrick Facon

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

For information : contact@oreon-project.org
*/
// JavaScript Document

<!-- Begin

	function toggleCheckAll(theElement, id){
		var a = document.getElementById(id);

		for(var i = 0; document.getElementById(id+'_'+i) ;i++){
			var b = document.getElementById(id+'_'+i);
			if(a.checked)
				b.checked = true;
			else
				b.checked = false;

			for(var j = 0; document.getElementById(id+'_'+i+'_'+j) ;j++){
				var c = document.getElementById(id+'_'+i+'_'+j);
				if(b.checked)
					c.checked = true;
				else
					c.checked = false;
				for(var k = 0; document.getElementById(id+'_'+i+'_'+j+'_'+k) ;k++){
					var d = document.getElementById(id+'_'+i+'_'+j+'_'+k);
					if(c.checked)
						d.checked = true;
					else
						d.checked = false;

				}

			}
		}

	}

	function toggleDisplay(id)
		{
			var d = document.getElementById(id);
			if(d)
			{
				if (d.style.display == 'block') {
				d.style.display='none';
				}
				else
				{
				d.style.display='block';
				}
			}
	}

	function checkUncheckAll(theElement) {

     var theForm = theElement.form, z = 0;
	 for(z=0; z<theForm.length;z++){
      if(theForm[z].type == 'checkbox' && theForm[z].disabled == '0'){
		  if(theForm[z].checked)
		  {
		   theForm[z].checked = false;
		   }
		  else{
		  theForm[z].checked = true;
		  }
	  }
     }
   }

	function DisplayHidden(id) {
		var d = document.getElementById(id);

if(d)
{
	if (d.style.display == 'block') {
	d.style.display='none';
	}
	else
	{
	d.style.display='block';
	}
}
}

//  End -->
<commit_msg>ajout d'un javascript pour plier/deplier la topology<commit_after>/**
Oreon is developped with Apache Licence 2.0 :
http://www.apache.org/licenses/LICENSE-2.0.txt
Developped by : Cedrick Facon

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

For information : contact@oreon-project.org
*/
// JavaScript Document

<!-- Begin

	function toggleCheckAll(theElement, id){
		var a = document.getElementById(id);

		for(var i = 0; document.getElementById(id+'_'+i) ;i++){
			var b = document.getElementById(id+'_'+i);
			if(a.checked)
				b.checked = true;
			else
				b.checked = false;

			for(var j = 0; document.getElementById(id+'_'+i+'_'+j) ;j++){
				var c = document.getElementById(id+'_'+i+'_'+j);
				if(b.checked)
					c.checked = true;
				else
					c.checked = false;
				for(var k = 0; document.getElementById(id+'_'+i+'_'+j+'_'+k) ;k++){
					var d = document.getElementById(id+'_'+i+'_'+j+'_'+k);
					if(c.checked)
						d.checked = true;
					else
						d.checked = false;

				}

			}
		}

	}

	function toggleDisplay(id)
		{

			var d = document.getElementById(id);
			if(d)
			{
				var img = document.getElementById('img_'+id);

				if(img){
					if(d.style.display == 'block')
						img.src = 'img/icones/16x16/navigate_plus.gif';
					else
						img.src = 'img/icones/16x16/navigate_minus.gif';
				}

				if (d.style.display == 'block') {
				d.style.display='none';
				}
				else
				{
				d.style.display='block';
				}
			}
	}

	function checkUncheckAll(theElement) {

     var theForm = theElement.form, z = 0;
	 for(z=0; z<theForm.length;z++){
      if(theForm[z].type == 'checkbox' && theForm[z].disabled == '0'){
		  if(theForm[z].checked)
		  {
		   theForm[z].checked = false;
		   }
		  else{
		  theForm[z].checked = true;
		  }
	  }
     }
   }

	function DisplayHidden(id) {
		var d = document.getElementById(id);

if(d)
{
	if (d.style.display == 'block') {
	d.style.display='none';
	}
	else
	{
	d.style.display='block';
	}
}
}

//  End -->
<|endoftext|>


<commit_before>
/*!
 * CSS - Lexer
 * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var Token = require('./token')
  , nodes = require('./nodes');

/**
 * Units.
 */

var units = [
    'em'
  , 'ex'
  , 'px'
  , 'cm'
  , 'mm'
  , 'in'
  , 'pt'
  , 'pc'
  , 'deg'
  , 'rad'
  , 'grad'
  , 'ms'
  , 's'
  , 'Hz'
  , 'kHz'
  , '%'].join('|');

/**
 * Unit RegExp.
 */

var unit = new RegExp('^(\\d+\\.\\d+|\\d+|\\.\\d+)(' + units + ') *');

/**
 * Initialize a new `Lexer` with the given `str` and `options`.
 *
 * @param {String} str
 * @param {Object} options
 * @api private
 */

var Lexer = module.exports = function Lexer(str, options) {
  options = options || {};
  this.str = str.replace(/\r\n?/g, '\n').replace(/\t/g, '  ');
  this.filename = options.filename || 'css';
  this.stash = [];
  this.prevIndents = 0;
};

/**
 * Lexer prototype.
 */

Lexer.prototype = {

  /**
   * Custom inspect.
   */

  inspect: function(){
    var tok
      , tmp = this.str
      , buf = [];
    while ('eos' != (tok = this.next).type) {
      buf.push(tok.inspect());
    }
    this.str = tmp;
    this.prevIndents = 0;
    return buf.concat(tok.inspect()).join('\n');
  },

  /**
   * Lookahead `n` tokens.
   *
   * @param {Number} n
   * @return {Object}
   * @api private
   */

  lookahead: function(n){
    var fetch = n - this.stash.length;
    while (fetch-- > 0) this.stash.push(this.next);
    return this.stash[--n];
  },

  /**
   * Fetch next token.
   *
   * @return {Token}
   * @api private
   */

  get next() {
    return this.eos
      || this.stashed
      || this.newline
      || this.variable
      || this.assignment
      || this.color
      || this.unit
      || this.property
      || this.selector;
  },

  /**
   * Lookahead a single token.
   *
   * @return {Token}
   * @api private
   */

  get peek() {
    return this.lookahead(1);
  },

  /**
   * Return the next possibly stashed token.
   *
   * @return {Token}
   * @api public
   */

  get stashed() {
    return this.stash.shift();
  },

  /**
   * Check current property state.
   *
   * @return {Boolean}
   * @api public
   */

  get isProperty() {
    return 1 == this.prevIndents % 2;
  },

  /**
   * EOS | trailing outdents.
   */

  get eos() {
    if (this.str.length) return;
    return this.prevIndents-- > 0
      ? new Token('outdent')
      : new Token('eos');
  },

  /**
   * @[-\w]+
   */

  get variable() {
    var captures;
    if (captures = /^@([-\w]+) */.exec(this.str)) {
      this.isVariable = true;
      this.str = this.str.substr(captures[0].length);
      return new Token('variable', captures[1]);
    }
  },

  /**
   * ':' ' '*
   */

  get assignment() {
    var captures;
    if (this.isVariable && (captures = /^: */.exec(this.str))) {
      this.str = this.str.substr(captures[0].length);
      return new Token('=');
    }
  },

  /**
   * '\n' ' '+
   */

  get newline() {
    var captures;
    if (captures = /^\n( *)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var tok
        , spaces = captures[1].length
        , indents = spaces / 2;

      // Reset state
      this.isVariable = false;

      // To few spaces
      if (0 != spaces % 2) {
        throw new Error('Invalid indentation, got ' + spaces + ' space(s), expected multiple of 2');
      // To many spaces
      } else if (indents > this.prevIndents + 1) {
        var expected = 2 * this.prevIndents || 2;
        throw new Error('Invalid indentation, got ' + spaces + ' space(s), expected ' + expected);
      // Outdent
      } else if (indents < this.prevIndents) {
        var n = this.prevIndents - indents;
        while (--n) this.stash.push(new Token('outdent'));
        this.prevIndents = indents;
        tok = new Token('outdent');
      // Indent
      } else if (indents != this.prevIndents) {
        this.prevIndents = indents;
        tok = new Token('indent');
      } else {
        tok = new Token('newline');
      }

      return tok;
    }
  },

  /**
   * (digit+ | digit* '.' digit+) unit
   */

  get unit() {
    var captures;
    if (captures = unit.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      return new Token('unit', new nodes.Unit(parseFloat(captures[1]), captures[2]));
    }
  },

  /**
   * hex | rgba | rgb
   */

  get color() {
    return this.hex
      || this.rgba
      || this.rgb;
  },

  /**
   * hex6 | hex3
   */

  get hex() {
    return this.hex6
      || this.hex3;
  },

  /**
   * rgb(n,n,n)
   */

  get rgb() {
    var captures;
    if (captures = /^rgb\( *(\d+) *, *(\d+) *, *(\d+) *\)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var r = parseInt(captures[1], 10)
        , g = parseInt(captures[2], 10)
        , b = parseInt(captures[3], 10);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  /**
   * rgba(n,n,n,n)
   */

  get rgba() {
    var captures;
    if (captures = /^rgba\( *(\d+) *, *(\d+) *, *(\d+) *, *(\.\d+|\d+\.\d+|\d+) *\)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var r = parseInt(captures[1], 10)
        , g = parseInt(captures[2], 10)
        , b = parseInt(captures[3], 10)
        , a = parseFloat(captures[4]);
      return new Token('color', new nodes.Color(r, g, b, a));
    }
  },

  /**
   * #nnn
   */

  get hex3() {
    var captures;
    if (captures = /^#([a-f-A-F0-9]{3})/.exec(this.str)) {
      this.str = this.str.substr(4);
      var rgb = captures[1]
        , r = parseInt(rgb[0] + rgb[0], 16)
        , g = parseInt(rgb[1] + rgb[1], 16)
        , b = parseInt(rgb[2] + rgb[2], 16);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  /**
   * #nnnnnn
   */

  get hex6() {
    var captures;
    if (captures = /^#([a-f-A-F0-9]{6})/.exec(this.str)) {
      this.str = this.str.substr(7);
      var rgb = captures[1]
        , r = parseInt(rgb.substr(0, 2), 16)
        , g = parseInt(rgb.substr(2, 2), 16)
        , b = parseInt(rgb.substr(4, 2), 16);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  /**
   * [-a-z][-a-z0-9]*
   */

  get property() {
    var captures;
    if (this.isProperty) {
      if (captures = /^([-a-z][-a-z0-9]*) */.exec(this.str)) {
        var prop = captures[1];
        this.str = this.str.substr(captures[0].length);
        return new Token('property', prop);
      }
    }
  },

  /**
   * [^\n]+
   */

  get selector() {
    var captures;
    if (captures = /^[^\n]+/.exec(this.str)) {
      var selector = captures[0];
      this.str = this.str.substr(selector.length);
      return new Token('selector', selector);
    }
  }
};
<commit_msg>Fixed lookahead<commit_after>
/*!
 * CSS - Lexer
 * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var Token = require('./token')
  , nodes = require('./nodes');

/**
 * Units.
 */

var units = [
    'em'
  , 'ex'
  , 'px'
  , 'cm'
  , 'mm'
  , 'in'
  , 'pt'
  , 'pc'
  , 'deg'
  , 'rad'
  , 'grad'
  , 'ms'
  , 's'
  , 'Hz'
  , 'kHz'
  , '%'].join('|');

/**
 * Unit RegExp.
 */

var unit = new RegExp('^(\\d+\\.\\d+|\\d+|\\.\\d+)(' + units + ') *');

/**
 * Initialize a new `Lexer` with the given `str` and `options`.
 *
 * @param {String} str
 * @param {Object} options
 * @api private
 */

var Lexer = module.exports = function Lexer(str, options) {
  options = options || {};
  this.str = str.replace(/\r\n?/g, '\n').replace(/\t/g, '  ');
  this.filename = options.filename || 'css';
  this.stash = [];
  this.prevIndents = 0;
};

/**
 * Lexer prototype.
 */

Lexer.prototype = {

  /**
   * Custom inspect.
   */

  inspect: function(){
    var tok
      , tmp = this.str
      , buf = [];
    while ('eos' != (tok = this.next).type) {
      buf.push(tok.inspect());
    }
    this.str = tmp;
    this.prevIndents = 0;
    return buf.concat(tok.inspect()).join('\n');
  },

  /**
   * Lookahead `n` tokens.
   *
   * @param {Number} n
   * @return {Object}
   * @api private
   */

  lookahead: function(n){
    var fetch = n - this.stash.length;
    while (fetch-- > 0) this.stash.push(this.advance);
    return this.stash[--n];
  },

  /**
   * Fetch next token including those stashed by peek.
   *
   * @return {Token}
   * @api private
   */

  get next() {
    return this.stashed
      || this.advance;
  },

  /**
   * Fetch next token.
   *
   * @return {Token}
   * @api private
   */

  get advance() {
    return this.eos
      || this.newline
      || this.variable
      || this.assignment
      || this.color
      || this.unit
      || this.property
      || this.selector;
  },

  /**
   * Lookahead a single token.
   *
   * @return {Token}
   * @api private
   */

  get peek() {
    return this.lookahead(1);
  },

  /**
   * Return the next possibly stashed token.
   *
   * @return {Token}
   * @api public
   */

  get stashed() {
    return this.stash.shift();
  },

  /**
   * Check current property state.
   *
   * @return {Boolean}
   * @api public
   */

  get isProperty() {
    return 1 == this.prevIndents % 2;
  },

  /**
   * EOS | trailing outdents.
   */

  get eos() {
    if (this.str.length) return;
    return this.prevIndents-- > 0
      ? new Token('outdent')
      : new Token('eos');
  },

  /**
   * @[-\w]+
   */

  get variable() {
    var captures;
    if (captures = /^@([-\w]+) */.exec(this.str)) {
      this.isVariable = true;
      this.str = this.str.substr(captures[0].length);
      return new Token('variable', captures[1]);
    }
  },

  /**
   * ':' ' '*
   */

  get assignment() {
    var captures;
    if (this.isVariable && (captures = /^: */.exec(this.str))) {
      this.str = this.str.substr(captures[0].length);
      return new Token('=');
    }
  },

  /**
   * '\n' ' '+
   */

  get newline() {
    var captures;
    if (captures = /^\n( *)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var tok
        , spaces = captures[1].length
        , indents = spaces / 2;

      // Reset state
      this.isVariable = false;

      // To few spaces
      if (0 != spaces % 2) {
        throw new Error('Invalid indentation, got ' + spaces + ' space(s), expected multiple of 2');
      // To many spaces
      } else if (indents > this.prevIndents + 1) {
        var expected = 2 * this.prevIndents || 2;
        throw new Error('Invalid indentation, got ' + spaces + ' space(s), expected ' + expected);
      // Outdent
      } else if (indents < this.prevIndents) {
        var n = this.prevIndents - indents;
        while (--n) this.stash.push(new Token('outdent'));
        this.prevIndents = indents;
        tok = new Token('outdent');
      // Indent
      } else if (indents != this.prevIndents) {
        this.prevIndents = indents;
        tok = new Token('indent');
      } else {
        tok = new Token('newline');
      }

      return tok;
    }
  },

  /**
   * (digit+ | digit* '.' digit+) unit
   */

  get unit() {
    var captures;
    if (captures = unit.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      return new Token('unit', new nodes.Unit(parseFloat(captures[1]), captures[2]));
    }
  },

  /**
   * hex | rgba | rgb
   */

  get color() {
    return this.hex
      || this.rgba
      || this.rgb;
  },

  /**
   * hex6 | hex3
   */

  get hex() {
    return this.hex6
      || this.hex3;
  },

  /**
   * rgb(n,n,n)
   */

  get rgb() {
    var captures;
    if (captures = /^rgb\( *(\d+) *, *(\d+) *, *(\d+) *\)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var r = parseInt(captures[1], 10)
        , g = parseInt(captures[2], 10)
        , b = parseInt(captures[3], 10);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  /**
   * rgba(n,n,n,n)
   */

  get rgba() {
    var captures;
    if (captures = /^rgba\( *(\d+) *, *(\d+) *, *(\d+) *, *(\.\d+|\d+\.\d+|\d+) *\)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var r = parseInt(captures[1], 10)
        , g = parseInt(captures[2], 10)
        , b = parseInt(captures[3], 10)
        , a = parseFloat(captures[4]);
      return new Token('color', new nodes.Color(r, g, b, a));
    }
  },

  /**
   * #nnn
   */

  get hex3() {
    var captures;
    if (captures = /^#([a-f-A-F0-9]{3})/.exec(this.str)) {
      this.str = this.str.substr(4);
      var rgb = captures[1]
        , r = parseInt(rgb[0] + rgb[0], 16)
        , g = parseInt(rgb[1] + rgb[1], 16)
        , b = parseInt(rgb[2] + rgb[2], 16);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  /**
   * #nnnnnn
   */

  get hex6() {
    var captures;
    if (captures = /^#([a-f-A-F0-9]{6})/.exec(this.str)) {
      this.str = this.str.substr(7);
      var rgb = captures[1]
        , r = parseInt(rgb.substr(0, 2), 16)
        , g = parseInt(rgb.substr(2, 2), 16)
        , b = parseInt(rgb.substr(4, 2), 16);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  /**
   * [-a-z][-a-z0-9]*
   */

  get property() {
    var captures;
    if (this.isProperty) {
      if (captures = /^([-a-z][-a-z0-9]*) */.exec(this.str)) {
        var prop = captures[1];
        this.str = this.str.substr(captures[0].length);
        return new Token('property', prop);
      }
    }
  },

  /**
   * [^\n]+
   */

  get selector() {
    var captures;
    if (captures = /^[^\n]+/.exec(this.str)) {
      var selector = captures[0];
      this.str = this.str.substr(selector.length);
      return new Token('selector', selector);
    }
  }
};
<|endoftext|>


<commit_before>var _ = require('lodash');
var Q = require('q');
var path = require('path');
var axios = require('axios');
var url = require('url');

var types = require('../types');
var errors = require('../errors');
var base64 = require('../utils/base64');
var arrayBuffer = require('../utils/arraybuffer');

function Driver(options) {
    this.options = _.defaults({}, options || {}, {
        repository: null,
        host: "https://api.github.com",
        rawhost: "https://raw.githubusercontent.com",
        username: null,
        token: null,
        includeTokenInRaw: false

    });
    if (!this.options.repository) throw "GitHub driver requires a 'repository' option";
}

// Map some file informations
Driver.prototype.mapFile = function(ref, infos) {
    var rawUrl = infos.download_url || url.resolve(this.options.rawhost, this.options.repository+'/'+ref+'/'+infos.path);
    if (this.options.includeTokenInRaw) rawUrl = rawUrl+'?token='+encodeURIComponent(base64.encode(this.options.username + ':' + this.options.token));

    return {
        "name": infos.name,
        "path": infos.path,
        "content": _.isString(infos.content)? arrayBuffer.fromBase64(infos.content.replace(/(\r\n|\n|\r)/gm,"")) : undefined,
        "sha": infos.sha,
        "type": infos.type,
        "size": infos.size,
        "url": rawUrl
    };
}

// Execute an HTTP API request
Driver.prototype.api = function (httpMethod, method, args, options) {
    var that = this;
    var opts = {
        method: httpMethod,
        url: url.resolve(this.options.host, "/repos/"+this.options.repository+"/"+method)+"?t="+Date.now(),
        headers: {
            'Accept': 'application/vnd.github.v3+json',
            'Content-type': 'application/json;charset=UTF-8'
        }
    };

    if (this.options.username) {
        opts.headers['Authorization'] = 'Basic ' + base64.encode(this.options.username + ':' + this.options.token);
    }

    if (httpMethod == 'get') opts.params = args;
    else opts.data = args;

    return Q(axios(opts))
    .get('data')
    .fail(function(response) {
        if (response instanceof Error) throw response;

        var e = new Error(response.data.message || "Error "+response.status+": "+response.data);
        e.statusCode = response.status;

        throw e;
    });
};

// Get informations about a file
Driver.prototype.stat = function(p, opts) {
    return this.api('get', 'contents'+path.join('/', p), {
        ref: opts.ref
    })
    .then(_.bind(this.mapFile, this, opts.ref));
};

// List files in a directory
Driver.prototype.readdir = function(p, opts) {
    var that = this;

    return this.api('get', 'contents'+path.join('/', p), {
        ref: opts.ref
    })
    .then(function(files) {
        return _.chain(files)
            .map(function(file) {
                return [file.name, that.mapFile(opts.ref, file)];
            })
            .object()
            .value();
    });
};

// Write a file
Driver.prototype.write = function(p, content, opts) {
    var encodedContent, that = this;

    encodedContent = arrayBuffer.enforceBase64(content);

    return that.stat(p, { ref: opts.ref })
    .then(function(infos) {
        return that.api("put", "contents/"+p, {
            branch: opts.ref,
            message: opts.message,
            content: encodedContent,
            sha: infos.sha,
            committer: that.options.commiter
        });
    })
    .then(function(result) {
        result.content.content = encodedContent;
        return that.mapFile(opts.ref, result.content);
    });
};

// Create a new file
Driver.prototype.create = function(p, content, opts) {
    var encodedContent, that = this;

    encodedContent = arrayBuffer.enforceBase64(content);

    return this.stat(p, { ref: opts.ref })
    .then(function() {
        throw errors.fileAlreadyExist(p);
    }, function() {
        return that.api("put", "contents/"+p, {
            message: opts.message,
            branch: opts.ref,
            content: encodedContent,
            commiter: that.options.commiter
        });
    })
    .then(function(result) {
        result.content.content = encodedContent;
        return that.mapFile(opts.ref, result.content);
    });
};

// Delete a file
Driver.prototype.unlink = function(p, opts) {
    var that = this;

    return that.stat(p, { ref: opts.ref })
    .then(function(infos) {
        return that.api('delete', 'contents'+path.join('/', p), {
            message: opts.message,
            sha: infos.sha,
            ref: opts.ref,
            commiter: that.options.commiter
        });
    });
};

// List branches
Driver.prototype.listBranches = function(p, opts) {
    var that = this;

    return this.api('get', 'branches')
    .then(function(branches) {
        return _.map(branches, function(branch) {
            return {
                name: branch.name,
                commit: branch.commit.sha
            };
        });
    });
};

// Create a branch
Driver.prototype.createBranch = function(name, from) {
    var that = this;

    return this.api("get", "branches/"+from)
    .then(function(branch) {
        return that.api("post", "git/refs", {
            "ref": "refs/heads/"+name,
            "sha": branch.commit.sha
        });
    });
};

// Remove a branch
Driver.prototype.removeBranch = function(name) {
    return this.api("delete", "git/refs/heads/"+name);
};

// Merge branches
Driver.prototype.mergeBranches = function(from, to, opts) {
    var that = this;

    return this.api("post", "merges", {
        base: to,
        head: from,
        commit_message: opts.message
    });
};

// List commits
// todo: handle pagination and opts.start/opts.limit
Driver.prototype.listCommits = function(opts) {
    var that = this;

    return this.api("get", "commits", { sha: opts.ref })
    .then(function(commits) {
        return _.map(commits, function(commit) {
            return {
                "sha": commit.sha,
                "author": _.omit(commit.commit.author, "date"),
                "message": commit.commit.message,
                "date": commit.commit.author.date
            };
        });
    });
};

// Get a single commit
Driver.prototype.getCommit = function(sha) {
    var that = this;

    return this.api("get", "commits/"+sha)
    .then(function(commit) {
        return {
            "sha": commit.sha,
            "author": _.omit(commit.commit.author, "date"),
            "message": commit.commit.message,
            "date": commit.commit.author.date,
            "files": _.map(commit.files, function(file) {
                return {
                    filename: file.filename,
                    patch: file.patch
                };
            })
        };
    });
};

Driver.id = "github";
module.exports = Driver;

<commit_msg>Fix unlink in github driver<commit_after>var _ = require('lodash');
var Q = require('q');
var path = require('path');
var axios = require('axios');
var url = require('url');

var types = require('../types');
var errors = require('../errors');
var base64 = require('../utils/base64');
var arrayBuffer = require('../utils/arraybuffer');

function Driver(options) {
    this.options = _.defaults({}, options || {}, {
        repository: null,
        host: "https://api.github.com",
        rawhost: "https://raw.githubusercontent.com",
        username: null,
        token: null,
        includeTokenInRaw: false

    });
    if (!this.options.repository) throw "GitHub driver requires a 'repository' option";
}

// Map some file informations
Driver.prototype.mapFile = function(ref, infos) {
    var rawUrl = infos.download_url || url.resolve(this.options.rawhost, this.options.repository+'/'+ref+'/'+infos.path);
    if (this.options.includeTokenInRaw) rawUrl = rawUrl+'?token='+encodeURIComponent(base64.encode(this.options.username + ':' + this.options.token));

    return {
        "name": infos.name,
        "path": infos.path,
        "content": _.isString(infos.content)? arrayBuffer.fromBase64(infos.content.replace(/(\r\n|\n|\r)/gm,"")) : undefined,
        "sha": infos.sha,
        "type": infos.type,
        "size": infos.size,
        "url": rawUrl
    };
}

// Execute an HTTP API request
Driver.prototype.api = function (httpMethod, method, args, options) {
    var that = this;
    var opts = {
        method: httpMethod,
        url: url.resolve(this.options.host, "/repos/"+this.options.repository+"/"+method)+"?t="+Date.now(),
        headers: {
            'Accept': 'application/vnd.github.v3+json',
            'Content-type': 'application/json;charset=UTF-8'
        }
    };

    if (this.options.username) {
        opts.headers['Authorization'] = 'Basic ' + base64.encode(this.options.username + ':' + this.options.token);
    }

    if (httpMethod == 'get') opts.params = args;
    else opts.data = args;

    return Q(axios(opts))
    .get('data')
    .fail(function(response) {
        if (response instanceof Error) throw response;

        var e = new Error(response.data.message || "Error "+response.status+": "+response.data);
        e.statusCode = response.status;

        throw e;
    });
};

// Get informations about a file
Driver.prototype.stat = function(p, opts) {
    return this.api('get', 'contents'+path.join('/', p), {
        ref: opts.ref
    })
    .then(_.bind(this.mapFile, this, opts.ref));
};

// List files in a directory
Driver.prototype.readdir = function(p, opts) {
    var that = this;

    return this.api('get', 'contents'+path.join('/', p), {
        ref: opts.ref
    })
    .then(function(files) {
        return _.chain(files)
            .map(function(file) {
                return [file.name, that.mapFile(opts.ref, file)];
            })
            .object()
            .value();
    });
};

// Write a file
Driver.prototype.write = function(p, content, opts) {
    var encodedContent, that = this;

    encodedContent = arrayBuffer.enforceBase64(content);

    return that.stat(p, { ref: opts.ref })
    .then(function(infos) {
        return that.api("put", "contents/"+p, {
            branch: opts.ref,
            message: opts.message,
            content: encodedContent,
            sha: infos.sha,
            committer: that.options.commiter
        });
    })
    .then(function(result) {
        result.content.content = encodedContent;
        return that.mapFile(opts.ref, result.content);
    });
};

// Create a new file
Driver.prototype.create = function(p, content, opts) {
    var encodedContent, that = this;

    encodedContent = arrayBuffer.enforceBase64(content);

    return this.stat(p, { ref: opts.ref })
    .then(function() {
        throw errors.fileAlreadyExist(p);
    }, function() {
        return that.api("put", "contents/"+p, {
            message: opts.message,
            branch: opts.ref,
            content: encodedContent,
            commiter: that.options.commiter
        });
    })
    .then(function(result) {
        result.content.content = encodedContent;
        return that.mapFile(opts.ref, result.content);
    });
};

// Delete a file
Driver.prototype.unlink = function(p, opts) {
    var that = this;

    return that.stat(p, { ref: opts.ref })
    .then(function(infos) {
        return that.api('delete', 'contents'+path.join('/', p), {
            message: opts.message,
            sha: infos.sha,
            branch: opts.ref,
            commiter: that.options.commiter
        });
    });
};

// List branches
Driver.prototype.listBranches = function(p, opts) {
    var that = this;

    return this.api('get', 'branches')
    .then(function(branches) {
        return _.map(branches, function(branch) {
            return {
                name: branch.name,
                commit: branch.commit.sha
            };
        });
    });
};

// Create a branch
Driver.prototype.createBranch = function(name, from) {
    var that = this;

    return this.api("get", "branches/"+from)
    .then(function(branch) {
        return that.api("post", "git/refs", {
            "ref": "refs/heads/"+name,
            "sha": branch.commit.sha
        });
    });
};

// Remove a branch
Driver.prototype.removeBranch = function(name) {
    return this.api("delete", "git/refs/heads/"+name);
};

// Merge branches
Driver.prototype.mergeBranches = function(from, to, opts) {
    var that = this;

    return this.api("post", "merges", {
        base: to,
        head: from,
        commit_message: opts.message
    });
};

// List commits
// todo: handle pagination and opts.start/opts.limit
Driver.prototype.listCommits = function(opts) {
    var that = this;

    return this.api("get", "commits", { sha: opts.ref })
    .then(function(commits) {
        return _.map(commits, function(commit) {
            return {
                "sha": commit.sha,
                "author": _.omit(commit.commit.author, "date"),
                "message": commit.commit.message,
                "date": commit.commit.author.date
            };
        });
    });
};

// Get a single commit
Driver.prototype.getCommit = function(sha) {
    var that = this;

    return this.api("get", "commits/"+sha)
    .then(function(commit) {
        return {
            "sha": commit.sha,
            "author": _.omit(commit.commit.author, "date"),
            "message": commit.commit.message,
            "date": commit.commit.author.date,
            "files": _.map(commit.files, function(file) {
                return {
                    filename: file.filename,
                    patch: file.patch
                };
            })
        };
    });
};

Driver.id = "github";
module.exports = Driver;

<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Horizontal flyout tray containing blocks which may be created.
 * @author fenichel@google.com (Rachel Fenichel)
 */
'use strict';

goog.provide('Blockly.HorizontalFlyout');

/** @suppress {extraRequire} */
goog.require('Blockly.Block');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
goog.require('Blockly.DropDownDiv');
goog.require('Blockly.Flyout');
goog.require('Blockly.registry');
goog.require('Blockly.Scrollbar');
goog.require('Blockly.utils');
goog.require('Blockly.utils.object');
goog.require('Blockly.utils.Rect');
goog.require('Blockly.utils.toolbox');
goog.require('Blockly.WidgetDiv');

goog.requireType('Blockly.Options');
goog.requireType('Blockly.utils.Coordinate');

/**
 * Class for a flyout.
 * @param {!Blockly.Options} workspaceOptions Dictionary of options for the
 *     workspace.
 * @extends {Blockly.Flyout}
 * @constructor
 */
Blockly.HorizontalFlyout = function(workspaceOptions) {
  Blockly.HorizontalFlyout.superClass_.constructor.call(this, workspaceOptions);
  this.horizontalLayout = true;
};
Blockly.utils.object.inherits(Blockly.HorizontalFlyout, Blockly.Flyout);

/**
 * Sets the translation of the flyout to match the scrollbars.
 * @param {!{x:number,y:number}} xyRatio Contains a y property which is a float
 *     between 0 and 1 specifying the degree of scrolling and a
 *     similar x property.
 * @protected
 */
Blockly.HorizontalFlyout.prototype.setMetrics_ = function(xyRatio) {
  if (!this.isVisible()) {
    return;
  }

  var metricsManager = this.workspace_.getMetricsManager();
  var scrollMetrics = metricsManager.getScrollMetrics();
  var viewMetrics = metricsManager.getViewMetrics();
  var absoluteMetrics = metricsManager.getAbsoluteMetrics();

  if (typeof xyRatio.x == 'number') {
    this.workspace_.scrollX =
        -(scrollMetrics.left +
            (scrollMetrics.width - viewMetrics.width) * xyRatio.x);
  }

  this.workspace_.translate(this.workspace_.scrollX + absoluteMetrics.left,
      this.workspace_.scrollY + absoluteMetrics.top);
};

/**
 * Calculates the x coordinate for the flyout position.
 * @return {number} X coordinate.
 */
Blockly.HorizontalFlyout.prototype.getX = function() {
  // X is always 0 since this is a horizontal flyout.
  return 0;
};

/**
 * Calculates the y coordinate for the flyout position.
 * @return {number} Y coordinate.
 */
Blockly.HorizontalFlyout.prototype.getY = function() {
  if (!this.isVisible()) {
    return 0;
  }
  var metricsManager = this.targetWorkspace.getMetricsManager();
  var absoluteMetrics = metricsManager.getAbsoluteMetrics();
  var viewMetrics = metricsManager.getViewMetrics();
  var toolboxMetrics = metricsManager.getToolboxMetrics();

  var y = 0;
  var atTop = this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP;
  // If this flyout is not the trashcan flyout (e.g. toolbox or mutator).
  if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_) {
    // If there is a category toolbox.
    if (this.targetWorkspace.getToolbox()) {
      if (atTop) {
        y = toolboxMetrics.height;
      } else {
        y = viewMetrics.height - this.height_;
      }
      // Simple (flyout-only) toolbox.
    } else {
      if (atTop) {
        y = 0;
      } else {
        // The simple flyout does not cover the workspace.
        y = viewMetrics.height;
      }
    }
    // Trashcan flyout is opposite the main flyout.
  } else {
    if (atTop) {
      y = 0;
    } else {
      // Because the anchor point of the flyout is on the top, but we want
      // to align the bottom edge of the flyout with the bottom edge of the
      // blocklyDiv, we calculate the full height of the div minus the height
      // of the flyout.
      y = viewMetrics.height + absoluteMetrics.top - this.height_;
    }
  }

  return y;
};

/**
 * Move the flyout to the edge of the workspace.
 */
Blockly.HorizontalFlyout.prototype.position = function() {
  if (!this.isVisible() || !this.targetWorkspace.isVisible()) {
    return;
  }
  var metricsManager = this.targetWorkspace.getMetricsManager();
  var targetWorkspaceViewMetrics = metricsManager.getViewMetrics();

  // Record the width for workspace metrics.
  this.width_ = targetWorkspaceViewMetrics.width;

  var edgeWidth = targetWorkspaceViewMetrics.width - 2 * this.CORNER_RADIUS;
  var edgeHeight = this.height_ - this.CORNER_RADIUS;
  this.setBackgroundPath_(edgeWidth, edgeHeight);

  var x = this.getX();
  var y = this.getY();

  this.positionAt_(this.width_, this.height_, x, y);
};

/**
 * Create and set the path for the visible boundaries of the flyout.
 * @param {number} width The width of the flyout, not including the
 *     rounded corners.
 * @param {number} height The height of the flyout, not including
 *     rounded corners.
 * @private
 */
Blockly.HorizontalFlyout.prototype.setBackgroundPath_ = function(
    width, height) {
  var atTop = this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP;
  // Start at top left.
  var path = ['M 0,' + (atTop ? 0 : this.CORNER_RADIUS)];

  if (atTop) {
    // Top.
    path.push('h', width + 2 * this.CORNER_RADIUS);
    // Right.
    path.push('v', height);
    // Bottom.
    path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
        -this.CORNER_RADIUS, this.CORNER_RADIUS);
    path.push('h', -width);
    // Left.
    path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
        -this.CORNER_RADIUS, -this.CORNER_RADIUS);
    path.push('z');
  } else {
    // Top.
    path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
        this.CORNER_RADIUS, -this.CORNER_RADIUS);
    path.push('h', width);
    // Right.
    path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
        this.CORNER_RADIUS, this.CORNER_RADIUS);
    path.push('v', height);
    // Bottom.
    path.push('h', -width - 2 * this.CORNER_RADIUS);
    // Left.
    path.push('z');
  }
  this.svgBackground_.setAttribute('d', path.join(' '));
};

/**
 * Scroll the flyout to the top.
 */
Blockly.HorizontalFlyout.prototype.scrollToStart = function() {
  this.workspace_.scrollbar.setX(this.RTL ? Infinity : 0);
};

/**
 * Scroll the flyout.
 * @param {!Event} e Mouse wheel scroll event.
 * @protected
 */
Blockly.HorizontalFlyout.prototype.wheel_ = function(e) {
  var scrollDelta = Blockly.utils.getScrollDeltaPixels(e);
  var delta = scrollDelta.x || scrollDelta.y;

  if (delta) {
    var metricsManager = this.workspace_.getMetricsManager();
    var scrollMetrics = metricsManager.getScrollMetrics();
    var viewMetrics = metricsManager.getViewMetrics();

    var pos = (viewMetrics.left - scrollMetrics.left) + delta;
    this.workspace_.scrollbar.setX(pos);
    // When the flyout moves from a wheel event, hide WidgetDiv and DropDownDiv.
    Blockly.WidgetDiv.hide();
    Blockly.DropDownDiv.hideWithoutAnimation();
  }

  // Don't scroll the page.
  e.preventDefault();
  // Don't propagate mousewheel event (zooming).
  e.stopPropagation();
};

/**
 * Lay out the blocks in the flyout.
 * @param {!Array<!Object>} contents The blocks and buttons to lay out.
 * @param {!Array<number>} gaps The visible gaps between blocks.
 * @protected
 */
Blockly.HorizontalFlyout.prototype.layout_ = function(contents, gaps) {
  this.workspace_.scale = this.targetWorkspace.scale;
  var margin = this.MARGIN;
  var cursorX = margin + this.tabWidth_;
  var cursorY = margin;
  if (this.RTL) {
    contents = contents.reverse();
  }

  for (var i = 0, item; (item = contents[i]); i++) {
    if (item.type == 'block') {
      var block = item.block;
      var allBlocks = block.getDescendants(false);
      for (var j = 0, child; (child = allBlocks[j]); j++) {
        // Mark blocks as being inside a flyout.  This is used to detect and
        // prevent the closure of the flyout if the user right-clicks on such a
        // block.
        child.isInFlyout = true;
      }
      block.render();
      var root = block.getSvgRoot();
      var blockHW = block.getHeightWidth();

      // Figure out where to place the block.
      var tab = block.outputConnection ? this.tabWidth_ : 0;
      if (this.RTL) {
        var moveX = cursorX + blockHW.width;
      } else {
        var moveX = cursorX - tab;
      }
      block.moveBy(moveX, cursorY);

      var rect = this.createRect_(block, moveX, cursorY, blockHW, i);
      cursorX += (blockHW.width + gaps[i]);

      this.addBlockListeners_(root, block, rect);
    } else if (item.type == 'button') {
      this.initFlyoutButton_(item.button, cursorX, cursorY);
      cursorX += (item.button.width + gaps[i]);
    }
  }
};

/**
 * Determine if a drag delta is toward the workspace, based on the position
 * and orientation of the flyout. This is used in determineDragIntention_ to
 * determine if a new block should be created or if the flyout should scroll.
 * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
 *     moved from the position at mouse down, in pixel units.
 * @return {boolean} True if the drag is toward the workspace.
 * @package
 */
Blockly.HorizontalFlyout.prototype.isDragTowardWorkspace = function(
    currentDragDeltaXY) {
  var dx = currentDragDeltaXY.x;
  var dy = currentDragDeltaXY.y;
  // Direction goes from -180 to 180, with 0 toward the right and 90 on top.
  var dragDirection = Math.atan2(dy, dx) / Math.PI * 180;

  var range = this.dragAngleRange_;
  // Check for up or down dragging.
  if ((dragDirection < 90 + range && dragDirection > 90 - range) ||
      (dragDirection > -90 - range && dragDirection < -90 + range)) {
    return true;
  }
  return false;
};

/**
 * Returns the bounding rectangle of the drag target area in pixel units
 * relative to viewport.
 * @return {?Blockly.utils.Rect} The component's bounding box. Null if drag
 *   target area should be ignored.
 */
Blockly.HorizontalFlyout.prototype.getClientRect = function() {
  if (!this.svgGroup_ || this.autoClose || !this.isVisible()) {
    // The bounding rectangle won't compute correctly if the flyout is closed
    // and auto-close flyouts aren't valid drag targets (or delete areas).
    return null;
  }

  var flyoutRect = this.svgGroup_.getBoundingClientRect();
  // BIG_NUM is offscreen padding so that blocks dragged beyond the shown flyout
  // area are still deleted.  Must be larger than the largest screen size,
  // but be smaller than half Number.MAX_SAFE_INTEGER (not available on IE).
  var BIG_NUM = 1000000000;
  var top = flyoutRect.top;

  if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP) {
    var height = flyoutRect.height;
    return new Blockly.utils.Rect(-BIG_NUM, top + height, -BIG_NUM, BIG_NUM);
  } else {  // Bottom.
    return new Blockly.utils.Rect(top, BIG_NUM, -BIG_NUM, BIG_NUM);
  }
};

/**
 * Compute height of flyout.  Position mat under each block.
 * For RTL: Lay out the blocks right-aligned.
 * @protected
 */
Blockly.HorizontalFlyout.prototype.reflowInternal_ = function() {
  this.workspace_.scale = this.getFlyoutScale();
  var flyoutHeight = 0;
  var blocks = this.workspace_.getTopBlocks(false);
  for (var i = 0, block; (block = blocks[i]); i++) {
    flyoutHeight = Math.max(flyoutHeight, block.getHeightWidth().height);
  }
  flyoutHeight += this.MARGIN * 1.5;
  flyoutHeight *= this.workspace_.scale;
  flyoutHeight += Blockly.Scrollbar.scrollbarThickness;

  if (this.height_ != flyoutHeight) {
    for (var i = 0, block; (block = blocks[i]); i++) {
      if (block.flyoutRect_) {
        this.moveRectToBlock_(block.flyoutRect_, block);
      }
    }

    if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_ &&
        this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP &&
        !this.targetWorkspace.getToolbox()) {
      // This flyout is a simple toolbox. Reposition the workspace so that (0,0)
      // is in the correct position relative to the new absolute edge (ie
      // toolbox edge).
      this.targetWorkspace.translate(
          this.targetWorkspace.scrollX, this.targetWorkspace.scrollY + flyoutHeight);
    }

    // Record the height for workspace metrics and .position.
    this.height_ = flyoutHeight;
    this.position();
  }
};

Blockly.registry.register(Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX,
    Blockly.registry.DEFAULT, Blockly.HorizontalFlyout);
<commit_msg>Keep horizontal flyout delete area in sync with its bounds.<commit_after>/**
 * @license
 * Copyright 2017 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Horizontal flyout tray containing blocks which may be created.
 * @author fenichel@google.com (Rachel Fenichel)
 */
'use strict';

goog.provide('Blockly.HorizontalFlyout');

/** @suppress {extraRequire} */
goog.require('Blockly.Block');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
goog.require('Blockly.DropDownDiv');
goog.require('Blockly.Flyout');
goog.require('Blockly.registry');
goog.require('Blockly.Scrollbar');
goog.require('Blockly.utils');
goog.require('Blockly.utils.object');
goog.require('Blockly.utils.Rect');
goog.require('Blockly.utils.toolbox');
goog.require('Blockly.WidgetDiv');

goog.requireType('Blockly.Options');
goog.requireType('Blockly.utils.Coordinate');

/**
 * Class for a flyout.
 * @param {!Blockly.Options} workspaceOptions Dictionary of options for the
 *     workspace.
 * @extends {Blockly.Flyout}
 * @constructor
 */
Blockly.HorizontalFlyout = function(workspaceOptions) {
  Blockly.HorizontalFlyout.superClass_.constructor.call(this, workspaceOptions);
  this.horizontalLayout = true;
};
Blockly.utils.object.inherits(Blockly.HorizontalFlyout, Blockly.Flyout);

/**
 * Sets the translation of the flyout to match the scrollbars.
 * @param {!{x:number,y:number}} xyRatio Contains a y property which is a float
 *     between 0 and 1 specifying the degree of scrolling and a
 *     similar x property.
 * @protected
 */
Blockly.HorizontalFlyout.prototype.setMetrics_ = function(xyRatio) {
  if (!this.isVisible()) {
    return;
  }

  var metricsManager = this.workspace_.getMetricsManager();
  var scrollMetrics = metricsManager.getScrollMetrics();
  var viewMetrics = metricsManager.getViewMetrics();
  var absoluteMetrics = metricsManager.getAbsoluteMetrics();

  if (typeof xyRatio.x == 'number') {
    this.workspace_.scrollX =
        -(scrollMetrics.left +
            (scrollMetrics.width - viewMetrics.width) * xyRatio.x);
  }

  this.workspace_.translate(this.workspace_.scrollX + absoluteMetrics.left,
      this.workspace_.scrollY + absoluteMetrics.top);
};

/**
 * Calculates the x coordinate for the flyout position.
 * @return {number} X coordinate.
 */
Blockly.HorizontalFlyout.prototype.getX = function() {
  // X is always 0 since this is a horizontal flyout.
  return 0;
};

/**
 * Calculates the y coordinate for the flyout position.
 * @return {number} Y coordinate.
 */
Blockly.HorizontalFlyout.prototype.getY = function() {
  if (!this.isVisible()) {
    return 0;
  }
  var metricsManager = this.targetWorkspace.getMetricsManager();
  var absoluteMetrics = metricsManager.getAbsoluteMetrics();
  var viewMetrics = metricsManager.getViewMetrics();
  var toolboxMetrics = metricsManager.getToolboxMetrics();

  var y = 0;
  var atTop = this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP;
  // If this flyout is not the trashcan flyout (e.g. toolbox or mutator).
  if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_) {
    // If there is a category toolbox.
    if (this.targetWorkspace.getToolbox()) {
      if (atTop) {
        y = toolboxMetrics.height;
      } else {
        y = viewMetrics.height - this.height_;
      }
      // Simple (flyout-only) toolbox.
    } else {
      if (atTop) {
        y = 0;
      } else {
        // The simple flyout does not cover the workspace.
        y = viewMetrics.height;
      }
    }
    // Trashcan flyout is opposite the main flyout.
  } else {
    if (atTop) {
      y = 0;
    } else {
      // Because the anchor point of the flyout is on the top, but we want
      // to align the bottom edge of the flyout with the bottom edge of the
      // blocklyDiv, we calculate the full height of the div minus the height
      // of the flyout.
      y = viewMetrics.height + absoluteMetrics.top - this.height_;
    }
  }

  return y;
};

/**
 * Move the flyout to the edge of the workspace.
 */
Blockly.HorizontalFlyout.prototype.position = function() {
  if (!this.isVisible() || !this.targetWorkspace.isVisible()) {
    return;
  }
  var metricsManager = this.targetWorkspace.getMetricsManager();
  var targetWorkspaceViewMetrics = metricsManager.getViewMetrics();

  // Record the width for workspace metrics.
  this.width_ = targetWorkspaceViewMetrics.width;

  var edgeWidth = targetWorkspaceViewMetrics.width - 2 * this.CORNER_RADIUS;
  var edgeHeight = this.height_ - this.CORNER_RADIUS;
  this.setBackgroundPath_(edgeWidth, edgeHeight);

  var x = this.getX();
  var y = this.getY();

  this.positionAt_(this.width_, this.height_, x, y);
};

/**
 * Create and set the path for the visible boundaries of the flyout.
 * @param {number} width The width of the flyout, not including the
 *     rounded corners.
 * @param {number} height The height of the flyout, not including
 *     rounded corners.
 * @private
 */
Blockly.HorizontalFlyout.prototype.setBackgroundPath_ = function(
    width, height) {
  var atTop = this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP;
  // Start at top left.
  var path = ['M 0,' + (atTop ? 0 : this.CORNER_RADIUS)];

  if (atTop) {
    // Top.
    path.push('h', width + 2 * this.CORNER_RADIUS);
    // Right.
    path.push('v', height);
    // Bottom.
    path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
        -this.CORNER_RADIUS, this.CORNER_RADIUS);
    path.push('h', -width);
    // Left.
    path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
        -this.CORNER_RADIUS, -this.CORNER_RADIUS);
    path.push('z');
  } else {
    // Top.
    path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
        this.CORNER_RADIUS, -this.CORNER_RADIUS);
    path.push('h', width);
    // Right.
    path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
        this.CORNER_RADIUS, this.CORNER_RADIUS);
    path.push('v', height);
    // Bottom.
    path.push('h', -width - 2 * this.CORNER_RADIUS);
    // Left.
    path.push('z');
  }
  this.svgBackground_.setAttribute('d', path.join(' '));
};

/**
 * Scroll the flyout to the top.
 */
Blockly.HorizontalFlyout.prototype.scrollToStart = function() {
  this.workspace_.scrollbar.setX(this.RTL ? Infinity : 0);
};

/**
 * Scroll the flyout.
 * @param {!Event} e Mouse wheel scroll event.
 * @protected
 */
Blockly.HorizontalFlyout.prototype.wheel_ = function(e) {
  var scrollDelta = Blockly.utils.getScrollDeltaPixels(e);
  var delta = scrollDelta.x || scrollDelta.y;

  if (delta) {
    var metricsManager = this.workspace_.getMetricsManager();
    var scrollMetrics = metricsManager.getScrollMetrics();
    var viewMetrics = metricsManager.getViewMetrics();

    var pos = (viewMetrics.left - scrollMetrics.left) + delta;
    this.workspace_.scrollbar.setX(pos);
    // When the flyout moves from a wheel event, hide WidgetDiv and DropDownDiv.
    Blockly.WidgetDiv.hide();
    Blockly.DropDownDiv.hideWithoutAnimation();
  }

  // Don't scroll the page.
  e.preventDefault();
  // Don't propagate mousewheel event (zooming).
  e.stopPropagation();
};

/**
 * Lay out the blocks in the flyout.
 * @param {!Array<!Object>} contents The blocks and buttons to lay out.
 * @param {!Array<number>} gaps The visible gaps between blocks.
 * @protected
 */
Blockly.HorizontalFlyout.prototype.layout_ = function(contents, gaps) {
  this.workspace_.scale = this.targetWorkspace.scale;
  var margin = this.MARGIN;
  var cursorX = margin + this.tabWidth_;
  var cursorY = margin;
  if (this.RTL) {
    contents = contents.reverse();
  }

  for (var i = 0, item; (item = contents[i]); i++) {
    if (item.type == 'block') {
      var block = item.block;
      var allBlocks = block.getDescendants(false);
      for (var j = 0, child; (child = allBlocks[j]); j++) {
        // Mark blocks as being inside a flyout.  This is used to detect and
        // prevent the closure of the flyout if the user right-clicks on such a
        // block.
        child.isInFlyout = true;
      }
      block.render();
      var root = block.getSvgRoot();
      var blockHW = block.getHeightWidth();

      // Figure out where to place the block.
      var tab = block.outputConnection ? this.tabWidth_ : 0;
      if (this.RTL) {
        var moveX = cursorX + blockHW.width;
      } else {
        var moveX = cursorX - tab;
      }
      block.moveBy(moveX, cursorY);

      var rect = this.createRect_(block, moveX, cursorY, blockHW, i);
      cursorX += (blockHW.width + gaps[i]);

      this.addBlockListeners_(root, block, rect);
    } else if (item.type == 'button') {
      this.initFlyoutButton_(item.button, cursorX, cursorY);
      cursorX += (item.button.width + gaps[i]);
    }
  }
};

/**
 * Determine if a drag delta is toward the workspace, based on the position
 * and orientation of the flyout. This is used in determineDragIntention_ to
 * determine if a new block should be created or if the flyout should scroll.
 * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
 *     moved from the position at mouse down, in pixel units.
 * @return {boolean} True if the drag is toward the workspace.
 * @package
 */
Blockly.HorizontalFlyout.prototype.isDragTowardWorkspace = function(
    currentDragDeltaXY) {
  var dx = currentDragDeltaXY.x;
  var dy = currentDragDeltaXY.y;
  // Direction goes from -180 to 180, with 0 toward the right and 90 on top.
  var dragDirection = Math.atan2(dy, dx) / Math.PI * 180;

  var range = this.dragAngleRange_;
  // Check for up or down dragging.
  if ((dragDirection < 90 + range && dragDirection > 90 - range) ||
      (dragDirection > -90 - range && dragDirection < -90 + range)) {
    return true;
  }
  return false;
};

/**
 * Returns the bounding rectangle of the drag target area in pixel units
 * relative to viewport.
 * @return {?Blockly.utils.Rect} The component's bounding box. Null if drag
 *   target area should be ignored.
 */
Blockly.HorizontalFlyout.prototype.getClientRect = function() {
  if (!this.svgGroup_ || this.autoClose || !this.isVisible()) {
    // The bounding rectangle won't compute correctly if the flyout is closed
    // and auto-close flyouts aren't valid drag targets (or delete areas).
    return null;
  }

  var flyoutRect = this.svgGroup_.getBoundingClientRect();
  // BIG_NUM is offscreen padding so that blocks dragged beyond the shown flyout
  // area are still deleted.  Must be larger than the largest screen size,
  // but be smaller than half Number.MAX_SAFE_INTEGER (not available on IE).
  var BIG_NUM = 1000000000;
  var top = flyoutRect.top;

  if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP) {
    var height = flyoutRect.height;
    return new Blockly.utils.Rect(-BIG_NUM, top + height, -BIG_NUM, BIG_NUM);
  } else {  // Bottom.
    return new Blockly.utils.Rect(top, BIG_NUM, -BIG_NUM, BIG_NUM);
  }
};

/**
 * Compute height of flyout.  Position mat under each block.
 * For RTL: Lay out the blocks right-aligned.
 * @protected
 */
Blockly.HorizontalFlyout.prototype.reflowInternal_ = function() {
  this.workspace_.scale = this.getFlyoutScale();
  var flyoutHeight = 0;
  var blocks = this.workspace_.getTopBlocks(false);
  for (var i = 0, block; (block = blocks[i]); i++) {
    flyoutHeight = Math.max(flyoutHeight, block.getHeightWidth().height);
  }
  flyoutHeight += this.MARGIN * 1.5;
  flyoutHeight *= this.workspace_.scale;
  flyoutHeight += Blockly.Scrollbar.scrollbarThickness;

  if (this.height_ != flyoutHeight) {
    for (var i = 0, block; (block = blocks[i]); i++) {
      if (block.flyoutRect_) {
        this.moveRectToBlock_(block.flyoutRect_, block);
      }
    }

    if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_ &&
        this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP &&
        !this.targetWorkspace.getToolbox()) {
      // This flyout is a simple toolbox. Reposition the workspace so that (0,0)
      // is in the correct position relative to the new absolute edge (ie
      // toolbox edge).
      this.targetWorkspace.translate(
          this.targetWorkspace.scrollX, this.targetWorkspace.scrollY + flyoutHeight);
    }

    // Record the height for workspace metrics and .position.
    this.height_ = flyoutHeight;
    this.position();
    this.targetWorkspace.recordDragTargets();
  }
};

Blockly.registry.register(Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX,
    Blockly.registry.DEFAULT, Blockly.HorizontalFlyout);
<|endoftext|>


<commit_before>module.exports = require('./StreamStash')
module.exports.codecs = require('./codecs')
module.exports.inputs = require('./inputs')
module.exports.outputs = require('./outputs')
module.exports.EventContainer = require('./EventContainer')
module.exports.Logger = require('./Logger')
<commit_msg>Expose parsers on lib require<commit_after>module.exports = require('./StreamStash')
module.exports.codecs = require('./codecs')
module.exports.inputs = require('./inputs')
module.exports.outputs = require('./outputs')
module.exports.parsers = require('./parsers')
module.exports.EventContainer = require('./EventContainer')
module.exports.Logger = require('./Logger')

<|endoftext|>


<commit_before>'use strict';

/* eslint comma-dangle:[0, "only-multiline"] */

module.exports = {
  client: {
    lib: {
      css: [
        // bower:css
        'public/lib/bootstrap/dist/css/bootstrap.css',
        // 'public/lib/bootstrap/dist/css/bootstrap-theme.css',
        'public/theme.css',
        'public/lib/angular-ui-notification/dist/angular-ui-notification.css'
        // endbower
      ],
      js: [
        // bower:js
        'public/lib/angular/angular.js',
        'public/lib/angular-animate/angular-animate.js',
        'public/lib/angular-bootstrap/ui-bootstrap-tpls.js',
        'public/lib/ng-file-upload/ng-file-upload.js',
        'public/lib/angular-messages/angular-messages.js',
        'public/lib/angular-mocks/angular-mocks.js',
        'public/lib/angular-resource/angular-resource.js',
        'public/lib/angular-ui-notification/dist/angular-ui-notification.js',
        'public/lib/angular-ui-router/release/angular-ui-router.js',
        'public/lib/owasp-password-strength-test/owasp-password-strength-test.js',
        // endbower
      ],
      tests: ['public/lib/angular-mocks/angular-mocks.js']
    },
    css: [
      'modules/*/client/{css,less,scss}/*.css'
    ],
    less: [
      'modules/*/client/less/*.less'
    ],
    sass: [
      'modules/*/client/scss/*.scss'
    ],
    js: [
      'modules/core/client/app/config.js',
      'modules/core/client/app/init.js',
      'modules/*/client/*.js',
      'modules/*/client/**/*.js'
    ],
    img: [
      'modules/**/*/img/**/*.jpg',
      'modules/**/*/img/**/*.png',
      'modules/**/*/img/**/*.gif',
      'modules/**/*/img/**/*.svg'
    ],
    views: ['modules/*/client/views/**/*.html'],
    templates: ['build/templates.js']
  },
  server: {
    gulpConfig: ['gulpfile.js'],
    allJS: ['server.js', 'config/**/*.js', 'modules/*/server/**/*.js'],
    models: 'modules/*/server/models/**/*.js',
    routes: ['modules/!(core)/server/routes/**/*.js', 'modules/core/server/routes/**/*.js'],
    sockets: 'modules/*/server/sockets/**/*.js',
    config: ['modules/*/server/config/*.js'],
    policies: 'modules/*/server/policies/*.js',
    views: ['modules/*/server/views/*.html']
  }
};
<commit_msg>assets file changes<commit_after>'use strict';

/* eslint comma-dangle:[0, "only-multiline"] */

module.exports = {
  client: {
    lib: {
      css: [
        // bower:css
        'public/lib/bootstrap/dist/css/bootstrap.css',
        // 'public/lib/bootstrap/dist/css/bootstrap-theme.css',
        'public/themeCss/theme.css',
        'public/lib/angular-ui-notification/dist/angular-ui-notification.css'
        // endbower
      ],
      js: [
        // bower:js
        'public/lib/angular/angular.js',
        'public/lib/angular-animate/angular-animate.js',
        'public/lib/angular-bootstrap/ui-bootstrap-tpls.js',
        'public/lib/ng-file-upload/ng-file-upload.js',
        'public/lib/angular-messages/angular-messages.js',
        'public/lib/angular-mocks/angular-mocks.js',
        'public/lib/angular-resource/angular-resource.js',
        'public/lib/angular-ui-notification/dist/angular-ui-notification.js',
        'public/lib/angular-ui-router/release/angular-ui-router.js',
        'public/lib/owasp-password-strength-test/owasp-password-strength-test.js',
        // endbower
      ],
      tests: ['public/lib/angular-mocks/angular-mocks.js']
    },
    css: [
      'modules/*/client/{css,less,scss}/*.css'
    ],
    less: [
      'modules/*/client/less/*.less'
    ],
    sass: [
      'modules/*/client/scss/*.scss'
    ],
    js: [
      'modules/core/client/app/config.js',
      'modules/core/client/app/init.js',
      'modules/*/client/*.js',
      'modules/*/client/**/*.js'
    ],
    img: [
      'modules/**/*/img/**/*.jpg',
      'modules/**/*/img/**/*.png',
      'modules/**/*/img/**/*.gif',
      'modules/**/*/img/**/*.svg'
    ],
    views: ['modules/*/client/views/**/*.html'],
    templates: ['build/templates.js']
  },
  server: {
    gulpConfig: ['gulpfile.js'],
    allJS: ['server.js', 'config/**/*.js', 'modules/*/server/**/*.js'],
    models: 'modules/*/server/models/**/*.js',
    routes: ['modules/!(core)/server/routes/**/*.js', 'modules/core/server/routes/**/*.js'],
    sockets: 'modules/*/server/sockets/**/*.js',
    config: ['modules/*/server/config/*.js'],
    policies: 'modules/*/server/policies/*.js',
    views: ['modules/*/server/views/*.html']
  }
};
<|endoftext|>


<commit_before>'use strict';

// Karma configuration
// Generated on Thu Nov 24 2016 06:53:29 GMT+0100 (WAT)

module.exports = (config) => {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'jasmine/books.json',
      'jasmine/books_2.json',
      'jasmine/empty_book.json',
      'jasmine/spec/all.js',
      'jasmine/spec/inverted-index-test.js'
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    preprocessors: {
      'jasmine/spec/all.js': 'coverage'
    },

    // test results reporter to use
    reporters: ['spec', 'coverage', 'coveralls'],

    coverageReporter: {
      type: 'lcov',
      dir: 'coverage/'
    },

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    logLevel: config.LOG_INFO,

    // enable/disable watching file
    autoWatch: true,

    customLaunchers: {
      Chrome_travis_ci: {
        base: 'Chrome',
        flags: ['--no-sandbox']
      }
    },

    // start these browsers depending on our enviroment
    browsers: process.env.TRAVIS ? ['Chrome_travis_ci'] : ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  });
};
<commit_msg>refactor karma config file to load refactored files into the browser<commit_after>'use strict';

// Karma configuration
// Generated on Thu Nov 24 2016 06:53:29 GMT+0100 (WAT)

module.exports = (config) => {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'src/js/inverted-index-utility.js',
      'src/js/inverted-index.js',
      'jasmine/books.json',
      'jasmine/invalid_book.json',
      'jasmine/empty_book.json',
      'jasmine/spec/inverted-index-test.js'
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    preprocessors: {
      'jasmine/spec/all.js': 'coverage'
    },

    // test results reporter to use
    reporters: ['spec', 'coverage', 'coveralls'],

    coverageReporter: {
      type: 'lcov',
      dir: 'coverage/'
    },

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    logLevel: config.LOG_INFO,

    // enable/disable watching file
    autoWatch: true,

    customLaunchers: {
      Chrome_travis_ci: {
        base: 'Chrome',
        flags: ['--no-sandbox']
      }
    },

    // start these browsers depending on our enviroment
    browsers: process.env.TRAVIS ? ['Chrome_travis_ci'] : ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  });
};
<|endoftext|>


<commit_before>(() => {
  const focusOptions = Array.from(document.getElementsByClassName('focus-option'));
  const resizeOriginal = document.getElementById('resize-original');
  const cloneOriginal = document.getElementById('clone-original');
  const clonePositions = Array.from(document.getElementsByName('clone-position'));
  const copyFullscreen = document.getElementById('copy-fullscreen');

  function get_focus_name() {
    const focused = focusOptions.find(option => option.checked);
    return focused === undefined ? 'original' : focused.id.replace('focus-', '');
  }

  function save(event) {
    localStorage.ttw_focus = get_focus_name();
    localStorage.ttw_resize_original = resizeOriginal.checked;
    localStorage.ttw_clone_original = cloneOriginal.checked;

    // Save to Local Storage

    // dimensions
    Array.from(document.getElementsByClassName('option')).forEach(input => {
      localStorage[`ttw_${input.id}`] = input.valueAsNumber;
    });

    // close position options
    localStorage.ttw_clone_position = clonePositions.find(cp => cp.checked).id;

    // fullscreen status
    localStorage.ttw_copy_fullscreen = copyFullscreen.checked;
  }

  function update_window_handling (input_id, window_id, enable_if_checked) {
    const $input =  $(input_id);
    const $win =    $(window_id);
    const checked = $input.prop('checked');
    const enable =  enable_if_checked ? checked : !checked;
    const action =  enable ? 'enable' : 'disable';

    $win.draggable(action);
    $win.resizable(action);
  }

  function update_window_size_and_position(win) {
    // update view
    const userScreen = document.getElementById('screen');
    const inner = win.getElementsByClassName('inner-window')[0];

    function getBorderWidth(keys) {
      const computed = getComputedStyle(inner);
      return keys.reduce((accumulator, key) => {
        return accumulator + parseInt(computed[`border${key}Width`], 10);
      }, 0);
    }
    const newInnerWidth = win.clientWidth - getBorderWidth(['Left', 'Right']);
    inner.style.width = `${newInnerWidth}px`;
    const newInnerHeight = win.clientHeight - getBorderWidth(['Top', 'Bottom']);
    inner.style.height = `${newInnerHeight}px`;

    // update form fields
    [['Width'], ['Height'], ['Left', 'Width'], ['Top', 'Height']].forEach(pair => {
      const windowDimension = win[`offset${pair[0]}`];
      const screenDimension = userScreen[`offset${pair[1 % pair.length]}`];
      const value = Math.floor((windowDimension / screenDimension) * 100);
      document.getElementById(`${win.id}-${pair[0].toLowerCase()}`).value = value;
    });
  }

  function setup_windows(gridsize) {
    const userScreen = document.getElementById('screen');
    const screenHeight = userScreen.clientHeight;

    Array.from(document.getElementsByClassName('window')).forEach(win => {
      // Restore positions from options
      ['width', 'height', 'left', 'top'].forEach(prop => {
        win.style[prop] = `${document.getElementById(`${win.id}-${prop}`).value}%`;
      });

      const grid = [userScreen.clientWidth / gridsize,
                    userScreen.clientHeight / gridsize];

      $(win).draggable({
        containment: "parent",
        grid: grid
      });

      $(win).resizable({
        containment: "parent",
        handles: "all",
        grid: grid,
        minWidth: $(win).parent().width() * 0.2,
        minHeight: $(win).parent().height() * 0.2
      });

      function onChange(event) {
         update_window_size_and_position(win);
         save();
      }

      win.onresize = onChange;
      win.ondrag = onChange;

    });
  }

  function update_resize_original() {
    update_window_handling('#resize-original', '#original', true);
  }

  function update_clone_original () {
    update_window_handling('#clone-original', '#new', false);

    // toggle clone position controls if cloning enabled/disabled
    Array.from(document.getElementsByClassName('clone-position-option')).forEach(opt => {
      opt.disabled = !cloneOriginal.checked;
    });

    const clonePositionOptions = document.getElementById('clone-position-options');
    clonePositionOptions.style.display = cloneOriginal.checked ? '' : 'none';
  }

  function update_focus() {
    function getElements(id) {
      const parent = document.getElementById(id);
      return ['inner-window', 'button'].reduce((accumulator, className) => {
        return accumulator.concat(Array.from(parent.getElementsByClassName(className)));
      }, []);
    }

    ['original', 'new'].forEach(id => {
      getElements(id).forEach(element => {
        element.style.opacity = get_focus_name() === id
          ? 1.0
          : element.classList.contains('inner-window') ? 0.92 : 0.1;
      });
    });
  }

  jQuery(document).ready(($) => {
    const gridsize = 20; // px to use for window grid
    // resize screen
    {
      const userScreen = document.getElementById('monitor');
      const ratio = screen.height / screen.width;
      const height = Math.round((userScreen.clientWidth * ratio) / gridsize) * gridsize;
      userScreen.style.height =  `${height}px`;
    }

    // restore_options
    focusOptions.forEach(opt => opt.checked = opt.id.includes(localStorage.ttw_focus));
    resizeOriginal.checked = localStorage.ttw_resize_original === 'true';
    cloneOriginal.checked = localStorage.ttw_clone_original === 'true';
    clonePositions.find(cp => cp.id === localStorage.ttw_clone_position).checked = true;
    copyFullscreen.checked = localStorage.ttw_copy_fullscreen === 'true';

    const defaults = {
      "original": { width: 50, height: 100, left: 0, top: 0 },
      "new": { width: 50, height: 100, left: 50, top: 0 }
    };
    Object.keys(defaults).forEach(wKey => {
      Object.keys(defaults[wKey]).forEach(pKey => {
        const id = `${wKey}-${pKey}`;
        const localId = `ttw_${id}`;
        document.getElementById(id).value = localStorage.hasOwnProperty(localId)
          ? localStorage[localId]
          : defaults[wKey][pKey];
      });
    });

    // add input handlers
    resizeOriginal.onchange = update_resize_original;
    cloneOriginal.onchange = update_clone_original;
    focusOptions.forEach(el => el.onchange = update_focus);

    // setup windows
    setup_windows(gridsize);
    update_resize_original();
    update_clone_original();
    update_focus();

    // display_shortcuts
    chrome.commands.getAll(cmds => {
      if (cmds.length === 0) {
        return;
      }
      const $shortcuts = $('#shortcuts');
      const $ul = $('#shortcut-list');

      cmds.forEach((cmd, i) => {
        const $li = $('<li>');
        const desc = cmd.description;
        const $shortcuts = $('<span>');
        $shortcuts.addClass('shortcut');
        $shortcuts.text(cmd.shortcut);
        $li.append(desc);
        $li.append(': ');
        $li.append($shortcuts);
        $ul.append($li);
      });
    });

    $('.window').trigger('resize');
    $('#extensions').click(event => {
      chrome.tabs.update({
        url: $(this).attr('href')
      });
    });

    [
    '#sub', '.focus-option', '#resize-original', '#clone-original',
     '#clone-position-same', '#clone-position-horizontal',
     '#clone-position-vertical', '#copy-fullscreen'
    ].forEach((item, i) => $(item).click(save));
  });
})();
<commit_msg>options removes outer function and jquery ready<commit_after>const focusOptions = Array.from(document.getElementsByClassName('focus-option'));
const resizeOriginal = document.getElementById('resize-original');
const cloneOriginal = document.getElementById('clone-original');
const clonePositions = Array.from(document.getElementsByName('clone-position'));
const copyFullscreen = document.getElementById('copy-fullscreen');

function get_focus_name() {
  const focused = focusOptions.find(option => option.checked);
  return focused === undefined ? 'original' : focused.id.replace('focus-', '');
}

function save(event) {
  localStorage.ttw_focus = get_focus_name();
  localStorage.ttw_resize_original = resizeOriginal.checked;
  localStorage.ttw_clone_original = cloneOriginal.checked;

  // Save to Local Storage

  // dimensions
  Array.from(document.getElementsByClassName('option')).forEach(input => {
    localStorage[`ttw_${input.id}`] = input.valueAsNumber;
  });

  // close position options
  localStorage.ttw_clone_position = clonePositions.find(cp => cp.checked).id;

  // fullscreen status
  localStorage.ttw_copy_fullscreen = copyFullscreen.checked;
}

function update_window_handling (input_id, window_id, enable_if_checked) {
  const $input =  $(input_id);
  const $win =    $(window_id);
  const checked = $input.prop('checked');
  const enable =  enable_if_checked ? checked : !checked;
  const action =  enable ? 'enable' : 'disable';

  $win.draggable(action);
  $win.resizable(action);
}

function update_window_size_and_position(win) {
  // update view
  const userScreen = document.getElementById('screen');
  const inner = win.getElementsByClassName('inner-window')[0];

  function getBorderWidth(keys) {
    const computed = getComputedStyle(inner);
    return keys.reduce((accumulator, key) => {
      return accumulator + parseInt(computed[`border${key}Width`], 10);
    }, 0);
  }
  const newInnerWidth = win.clientWidth - getBorderWidth(['Left', 'Right']);
  inner.style.width = `${newInnerWidth}px`;
  const newInnerHeight = win.clientHeight - getBorderWidth(['Top', 'Bottom']);
  inner.style.height = `${newInnerHeight}px`;

  // update form fields
  [['Width'], ['Height'], ['Left', 'Width'], ['Top', 'Height']].forEach(pair => {
    const windowDimension = win[`offset${pair[0]}`];
    const screenDimension = userScreen[`offset${pair[1 % pair.length]}`];
    const value = Math.floor((windowDimension / screenDimension) * 100);
    document.getElementById(`${win.id}-${pair[0].toLowerCase()}`).value = value;
  });
}

function setup_windows(gridsize) {
  const userScreen = document.getElementById('screen');
  const screenHeight = userScreen.clientHeight;

  Array.from(document.getElementsByClassName('window')).forEach(win => {
    // Restore positions from options
    ['width', 'height', 'left', 'top'].forEach(prop => {
      win.style[prop] = `${document.getElementById(`${win.id}-${prop}`).value}%`;
    });

    const grid = [userScreen.clientWidth / gridsize,
                  userScreen.clientHeight / gridsize];

    $(win).draggable({
      containment: "parent",
      grid: grid
    });

    $(win).resizable({
      containment: "parent",
      handles: "all",
      grid: grid,
      minWidth: $(win).parent().width() * 0.2,
      minHeight: $(win).parent().height() * 0.2
    });

    function onChange(event) {
       update_window_size_and_position(win);
       save();
    }

    win.onresize = onChange;
    win.ondrag = onChange;

  });
}

function update_resize_original() {
  update_window_handling('#resize-original', '#original', true);
}

function update_clone_original () {
  update_window_handling('#clone-original', '#new', false);

  // toggle clone position controls if cloning enabled/disabled
  Array.from(document.getElementsByClassName('clone-position-option')).forEach(opt => {
    opt.disabled = !cloneOriginal.checked;
  });

  const clonePositionOptions = document.getElementById('clone-position-options');
  clonePositionOptions.style.display = cloneOriginal.checked ? '' : 'none';
}

function update_focus() {
  function getElements(id) {
    const parent = document.getElementById(id);
    return ['inner-window', 'button'].reduce((accumulator, className) => {
      return accumulator.concat(Array.from(parent.getElementsByClassName(className)));
    }, []);
  }

  ['original', 'new'].forEach(id => {
    getElements(id).forEach(element => {
      element.style.opacity = get_focus_name() === id
        ? 1.0
        : element.classList.contains('inner-window') ? 0.92 : 0.1;
    });
  });
}

const gridsize = 20; // px to use for window grid
// resize screen
{
  const userScreen = document.getElementById('monitor');
  const ratio = screen.height / screen.width;
  const height = Math.round((userScreen.clientWidth * ratio) / gridsize) * gridsize;
  userScreen.style.height =  `${height}px`;
}

// restore_options
focusOptions.forEach(opt => opt.checked = opt.id.includes(localStorage.ttw_focus));
resizeOriginal.checked = localStorage.ttw_resize_original === 'true';
cloneOriginal.checked = localStorage.ttw_clone_original === 'true';
clonePositions.find(cp => cp.id === localStorage.ttw_clone_position).checked = true;
copyFullscreen.checked = localStorage.ttw_copy_fullscreen === 'true';

const defaults = {
  "original": { width: 50, height: 100, left: 0, top: 0 },
  "new": { width: 50, height: 100, left: 50, top: 0 }
};
Object.keys(defaults).forEach(wKey => {
  Object.keys(defaults[wKey]).forEach(pKey => {
    const id = `${wKey}-${pKey}`;
    const localId = `ttw_${id}`;
    document.getElementById(id).value = localStorage.hasOwnProperty(localId)
      ? localStorage[localId]
      : defaults[wKey][pKey];
  });
});

// add input handlers
resizeOriginal.onchange = update_resize_original;
cloneOriginal.onchange = update_clone_original;
focusOptions.forEach(el => el.onchange = update_focus);

// setup windows
setup_windows(gridsize);
update_resize_original();
update_clone_original();
update_focus();

// display_shortcuts
chrome.commands.getAll(cmds => {
  if (cmds.length === 0) {
    return;
  }
  const $shortcuts = $('#shortcuts');
  const $ul = $('#shortcut-list');

  cmds.forEach((cmd, i) => {
    const $li = $('<li>');
    const desc = cmd.description;
    const $shortcuts = $('<span>');
    $shortcuts.addClass('shortcut');
    $shortcuts.text(cmd.shortcut);
    $li.append(desc);
    $li.append(': ');
    $li.append($shortcuts);
    $ul.append($li);
  });
});

$('.window').trigger('resize');
$('#extensions').click(event => {
  chrome.tabs.update({
    url: $(this).attr('href')
  });
});

[
'#sub', '.focus-option', '#resize-original', '#clone-original',
 '#clone-position-same', '#clone-position-horizontal',
 '#clone-position-vertical', '#copy-fullscreen'
].forEach((item, i) => $(item).click(save));
<|endoftext|>


<commit_before>/* global describe it */
import postcss from 'postcss';
import {expect} from 'chai';
import plugin from '../lib/index';
const test = (input, output, opts) => {
	expect(postcss([plugin(opts)]).process(input).css).to.eql(output);
};

describe('postcss-at-rules-variables', () => {
	it('it change first properties for @for', () => {
		test(
			':root{ --from: 1; } @for $i from var(--from) to 2',
			':root{ --from: 1; } @for $i from 1 to 2'
		);
	});

	it('it change second properties for @for', () => {
		test(
			':root{ --to: 2; } @for $i from 1 to var(--to)',
			':root{ --to: 2; } @for $i from 1 to 2'
		);
	});

	it('it change two properties for @for', () => {
		test(
			':root{ --from: 1; --to: 2; } @for $i from var(--from) to var(--to)',
			':root{ --from: 1; --to: 2; } @for $i from 1 to 2'
		);
	});

	it('it change three properties for @for', () => {
		test(
			':root{ --from: 1; --to: 2; --step: 5 } @for $i from var(--from) to var(--to) by var(--step)',
			':root{ --from: 1; --to: 2; --step: 5 } @for $i from 1 to 2 by 5'
		);
	});

	it('it change two properties for @if', () => {
		test(
			':root{ --first: 1; --second: 2; } @if var(--first) < var(--second)',
			':root{ --first: 1; --second: 2; } @if 1 < 2',
			{atRules: ['if']}
		);
	});

	it('it change two properties for @if, @else if', () => {
		test(
			':root{ --first: 1; --second: 2; } @if var(--first) < var(--second) { color: olive; } @else if var(--first) > var(--second) { color: red; }',
			':root{ --first: 1; --second: 2; } @if 1 < 2 { color: olive; } @else if 1 > 2 { color: red; }',
			{atRules: ['if', 'else']}
		);
	});

	it('it change multi properties for @each', () => {
		test(
			':root{ --array: foo, bar, baz; } @each $val in var(--array)',
			':root{ --array: foo, bar, baz; } @each $val in foo, bar, baz',
			{atRules: ['each']}
		);
	});
});
<commit_msg>Fixed #11, add test if not enter params<commit_after>/* global describe it */
import postcss from 'postcss';
import {expect} from 'chai';
import plugin from '../lib/index';
const test = (input, output, opts) => {
	expect(postcss([plugin(opts)]).process(input).css).to.eql(output);
};

describe('postcss-at-rules-variables', () => {
	it('it change first properties for @for', () => {
		test(
			':root{ --from: 1; } @for $i from var(--from) to 2',
			':root{ --from: 1; } @for $i from 1 to 2'
		);
	});

	it('it change second properties for @for', () => {
		test(
			':root{ --to: 2; } @for $i from 1 to var(--to)',
			':root{ --to: 2; } @for $i from 1 to 2'
		);
	});

	it('it change two properties for @for', () => {
		test(
			':root{ --from: 1; --to: 2; } @for $i from var(--from) to var(--to)',
			':root{ --from: 1; --to: 2; } @for $i from 1 to 2'
		);
	});

	it('it change three properties for @for', () => {
		test(
			':root{ --from: 1; --to: 2; --step: 5 } @for $i from var(--from) to var(--to) by var(--step)',
			':root{ --from: 1; --to: 2; --step: 5 } @for $i from 1 to 2 by 5'
		);
	});

	it('it change two properties for @if', () => {
		test(
			':root{ --first: 1; --second: 2; } @if var(--first) < var(--second)',
			':root{ --first: 1; --second: 2; } @if 1 < 2',
			{atRules: ['if']}
		);
	});

	it('it change two properties for @if, @else if', () => {
		test(
			':root{ --first: 1; --second: 2; } @if var(--first) < var(--second) { color: olive; } @else if var(--first) > var(--second) { color: red; }',
			':root{ --first: 1; --second: 2; } @if 1 < 2 { color: olive; } @else if 1 > 2 { color: red; }',
			{atRules: ['if', 'else']}
		);
	});

	it('it change multi properties for @each', () => {
		test(
			':root{ --array: foo, bar, baz; } @each $val in var(--array)',
			':root{ --array: foo, bar, baz; } @each $val in foo, bar, baz',
			{atRules: ['each']}
		);
	});

	it('it not enter params', () => {
		test(
			':root{ --red: red; } @if var(--green) { color: var(--green) }',
			':root{ --red: red; } @if var(--green) { color: var(--green) }'
		);
	});
});
<|endoftext|>