<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 */

var Editor = function () {

	var SIGNALS = signals;

	this.signals = {

		// script

		editScript: new SIGNALS.Signal(),

		// player

		startPlayer: new SIGNALS.Signal(),
		stopPlayer: new SIGNALS.Signal(),

		// actions

		// showDialog: new SIGNALS.Signal(),

		// notifications

		editorCleared: new SIGNALS.Signal(),

		savingStarted: new SIGNALS.Signal(),
		savingFinished: new SIGNALS.Signal(),

		themeChanged: new SIGNALS.Signal(),

		transformModeChanged: new SIGNALS.Signal(),
		snapChanged: new SIGNALS.Signal(),
		spaceChanged: new SIGNALS.Signal(),
		rendererChanged: new SIGNALS.Signal(),

		sceneGraphChanged: new SIGNALS.Signal(),

		cameraChanged: new SIGNALS.Signal(),

		geometryChanged: new SIGNALS.Signal(),

		objectSelected: new SIGNALS.Signal(),
		objectFocused: new SIGNALS.Signal(),

		objectAdded: new SIGNALS.Signal(),
		objectChanged: new SIGNALS.Signal(),
		objectRemoved: new SIGNALS.Signal(),

		helperAdded: new SIGNALS.Signal(),
		helperRemoved: new SIGNALS.Signal(),

		materialChanged: new SIGNALS.Signal(),

		scriptAdded: new SIGNALS.Signal(),
		scriptChanged: new SIGNALS.Signal(),
		scriptRemoved: new SIGNALS.Signal(),

		fogTypeChanged: new SIGNALS.Signal(),
		fogColorChanged: new SIGNALS.Signal(),
		fogParametersChanged: new SIGNALS.Signal(),
		windowResize: new SIGNALS.Signal(),

		showGridChanged: new SIGNALS.Signal()

	};

	this.config = new Config();
	this.history = new History( this );
	this.storage = new Storage();
	this.loader = new Loader( this );

	this.camera = new THREE.PerspectiveCamera( 50, 1, 1, 100000 );
	this.camera.position.set( 500, 250, 500 );
	this.camera.lookAt( new THREE.Vector3() );
	this.camera.name = 'Camera';

	this.scene = new THREE.Scene();
	this.scene.name = 'Scene';

	this.sceneHelpers = new THREE.Scene();

	this.object = {};
	this.geometries = {};
	this.materials = {};
	this.textures = {};
	this.scripts = {};

	this.selected = null;
	this.helpers = {};

};

Editor.prototype = {

	setTheme: function ( value ) {

		document.getElementById( 'theme' ).href = value;

		this.signals.themeChanged.dispatch( value );

	},

	/*
	showDialog: function ( value ) {

		this.signals.showDialog.dispatch( value );

	},
	*/

	//

	setScene: function ( scene ) {

		this.scene.uuid = scene.uuid;
		this.scene.name = scene.name;
		this.scene.userData = JSON.parse( JSON.stringify( scene.userData ) );

		// avoid render per object

		this.signals.sceneGraphChanged.active = false;

		while ( scene.children.length > 0 ) {

			this.addObject( scene.children[ 0 ] );

		}

		this.signals.sceneGraphChanged.active = true;
		this.signals.sceneGraphChanged.dispatch();

	},

	//

	addObject: function ( object ) {

		var scope = this;

		object.traverse( function ( child ) {

			if ( child.geometry !== undefined ) scope.addGeometry( child.geometry );
			if ( child.material !== undefined ) scope.addMaterial( child.material );

			scope.addHelper( child );

		} );

		this.scene.add( object );

		this.signals.objectAdded.dispatch( object );
		this.signals.sceneGraphChanged.dispatch();

	},

	moveObject: function ( object, parent, before ) {

		if ( parent === undefined ) {

			parent = this.scene;

		}

		parent.add( object );

		// sort children array

		if ( before !== undefined ) {

			var index = parent.children.indexOf( before );
			parent.children.splice( index, 0, object );
			parent.children.pop();

		}

		this.signals.sceneGraphChanged.dispatch();

	},

	nameObject: function ( object, name ) {

		object.name = name;
		this.signals.sceneGraphChanged.dispatch();

	},

	removeObject: function ( object ) {

		if ( object.parent === null ) return; // avoid deleting the camera or scene

		var scope = this;

		object.traverse( function ( child ) {

			scope.removeHelper( child );

		} );

		object.parent.remove( object );

		this.signals.objectRemoved.dispatch( object );
		this.signals.sceneGraphChanged.dispatch();

	},

	addGeometry: function ( geometry ) {

		this.geometries[ geometry.uuid ] = geometry;

	},

	setGeometryName: function ( geometry, name ) {

		geometry.name = name;
		this.signals.sceneGraphChanged.dispatch();

	},

	addMaterial: function ( material ) {

		this.materials[ material.uuid ] = material;

	},

	setMaterialName: function ( material, name ) {

		material.name = name;
		this.signals.sceneGraphChanged.dispatch();

	},

	addTexture: function ( texture ) {

		this.textures[ texture.uuid ] = texture;

	},

	//

	addHelper: function () {

		var geometry = new THREE.SphereGeometry( 20, 4, 2 );
		var material = new THREE.MeshBasicMaterial( { color: 0xff0000, visible: false } );

		return function ( object ) {

			var helper;

			if ( object instanceof THREE.Camera ) {

				helper = new THREE.CameraHelper( object, 10 );

			} else if ( object instanceof THREE.PointLight ) {

				helper = new THREE.PointLightHelper( object, 10 );

			} else if ( object instanceof THREE.DirectionalLight ) {

				helper = new THREE.DirectionalLightHelper( object, 20 );

			} else if ( object instanceof THREE.SpotLight ) {

				helper = new THREE.SpotLightHelper( object, 10 );

			} else if ( object instanceof THREE.HemisphereLight ) {

				helper = new THREE.HemisphereLightHelper( object, 10 );

			} else if ( object instanceof THREE.SkinnedMesh ) {

				helper = new THREE.SkeletonHelper( object );

			} else {

				// no helper for this object type
				return;

			}

			var picker = new THREE.Mesh( geometry, material );
			picker.name = 'picker';
			picker.userData.object = object;
			helper.add( picker );

			this.sceneHelpers.add( helper );
			this.helpers[ object.id ] = helper;

			this.signals.helperAdded.dispatch( helper );

		};

	}(),

	removeHelper: function ( object ) {

		if ( this.helpers[ object.id ] !== undefined ) {

			var helper = this.helpers[ object.id ];
			helper.parent.remove( helper );

			delete this.helpers[ object.id ];

			this.signals.helperRemoved.dispatch( helper );

		}

	},

	//

	addScript: function ( object, script ) {

		if ( this.scripts[ object.uuid ] === undefined ) {

			this.scripts[ object.uuid ] = [];

		}

		this.scripts[ object.uuid ].push( script );

		this.signals.scriptAdded.dispatch( script );

	},

	removeScript: function ( object, script ) {

		if ( this.scripts[ object.uuid ] === undefined ) return;

		var index = this.scripts[ object.uuid ].indexOf( script );

		if ( index !== - 1 ) {

			this.scripts[ object.uuid ].splice( index, 1 );

		}

		this.signals.scriptRemoved.dispatch( script );

	},

	//

	select: function ( object ) {

		if ( this.selected === object ) return;

		var uuid = null;

		if ( object !== null ) {

			uuid = object.uuid;

		}

		this.selected = object;

		this.config.setKey( 'selected', uuid );
		this.signals.objectSelected.dispatch( object );

	},

	selectById: function ( id ) {

		if ( id === this.camera.id ) {

			this.select( this.camera );
			return;

		}

		this.select( this.scene.getObjectById( id, true ) );

	},

	selectByUuid: function ( uuid ) {

		var scope = this;

		this.scene.traverse( function ( child ) {

			if ( child.uuid === uuid ) {

				scope.select( child );

			}

		} );

	},

	deselect: function () {

		this.select( null );

	},

	focus: function ( object ) {

		this.signals.objectFocused.dispatch( object );

	},

	focusById: function ( id ) {

		this.focus( this.scene.getObjectById( id, true ) );

	},

	clear: function () {

		this.history.clear();

		this.camera.position.set( 500, 250, 500 );
		this.camera.lookAt( new THREE.Vector3() );

		var objects = this.scene.children;

		while ( objects.length > 0 ) {

			this.removeObject( objects[ 0 ] );

		}

		this.geometries = {};
		this.materials = {};
		this.textures = {};
		this.scripts = {};

		this.deselect();

		this.signals.editorCleared.dispatch();

	},

	//

	fromJSON: function ( json ) {

		var loader = new THREE.ObjectLoader();

		// backwards

		if ( json.scene === undefined ) {

			this.setScene( loader.parse( json ) );
			return;

		}

		// TODO: Clean this up somehow

		var camera = loader.parse( json.camera );

		this.camera.position.copy( camera.position );
		this.camera.rotation.copy( camera.rotation );
		this.camera.aspect = camera.aspect;
		this.camera.near = camera.near;
		this.camera.far = camera.far;

		this.setScene( loader.parse( json.scene ) );
		this.scripts = json.scripts;

	},

	toJSON: function () {

		return {

			project: {
				vr: this.config.getKey( 'project/vr' )
			},
			camera: this.camera.toJSON(),
			scene: this.scene.toJSON(),
			scripts: this.scripts

		};

	}

}
<commit_msg>Editor: Using BufferGeometry for pickers.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 */

var Editor = function () {

	var SIGNALS = signals;

	this.signals = {

		// script

		editScript: new SIGNALS.Signal(),

		// player

		startPlayer: new SIGNALS.Signal(),
		stopPlayer: new SIGNALS.Signal(),

		// actions

		// showDialog: new SIGNALS.Signal(),

		// notifications

		editorCleared: new SIGNALS.Signal(),

		savingStarted: new SIGNALS.Signal(),
		savingFinished: new SIGNALS.Signal(),

		themeChanged: new SIGNALS.Signal(),

		transformModeChanged: new SIGNALS.Signal(),
		snapChanged: new SIGNALS.Signal(),
		spaceChanged: new SIGNALS.Signal(),
		rendererChanged: new SIGNALS.Signal(),

		sceneGraphChanged: new SIGNALS.Signal(),

		cameraChanged: new SIGNALS.Signal(),

		geometryChanged: new SIGNALS.Signal(),

		objectSelected: new SIGNALS.Signal(),
		objectFocused: new SIGNALS.Signal(),

		objectAdded: new SIGNALS.Signal(),
		objectChanged: new SIGNALS.Signal(),
		objectRemoved: new SIGNALS.Signal(),

		helperAdded: new SIGNALS.Signal(),
		helperRemoved: new SIGNALS.Signal(),

		materialChanged: new SIGNALS.Signal(),

		scriptAdded: new SIGNALS.Signal(),
		scriptChanged: new SIGNALS.Signal(),
		scriptRemoved: new SIGNALS.Signal(),

		fogTypeChanged: new SIGNALS.Signal(),
		fogColorChanged: new SIGNALS.Signal(),
		fogParametersChanged: new SIGNALS.Signal(),
		windowResize: new SIGNALS.Signal(),

		showGridChanged: new SIGNALS.Signal()

	};

	this.config = new Config();
	this.history = new History( this );
	this.storage = new Storage();
	this.loader = new Loader( this );

	this.camera = new THREE.PerspectiveCamera( 50, 1, 1, 100000 );
	this.camera.position.set( 500, 250, 500 );
	this.camera.lookAt( new THREE.Vector3() );
	this.camera.name = 'Camera';

	this.scene = new THREE.Scene();
	this.scene.name = 'Scene';

	this.sceneHelpers = new THREE.Scene();

	this.object = {};
	this.geometries = {};
	this.materials = {};
	this.textures = {};
	this.scripts = {};

	this.selected = null;
	this.helpers = {};

};

Editor.prototype = {

	setTheme: function ( value ) {

		document.getElementById( 'theme' ).href = value;

		this.signals.themeChanged.dispatch( value );

	},

	/*
	showDialog: function ( value ) {

		this.signals.showDialog.dispatch( value );

	},
	*/

	//

	setScene: function ( scene ) {

		this.scene.uuid = scene.uuid;
		this.scene.name = scene.name;
		this.scene.userData = JSON.parse( JSON.stringify( scene.userData ) );

		// avoid render per object

		this.signals.sceneGraphChanged.active = false;

		while ( scene.children.length > 0 ) {

			this.addObject( scene.children[ 0 ] );

		}

		this.signals.sceneGraphChanged.active = true;
		this.signals.sceneGraphChanged.dispatch();

	},

	//

	addObject: function ( object ) {

		var scope = this;

		object.traverse( function ( child ) {

			if ( child.geometry !== undefined ) scope.addGeometry( child.geometry );
			if ( child.material !== undefined ) scope.addMaterial( child.material );

			scope.addHelper( child );

		} );

		this.scene.add( object );

		this.signals.objectAdded.dispatch( object );
		this.signals.sceneGraphChanged.dispatch();

	},

	moveObject: function ( object, parent, before ) {

		if ( parent === undefined ) {

			parent = this.scene;

		}

		parent.add( object );

		// sort children array

		if ( before !== undefined ) {

			var index = parent.children.indexOf( before );
			parent.children.splice( index, 0, object );
			parent.children.pop();

		}

		this.signals.sceneGraphChanged.dispatch();

	},

	nameObject: function ( object, name ) {

		object.name = name;
		this.signals.sceneGraphChanged.dispatch();

	},

	removeObject: function ( object ) {

		if ( object.parent === null ) return; // avoid deleting the camera or scene

		var scope = this;

		object.traverse( function ( child ) {

			scope.removeHelper( child );

		} );

		object.parent.remove( object );

		this.signals.objectRemoved.dispatch( object );
		this.signals.sceneGraphChanged.dispatch();

	},

	addGeometry: function ( geometry ) {

		this.geometries[ geometry.uuid ] = geometry;

	},

	setGeometryName: function ( geometry, name ) {

		geometry.name = name;
		this.signals.sceneGraphChanged.dispatch();

	},

	addMaterial: function ( material ) {

		this.materials[ material.uuid ] = material;

	},

	setMaterialName: function ( material, name ) {

		material.name = name;
		this.signals.sceneGraphChanged.dispatch();

	},

	addTexture: function ( texture ) {

		this.textures[ texture.uuid ] = texture;

	},

	//

	addHelper: function () {

		var geometry = new THREE.SphereBufferGeometry( 20, 4, 2 );
		var material = new THREE.MeshBasicMaterial( { color: 0xff0000, visible: false } );

		return function ( object ) {

			var helper;

			if ( object instanceof THREE.Camera ) {

				helper = new THREE.CameraHelper( object, 10 );

			} else if ( object instanceof THREE.PointLight ) {

				helper = new THREE.PointLightHelper( object, 10 );

			} else if ( object instanceof THREE.DirectionalLight ) {

				helper = new THREE.DirectionalLightHelper( object, 20 );

			} else if ( object instanceof THREE.SpotLight ) {

				helper = new THREE.SpotLightHelper( object, 10 );

			} else if ( object instanceof THREE.HemisphereLight ) {

				helper = new THREE.HemisphereLightHelper( object, 10 );

			} else if ( object instanceof THREE.SkinnedMesh ) {

				helper = new THREE.SkeletonHelper( object );

			} else {

				// no helper for this object type
				return;

			}

			var picker = new THREE.Mesh( geometry, material );
			picker.name = 'picker';
			picker.userData.object = object;
			helper.add( picker );

			this.sceneHelpers.add( helper );
			this.helpers[ object.id ] = helper;

			this.signals.helperAdded.dispatch( helper );

		};

	}(),

	removeHelper: function ( object ) {

		if ( this.helpers[ object.id ] !== undefined ) {

			var helper = this.helpers[ object.id ];
			helper.parent.remove( helper );

			delete this.helpers[ object.id ];

			this.signals.helperRemoved.dispatch( helper );

		}

	},

	//

	addScript: function ( object, script ) {

		if ( this.scripts[ object.uuid ] === undefined ) {

			this.scripts[ object.uuid ] = [];

		}

		this.scripts[ object.uuid ].push( script );

		this.signals.scriptAdded.dispatch( script );

	},

	removeScript: function ( object, script ) {

		if ( this.scripts[ object.uuid ] === undefined ) return;

		var index = this.scripts[ object.uuid ].indexOf( script );

		if ( index !== - 1 ) {

			this.scripts[ object.uuid ].splice( index, 1 );

		}

		this.signals.scriptRemoved.dispatch( script );

	},

	//

	select: function ( object ) {

		if ( this.selected === object ) return;

		var uuid = null;

		if ( object !== null ) {

			uuid = object.uuid;

		}

		this.selected = object;

		this.config.setKey( 'selected', uuid );
		this.signals.objectSelected.dispatch( object );

	},

	selectById: function ( id ) {

		if ( id === this.camera.id ) {

			this.select( this.camera );
			return;

		}

		this.select( this.scene.getObjectById( id, true ) );

	},

	selectByUuid: function ( uuid ) {

		var scope = this;

		this.scene.traverse( function ( child ) {

			if ( child.uuid === uuid ) {

				scope.select( child );

			}

		} );

	},

	deselect: function () {

		this.select( null );

	},

	focus: function ( object ) {

		this.signals.objectFocused.dispatch( object );

	},

	focusById: function ( id ) {

		this.focus( this.scene.getObjectById( id, true ) );

	},

	clear: function () {

		this.history.clear();

		this.camera.position.set( 500, 250, 500 );
		this.camera.lookAt( new THREE.Vector3() );

		var objects = this.scene.children;

		while ( objects.length > 0 ) {

			this.removeObject( objects[ 0 ] );

		}

		this.geometries = {};
		this.materials = {};
		this.textures = {};
		this.scripts = {};

		this.deselect();

		this.signals.editorCleared.dispatch();

	},

	//

	fromJSON: function ( json ) {

		var loader = new THREE.ObjectLoader();

		// backwards

		if ( json.scene === undefined ) {

			this.setScene( loader.parse( json ) );
			return;

		}

		// TODO: Clean this up somehow

		var camera = loader.parse( json.camera );

		this.camera.position.copy( camera.position );
		this.camera.rotation.copy( camera.rotation );
		this.camera.aspect = camera.aspect;
		this.camera.near = camera.near;
		this.camera.far = camera.far;

		this.setScene( loader.parse( json.scene ) );
		this.scripts = json.scripts;

	},

	toJSON: function () {

		return {

			project: {
				vr: this.config.getKey( 'project/vr' )
			},
			camera: this.camera.toJSON(),
			scene: this.scene.toJSON(),
			scripts: this.scripts

		};

	}

}
<|endoftext|>


<commit_before>'use strict';
require('dotenv').config();
/*
Hey, welcome to the changeset config! This file has been generated
for you with the default configs we use, and some comments around
what options mean, so that it's easy to customise your workflow.

You should update this as you need to craft your workflow.

Config provided by a CI command takes precedence over the contents of this file.

If a config option isn't present here, we will fall back to the defaults.
*/

const changesetOptions = {
  // If true, we will automatically commit the changeset when the command is run
  commit: false,
};

// This function takes information about a changeset to generate an entry for it in your
// changelog. We provide the full changeset object as well as the version.
// It may be a good idea to replace the commit hash with a link to the commit.

/* the default shape is:
- [patch] ABCDEFG:

  A summary message you wrote, indented
*/

function makeQuery(commitShas) {
  return `
    query {
      ${commitShas.map((commitSha, i) => {
        return `a${i}: search(
          type: ISSUE
          query: "sha:${commitSha}+repo:JedWatson/react-select"
          first: 1
        ) {
          edges {
            node {
              ... on PullRequest {
                number
                author {
                  login
                }
              }
            }
          }
        }}`;
      })}
  `;
}

const fetch = require('node-fetch');
const DataLoader = require('dataloader');

const GHDataLoader = new DataLoader(async commitShas => {
  if (!process.env.GITHUB_TOKEN) {
    throw new Error(
      'Please create a GitHub personal access token at https://github.com/settings/tokens/new and add it to a .env file in the root of the repository'
    );
  }
  let data = await fetch(
    `https://api.github.com/graphql?access_token=${process.env.GITHUB_TOKEN}`,
    {
      method: 'POST',
      body: JSON.stringify({ query: makeQuery(commitShas) }),
    }
  ).then(x => x.json());

  // this is mainly for the case where there's an authentication problem
  if (!data.data || !data.data.search || !data.data.search.edges) {
    throw new Error(
      'An error occurred when fetching data from GitHub\n' +
        JSON.stringify(data)
    );
  }
  return data.data.search.edges.map(edge => {
    if (
      edge.node &&
      typeof edge.node.number === 'number' &&
      edge.node.author &&
      typeof node.author.login === 'string'
    ) {
      return { username: edge.node.author.login, number: edge.node.number };
    }
    return null;
  });
});

async function fetchGHData(commitShas) {}

const getReleaseLine = async (changeset, versionType) => {
  const indentedSummary = changeset.summary
    .split('\n')
    .map(l => `  ${l}`.trimRight())
    .join('\n');
  let data = await GHDataLoader.load(changeset.commit);
  if (data !== null) {
    let { number, username } = data;
    return `- [${versionType}] ${
      changeset.commit
    } [#${number}](https://github.com/JedWatson/react-select/pulls/${number}) Thanks [@${username}](https://github.com/${username}):\n\n${indentedSummary}`;
  }
  return `- [${versionType}] ${changeset.commit}:\n\n${indentedSummary}`;
};

// This function takes information about what dependencies we are updating in the package.
// It provides an array of related changesets, as well as the dependencies updated.

/*
- Updated dependencies: [ABCDEFG]:
- Updated dependencies: [HIJKLMN]:
  - dependencyA@1.0.1
  - dependencyb@1.2.0
*/
const getDependencyReleaseLine = async (changesets, dependenciesUpdated) => {
  if (dependenciesUpdated.length === 0) return '';

  const changesetLinks = changesets.map(
    changeset => `- Updated dependencies [${changeset.commit}]:`
  );

  const updatedDepenenciesList = dependenciesUpdated.map(
    dependency => `  - ${dependency.name}@${dependency.version}`
  );

  return [...changesetLinks, ...updatedDepenenciesList].join('\n');
};

const versionOptions = {
  // If true, we will automatically commit the version updating when the command is run
  commit: false,
  // Adds a skipCI flag to the commit - only valid if `commit` is also true.
  skipCI: false,
  // Do not modify the `changelog.md` files for packages that are updated
  noChangelog: false,
  // A function that returns a string. It takes in options about a change. This allows you to customise your changelog entries
  getReleaseLine,
  // A function that returns a string. It takes in options about when a pacakge is updated because
  getDependencyReleaseLine,
};

const publishOptions = {
  // This sets whether unpublished packages are public by default. We err on the side of caution here.
  public: true,
};

module.exports = {
  versionOptions,
  changesetOptions,
  publishOptions,
};
<commit_msg>Fix some bugs in the GH data fetching<commit_after>'use strict';
require('dotenv').config();
/*
Hey, welcome to the changeset config! This file has been generated
for you with the default configs we use, and some comments around
what options mean, so that it's easy to customise your workflow.

You should update this as you need to craft your workflow.

Config provided by a CI command takes precedence over the contents of this file.

If a config option isn't present here, we will fall back to the defaults.
*/

const changesetOptions = {
  // If true, we will automatically commit the changeset when the command is run
  commit: false,
};

// This function takes information about a changeset to generate an entry for it in your
// changelog. We provide the full changeset object as well as the version.
// It may be a good idea to replace the commit hash with a link to the commit.

/* the default shape is:
- [patch] ABCDEFG:

  A summary message you wrote, indented
*/

function makeQuery(commitShas) {
  return `
    query {
      ${commitShas
        .map(
          (commitSha, i) =>
            `a${i}: search(
          type: ISSUE
          query: "sha:${commitSha}+repo:JedWatson/react-select"
          first: 1
        ) {
          edges {
            node {
              ... on PullRequest {
                number
                author {
                  login
                }
              }
            }
          }
        }`
        )
        .join('\n')}}
  `;
}

const fetch = require('node-fetch');
const DataLoader = require('dataloader');

const GHDataLoader = new DataLoader(async commitShas => {
  if (!process.env.GITHUB_TOKEN) {
    throw new Error(
      'Please create a GitHub personal access token at https://github.com/settings/tokens/new and add it to a .env file in the root of the repository'
    );
  }
  let data = await fetch(
    `https://api.github.com/graphql?access_token=${process.env.GITHUB_TOKEN}`,
    {
      method: 'POST',
      body: JSON.stringify({ query: makeQuery(commitShas) }),
    }
  ).then(x => x.json());

  // this is mainly for the case where there's an authentication problem
  if (!data.data) {
    throw new Error(
      'An error occurred when fetching data from GitHub\n' +
        JSON.stringify(data)
    );
  }
  return Object.values(data.data).map(({ edges }) => {
    if (
      edges[0] &&
      edges[0].node &&
      typeof edges[0].node.number === 'number' &&
      edges[0].node.author &&
      typeof edges[0].node.author.login === 'string'
    ) {
      return {
        username: edges[0].node.author.login,
        number: edges[0].node.number,
      };
    }
    return null;
  });
});

async function fetchGHData(commitShas) {}

const getReleaseLine = async (changeset, versionType) => {
  const indentedSummary = changeset.summary
    .split('\n')
    .map(l => `  ${l}`.trimRight())
    .join('\n');
  let data = await GHDataLoader.load(changeset.commit);
  if (data !== null) {
    let { number, username } = data;
    return `- [${versionType}] ${
      changeset.commit
    } [#${number}](https://github.com/JedWatson/react-select/pulls/${number}) Thanks [@${username}](https://github.com/${username}):\n\n${indentedSummary}`;
  }
  return `- [${versionType}] ${changeset.commit}:\n\n${indentedSummary}`;
};

// This function takes information about what dependencies we are updating in the package.
// It provides an array of related changesets, as well as the dependencies updated.

/*
- Updated dependencies: [ABCDEFG]:
- Updated dependencies: [HIJKLMN]:
  - dependencyA@1.0.1
  - dependencyb@1.2.0
*/
const getDependencyReleaseLine = async (changesets, dependenciesUpdated) => {
  if (dependenciesUpdated.length === 0) return '';

  const changesetLinks = changesets.map(
    changeset => `- Updated dependencies [${changeset.commit}]:`
  );

  const updatedDepenenciesList = dependenciesUpdated.map(
    dependency => `  - ${dependency.name}@${dependency.version}`
  );

  return [...changesetLinks, ...updatedDepenenciesList].join('\n');
};

const versionOptions = {
  // If true, we will automatically commit the version updating when the command is run
  commit: false,
  // Adds a skipCI flag to the commit - only valid if `commit` is also true.
  skipCI: false,
  // Do not modify the `changelog.md` files for packages that are updated
  noChangelog: false,
  // A function that returns a string. It takes in options about a change. This allows you to customise your changelog entries
  getReleaseLine,
  // A function that returns a string. It takes in options about when a pacakge is updated because
  getDependencyReleaseLine,
};

const publishOptions = {
  // This sets whether unpublished packages are public by default. We err on the side of caution here.
  public: true,
};

module.exports = {
  versionOptions,
  changesetOptions,
  publishOptions,
};
<|endoftext|>


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

console.log('starting script');

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

  // header.classList.contains("bar-row")
  title() {
    // look for child td with class = barRow-contents
    // const td = header.getElementsByClassName('barRow-contents')
    const textareas = this.header.getElementsByClassName('task-row-text-input');
    if (textareas.length !== 1) {
      return null;
    }

    return textareas[0].value;
  }

// const wipLimit = header => {
//
// }
// const isOver = header => {
//    header
// }
}

// let header = new Header();
// console.log(header.title())

const markWholeDocument = () => {
  console.log('starting to mark whole document');
  const headers = document.getElementsByClassName('bar-row');
  console.log(headers);
  if (headers.length > 0) {
    const headerElement = headers[0];
    const header = new Header(headerElement);
    console.log(`title is ${header.title()}`);
  } else {
    console.log('no headers found');
  }
};

const watchChanges = () => {
  const divs = document.getElementsByClassName('item-list-groups');
  for (const div of divs) {
    // create an observer instance
    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        console.log(mutation.type);
      });
    });

    // configuration of the observer:
    const config = { attributes: true, childList: true, characterData: true };

    // pass in the target node, as well as the observer options
    observer.observe(div, config);

    // later, you can stop observing
    // observer.disconnect();
  }
};

// watchChanges();

setInterval(() => {
  markWholeDocument();
}, 1000);

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

// // const textareas = header.getElementsByClassName('task-row-text-input');
// // let headerTitle = textareas[0].value;
// // let wipFinder = /.*\[(\d*)\]:$/;
// // let results = wipFinder.exec(headerTitle);
// // wipLimit = parseInt(results[1])
<commit_msg>Add a log message<commit_after>// ==UserScript==
// @name WIP Limiter
// @namespace http://github.com/apiology/
// @description Add Kanban-style visual WIP limit indicators
// @match https://app.asana.com/*
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==

console.log('starting script');

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

  // header.classList.contains("bar-row")
  title() {
    // look for child td with class = barRow-contents
    // const td = header.getElementsByClassName('barRow-contents')
    const textareas = this.header.getElementsByClassName('task-row-text-input');
    if (textareas.length !== 1) {
      return null;
    }

    return textareas[0].value;
  }

// const wipLimit = header => {
//
// }
// const isOver = header => {
//    header
// }
}

// let header = new Header();
// console.log(header.title())

const markWholeDocument = () => {
  console.log('starting to mark whole document');
  const headers = document.getElementsByClassName('bar-row');
  console.log(headers);
  if (headers.length > 0) {
    const headerElement = headers[0];
    const header = new Header(headerElement);
    console.log(`title is ${header.title()}`);
  } else {
    console.log('no headers found');
  }
};

const watchChanges = () => {
  const divs = document.getElementsByClassName('item-list-groups');
  for (const div of divs) {
    // create an observer instance
    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        console.log(mutation.type);
      });
    });

    // configuration of the observer:
    const config = { attributes: true, childList: true, characterData: true };

    // pass in the target node, as well as the observer options
    observer.observe(div, config);

    // later, you can stop observing
    // observer.disconnect();
  }
};

// watchChanges();

setInterval(markWholeDocument(), 1000);
console.log('setInterval run');

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

// // const textareas = header.getElementsByClassName('task-row-text-input');
// // let headerTitle = textareas[0].value;
// // let wipFinder = /.*\[(\d*)\]:$/;
// // let results = wipFinder.exec(headerTitle);
// // wipLimit = parseInt(results[1])
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var mkdirp = require('mkdirp');
var path = require('path');
var assert = require('assert');
var cp = require('child_process');

// Sets directory to output coverage data to
// Incremented every time getRunner() is called.
var covCount = 1;
var isIstanbul = process.env.running_under_istanbul;

/**
 * Gets an array containing the routine to run the jade CLI. If this file is
 * being processed with istanbul then this function will return a routine
 * asking istanbul to store coverage data to a unique directory
 * (cov-pt<covCount>/).
 */
function getRunner() {
  var jadeExe = __dirname + '/../bin/jade.js';

  if (!isIstanbul) return ['node', jadeExe];
  else {
    return ['istanbul', 'cover',
            '--print',  'none',
            '--report', 'none',
            '--root',   process.cwd(),
            '--dir',    process.cwd() + '/cov-pt' + (covCount++),
            jadeExe,
            '--'];
  }
}

function run(args, stdin, callback) {
  if (arguments.length === 2) {
    callback = stdin;
    stdin    = null;
  }
  var runner = getRunner().join(' ');
  cp.exec((stdin || '') + runner + ' ' + args, {
    cwd: __dirname + '/temp'
  }, callback);
}

mkdirp.sync(__dirname + '/temp/inputs/level-1-1');
mkdirp.sync(__dirname + '/temp/inputs/level-1-2');
mkdirp.sync(__dirname + '/temp/outputs');

describe('command line with HTML output', function () {
  if (isIstanbul) {
    this.timeout(8000);
    this.slow(6000);
  } else {
    this.slow(250);
  }
  it('jade --no-debug input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.html', '
output not written
');
    run('--no-debug input.jade', function (err) {
      if (err) return done(err);
      var html = fs.readFileSync(__dirname + '/temp/input.html', 'utf8');
      assert(html === '
bar
');
      done();
    });
  });
  it('jade --no-debug -E special-html input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.special-html', '
output not written
');
    run('--no-debug -E special-html input.jade', function (err) {
      if (err) return done(err);
      var html = fs.readFileSync(__dirname + '/temp/input.special-html', 'utf8');
      assert(html === '
bar
');
      done();
    });
  });
  it('jade --no-debug --obj "{\'loc\':\'str\'}" input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo= loc');
    fs.writeFileSync(__dirname + '/temp/input.html', '
output not written
');
    run('--no-debug --obj "{\'loc\':\'str\'}" input.jade', function (err) {
      if (err) return done(err);
      var html = fs.readFileSync(__dirname + '/temp/input.html', 'utf8');
      assert(html === '
str
');
      done();
    });
  });
  it('cat input.jade | jade --no-debug', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    run('--no-debug', 'cat input.jade | ', function (err, stdout, stderr) {
      if (err) return done(err);
      assert(stdout === '
bar
');
      done();
    });
  });
  it('jade --no-debug --out outputs input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.html', '
output not written
');
    run('--no-debug --out outputs input.jade', function (err) {
      if (err) return done(err);
      var html = fs.readFileSync(__dirname + '/temp/outputs/input.html', 'utf8');
      assert(html === '
bar
');
      done();
    });
  });
  context('when input is directory', function () {
    it('jade --no-debug --out outputs inputs', function (done) {
      fs.writeFileSync(__dirname + '/temp/inputs/input.jade', '.foo bar 1');
      fs.writeFileSync(__dirname + '/temp/inputs/level-1-1/input.jade', '.foo bar 1-1');
      fs.writeFileSync(__dirname + '/temp/inputs/level-1-2/input.jade', '.foo bar 1-2');
      fs.writeFileSync(__dirname + '/temp/outputs/input.html', 'BIG FAT HEN 1');
      fs.writeFileSync(__dirname + '/temp/outputs/level-1-1/input.html', 'BIG FAT HEN 1-1');
      fs.writeFileSync(__dirname + '/temp/outputs/level-1-2/input.html', 'BIG FAT HEN 1-2');
      run('--no-debug --out outputs inputs', function (err) {
        if (err) return done(err);
        var html = fs.readFileSync(__dirname + '/temp/outputs/input.html', 'utf8');
        assert(html === '
bar 1
');
        var html = fs.readFileSync(__dirname + '/temp/outputs/level-1-1/input.html', 'utf8');
        assert(html === '
bar 1-1
');
        var html = fs.readFileSync(__dirname + '/temp/outputs/level-1-2/input.html', 'utf8');
        assert(html === '
bar 1-2
');
        done();
      });
    });
  });
});

describe('command line with client JS output', function () {
  if (isIstanbul) {
    this.timeout(8000);
    this.slow(6000);
  } else {
    this.slow(250);
  }
  it('jade --no-debug --client --name myTemplate input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.js', 'throw new Error("output not written");');
    run('--no-debug --client --name myTemplate input.jade', function (err) {
      if (err) return done(err);
      var template = Function('', fs.readFileSync(__dirname + '/temp/input.js', 'utf8') + ';return myTemplate;')();
      assert(template() === '
bar
');
      done();
    });
  });
  it('jade --no-debug --client -E special-js --name myTemplate input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.special-js', 'throw new Error("output not written");');
    run('--no-debug --client -E special-js --name myTemplate input.jade', function (err) {
      if (err) return done(err);
      var template = Function('', fs.readFileSync(__dirname + '/temp/input.special-js', 'utf8') + ';return myTemplate;')();
      assert(template() === '
bar
');
      done();
    });
  });
  it('cat input.jade | jade --no-debug --client --name myTemplate', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.js', 'throw new Error("output not written");');
    run('--no-debug --client --name myTemplate', 'cat input.jade | ', function (err, stdout) {
      if (err) return done(err);
      var template = Function('', stdout + ';return myTemplate;')();
      assert(template() === '
bar
');
      done();
    });
  });
  it('jade --no-debug --client --name-after-file input-file.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input-file.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input-file.js', 'throw new Error("output not written");');
    run('--no-debug --client --name-after-file input-file.jade', function (err, stdout, stderr) {
      if (err) return done(err);
      var template = Function('', fs.readFileSync(__dirname + '/temp/input-file.js', 'utf8') + ';return inputFileTemplate;')();
      assert(template() === '
bar
');
      return done();
    });
  });
  it('jade --no-debug --client --name-after-file _InPuTwIthWEiRdNaMME.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/_InPuTwIthWEiRdNaMME.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/_InPuTwIthWEiRdNaMME.js', 'throw new Error("output not written");');
    run('--no-debug --client --name-after-file _InPuTwIthWEiRdNaMME.jade', function (err, stdout, stderr) {
      if (err) return done(err);
      var template = Function('', fs.readFileSync(__dirname + '/temp/_InPuTwIthWEiRdNaMME.js', 'utf8') + ';return InputwithweirdnammeTemplate;')();
      assert(template() === '
bar
');
      return done();
    });
  });
});

describe('command line watch mode', function () {
  var watchProc;
  var stdout = '';
  after(function() {
    // Just to be sure
    watchProc.stderr.removeAllListeners('data');
    watchProc.stdout.removeAllListeners('data');
    watchProc.removeAllListeners('error');
    watchProc.removeAllListeners('close');

    watchProc.kill('SIGINT');
  });
  afterEach(function (done) {
    // jade --watch can only detect changes that are at least 1 second apart
    setTimeout(done, 1000);
  });
  it('jade --no-debug --client --name-after-file --watch input-file.jade (pass 1)', function (done) {
    if (isIstanbul) {
      this.timeout(8000);
      this.slow(6000);
    } else {
      this.slow(300);
    }
    fs.writeFileSync(__dirname + '/temp/input-file.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input-file.js', 'throw new Error("output not written (pass 1)");');
    var cmd = getRunner();
    cmd.push.apply(cmd,
      ['--no-debug', '--client', '--name-after-file', '--watch', 'input-file.jade']);
    watchProc = cp.spawn(cmd[0], cmd.slice(1),  {
      cwd: __dirname + '/temp'
    });

    watchProc.stdout.setEncoding('utf8');
    watchProc.stderr.setEncoding('utf8');
    watchProc
      .on('error', done)
      .stdout.on('data', function(buf) {
        stdout += buf;
        if (/.*rendered.*/.test(stdout)) {
          stdout = '';
          var template = Function('', fs.readFileSync(__dirname + '/temp/input-file.js', 'utf8') + ';return inputFileTemplate;')();
          assert(template() === '
bar
');

          watchProc.stdout.removeAllListeners('data');
          watchProc.removeAllListeners('error');
          return done();
        }
      });
  });
  it('jade --no-debug --client --name-after-file --watch input-file.jade (pass 2)', function (done) {
    // Just to be sure
    watchProc.stdout.removeAllListeners('data');
    watchProc.removeAllListeners('error');

    fs.writeFileSync(__dirname + '/temp/input-file.js', 'throw new Error("output not written (pass 2)");');
    fs.writeFileSync(__dirname + '/temp/input-file.jade', '.foo baz');

    watchProc
      .on('error', done)
      .stdout.on('data', function(buf) {
        stdout += buf;
        if (/.*rendered.*/.test(stdout)) {
          stdout = '';
          var template = Function('', fs.readFileSync(__dirname + '/temp/input-file.js', 'utf8') + ';return inputFileTemplate;')();
          assert(template() === '
baz
');

          watchProc.stdout.removeAllListeners('data');
          watchProc.removeAllListeners('error');
          return done();
        }
      });
  });
  it('jade --no-debug --client --name-after-file --watch input-file.jade (intentional errors in the jade file)', function (done) {
    // Just to be sure
    watchProc.stdout.removeAllListeners('data');
    watchProc.removeAllListeners('error');

    var stderr = '';
    var errored = false;
    watchProc
      .on('error', done)
      .on('close', function() {
        errored = true;
        return done(new Error('Jade should not terminate in watch mode'));
      })
      .stdout.on('data', function(buf) {
        stdout += buf;
        if (/.*rendered.*/.test(stdout)) {
          stdout = '';
          return done(new Error('Jade compiles an erroneous file w/o error'));
        }
      })
    watchProc
      .stderr.on('data', function(buf) {
        stderr += buf;
        if (!/.*Invalid indentation.*/.test(stderr)) return;
        stderr = '';
        var template = Function('', fs.readFileSync(__dirname + '/temp/input-file.js', 'utf8') + ';return inputFileTemplate;')();
        assert(template() === '
baz
');

        watchProc.stderr.removeAllListeners('data');
        watchProc.stdout.removeAllListeners('data');
        watchProc.removeAllListeners('error');
        watchProc.removeAllListeners('exit');
        // The stderr event will always fire sooner than the close event.
        // Wait for it.
        setTimeout(function() {
          if (!errored) done();
        }, 100);
      });
    fs.writeFileSync(__dirname + '/temp/input-file.jade',
                     fs.readFileSync(__dirname
                                     + '/anti-cases/tabs-and-spaces.jade'));
  });
});
<commit_msg>Fix command line tests<commit_after>'use strict';

var fs = require('fs');
var mkdirp = require('mkdirp');
var path = require('path');
var assert = require('assert');
var cp = require('child_process');

// Sets directory to output coverage data to
// Incremented every time getRunner() is called.
var covCount = 1;
var isIstanbul = process.env.running_under_istanbul;

/**
 * Gets an array containing the routine to run the jade CLI. If this file is
 * being processed with istanbul then this function will return a routine
 * asking istanbul to store coverage data to a unique directory
 * (cov-pt<covCount>/).
 */
function getRunner() {
  var jadeExe = __dirname + '/../bin/jade.js';

  if (!isIstanbul) return ['node', jadeExe];
  else {
    return ['istanbul', 'cover',
            '--print',  'none',
            '--report', 'none',
            '--root',   process.cwd(),
            '--dir',    process.cwd() + '/cov-pt' + (covCount++),
            jadeExe,
            '--'];
  }
}

function run(args, stdin, callback) {
  if (arguments.length === 2) {
    callback = stdin;
    stdin    = null;
  }
  var runner = getRunner().join(' ');
  cp.exec((stdin || '') + runner + ' ' + args, {
    cwd: __dirname + '/temp'
  }, callback);
}

mkdirp.sync(__dirname + '/temp/inputs/level-1-1');
mkdirp.sync(__dirname + '/temp/inputs/level-1-2');
mkdirp.sync(__dirname + '/temp/outputs/level-1-1');
mkdirp.sync(__dirname + '/temp/outputs/level-1-2');

describe('command line with HTML output', function () {
  if (isIstanbul) {
    this.timeout(8000);
    this.slow(6000);
  } else {
    this.slow(250);
  }
  it('jade --no-debug input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.html', '
output not written
');
    run('--no-debug input.jade', function (err) {
      if (err) return done(err);
      var html = fs.readFileSync(__dirname + '/temp/input.html', 'utf8');
      assert(html === '
bar
');
      done();
    });
  });
  it('jade --no-debug -E special-html input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.special-html', '
output not written
');
    run('--no-debug -E special-html input.jade', function (err) {
      if (err) return done(err);
      var html = fs.readFileSync(__dirname + '/temp/input.special-html', 'utf8');
      assert(html === '
bar
');
      done();
    });
  });
  it('jade --no-debug --obj "{\'loc\':\'str\'}" input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo= loc');
    fs.writeFileSync(__dirname + '/temp/input.html', '
output not written
');
    run('--no-debug --obj "{\'loc\':\'str\'}" input.jade', function (err) {
      if (err) return done(err);
      var html = fs.readFileSync(__dirname + '/temp/input.html', 'utf8');
      assert(html === '
str
');
      done();
    });
  });
  it('cat input.jade | jade --no-debug', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    run('--no-debug', 'cat input.jade | ', function (err, stdout, stderr) {
      if (err) return done(err);
      assert(stdout === '
bar
');
      done();
    });
  });
  it('jade --no-debug --out outputs input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.html', '
output not written
');
    run('--no-debug --out outputs input.jade', function (err) {
      if (err) return done(err);
      var html = fs.readFileSync(__dirname + '/temp/outputs/input.html', 'utf8');
      assert(html === '
bar
');
      done();
    });
  });
  context('when input is directory', function () {
    it('jade --no-debug --out outputs inputs', function (done) {
      fs.writeFileSync(__dirname + '/temp/inputs/input.jade', '.foo bar 1');
      fs.writeFileSync(__dirname + '/temp/inputs/level-1-1/input.jade', '.foo bar 1-1');
      fs.writeFileSync(__dirname + '/temp/inputs/level-1-2/input.jade', '.foo bar 1-2');
      fs.writeFileSync(__dirname + '/temp/outputs/input.html', 'BIG FAT HEN 1');
      fs.writeFileSync(__dirname + '/temp/outputs/level-1-1/input.html', 'BIG FAT HEN 1-1');
      fs.writeFileSync(__dirname + '/temp/outputs/level-1-2/input.html', 'BIG FAT HEN 1-2');
      run('--no-debug --out outputs inputs', function (err) {
        if (err) return done(err);
        var html = fs.readFileSync(__dirname + '/temp/outputs/input.html', 'utf8');
        assert(html === '
bar 1
');
        var html = fs.readFileSync(__dirname + '/temp/outputs/level-1-1/input.html', 'utf8');
        assert(html === '
bar 1-1
');
        var html = fs.readFileSync(__dirname + '/temp/outputs/level-1-2/input.html', 'utf8');
        assert(html === '
bar 1-2
');
        done();
      });
    });
  });
});

describe('command line with client JS output', function () {
  if (isIstanbul) {
    this.timeout(8000);
    this.slow(6000);
  } else {
    this.slow(250);
  }
  it('jade --no-debug --client --name myTemplate input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.js', 'throw new Error("output not written");');
    run('--no-debug --client --name myTemplate input.jade', function (err) {
      if (err) return done(err);
      var template = Function('', fs.readFileSync(__dirname + '/temp/input.js', 'utf8') + ';return myTemplate;')();
      assert(template() === '
bar
');
      done();
    });
  });
  it('jade --no-debug --client -E special-js --name myTemplate input.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.special-js', 'throw new Error("output not written");');
    run('--no-debug --client -E special-js --name myTemplate input.jade', function (err) {
      if (err) return done(err);
      var template = Function('', fs.readFileSync(__dirname + '/temp/input.special-js', 'utf8') + ';return myTemplate;')();
      assert(template() === '
bar
');
      done();
    });
  });
  it('cat input.jade | jade --no-debug --client --name myTemplate', function (done) {
    fs.writeFileSync(__dirname + '/temp/input.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input.js', 'throw new Error("output not written");');
    run('--no-debug --client --name myTemplate', 'cat input.jade | ', function (err, stdout) {
      if (err) return done(err);
      var template = Function('', stdout + ';return myTemplate;')();
      assert(template() === '
bar
');
      done();
    });
  });
  it('jade --no-debug --client --name-after-file input-file.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/input-file.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input-file.js', 'throw new Error("output not written");');
    run('--no-debug --client --name-after-file input-file.jade', function (err, stdout, stderr) {
      if (err) return done(err);
      var template = Function('', fs.readFileSync(__dirname + '/temp/input-file.js', 'utf8') + ';return inputFileTemplate;')();
      assert(template() === '
bar
');
      return done();
    });
  });
  it('jade --no-debug --client --name-after-file _InPuTwIthWEiRdNaMME.jade', function (done) {
    fs.writeFileSync(__dirname + '/temp/_InPuTwIthWEiRdNaMME.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/_InPuTwIthWEiRdNaMME.js', 'throw new Error("output not written");');
    run('--no-debug --client --name-after-file _InPuTwIthWEiRdNaMME.jade', function (err, stdout, stderr) {
      if (err) return done(err);
      var template = Function('', fs.readFileSync(__dirname + '/temp/_InPuTwIthWEiRdNaMME.js', 'utf8') + ';return InputwithweirdnammeTemplate;')();
      assert(template() === '
bar
');
      return done();
    });
  });
});

describe('command line watch mode', function () {
  var watchProc;
  var stdout = '';
  after(function() {
    // Just to be sure
    watchProc.stderr.removeAllListeners('data');
    watchProc.stdout.removeAllListeners('data');
    watchProc.removeAllListeners('error');
    watchProc.removeAllListeners('close');

    watchProc.kill('SIGINT');
  });
  afterEach(function (done) {
    // jade --watch can only detect changes that are at least 1 second apart
    setTimeout(done, 1000);
  });
  it('jade --no-debug --client --name-after-file --watch input-file.jade (pass 1)', function (done) {
    if (isIstanbul) {
      this.timeout(8000);
      this.slow(6000);
    } else {
      this.slow(300);
    }
    fs.writeFileSync(__dirname + '/temp/input-file.jade', '.foo bar');
    fs.writeFileSync(__dirname + '/temp/input-file.js', 'throw new Error("output not written (pass 1)");');
    var cmd = getRunner();
    cmd.push.apply(cmd,
      ['--no-debug', '--client', '--name-after-file', '--watch', 'input-file.jade']);
    watchProc = cp.spawn(cmd[0], cmd.slice(1),  {
      cwd: __dirname + '/temp'
    });

    watchProc.stdout.setEncoding('utf8');
    watchProc.stderr.setEncoding('utf8');
    watchProc
      .on('error', done)
      .stdout.on('data', function(buf) {
        stdout += buf;
        if (/.*rendered.*/.test(stdout)) {
          stdout = '';
          var template = Function('', fs.readFileSync(__dirname + '/temp/input-file.js', 'utf8') + ';return inputFileTemplate;')();
          assert(template() === '
bar
');

          watchProc.stdout.removeAllListeners('data');
          watchProc.removeAllListeners('error');
          return done();
        }
      });
  });
  it('jade --no-debug --client --name-after-file --watch input-file.jade (pass 2)', function (done) {
    // Just to be sure
    watchProc.stdout.removeAllListeners('data');
    watchProc.removeAllListeners('error');

    fs.writeFileSync(__dirname + '/temp/input-file.js', 'throw new Error("output not written (pass 2)");');
    fs.writeFileSync(__dirname + '/temp/input-file.jade', '.foo baz');

    watchProc
      .on('error', done)
      .stdout.on('data', function(buf) {
        stdout += buf;
        if (/.*rendered.*/.test(stdout)) {
          stdout = '';
          var template = Function('', fs.readFileSync(__dirname + '/temp/input-file.js', 'utf8') + ';return inputFileTemplate;')();
          assert(template() === '
baz
');

          watchProc.stdout.removeAllListeners('data');
          watchProc.removeAllListeners('error');
          return done();
        }
      });
  });
  it('jade --no-debug --client --name-after-file --watch input-file.jade (intentional errors in the jade file)', function (done) {
    // Just to be sure
    watchProc.stdout.removeAllListeners('data');
    watchProc.removeAllListeners('error');

    var stderr = '';
    var errored = false;
    watchProc
      .on('error', done)
      .on('close', function() {
        errored = true;
        return done(new Error('Jade should not terminate in watch mode'));
      })
      .stdout.on('data', function(buf) {
        stdout += buf;
        if (/.*rendered.*/.test(stdout)) {
          stdout = '';
          return done(new Error('Jade compiles an erroneous file w/o error'));
        }
      })
    watchProc
      .stderr.on('data', function(buf) {
        stderr += buf;
        if (!/.*Invalid indentation.*/.test(stderr)) return;
        stderr = '';
        var template = Function('', fs.readFileSync(__dirname + '/temp/input-file.js', 'utf8') + ';return inputFileTemplate;')();
        assert(template() === '
baz
');

        watchProc.stderr.removeAllListeners('data');
        watchProc.stdout.removeAllListeners('data');
        watchProc.removeAllListeners('error');
        watchProc.removeAllListeners('exit');
        // The stderr event will always fire sooner than the close event.
        // Wait for it.
        setTimeout(function() {
          if (!errored) done();
        }, 100);
      });
    fs.writeFileSync(__dirname + '/temp/input-file.jade',
                     fs.readFileSync(__dirname
                                     + '/anti-cases/tabs-and-spaces.jade'));
  });
});
<|endoftext|>


<commit_before>const path = require('path')
const ReadStreamTaskParser = require('./ReadStreamTaskParser')
const CodeStyleTaskParser = require('../task/CodeStyleTaskParser')
const extractComments = require('multilang-extract-comments')
const eol = require('eol')
const ReadLine = require('readline')
const { Readable } = require('stream')
/**
 * DOING:0 ## create ReadStreamCodeParser
 * #adapter
 * [${source.path}](${source.path})
 * <!-- epic:"Release 1.29.0" -->
 */

async function streamToString(stream) {
  const chunks = []

  for await (const chunk of stream) {
    chunks.push(Buffer.from(chunk))
  }

  return Buffer.concat(chunks).toString('utf-8')
}

function stringToStream(string) {
  const lines = eol.split(string).map((line) => line + String(eol.auto))
  return Readable.from(lines)
}

module.exports = class ReadStreamCodeParser extends ReadStreamTaskParser {
  constructor(readStream, filePath, lang) {
    super(readStream)
    this.filePath = filePath
    this.lang = lang
    this.taskParsers = [new CodeStyleTaskParser()]
  }

  async init() {
    const content = await streamToString(this.readStream)
    this.comments = await this.extractComments(content)
    this.readStream = stringToStream(content)
    this.readInterface = this.getReadInterface()

    let line = null
    let lines = []
    let lineNo = 1
    let comment = null
    do {
      const { value, done } = await this.readLine()
      line = done ? null : value
      comment = this.getCommentAtLine(lineNo)
      let lineInComment = ''
      if (comment) {
        lineInComment = comment.lines[lineNo - comment.begin]
      }
      lines.push(lineInComment)
      lineNo += 1
    } while (line !== null)
    this.readInterface.close()
    this.readStream = Readable.from(
      lines.map((line) => line + String(eol.auto))
    )
    this.readInterface = this.getReadInterface()
  }

  async readTask() {
    const task = await super.readTask()
    task.multiLineComment =
      this.getCommentAtLine(task.line).info.type === 'multiline'
    task.descriptionStartsWith = task.multiLineComment
      ? this.lang.block.ignore
      : this.lang.symbol

    return task
  }

  getCommentAtLine(lineNo) {
    return this.comments.find(
      (comment) => lineNo >= comment.begin && lineNo <= comment.end
    )
  }

  getReadInterface() {
    return ReadLine.createInterface({
      input: this.readStream,
      crlfDelay: Infinity,
      console: false,
    })
  }

  async extractComments(content) {
    const lang = this.lang
    const multiLineComment = lang.block
      ? [
          {
            start: lang.block.start,
            middle: lang.block.ignore,
            end: lang.block.end,
          },
        ]
      : []
    const options = {
      pattern: {
        name: lang.name,
        nameMatchers: [path.extname(this.filePath)],
        singleLineComment: [{ start: lang.symbol }],
        multiLineComment,
      },
    }
    const comments = extractComments(content, options)
    const contentLines = eol.split(content)
    return Object.values(comments).map((comment) => {
      const lines = eol.split(comment.content)
      const linesInContent = contentLines.slice(comment.begin - 1, comment.end)
      let contentStartIndex = linesInContent.findIndex((line, index) =>
        line.includes(lines[0])
      )
      for (let i = 0; i < contentStartIndex; i++) {
        lines.unshift('')
      }
      return {
        ...comment,
        lines,
      }
    })
  }
}
<commit_msg>Remove unused argument<commit_after>const path = require('path')
const ReadStreamTaskParser = require('./ReadStreamTaskParser')
const CodeStyleTaskParser = require('../task/CodeStyleTaskParser')
const extractComments = require('multilang-extract-comments')
const eol = require('eol')
const ReadLine = require('readline')
const { Readable } = require('stream')
/**
 * DOING:0 ## create ReadStreamCodeParser
 * #adapter
 * [${source.path}](${source.path})
 * <!-- epic:"Release 1.29.0" -->
 */

async function streamToString(stream) {
  const chunks = []

  for await (const chunk of stream) {
    chunks.push(Buffer.from(chunk))
  }

  return Buffer.concat(chunks).toString('utf-8')
}

function stringToStream(string) {
  const lines = eol.split(string).map((line) => line + String(eol.auto))
  return Readable.from(lines)
}

module.exports = class ReadStreamCodeParser extends ReadStreamTaskParser {
  constructor(readStream, filePath, lang) {
    super(readStream)
    this.filePath = filePath
    this.lang = lang
    this.taskParsers = [new CodeStyleTaskParser()]
  }

  async init() {
    const content = await streamToString(this.readStream)
    this.comments = await this.extractComments(content)
    this.readStream = stringToStream(content)
    this.readInterface = this.getReadInterface()

    let line = null
    let lines = []
    let lineNo = 1
    let comment = null
    do {
      const { value, done } = await this.readLine()
      line = done ? null : value
      comment = this.getCommentAtLine(lineNo)
      let lineInComment = ''
      if (comment) {
        lineInComment = comment.lines[lineNo - comment.begin]
      }
      lines.push(lineInComment)
      lineNo += 1
    } while (line !== null)
    this.readInterface.close()
    this.readStream = Readable.from(
      lines.map((line) => line + String(eol.auto))
    )
    this.readInterface = this.getReadInterface()
  }

  async readTask() {
    const task = await super.readTask()
    task.multiLineComment =
      this.getCommentAtLine(task.line).info.type === 'multiline'
    task.descriptionStartsWith = task.multiLineComment
      ? this.lang.block.ignore
      : this.lang.symbol

    return task
  }

  getCommentAtLine(lineNo) {
    return this.comments.find(
      (comment) => lineNo >= comment.begin && lineNo <= comment.end
    )
  }

  getReadInterface() {
    return ReadLine.createInterface({
      input: this.readStream,
      crlfDelay: Infinity,
      console: false,
    })
  }

  async extractComments(content) {
    const lang = this.lang
    const multiLineComment = lang.block
      ? [
          {
            start: lang.block.start,
            middle: lang.block.ignore,
            end: lang.block.end,
          },
        ]
      : []
    const options = {
      pattern: {
        name: lang.name,
        nameMatchers: [path.extname(this.filePath)],
        singleLineComment: [{ start: lang.symbol }],
        multiLineComment,
      },
    }
    const comments = extractComments(content, options)
    const contentLines = eol.split(content)
    return Object.values(comments).map((comment) => {
      const lines = eol.split(comment.content)
      const linesInContent = contentLines.slice(comment.begin - 1, comment.end)
      let contentStartIndex = linesInContent.findIndex((line) =>
        line.includes(lines[0])
      )
      for (let i = 0; i < contentStartIndex; i++) {
        lines.unshift('')
      }
      return {
        ...comment,
        lines,
      }
    })
  }
}
<|endoftext|>


<commit_before>/* ©Copyright Utrecht University (Department of Information and Computing Sciences) */

var Config;

(function ()
{
    Config =
    {
        configObject: {},
        types: {}
    };

    $(document).ready(loadConfig);

    function loadConfig()
    {
        var configXML = $($.parseXML($('#config').text())).children('config');
        var config = {};

        var defaultScopes = { statementScope: 'independent' };
        config.properties = loadPropertyGroup(configXML.children('properties'), defaultScopes);

        Config.configObject = config;
    }

    function loadPropertyGroup(groupXML, parentScopes)
    {
        var groupScopes = loadScopes(groupXML[0]);
        mergeScopes(groupScopes, parentScopes);

        var properties = {};
        groupXML.children().each(function (index, childXML)
        {
            if (childXML.nodeName === "property")
            {
                var id = childXML.getAttribute('id');
                var propertyScopes = loadScopes(childXML);
                mergeScopes(propertyScopes, groupScopes);
                properties[id] =
                {
                    id: id,
                    name: childXML.getAttribute('name'),
                    description: childXML.getAttribute('description'),
                    optional: Boolean(childXML.getAttribute('optional')),
                    scopes: propertyScopes,
                    type: loadType($(childXML).children().eq(0))
                }
            }
            else
            {
                $.extend(properties, loadPropertyGroup($(childXML), groupScopes));
            }
        });
        return properties;
    }

    function loadScopes(scopedXML)
    {
        return { statementScope: scopedXML.getAttribute('statementScope') };
    }

    function mergeScopes(localScopes, parentScopes)
    {
        for (var scopeName in parentScopes)
        {
            if (!localScopes[scopeName])
            {
                localScopes[scopeName] = parentScopes[scopeName];
            }
        }
    }

    function loadType(typeXML)
    {
        var typeName = typeXML[0].nodeName.substr('type'.length).toLowerCase();
        return Config.types[typeName].loadType(typeXML);
    }

    Config.types =
    {
        'string':
        {
            name: 'string',
            loadType: function(typeXML) { return this; },
            appendControlTo: function(containerEl, htmlId)
            {
                containerEl.append($('<input>', { id: htmlId, type: 'text' }));
            }
        },
        'integer':
        {
            name: 'integer',
            loadType: function(typeXML) { return this; },
            appendControlTo: function(containerEl, htmlId)
            {
                containerEl.append($('<input>', { id: htmlId, type: 'number' }));
            }
        },
        'boolean':
        {
            name: 'boolean',
            loadType: function(typeXML) { return this; },
            appendControlTo: function(containerEl, htmlId)
            {
                containerEl.append($('<input>', { id: htmlId, type: 'checkbox' }));
            }
        },
        'enumeration':
        {
            name: 'enumeration',
            loadType: function(typeXML)
            {
                var values = [];
                typeXML.children('value').each(function(index, valueXML)
                {
                    values.push(valueXML.textContent);
                });
                return $.extend({ values: values }, this);
            },
            appendControlTo: function(containerEl, htmlId)
            {
                var selectEl = $('<select>', { id: htmlId });
                this.values.forEach(function(value)
                {
                    selectEl.append($('<option>', { text: value, value: value }));
                });
                containerEl.append(selectEl);
            }
        }
    };
})();
<commit_msg>Renamed value to option in typeEnumeration<commit_after>/* ©Copyright Utrecht University (Department of Information and Computing Sciences) */

var Config;

(function ()
{
    Config =
    {
        configObject: {},
        types: {}
    };

    $(document).ready(loadConfig);

    function loadConfig()
    {
        var configXML = $($.parseXML($('#config').text())).children('config');
        var config = {};

        var defaultScopes = { statementScope: 'independent' };
        config.properties = loadPropertyGroup(configXML.children('properties'), defaultScopes);

        Config.configObject = config;
    }

    function loadPropertyGroup(groupXML, parentScopes)
    {
        var groupScopes = loadScopes(groupXML[0]);
        mergeScopes(groupScopes, parentScopes);

        var properties = {};
        groupXML.children().each(function (index, childXML)
        {
            if (childXML.nodeName === "property")
            {
                var id = childXML.getAttribute('id');
                var propertyScopes = loadScopes(childXML);
                mergeScopes(propertyScopes, groupScopes);
                properties[id] =
                {
                    id: id,
                    name: childXML.getAttribute('name'),
                    description: childXML.getAttribute('description'),
                    optional: Boolean(childXML.getAttribute('optional')),
                    scopes: propertyScopes,
                    type: loadType($(childXML).children().eq(0))
                }
            }
            else
            {
                $.extend(properties, loadPropertyGroup($(childXML), groupScopes));
            }
        });
        return properties;
    }

    function loadScopes(scopedXML)
    {
        return { statementScope: scopedXML.getAttribute('statementScope') };
    }

    function mergeScopes(localScopes, parentScopes)
    {
        for (var scopeName in parentScopes)
        {
            if (!localScopes[scopeName])
            {
                localScopes[scopeName] = parentScopes[scopeName];
            }
        }
    }

    function loadType(typeXML)
    {
        var typeName = typeXML[0].nodeName.substr('type'.length).toLowerCase();
        return Config.types[typeName].loadType(typeXML);
    }

    Config.types =
    {
        'string':
        {
            name: 'string',
            loadType: function(typeXML) { return this; },
            appendControlTo: function(containerEl, htmlId)
            {
                containerEl.append($('<input>', { id: htmlId, type: 'text' }));
            }
        },
        'integer':
        {
            name: 'integer',
            loadType: function(typeXML) { return this; },
            appendControlTo: function(containerEl, htmlId)
            {
                containerEl.append($('<input>', { id: htmlId, type: 'number' }));
            }
        },
        'boolean':
        {
            name: 'boolean',
            loadType: function(typeXML) { return this; },
            appendControlTo: function(containerEl, htmlId)
            {
                containerEl.append($('<input>', { id: htmlId, type: 'checkbox' }));
            }
        },
        'enumeration':
        {
            name: 'enumeration',
            loadType: function(typeXML)
            {
                var values = [];
                typeXML.children('option').each(function(index, valueXML)
                {
                    values.push(valueXML.textContent);
                });
                return $.extend({ values: values }, this);
            },
            appendControlTo: function(containerEl, htmlId)
            {
                var selectEl = $('<select>', { id: htmlId });
                this.values.forEach(function(value)
                {
                    selectEl.append($('<option>', { text: value, value: value }));
                });
                containerEl.append(selectEl);
            }
        }
    };
})();
<|endoftext|>


<commit_before>import React from 'react';
import Analyzer, { SELECTED_PLAYER } from 'parser/core/Analyzer';
import SPELLS from 'common/SPELLS/index';
import TraitStatisticBox, { STATISTIC_ORDER } from 'interface/others/TraitStatisticBox';
import { calculateAzeriteEffects } from 'common/stats';
import CriticalStrikeIcon from 'interface/icons/CriticalStrike';
import HasteIcon from 'interface/icons/Haste';
import MasteryIcon from 'interface/icons/Mastery';
import VersatilityIcon from 'interface/icons/Versatility';
import { formatNumber, formatPercentage } from 'common/format';
import Events from 'parser/core/Events';
import StatTracker from 'parser/shared/modules/StatTracker';

/*
  Your Mastery is increased by 150, plus an additional 37 for each ally also affected by Loyal to the End, up to 299.
  When you die, your allies gain Critical Strike, Haste, and Versatility equal to their Mastery bonus from this trait.

  Example Logs:
    Holy Priest:  /report/vVaHPpZN3cmM6x7Y/36-Mythic+Blackwater+Behemoth+-+Kill+(6:12)/Menya
    Resto Druid:  /report/Cbmyth6c7xYvd8FM/16-Heroic+Lady+Ashvane+-+Kill+(2:40)/Séyah
    Rogue:        /report/Cbmyth6c7xYvd8FM/16-Heroic+Lady+Ashvane+-+Kill+(2:40)/Slynestra     <= buff log
 */
const loyalToTheEndStats = traits => Object.values(traits).reduce((obj, rank) => {
  const [baseMastery, additiveMastery, masteryCap] = calculateAzeriteEffects(SPELLS.LOYAL_TO_THE_END.id, rank);

  obj.baseMastery += baseMastery || 0;
  obj.additiveMastery += additiveMastery || 0;
  obj.masteryCap += masteryCap || 0;
  return obj;
}, {
  baseMastery: 0,
  additiveMastery: 0,
  masteryCap: 0,
});

class LoyalToTheEnd extends Analyzer {
  static dependencies = {
    statTracker: StatTracker,
  };

  baseMastery = 0;
  additiveMastery = 0;
  masteryCap = 0;
  buffUptime = 0;
  buffLastApplied = 0;
  playersWithTrait = {};

  get numberOfPlayersWithTrait() {
    if (!this.playersWithTrait) {
      return 0;
    }
    return Object.keys(this.playersWithTrait).length;
  }

  get personalMasteryValue() {
    return Math.min((this.baseMastery + (this.additiveMastery * this.numberOfPlayersWithTrait)), this.masteryCap);
  }

  get buffUptimePercent() {
    return this.buffUptime / this.owner.fightDuration;
  }

  get averageBuffContribution() {
    return this.personalMasteryValue * this.buffUptimePercent;
  }

  constructor(...args) {
    super(...args);
    this.active = this.selectedCombatant.hasTrait(SPELLS.LOYAL_TO_THE_END.id);
    if (!this.active) {
      return;
    }

    const { baseMastery, additiveMastery, masteryCap } = loyalToTheEndStats(this.selectedCombatant.traitsBySpellId[SPELLS.LOYAL_TO_THE_END.id]);

    this.baseMastery = baseMastery;
    this.additiveMastery = additiveMastery;
    this.masteryCap = masteryCap;

    this.findPlayersWithTrait();

    // When this buff is active, it gives you as much of each stat as it does mastery.
    this.statTracker.add(SPELLS.LOYAL_TO_THE_END_SECONDARY_BUFF.id, {
      crit: this.personalMasteryValue,
      haste: this.personalMasteryValue,
      versatility: this.personalMasteryValue,
    });

    this.addEventListener(Events.applybuff.to(SELECTED_PLAYER).spell(SPELLS.LOYAL_TO_THE_END_SECONDARY_BUFF), this.applyPersonalBuff);
    this.addEventListener(Events.removebuff.to(SELECTED_PLAYER).spell(SPELLS.LOYAL_TO_THE_END_SECONDARY_BUFF), this.removePersonalBuff);
    this.addEventListener(Events.fightend, this.fightEnd);
  }

  findPlayersWithTrait() {
    for (const combatant of this.owner.combatantInfoEvents) {
      for (const artifact of combatant.artifact) {
        if (artifact.spellID === SPELLS.LOYAL_TO_THE_END.id) {
          this.playersWithTrait[combatant.sourceID] = this.playersWithTrait[combatant.sourceID] ? this.playersWithTrait[combatant.sourceID] : [];
          this.playersWithTrait[combatant.sourceID].push(artifact.rank);
        }
      }
    }
  }

  applyPersonalBuff(event) {
    this.buffLastApplied = this.buffLastApplied === 0 ? event.timestamp : this.buffLastApplied;
  }

  removePersonalBuff(event) {
    this.buffUptime += event.timestamp - this.buffLastApplied;
    this.buffLastApplied = 0;
  }

  fightEnd(event) {
    if (this.buffLastApplied !== 0) {
      this.buffUptime += event.timestamp - this.buffLastApplied;
      this.buffLastApplied = 0;
    }
  }

  statistic() {
    return (
      <TraitStatisticBox
        position={STATISTIC_ORDER.OPTIONAL()}
        trait={SPELLS.LOYAL_TO_THE_END.id}
        value={(
          <>
            <MasteryIcon /> {formatNumber(this.personalMasteryValue)} average Mastery gained

            {this.averageBuffContribution > 0 && (
              <>
                <CriticalStrikeIcon /> {formatNumber(this.averageBuffContribution)} average Critical Strike gained

                <HasteIcon /> {formatNumber(this.averageBuffContribution)} average Haste gained

                <VersatilityIcon /> {formatNumber(this.averageBuffContribution)} average Versatility gained

              </>
            )}
          </>
        )}
        tooltip={(
          <>
            {formatNumber(this.numberOfPlayersWithTrait)} Other players with trait

            {formatPercentage(this.buffUptimePercent)}% Uptime on secondary buff
          </>
        )}
      />
    );
  }
}

export default LoyalToTheEnd;
<commit_msg>updating doc<commit_after>import React from 'react';
import Analyzer, { SELECTED_PLAYER } from 'parser/core/Analyzer';
import SPELLS from 'common/SPELLS/index';
import TraitStatisticBox, { STATISTIC_ORDER } from 'interface/others/TraitStatisticBox';
import { calculateAzeriteEffects } from 'common/stats';
import CriticalStrikeIcon from 'interface/icons/CriticalStrike';
import HasteIcon from 'interface/icons/Haste';
import MasteryIcon from 'interface/icons/Mastery';
import VersatilityIcon from 'interface/icons/Versatility';
import { formatNumber, formatPercentage } from 'common/format';
import Events from 'parser/core/Events';
import StatTracker from 'parser/shared/modules/StatTracker';

/*
  Your Mastery is increased by 150, plus an additional 37 for each ally also affected by Loyal to the End, up to 299.
  When you die, your allies gain Critical Strike, Haste, and Versatility equal to their Mastery bonus from this trait.

  Example Logs:
    Holy Priest:  /report/vVaHPpZN3cmM6x7Y/36-Mythic+Blackwater+Behemoth+-+Kill+(6:12)/Menya
    Resto Druid:  /report/Cbmyth6c7xYvd8FM/16-Heroic+Lady+Ashvane+-+Kill+(2:40)/Séyah
    Rogue:        /report/Cbmyth6c7xYvd8FM/16-Heroic+Lady+Ashvane+-+Kill+(2:40)/Slynestra     <= buff log
 */
const loyalToTheEndStats = traits => Object.values(traits).reduce((obj, rank) => {
  const [baseMastery, additiveMastery, masteryCap] = calculateAzeriteEffects(SPELLS.LOYAL_TO_THE_END.id, rank);

  obj.baseMastery += baseMastery || 0;
  obj.additiveMastery += additiveMastery || 0;
  obj.masteryCap += masteryCap || 0;
  return obj;
}, {
  baseMastery: 0,
  additiveMastery: 0,
  masteryCap: 0,
});

class LoyalToTheEnd extends Analyzer {
  static dependencies = {
    statTracker: StatTracker,
  };

  baseMastery = 0;
  additiveMastery = 0;
  masteryCap = 0;
  buffUptime = 0;
  buffLastApplied = 0;
  playersWithTrait = {};

  get numberOfPlayersWithTrait() {
    if (!this.playersWithTrait) {
      return 0;
    }
    return Object.keys(this.playersWithTrait).length;
  }

  get personalMasteryValue() {
    return Math.min((this.baseMastery + (this.additiveMastery * this.numberOfPlayersWithTrait)), this.masteryCap);
  }

  get buffUptimePercent() {
    return this.buffUptime / this.owner.fightDuration;
  }

  get averageBuffContribution() {
    return this.personalMasteryValue * this.buffUptimePercent;
  }

  constructor(...args) {
    super(...args);
    this.active = this.selectedCombatant.hasTrait(SPELLS.LOYAL_TO_THE_END.id);
    if (!this.active) {
      return;
    }

    const { baseMastery, additiveMastery, masteryCap } = loyalToTheEndStats(this.selectedCombatant.traitsBySpellId[SPELLS.LOYAL_TO_THE_END.id]);

    this.baseMastery = baseMastery;
    this.additiveMastery = additiveMastery;
    this.masteryCap = masteryCap;

    this.findPlayersWithTrait();

    // When this buff is active, it gives you as much of each stat as it does mastery.
    // The base mastery you get is always active, so it should be included in the players base data.
    this.statTracker.add(SPELLS.LOYAL_TO_THE_END_SECONDARY_BUFF.id, {
      crit: this.personalMasteryValue,
      haste: this.personalMasteryValue,
      versatility: this.personalMasteryValue,
    });

    this.addEventListener(Events.applybuff.to(SELECTED_PLAYER).spell(SPELLS.LOYAL_TO_THE_END_SECONDARY_BUFF), this.applyPersonalBuff);
    this.addEventListener(Events.removebuff.to(SELECTED_PLAYER).spell(SPELLS.LOYAL_TO_THE_END_SECONDARY_BUFF), this.removePersonalBuff);
    this.addEventListener(Events.fightend, this.fightEnd);
  }

  findPlayersWithTrait() {
    for (const combatant of this.owner.combatantInfoEvents) {
      for (const artifact of combatant.artifact) {
        if (artifact.spellID === SPELLS.LOYAL_TO_THE_END.id) {
          this.playersWithTrait[combatant.sourceID] = this.playersWithTrait[combatant.sourceID] ? this.playersWithTrait[combatant.sourceID] : [];
          this.playersWithTrait[combatant.sourceID].push(artifact.rank);
        }
      }
    }
  }

  applyPersonalBuff(event) {
    this.buffLastApplied = this.buffLastApplied === 0 ? event.timestamp : this.buffLastApplied;
  }

  removePersonalBuff(event) {
    this.buffUptime += event.timestamp - this.buffLastApplied;
    this.buffLastApplied = 0;
  }

  fightEnd(event) {
    if (this.buffLastApplied !== 0) {
      this.buffUptime += event.timestamp - this.buffLastApplied;
      this.buffLastApplied = 0;
    }
  }

  statistic() {
    return (
      <TraitStatisticBox
        position={STATISTIC_ORDER.OPTIONAL()}
        trait={SPELLS.LOYAL_TO_THE_END.id}
        value={(
          <>
            <MasteryIcon /> {formatNumber(this.personalMasteryValue)} average Mastery gained

            {this.averageBuffContribution > 0 && (
              <>
                <CriticalStrikeIcon /> {formatNumber(this.averageBuffContribution)} average Critical Strike gained

                <HasteIcon /> {formatNumber(this.averageBuffContribution)} average Haste gained

                <VersatilityIcon /> {formatNumber(this.averageBuffContribution)} average Versatility gained

              </>
            )}
          </>
        )}
        tooltip={(
          <>
            {formatNumber(this.numberOfPlayersWithTrait)} Other players with trait

            {formatPercentage(this.buffUptimePercent)}% Uptime on secondary buff
          </>
        )}
      />
    );
  }
}

export default LoyalToTheEnd;
<|endoftext|>


<commit_before>let async = require('async');

const ContractDeployer = require('./contract_deployer.js');
const cloneDeep = require('clone-deep');

class DeployManager {
  constructor(embark, options) {
    const self = this;
    this.config = embark.config;
    this.logger = embark.logger;
    this.blockchainConfig = this.config.blockchainConfig;

    this.events = embark.events;
    this.plugins = options.plugins;
    this.blockchain = options.blockchain;
    this.gasLimit = false;
    this.fatalErrors = false;
    this.deployOnlyOnConfig = false;
    this.onlyCompile = options.onlyCompile !== undefined ? options.onlyCompile : false;

    this.contractDeployer = new ContractDeployer({
      logger: this.logger,
      events: this.events,
      plugins: this.plugins
    });

    this.events.setCommandHandler('deploy:setGasLimit', (gasLimit) => {
      self.gasLimit = gasLimit;
    });

    this.events.setCommandHandler('deploy:contracts', (cb) => {
      self.deployContracts(cb);
    });

    this.events.setCommandHandler('deploy:contracts:test', (cb) => {
      self.fatalErrors = true;
      self.deployOnlyOnConfig = true;
      self.deployContracts(cb);
    });
  }

  deployAll(done) {
    let self = this;

    self.events.request('contracts:dependencies', (err, contractDependencies) => {
      self.events.request('contracts:list', (err, contracts) => {
        if (err) {
          return done(err);
        }

        self.logger.info(__("deploying contracts"));
        self.events.emit("deploy:beforeAll");

        const contractDeploys = {};
        const errors = [];
        contracts.forEach(contract => {
          function deploy(result, callback) {
            if (typeof result === 'function') {
              callback = result;
            }
            contract._gasLimit = self.gasLimit;
            self.events.request('deploy:contract', contract, (err) => {
              if (err) {
                contract.error = err.message || err;
                errors.push(err);
              }
              callback();
            });
          }

          const className = contract.className;
          if (!contractDependencies[className] || contractDependencies[className].length === 0) {
            contractDeploys[className] = deploy;
            return;
          }
          contractDeploys[className] = cloneDeep(contractDependencies[className]);
          contractDeploys[className].push(deploy);
        });

        try {
          async.auto(contractDeploys, function(_err, _results) {
            if (errors.length) {
              self.logger.error(__("error deploying contracts"));
              errors.forEach(error => {
                self.logger.error(error.message || error);
              });
            }
            if (contracts.length === 0) {
              self.logger.info(__("no contracts found"));
              return done();
            }
            self.logger.info(__("finished deploying contracts"));
            done(err);
          });
        } catch (e) {
          self.logger.error(e.message || e);
          done(__('Error deploying'));
        }
      });
    });
  }

  deployContracts(done) {
    let self = this;

    if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
      self.logger.info(__("Blockchain component is disabled in the config").underline);
      this.events.emit('blockchainDisabled', {});
      return done();
    }

    async.waterfall([
      function requestBlockchainConnector(callback) {
        self.events.request("blockchain:object", (blockchain) => {
          self.blockchain = blockchain;
          callback();
        });
      },

      function buildContracts(callback) {
        self.events.request("contracts:build", self.deployOnlyOnConfig, (err) => {
          callback(err);
        });
      },

      // TODO: shouldn't be necessary
      function checkCompileOnly(callback) {
        if (self.onlyCompile) {
          self.events.emit('contractsDeployed');
          return done();
        }
        return callback();
      },

      // TODO: could be implemented as an event (beforeDeployAll)
      function checkIsConnectedToBlockchain(callback) {
        self.blockchain.onReady((err) => {
          callback(err);
        });
      },

      // TODO: this can be done on the fly or as part of the initialization
      function determineDefaultAccount(callback) {
        self.blockchain.determineDefaultAccount((err) => {
          callback(err);
        });
      },

      function deployAllContracts(callback) {
        self.deployAll(function (err) {
          if (!err) {
            self.events.emit('contractsDeployed');
          }
          if (err && self.fatalErrors) {
            return callback(err);
          }
          callback();
        });
      },
      function runAfterDeploy(callback) {
        self.plugins.emitAndRunActionsForEvent('contracts:deploy:afterAll', callback);
      }
    ], function (err, _result) {
      done(err);
    });
  }

}

module.exports = DeployManager;
<commit_msg>stop on error<commit_after>let async = require('async');

const ContractDeployer = require('./contract_deployer.js');
const cloneDeep = require('clone-deep');

class DeployManager {
  constructor(embark, options) {
    const self = this;
    this.config = embark.config;
    this.logger = embark.logger;
    this.blockchainConfig = this.config.blockchainConfig;

    this.events = embark.events;
    this.plugins = options.plugins;
    this.blockchain = options.blockchain;
    this.gasLimit = false;
    this.fatalErrors = false;
    this.deployOnlyOnConfig = false;
    this.onlyCompile = options.onlyCompile !== undefined ? options.onlyCompile : false;

    this.contractDeployer = new ContractDeployer({
      logger: this.logger,
      events: this.events,
      plugins: this.plugins
    });

    this.events.setCommandHandler('deploy:setGasLimit', (gasLimit) => {
      self.gasLimit = gasLimit;
    });

    this.events.setCommandHandler('deploy:contracts', (cb) => {
      self.deployContracts(cb);
    });

    this.events.setCommandHandler('deploy:contracts:test', (cb) => {
      self.fatalErrors = true;
      self.deployOnlyOnConfig = true;
      self.deployContracts(cb);
    });
  }

  deployAll(done) {
    let self = this;

    self.events.request('contracts:dependencies', (err, contractDependencies) => {
      self.events.request('contracts:list', (err, contracts) => {
        if (err) {
          return done(err);
        }

        self.logger.info(__("deploying contracts"));
        self.events.emit("deploy:beforeAll");

        const contractDeploys = {};
        const errors = [];
        contracts.forEach(contract => {
          function deploy(result, callback) {
            if (typeof result === 'function') {
              callback = result;
            }
            contract._gasLimit = self.gasLimit;
            self.events.request('deploy:contract', contract, (err) => {
              if (err) {
                contract.error = err.message || err;
                self.logger.error(err.message || err);
                errors.push(err);
              }
              callback();
            });
          }

          const className = contract.className;
          if (!contractDependencies[className] || contractDependencies[className].length === 0) {
            contractDeploys[className] = deploy;
            return;
          }
          contractDeploys[className] = cloneDeep(contractDependencies[className]);
          contractDeploys[className].push(deploy);
        });

        try {
          async.auto(contractDeploys, function(_err, _results) {
            if (errors.length) {
              _err = __("Error deploying contracts. Please fix errors to continue.");
              self.logger.error(_err);
              return done(_err);
            }
            if (contracts.length === 0) {
              self.logger.info(__("no contracts found"));
              return done();
            }
            self.logger.info(__("finished deploying contracts"));
            done(err);
          });
        } catch (e) {
          self.logger.error(e.message || e);
          done(__('Error deploying'));
        }
      });
    });
  }

  deployContracts(done) {
    let self = this;

    if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
      self.logger.info(__("Blockchain component is disabled in the config").underline);
      this.events.emit('blockchainDisabled', {});
      return done();
    }

    async.waterfall([
      function requestBlockchainConnector(callback) {
        self.events.request("blockchain:object", (blockchain) => {
          self.blockchain = blockchain;
          callback();
        });
      },

      function buildContracts(callback) {
        self.events.request("contracts:build", self.deployOnlyOnConfig, (err) => {
          callback(err);
        });
      },

      // TODO: shouldn't be necessary
      function checkCompileOnly(callback) {
        if (self.onlyCompile) {
          self.events.emit('contractsDeployed');
          return done();
        }
        return callback();
      },

      // TODO: could be implemented as an event (beforeDeployAll)
      function checkIsConnectedToBlockchain(callback) {
        self.blockchain.onReady((err) => {
          callback(err);
        });
      },

      // TODO: this can be done on the fly or as part of the initialization
      function determineDefaultAccount(callback) {
        self.blockchain.determineDefaultAccount((err) => {
          callback(err);
        });
      },

      function deployAllContracts(callback) {
        self.deployAll(function (err) {
          if (!err) {
            self.events.emit('contractsDeployed');
          }
          if (err && self.fatalErrors) {
            return callback(err);
          }
          callback();
        });
      },
      function runAfterDeploy(callback) {
        self.plugins.emitAndRunActionsForEvent('contracts:deploy:afterAll', callback);
      }
    ], function (err, _result) {
      done(err);
    });
  }

}

module.exports = DeployManager;
<|endoftext|>