<commit_before>// === UI stuff ===
//TODO visualize the alchemicals in the row headers of the table
//TODO add pictures for the ingredients in the column headers of the table
//TODO add pictures for the ingredients in the radio buttons
//TODO add pictures of the potions for the check boxes
//TODO add refresh indicators http://www.material-ui.com/#/components/refresh-indicator

// === Other stuff ===
//TODO add other views
//TODO add other fact types (periscope / beginner debunking
//TODO make the view match the state for the buttons etc.

// The expected number of bits of information from real science is
// -[1/7*lg(1/7) * 7]
// = 2.807 bits

// The expected number of bits of information from experimenting randomly on an adventurer is
// -[1/7*lg(1/7) + 2/7*lg(2/7) + 1/7*lg(1/7) + 3/7*lg(3/7)]
// = 1.842 bits

import React from 'react';
// import logo from './logo.svg';
import './App.css';

import _ from 'lodash'
import update from 'react-addons-update'
import PureRenderMixin from 'react-addons-pure-render-mixin';

import {Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn} from 'material-ui/Table';
import RaisedButton from 'material-ui/RaisedButton';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

const style = {
  margin: 12,
};

// This is what an Alchemical looks like:
// [1, 1, -1]

// Here are all of the Alchemicals:
var alchemicals = [
  [-1, +1, -1],
  [+1, -1, +1],
  [+1, -1, -1],
  [-1, +1, +1],
  [-1, -1, +1],
  [+1, +1, -1],
  [-1, -1, -1],
  [+1, +1, +1],
]

var ingredients = [
  "Mushroom",
  "Fern",
  "Toad",
  "Birdclaw",
  "Flower",
  "Mandrake",
  "Scorion",
  "Feather",
]

var potions = {
  "Red+":   [+1, 0, 0],
  "Red-":   [-1, 0, 0],
  "Green+": [0, +1, 0],
  "Green-": [0, -1, 0],
  "Blue+":  [0, 0, +1],
  "Blue-":  [0, 0, -1],
  "Soup":   [0, 0, 0],
}

var Fact = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return

      {this.props.index}: {JSON.stringify(this.props.item)}
      <RaisedButton onClick={this.props.deleteFact} value={this.props.index} style={style}>Delete</RaisedButton>

  }
});

var FactList = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return
{this.props.items.map((fact, factIndex) => <Fact key={factIndex} item={fact} index={factIndex} deleteFact={this.props.deleteFact}/>)}
;
  }
});

var Ingredient = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return
<input type="radio" name="ingredient" onChange={this.props.callback}/>{this.props.name}

  }
})

var Potion = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return
<input type="checkbox" name="potion" onChange={this.props.callback}/>{this.props.name}

  }
})

var SheetCell = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return <TableRowColumn>{this.percentage()}</TableRowColumn>
  },
  percentage: function() {
    var worlds = _.filter(this.props.worlds, _.bind(function(world) {
      return _.isEqual(world[this.props.ingredientIndex], this.props.alchemical)
    }, this))
    return Math.round(100 * worlds.length / this.props.worlds.length, 0)
  }
})

var SheetRow = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return (
      <TableRow>
        <TableRowColumn>{this.props.alchemical}</TableRowColumn>
        {ingredients.map((ingredient, index) => <SheetCell ingredientIndex={index} alchemical={this.props.alchemical} key={index} worlds={this.props.worlds}/>)}
      </TableRow>
    )
  }
})

var AlchemistsSolverApp = React.createClass({
  mixins: [PureRenderMixin],

  getInitialState: function() {
    return {
      factlist: [],
      currentFact: this.makeNewFact(),
      worlds: permutator(alchemicals),
    }
  },
  makeNewFact: function() {
    return {
      ingredients: [0, 1],
      possibleResults: [false, false, false, false, false, false, false]
    }
  },
  handleSubmit: function(e) {
    e.preventDefault();
    this.setState({
      factlist: this.state.factlist.concat([this.state.currentFact]),
      worlds: _.filter(this.state.worlds, _.curry(check)(this.state.currentFact)),
    });
  },
  ingredientChange: function(ingredientIndex, ingredient) {
    var newIngredients = [];
    newIngredients[ingredientIndex] = ingredient;
    var newState = update(this.state,
      {currentFact: {ingredients: {$merge: newIngredients}}})
    this.setState(newState)
  },
  potionChange: function(potionIndex) {
    var newPossibleResults = [];
    newPossibleResults[potionIndex] = !this.state.currentFact.possibleResults[potionIndex];
    var newState = update(this.state,
      {currentFact: {possibleResults: {$merge: newPossibleResults}}})
    this.setState(newState)
  },
  render: function() {
    var self = this;
    return (
      <MuiThemeProvider>

Alchemists Solver

          <FactList items={this.state.factlist} deleteFact={this.deleteFact}/>

          <form action="" style={{display: "inline-block"}}>
            {ingredients.map((name, index) => <Ingredient name={name} ingredientNumber={0} key={index} callback={function() {self.ingredientChange(0, index)}} />)}
          </form>

          <form action="" style={{display: "inline-block"}}>
            {ingredients.map((name, index) => <Ingredient name={name} ingredientNumber={1} key={index} callback={function() {self.ingredientChange(1, index)}} />)}
          </form>

          <form action="" style={{display: "inline-block"}}>
            {_.keys(potions).map((name, index) => <Potion name={name} key={index} callback={function() {self.potionChange(index)}} />)}
          </form>

          <RaisedButton label="Add Fact" primary={true} style={style} onClick={this.handleSubmit}/>

Remaining worlds: {this.computeStuff()}

            <TableHeader displaySelectAll={false} adjustForCheckbox={false}>
              <TableRow>
                <TableHeaderColumn/>
                {ingredients.map((name, index) => <TableHeaderColumn key={index}>{name}</TableHeaderColumn>)}
              </TableRow>
            </TableHeader>
            <TableBody>
              {alchemicals.map((alchemical, index) => <SheetRow alchemical={alchemical} key={index} worlds={this.state.worlds}/>)}
            </TableBody>

      </MuiThemeProvider>
    );
  },
  deleteFact: function(e) {
    var newFactList = removeAtIndex(this.state.factlist, parseInt(e.target.value, 10))
    var worlds = permutator(alchemicals)
    for (var factIndex in newFactList) {
      var fact = newFactList[factIndex]
      console.log(fact)
      worlds = _.filter(worlds, _.curry(check)(fact))
    }
    this.setState({factlist: newFactList, worlds: worlds})
  },
  computeStuff: function() {
    return this.state.worlds.length
  }
});

// non-mutating
function removeAtIndex(arr, index) {
  return _.filter(arr, function(val, idx) {return idx !== index})
}

var ColorMapping = {
  0: "red",
  1: "green",
  2: "blue",
};

// var SignMapping = {
//   -1: "minus",
//   0: "neutral",
//   1: "plus",
// };

// Alchemical -> Alchemical -> Potion
function mix(alchemicalA, alchemicalB) {
  var mean = _.zipWith(alchemicalA, alchemicalB, function(a,b){return (a+b)/2})
  for (var index = 0; index < 3; index++) {
    if (mean[(index+1) % 3] !== 0)
      mean[index] = 0
  }

  return mean
}

function check(fact, world) {
  var alchemicalA = world[fact.ingredients[0]]
  var alchemicalB = world[fact.ingredients[1]]
  var result = mix(alchemicalA, alchemicalB)
  var potionIndex = _.findIndex(_.values(potions), _.curry(_.isEqual)(result))
  return fact.possibleResults[potionIndex]
}

// http://stackoverflow.com/a/20871714/6036628
function permutator(inputArr) {
  var results = [];

  function permute(arr, memo) {
    var cur, memo = memo || [];

    for (var i = 0; i < arr.length; i++) {
      cur = arr.splice(i, 1);
      if (arr.length === 0) {
        results.push(memo.concat(cur));
      }
      permute(arr.slice(), memo.concat(cur));
      arr.splice(i, 0, cur[0]);
    }

    return results;
  }

  return permute(inputArr);
}

// ===== Unit tests =====

// Here is what a World looks like:
var exampleWorld = [
  [+1, -1, -1],
  [-1, +1, -1],
  [+1, -1, +1],
  [-1, +1, +1],
  [+1, +1, +1],
  [-1, -1, +1],
  [+1, +1, -1],
  [-1, -1, -1],
]

// This is what an Ingredient looks like:
var exampleIngredientA = 4
var exampleIngredientB = 5

// This is what a Potion looks like:
var examplePotionA = [0, 0, 1] // this is a blue+
var examplePotionB = [0, 0, 0] // this is soup

// This is what a Fact looks like:
// {
//   ingredients: [5, 7]
//   possibleResults: [true, false, false, false, false, false, true]
// }
// combining ingredient 5 and 7 make either a red+ or a soup
var exampleFact = {
  ingredients: [exampleIngredientA, exampleIngredientB],
  possibleResults: [examplePotionA, examplePotionB]
}

console.log(check(exampleFact, exampleWorld))

export default AlchemistsSolverApp;
<commit_msg>adds todos<commit_after>// === UI stuff ===
//TODO visualize the alchemicals in the row headers of the table
//TODO add pictures for the ingredients in the column headers of the table
//TODO add pictures for the ingredients in the radio buttons
//TODO add pictures of the potions for the check boxes
//TODO add refresh indicators http://www.material-ui.com/#/components/refresh-indicator

// === Other stuff ===
//TODO add other fact types (periscope / beginner debunking
//TODO make the view match the state for the buttons etc.

// === Additional views ===
//TODO add view to see individual worlds when you have just a few

// The expected number of bits of information from real science is
// -[1/7*lg(1/7) * 7]
// = 2.807 bits

// The expected number of bits of information from experimenting randomly on an adventurer is
// -[1/7*lg(1/7) + 2/7*lg(2/7) + 1/7*lg(1/7) + 3/7*lg(3/7)]
// = 1.842 bits

import React from 'react';
// import logo from './logo.svg';
import './App.css';

import _ from 'lodash'
import update from 'react-addons-update'
import PureRenderMixin from 'react-addons-pure-render-mixin';

import {Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn} from 'material-ui/Table';
import RaisedButton from 'material-ui/RaisedButton';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

const style = {
  margin: 12,
};

// This is what an Alchemical looks like:
// [1, 1, -1]

// Here are all of the Alchemicals:
var alchemicals = [
  [-1, +1, -1],
  [+1, -1, +1],
  [+1, -1, -1],
  [-1, +1, +1],
  [-1, -1, +1],
  [+1, +1, -1],
  [-1, -1, -1],
  [+1, +1, +1],
]

var ingredients = [
  "Mushroom",
  "Fern",
  "Toad",
  "Birdclaw",
  "Flower",
  "Mandrake",
  "Scorpion",
  "Feather",
]

var potions = {
  "Red+":   [+1, 0, 0],
  "Red-":   [-1, 0, 0],
  "Green+": [0, +1, 0],
  "Green-": [0, -1, 0],
  "Blue+":  [0, 0, +1],
  "Blue-":  [0, 0, -1],
  "Soup":   [0, 0, 0],
}

var Fact = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return

      {this.props.index}: {JSON.stringify(this.props.item)}
      <RaisedButton onClick={this.props.deleteFact} value={this.props.index} style={style}>Delete</RaisedButton>

  }
});

var FactList = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return
{this.props.items.map((fact, factIndex) => <Fact key={factIndex} item={fact} index={factIndex} deleteFact={this.props.deleteFact}/>)}
;
  }
});

var Ingredient = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return
<input type="radio" name="ingredient" onChange={this.props.callback}/>{this.props.name}

  }
})

var Potion = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return
<input type="checkbox" name="potion" onChange={this.props.callback}/>{this.props.name}

  }
})

var SheetCell = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return <TableRowColumn>{this.percentage()}</TableRowColumn>
  },
  percentage: function() {
    var worlds = _.filter(this.props.worlds, _.bind(function(world) {
      return _.isEqual(world[this.props.ingredientIndex], this.props.alchemical)
    }, this))
    return Math.round(100 * worlds.length / this.props.worlds.length, 0)
  }
})

var SheetRow = React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return (
      <TableRow>
        <TableRowColumn>{this.props.alchemical}</TableRowColumn>
        {ingredients.map((ingredient, index) => <SheetCell ingredientIndex={index} alchemical={this.props.alchemical} key={index} worlds={this.props.worlds}/>)}
      </TableRow>
    )
  }
})

var AlchemistsSolverApp = React.createClass({
  mixins: [PureRenderMixin],

  getInitialState: function() {
    return {
      factlist: [],
      currentFact: this.makeNewFact(),
      worlds: permutator(alchemicals),
    }
  },
  makeNewFact: function() {
    return {
      ingredients: [0, 1],
      possibleResults: [false, false, false, false, false, false, false]
    }
  },
  handleSubmit: function(e) {
    e.preventDefault();
    this.setState({
      factlist: this.state.factlist.concat([this.state.currentFact]),
      worlds: _.filter(this.state.worlds, _.curry(check)(this.state.currentFact)),
    });
  },
  ingredientChange: function(ingredientIndex, ingredient) {
    var newIngredients = [];
    newIngredients[ingredientIndex] = ingredient;
    var newState = update(this.state,
      {currentFact: {ingredients: {$merge: newIngredients}}})
    this.setState(newState)
  },
  potionChange: function(potionIndex) {
    var newPossibleResults = [];
    newPossibleResults[potionIndex] = !this.state.currentFact.possibleResults[potionIndex];
    var newState = update(this.state,
      {currentFact: {possibleResults: {$merge: newPossibleResults}}})
    this.setState(newState)
  },
  render: function() {
    var self = this;
    return (
      <MuiThemeProvider>

Alchemists Solver

          <FactList items={this.state.factlist} deleteFact={this.deleteFact}/>

          <form action="" style={{display: "inline-block"}}>
            {ingredients.map((name, index) => <Ingredient name={name} ingredientNumber={0} key={index} callback={function() {self.ingredientChange(0, index)}} />)}
          </form>

          <form action="" style={{display: "inline-block"}}>
            {ingredients.map((name, index) => <Ingredient name={name} ingredientNumber={1} key={index} callback={function() {self.ingredientChange(1, index)}} />)}
          </form>

          <form action="" style={{display: "inline-block"}}>
            {_.keys(potions).map((name, index) => <Potion name={name} key={index} callback={function() {self.potionChange(index)}} />)}
          </form>

          <RaisedButton label="Add Fact" primary={true} style={style} onClick={this.handleSubmit}/>

Remaining worlds: {this.computeStuff()}

            <TableHeader displaySelectAll={false} adjustForCheckbox={false}>
              <TableRow>
                <TableHeaderColumn/>
                {ingredients.map((name, index) => <TableHeaderColumn key={index}>{name}</TableHeaderColumn>)}
              </TableRow>
            </TableHeader>
            <TableBody>
              {alchemicals.map((alchemical, index) => <SheetRow alchemical={alchemical} key={index} worlds={this.state.worlds}/>)}
            </TableBody>

      </MuiThemeProvider>
    );
  },
  deleteFact: function(e) {
    var newFactList = removeAtIndex(this.state.factlist, parseInt(e.target.value, 10))
    var worlds = permutator(alchemicals)
    for (var factIndex in newFactList) {
      var fact = newFactList[factIndex]
      console.log(fact)
      worlds = _.filter(worlds, _.curry(check)(fact))
    }
    this.setState({factlist: newFactList, worlds: worlds})
  },
  computeStuff: function() {
    return this.state.worlds.length
  }
});

// non-mutating
function removeAtIndex(arr, index) {
  return _.filter(arr, function(val, idx) {return idx !== index})
}

var ColorMapping = {
  0: "red",
  1: "green",
  2: "blue",
};

// var SignMapping = {
//   -1: "minus",
//   0: "neutral",
//   1: "plus",
// };

// Alchemical -> Alchemical -> Potion
function mix(alchemicalA, alchemicalB) {
  var mean = _.zipWith(alchemicalA, alchemicalB, function(a,b){return (a+b)/2})
  for (var index = 0; index < 3; index++) {
    if (mean[(index+1) % 3] !== 0)
      mean[index] = 0
  }

  return mean
}

function check(fact, world) {
  var alchemicalA = world[fact.ingredients[0]]
  var alchemicalB = world[fact.ingredients[1]]
  var result = mix(alchemicalA, alchemicalB)
  var potionIndex = _.findIndex(_.values(potions), _.curry(_.isEqual)(result))
  return fact.possibleResults[potionIndex]
}

// http://stackoverflow.com/a/20871714/6036628
function permutator(inputArr) {
  var results = [];

  function permute(arr, memo) {
    var cur, memo = memo || [];

    for (var i = 0; i < arr.length; i++) {
      cur = arr.splice(i, 1);
      if (arr.length === 0) {
        results.push(memo.concat(cur));
      }
      permute(arr.slice(), memo.concat(cur));
      arr.splice(i, 0, cur[0]);
    }

    return results;
  }

  return permute(inputArr);
}

// ===== Unit tests =====

// Here is what a World looks like:
var exampleWorld = [
  [+1, -1, -1],
  [-1, +1, -1],
  [+1, -1, +1],
  [-1, +1, +1],
  [+1, +1, +1],
  [-1, -1, +1],
  [+1, +1, -1],
  [-1, -1, -1],
]

// This is what an Ingredient looks like:
var exampleIngredientA = 4
var exampleIngredientB = 5

// This is what a Potion looks like:
var examplePotionA = [0, 0, 1] // this is a blue+
var examplePotionB = [0, 0, 0] // this is soup

// This is what a Fact looks like:
// {
//   ingredients: [5, 7]
//   possibleResults: [true, false, false, false, false, false, true]
// }
// combining ingredient 5 and 7 make either a red+ or a soup
var exampleFact = {
  ingredients: [exampleIngredientA, exampleIngredientB],
  possibleResults: [examplePotionA, examplePotionB]
}

console.log(check(exampleFact, exampleWorld))

export default AlchemistsSolverApp;
<|endoftext|>


<commit_before>/**
 * Developer: Ksenia Kartvelishvili
 * Date: 26.06.2015
 * Copyright: 2009-2015 Comindware®
 *       All Rights Reserved
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Comindware
 *       The copyright notice above does not evidence any
 *       actual or intended publication of such source code.
 */

/* global define, require, Handlebars, Backbone, Marionette, $, _, Localizer, Promise */

define(['core/utils/helpers', './loading/views/LoadingView'],
    function (helpers, LoadingView) {
        'use strict';

        return Marionette.Behavior.extend({
            initialize: function (options, view) {
                helpers.ensureOption(options, 'region');

                this.loadingViewOptions = {
                    text: options.text || Localizer.get('PROCESS.COMMON.DEFAULTLOADING')
                };
                view.loading = {
                    setLoading: this.setLoading.bind(this)
                };
            },

            setLoading: function (visible) {
                if (_.isBoolean(visible)) {
                    if (visible) {
                        this.view[this.options.region].show(new LoadingView(this.loadingViewOptions));
                    } else {
                        this.view[this.options.region].reset();
                    }
                } else if (_.isObject(visible)) {
                    this.setLoading(true);
                    Promise.resolve(visible).bind(this).then(function () {
                        //noinspection JSPotentiallyInvalidUsageOfThis
                        this.setLoading(false);
                    }, function () {
                        //noinspection JSPotentiallyInvalidUsageOfThis
                        this.setLoading(false);
                    });
                } else {
                    helpers.throwError('Invalid argument format.', 'FormatError');
                }
            }
        });
    });
<commit_msg>[183434] create model & moduleView<commit_after>/**
 * Developer: Ksenia Kartvelishvili
 * Date: 26.06.2015
 * Copyright: 2009-2015 Comindware®
 *       All Rights Reserved
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Comindware
 *       The copyright notice above does not evidence any
 *       actual or intended publication of such source code.
 */

/* global define, require, Handlebars, Backbone, Marionette, $, _, Localizer, Promise */

define(['core/utils/helpers', './loading/views/LoadingView'],
    function (helpers, LoadingView) {
        'use strict';

        return Marionette.Behavior.extend({
            initialize: function (options, view) {
                helpers.ensureOption(options, 'region');

                this.loadingViewOptions = {
                    text: options.text || Localizer.get('PROCESS.COMMON.DEFAULTLOADINGSMALL')
                };
                view.loading = {
                    setLoading: this.setLoading.bind(this)
                };
            },

            setLoading: function (visible) {
                if (_.isBoolean(visible)) {
                    if (visible) {
                        this.view[this.options.region].show(new LoadingView(this.loadingViewOptions));
                    } else {
                        this.view[this.options.region].reset();
                    }
                } else if (_.isObject(visible)) {
                    this.setLoading(true);
                    Promise.resolve(visible).bind(this).then(function () {
                        //noinspection JSPotentiallyInvalidUsageOfThis
                        this.setLoading(false);
                    }, function () {
                        //noinspection JSPotentiallyInvalidUsageOfThis
                        this.setLoading(false);
                    });
                } else {
                    helpers.throwError('Invalid argument format.', 'FormatError');
                }
            }
        });
    });
<|endoftext|>


<commit_before>var counter=false;
var cancel='';

	function comparePwds(){

	  var pass = document.getElementById('frmPass');
	  var nomatch = document.getElementById('PassNoMatch');
	  var passscore = document.getElementById('passScore');

	  if (passscore.value != 'strong' && passscore.value != 'stronger'){

	    nomatch.innerHTML = "Password is too weak";
	   nomatch.style.display = 'inline-block';

	   return false;

	  }

	 if (pass.value != document.getElementById('frmPassConf').value){
	   nomatch.innerHTML = "Passwords don't match";
	   nomatch.style.display = 'inline-block';

	   return false;
	 }

	 if (pass.value == null || pass.value == ''){

	   document.getElementById('PassNoMatch').innerHTML = "You must set a password";
	   nomatch.style.display = 'inline-block';
	   return false;
	 }
	 nomatch.style.display = 'none';
	  return true;

	}

	function validateUserAdd(){
	  var username = document.getElementById('frmUsername');
	  var RealName = document.getElementById('frmRName');
	  var error = 0;

	 if (username.value == null || username.value == ''){
	  username.className = 'frmEntryMissed';
	  error = 1;
	 }

	   if (RealName.value == null || RealName.value == ''){
	  RealName.className = 'frmEntryMissed';
	  error = 1;
	 }

	  if (!comparePwds()){

	   error = 1;
	  }

	  if (error == 1){

	   alert("Please correct input errors and re-submit");
	   return false;
	  }

	  return true;
	}

	function validateUserEdit(){

	  var username = document.getElementById('frmUsername');
	  var RealName = document.getElementById('frmRName');
	  var pass = document.getElementById('frmPass');
	  var error = 0;

	  if (username.value == null || username.value == ''){
	  username.className = 'frmEntryMissed';
	  error = 1;
	 }

	   if (RealName.value == null || RealName.value == ''){
	  RealName.className = 'frmEntryMissed';
	  error = 1;
	 }

	  if (pass.value != null && pass.value != ''){
	  if (!comparePwds()){

	   error = 1;
	  }
	  }

	  if (error == 1){

	   alert("Please correct input errors and re-submit");
	   return false;
	  }

	  return true;

	}

function getCreds(id){

  var xmlhttp;
var resp;
var jsonObj;

var clicky = document.getElementById('retrievePassword'+id);
var Address = document.getElementById('Address'+id);
var User = document.getElementById('UserName'+id);
var Pass = document.getElementById('Password'+id);

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0){
     // Request failed, authentication issue maybe?
      clicky.innerHTML = 'Failed to retrieve credentials. Click to try again';
      return false;
    }

    var limit = document.getElementById('defaultInterval').value;
    var cnt = document.getElementById('PassCount'+id);
     cnt.value = limit;
     var count = limit;
      Address.innerHTML = resp[2];
      Pass.innerHTML = resp[1];
      User.innerHTML = resp[3];
      clicky.innerHTML = 'Displaying Password for ' +count+ ' seconds';

      if (counter){
	cancel=1;

	setTimeout(function() {cancel=false; counter=setInterval("Credtimer('"+id+"')", 1000);},1000);
	return;
      }

      counter=setInterval("Credtimer('"+id+"')", 1000);

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=retCred&id='+id);

}

function DelCust(id){

  var xmlhttp;
var resp;
var jsonObj;

if (!confirm("Are you sure you want to delete this customer and all associated credentials?")){
 return false;
}

var credrow = document.getElementById('CustDisp'+id);
var notify = document.getElementById('NotificationArea');

if (document.getElementById('Custmenu'+id)){
	var menu = document.getElementById('Custmenu'+id);
      }

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0 || resp[1] == 0){
     // Request failed, authentication issue maybe?
      notify.innerHTML += '
Failed to Delete
';
      return false;
    }
      credrow.parentNode.removeChild(credrow);
    notify.innerHTML += '
Customer and all associated credentials Deleted
';

	  if (menu){
	  menu.parentNode.removeChild(menu);
	  }

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=delCust&id='+id);

}

function delGroup(id){

  var xmlhttp;
var resp;
var jsonObj;

if (!confirm("Are you sure you want to delete this group (any credentials recorded against the group will be deleted)?")){
 return false;
}

var credrow = document.getElementById('GroupDisp'+id);

var notify = document.getElementById('NotificationArea');

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0 || resp[1] == 0){
     // Request failed, authentication issue maybe?
       notify.innerHTML += '
Failed to Delete
';
      return false;
    }
      credrow.parentNode.removeChild(credrow);
      notify.innerHTML += '
Group Deleted
';

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=delGroup&id='+id);

}

function delUser(id){

  var xmlhttp;
var resp;
var jsonObj;

if (!confirm("Are you sure you want to delete this user?")){
 return false;
}

var credrow = document.getElementById('User'+id);

var notify = document.getElementById('NotificationArea');

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0 || resp[1] == 0){
     // Request failed, authentication issue maybe?
       notify.innerHTML += '
Failed to Delete
';
      return false;
    }
      credrow.parentNode.removeChild(credrow);
      notify.innerHTML += '
User Deleted
';

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=delUser&id='+id);

}

function delCredType(id){

  var xmlhttp;
var resp;
var jsonObj;

if (!confirm("Are you sure you want to delete this Credential Type (any associated credentials will be deleted)?")){
 return false;
}

var credrow = document.getElementById('CredType'+id);

var notify = document.getElementById('NotificationArea');

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0 || resp[1] == 0){
     // Request failed, authentication issue maybe?
       notify.innerHTML += '
Failed to Delete
';
      return false;
    }
      credrow.parentNode.removeChild(credrow);
      notify.innerHTML += '
Credential Type Deleted
';

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=delCredType&id='+id);

}

function DelCred(id){

  var xmlhttp;
var resp;
var jsonObj;

if (!confirm("Are you sure you want to delete this credential?")){
 return false;
}

var credrow = document.getElementById('CredDisp'+id);

var notify = document.getElementById('NotificationArea');

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0 || resp[1] == 0){
     // Request failed, authentication issue maybe?
       notify.innerHTML += '
Failed to Delete
';
      return false;
    }
      credrow.parentNode.removeChild(credrow);
      notify.innerHTML += '
Customer and all associated credentials Deleted
';

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=delCred&id='+id);

}

function Credtimer(id)
{
  var cnt = document.getElementById('PassCount'+id);
  var count=cnt.value-1;
  cnt.value = count;
  var field = document.getElementById('retrievePassword'+id);

  if (count <= 0 || cancel == 1)
  {
     clearInterval(counter);

     field.innerHTML = 'Display Password';
     document.getElementById('Address'+id).innerHTML = '';
     document.getElementById('UserName'+id).innerHTML = '';
     document.getElementById('Password'+id).innerHTML = '';
     return;
  }

  field.innerHTML = 'Displaying Password for ' +count+ ' seconds';
}

function checkNewCred(){

  var cred = document.getElementById('frmCredential');
  var user = document.getElementById('frmUser');
  var addr = document.getElementById('frmAddress');

if (cred.value.indexOf("http") !== -1){

if (confirm("Click OK to make this credential a hyperlink in the database, click cancel to set not clicky")){

document.getElementById('frmClicky').value = 1;
}

}
}

function checkEditCred(){

  var cred = document.getElementById('frmCredential');
  var user = document.getElementById('frmUser');
  var addr = document.getElementById('frmAddress');

if (cred.value.indexOf("http") !== -1){

if (confirm("Click OK to make this credential a hyperlink in the database, click cancel to set not clicky")){

document.getElementById('frmClicky').value = 1;
}

}

// See if any have been blanked

if (cred.value == null || cred.value == ''){
 cred.value = ' ';
}

if (user.value == null || user.value == ''){
 user.value = ' ';
}

if (addr.value == null || addr.value == ''){
 cred.value = ' ';
}

return true;
}

function noCredTypes(){

  $(document).ready(function(){
    if (document.getElementById('AddCredBtnTop')){
     var btntop =  document.getElementById('AddCredBtnTop');
     btntop.parentNode.removeChild(btntop);
    }

    if (document.getElementById('AddCredBtnBottom')){
     var btntop =  document.getElementById('AddCredBtnBottom');
     btntop.parentNode.removeChild(btntop);
    }
  });

}<commit_msg>Creating Search Javascript<commit_after>var counter=false;
var cancel='';

	function comparePwds(){

	  var pass = document.getElementById('frmPass');
	  var nomatch = document.getElementById('PassNoMatch');
	  var passscore = document.getElementById('passScore');

	  if (passscore.value != 'strong' && passscore.value != 'stronger'){

	    nomatch.innerHTML = "Password is too weak";
	   nomatch.style.display = 'inline-block';

	   return false;

	  }

	 if (pass.value != document.getElementById('frmPassConf').value){
	   nomatch.innerHTML = "Passwords don't match";
	   nomatch.style.display = 'inline-block';

	   return false;
	 }

	 if (pass.value == null || pass.value == ''){

	   document.getElementById('PassNoMatch').innerHTML = "You must set a password";
	   nomatch.style.display = 'inline-block';
	   return false;
	 }
	 nomatch.style.display = 'none';
	  return true;

	}

	function validateUserAdd(){
	  var username = document.getElementById('frmUsername');
	  var RealName = document.getElementById('frmRName');
	  var error = 0;

	 if (username.value == null || username.value == ''){
	  username.className = 'frmEntryMissed';
	  error = 1;
	 }

	   if (RealName.value == null || RealName.value == ''){
	  RealName.className = 'frmEntryMissed';
	  error = 1;
	 }

	  if (!comparePwds()){

	   error = 1;
	  }

	  if (error == 1){

	   alert("Please correct input errors and re-submit");
	   return false;
	  }

	  return true;
	}

	function validateUserEdit(){

	  var username = document.getElementById('frmUsername');
	  var RealName = document.getElementById('frmRName');
	  var pass = document.getElementById('frmPass');
	  var error = 0;

	  if (username.value == null || username.value == ''){
	  username.className = 'frmEntryMissed';
	  error = 1;
	 }

	   if (RealName.value == null || RealName.value == ''){
	  RealName.className = 'frmEntryMissed';
	  error = 1;
	 }

	  if (pass.value != null && pass.value != ''){
	  if (!comparePwds()){

	   error = 1;
	  }
	  }

	  if (error == 1){

	   alert("Please correct input errors and re-submit");
	   return false;
	  }

	  return true;

	}

function getCreds(id){

  var xmlhttp;
var resp;
var jsonObj;

var clicky = document.getElementById('retrievePassword'+id);
var Address = document.getElementById('Address'+id);
var User = document.getElementById('UserName'+id);
var Pass = document.getElementById('Password'+id);

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0){
     // Request failed, authentication issue maybe?
      clicky.innerHTML = 'Failed to retrieve credentials. Click to try again';
      return false;
    }

    var limit = document.getElementById('defaultInterval').value;
    var cnt = document.getElementById('PassCount'+id);
     cnt.value = limit;
     var count = limit;
      Address.innerHTML = resp[2];
      Pass.innerHTML = resp[1];
      User.innerHTML = resp[3];
      clicky.innerHTML = 'Displaying Password for ' +count+ ' seconds';

      if (counter){
	cancel=1;

	setTimeout(function() {cancel=false; counter=setInterval("Credtimer('"+id+"')", 1000);},1000);
	return;
      }

      counter=setInterval("Credtimer('"+id+"')", 1000);

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=retCred&id='+id);

}

function DelCust(id){

  var xmlhttp;
var resp;
var jsonObj;

if (!confirm("Are you sure you want to delete this customer and all associated credentials?")){
 return false;
}

var credrow = document.getElementById('CustDisp'+id);
var notify = document.getElementById('NotificationArea');

if (document.getElementById('Custmenu'+id)){
	var menu = document.getElementById('Custmenu'+id);
      }

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0 || resp[1] == 0){
     // Request failed, authentication issue maybe?
      notify.innerHTML += '
Failed to Delete
';
      return false;
    }
      credrow.parentNode.removeChild(credrow);
    notify.innerHTML += '
Customer and all associated credentials Deleted
';

	  if (menu){
	  menu.parentNode.removeChild(menu);
	  }

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=delCust&id='+id);

}

function delGroup(id){

  var xmlhttp;
var resp;
var jsonObj;

if (!confirm("Are you sure you want to delete this group (any credentials recorded against the group will be deleted)?")){
 return false;
}

var credrow = document.getElementById('GroupDisp'+id);

var notify = document.getElementById('NotificationArea');

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0 || resp[1] == 0){
     // Request failed, authentication issue maybe?
       notify.innerHTML += '
Failed to Delete
';
      return false;
    }
      credrow.parentNode.removeChild(credrow);
      notify.innerHTML += '
Group Deleted
';

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=delGroup&id='+id);

}

function delUser(id){

  var xmlhttp;
var resp;
var jsonObj;

if (!confirm("Are you sure you want to delete this user?")){
 return false;
}

var credrow = document.getElementById('User'+id);

var notify = document.getElementById('NotificationArea');

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0 || resp[1] == 0){
     // Request failed, authentication issue maybe?
       notify.innerHTML += '
Failed to Delete
';
      return false;
    }
      credrow.parentNode.removeChild(credrow);
      notify.innerHTML += '
User Deleted
';

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=delUser&id='+id);

}

function delCredType(id){

  var xmlhttp;
var resp;
var jsonObj;

if (!confirm("Are you sure you want to delete this Credential Type (any associated credentials will be deleted)?")){
 return false;
}

var credrow = document.getElementById('CredType'+id);

var notify = document.getElementById('NotificationArea');

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0 || resp[1] == 0){
     // Request failed, authentication issue maybe?
       notify.innerHTML += '
Failed to Delete
';
      return false;
    }
      credrow.parentNode.removeChild(credrow);
      notify.innerHTML += '
Credential Type Deleted
';

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=delCredType&id='+id);

}

function DelCred(id){

  var xmlhttp;
var resp;
var jsonObj;

if (!confirm("Are you sure you want to delete this credential?")){
 return false;
}

var credrow = document.getElementById('CredDisp'+id);

var notify = document.getElementById('NotificationArea');

  if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
  }
else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    resp = xmlhttp.responseText.split('|..|');
    if (resp[0] == 0 || resp[1] == 0){
     // Request failed, authentication issue maybe?
       notify.innerHTML += '
Failed to Delete
';
      return false;
    }
      credrow.parentNode.removeChild(credrow);
      notify.innerHTML += '
Customer and all associated credentials Deleted
';

      }

    }

xmlhttp.open("POST","api.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('option=delCred&id='+id);

}

function Credtimer(id)
{
  var cnt = document.getElementById('PassCount'+id);
  var count=cnt.value-1;
  cnt.value = count;
  var field = document.getElementById('retrievePassword'+id);

  if (count <= 0 || cancel == 1)
  {
     clearInterval(counter);

     field.innerHTML = 'Display Password';
     document.getElementById('Address'+id).innerHTML = '';
     document.getElementById('UserName'+id).innerHTML = '';
     document.getElementById('Password'+id).innerHTML = '';
     return;
  }

  field.innerHTML = 'Displaying Password for ' +count+ ' seconds';
}

function checkNewCred(){

  var cred = document.getElementById('frmCredential');
  var user = document.getElementById('frmUser');
  var addr = document.getElementById('frmAddress');

if (cred.value.indexOf("http") !== -1){

if (confirm("Click OK to make this credential a hyperlink in the database, click cancel to set not clicky")){

document.getElementById('frmClicky').value = 1;
}

}
}

function checkEditCred(){

  var cred = document.getElementById('frmCredential');
  var user = document.getElementById('frmUser');
  var addr = document.getElementById('frmAddress');

if (cred.value.indexOf("http") !== -1){

if (confirm("Click OK to make this credential a hyperlink in the database, click cancel to set not clicky")){

document.getElementById('frmClicky').value = 1;
}

}

// See if any have been blanked

if (cred.value == null || cred.value == ''){
 cred.value = ' ';
}

if (user.value == null || user.value == ''){
 user.value = ' ';
}

if (addr.value == null || addr.value == ''){
 cred.value = ' ';
}

return true;
}

function noCredTypes(){

  $(document).ready(function(){
    if (document.getElementById('AddCredBtnTop')){
     var btntop =  document.getElementById('AddCredBtnTop');
     btntop.parentNode.removeChild(btntop);
    }

    if (document.getElementById('AddCredBtnBottom')){
     var btntop =  document.getElementById('AddCredBtnBottom');
     btntop.parentNode.removeChild(btntop);
    }
  });

}

/****                  SEARCH FUNCTIONS                 *******/

function SearchTable(val,tbl,dispdiv,cellNr){

  // Many thanks to http://www.vonloesch.de/node/23 for the headstart on this function!

  // Reset the display div
  var disp = document.getElementById(dispdiv);
  disp.innerHTML = '';

  // Only search after 3 chars have been entered
  if (val.length < 3){
    return;
    }

  var suche = val.toLowerCase();
  var table = document.getElementById(tbl);

  var ele;
	for (var r = 0; r < table.rows.length; r++){
		ele = table.rows[r].cells[cellNr].innerHTML.replace(/<[^>]+>/g,"");
		if (ele.toLowerCase().indexOf(suche)>=0 ){
		  disp.style.display = 'block';
		  disp.innerHTML += table.rows[r].cells[cellNr].innerHTML;

		  }

	}

}

function hideSearchDiv(dispdiv){
  var div = document.getElementById(dispdiv);
  div.style.display = 'none';
}

function checkExistingSearch(val,div){
      if (val.length > 3){
	  document.getElementById(div).style.display = 'block';
	  }
}
<|endoftext|>


<commit_before>'use strict';

/* eslint-disable max-len, complexity, no-else-return, require-jsdoc */

const Generator = require('yeoman-generator');
const chalk = require('chalk');
const yosay = require('yosay');
const request = require('request');
const path = require('path');
const fs = require('fs');
const glob = require('glob');
const _ = require('lodash');

module.exports = class extends Generator {

	constructor(args, opts) {
		// Calling the super constructor
		super(args, opts);

		this._pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf8'));

		this._passedInOptions = {
			name: this.options.name,
			viewExt: this.options.viewExt,
			templateEngine: this.options.templateEngine,
			clientTpl: this.options.clientTpl,
			exampleCode: this.options.exampleCode,
			exporter: this.options.exporter,
		};

		this.option('name', {
			desc: 'the name of your app',
			type: String,
			defaults: this._passedInOptions.name || path.basename(process.cwd()),
		});
		this.options.name = _.kebabCase(this.options.name);

		this._templateEngineOptions = ['hbs', 'twig'];
		this.option('templateEngine', {
			desc: `your desired template engine [${this._templateEngineOptions.join('|')}]`,
			type: String,
			defaults: this._passedInOptions.templateEngine || this._templateEngineOptions[0],
		});

		this._viewExtOptions = ['hbs', 'twig'];
		this.option('viewExt', {
			desc: `your desired view file extension [${this._viewExtOptions.join('|')}]`,
			type: String,
			defaults: this._passedInOptions.viewExt || this._viewExtOptions[0],
		});

		this.option('clientTpl', {
			desc: 'do you need client side templates',
			type: Boolean,
			defaults: this._passedInOptions.clientTpl || false,
		});

		this.option('exampleCode', {
			desc: 'do you want to include the example code',
			type: Boolean,
			defaults: this._passedInOptions.exampleCode || false,
		});

		this.option('exporter', {
			desc: 'do you need static exporting functionalities',
			type: Boolean,
			defaults: this._passedInOptions.exporter || false,
		});

		this.option('skipQuestions', {
			desc: 'use default for not specified options and skip questions',
			type: Boolean,
			defaults: false,
		});

		this._skipQuestions = this.options.skipQuestions;
	}

	initializing() {}

	prompting() {

		this.log(yosay(
			`Welcome to the awe-inspiring ${chalk.cyan('Nitro')} generator!`
		));

		// check whether there is already a nitro application in place and we only have to update the application
		const json = this.fs.readJSON(this.destinationPath('.yo-rc.json'), { 'new': true });

		if (!json.new) {
			// update existing application
			return this.prompt([
				{
					name: 'update',
					type: 'confirm',
					message: `There is already a ${chalk.cyan('Nitro')} application in place! Should I serve you an update?`,
					default: true,
				},
			]).then((answers) => {
				this._update = answers.update;
				this.options.skipInstall = true;

				if (!this._update) {
					return;
				}

				const config = this.config.getAll();
				if (config) {
					this.options.name = config.name || this.options.name;
					this.options.viewExt = config.viewExtension || config.templateEngine ? config.templateEngine : this.options.viewExt;
					this.options.templateEngine = config.templateEngine || this.options.templateEngine;
					this.options.clientTpl = typeof config.clientTemplates === 'boolean' ? config.clientTemplates : this.options.clientTpl;
					this.options.exampleCode = typeof config.exampleCode === 'boolean' ? config.exampleCode : this.options.exampleCode;
					this.options.exporter = typeof config.exporter === 'boolean' ? config.exporter : this.options.exporter;

					this.options.name = _.kebabCase(this.options.name);
				}
			});
		} else {
			// create new application
			return this.prompt([
				{
					name: 'name',
					message: 'What\'s the name of your app?',
					default: this.options.name,
					when: () => !this._skipQuestions && !this._passedInOptions.name,
				},
				{
					name: 'templateEngine',
					type: 'list',
					message: 'What\'s your desired template engine?',
					choices: this._templateEngineOptions,
					default: this.options.templateEngine,
					store: true,
					when: () => !this._skipQuestions && !this._passedInOptions.templateEngine,
				},
				{
					name: 'clientTpl',
					type: 'confirm',
					message: 'Would you like to include client side templates?',
					default: this.options.clientTpl,
					store: true,
					when: () => !this._skipQuestions && typeof this._passedInOptions.clientTpl !== 'boolean',
				},
				{
					name: 'exampleCode',
					type: 'confirm',
					message: 'Would you like to include the example code?',
					default: this.options.exampleCode,
					store: true,
					when: () => !this._skipQuestions && typeof this._passedInOptions.exampleCode !== 'boolean',
				},
				{
					name: 'exporter',
					type: 'confirm',
					message: 'Would you like to include static exporting functionalities?',
					default: this.options.exporter,
					store: true,
					when: () => !this._skipQuestions && typeof this._passedInOptions.exporter !== 'boolean',
				},
			]).then((answers) => {
				this.options.name = answers.name || this.options.name;
				this.options.templateEngine = answers.templateEngine || this.options.templateEngine;
				this.options.viewExt = this.options.templateEngine;
				this.options.clientTpl = answers.clientTpl !== undefined ? answers.clientTpl : this.options.clientTpl;
				this.options.exampleCode = answers.exampleCode !== undefined ? answers.exampleCode : this.options.exampleCode;
				this.options.exporter = answers.exporter !== undefined ? answers.exporter : this.options.exporter;

				this.options.name = _.kebabCase(this.options.name);

				this.config.set('name', this.options.name);
				this.config.set('templateEngine', this.options.templateEngine);
				this.config.set('clientTemplates', this.options.clientTpl);
				this.config.set('exampleCode', this.options.exampleCode);
				this.config.set('exporter', this.options.exporter);

				this.config.save();
			});
		}
	}

	writing() {

		this.log('Scaffolding your app');

		const files = glob.sync('**/*', { cwd: this.sourceRoot(), nodir: true, dot: true });

		const tplFiles = [
			// files to process with copyTpl
			'config/default.js',
			'config/webpack/options.js',
			'project/docs/nitro.md',
			'project/docs/client-templates.md',
			'project/helpers/readme.md',
			'src/patterns/molecules/example/example.hbs',
			'src/patterns/molecules/example/example.twig',
			'src/patterns/molecules/example/schema.json',
			'src/patterns/molecules/example/index.js',
			'src/proto/js/prototype.js',
			'src/views/index.hbs',
			'src/views/index.twig',
			'src/views/_partials/head.hbs',
			'src/views/_partials/head.twig',
			'src/ui.js',
			'src/proto.js',
			'tests/backstop/backstop.config.js',
			'docker-compose.yml',
			'docker-compose-dev.yml',
			'gulpfile.js',
			'package.json',
		];
		const ignores = [
			// files to ignore
			'.DS_Store',
			'.npmignore',
		];
		const ignoresOnUpdate = [
			// files to ignore on updating projects
			'config/local.js',
		];
		const clientTplFiles = [
			// files only for this.options.clientTpl===true
			'src/patterns/molecules/example/_data/example-template.json',
			'src/patterns/molecules/example/js/decorator/example-template.js',
			'src/patterns/molecules/example/template/example.hbs',
			'src/patterns/molecules/example/template/example.links.hbs',
			'src/patterns/molecules/example/template/partial/example.link.hbs',
			'project/docs/client-templates.md',
			'project/blueprints/pattern/template/$pattern$.hbs',
		];
		const viewFiles = [
			// all view files exists in different templateEngine variants
			'src/views/404',
			'src/views/index',
			'src/views/example/patterns',
			'src/views/_layouts/default',
			'src/views/_partials/foot',
			'src/views/_partials/head',
			'src/patterns/atoms/box/box',
			'src/patterns/atoms/button/button',
			'src/patterns/atoms/checkbox/checkbox',
			'src/patterns/atoms/cta/cta',
			'src/patterns/atoms/datepicker/datepicker',
			'src/patterns/atoms/gondel/gondel',
			'src/patterns/atoms/heading/heading',
			'src/patterns/atoms/icon/icon',
			'src/patterns/atoms/image/image',
			'src/patterns/atoms/list/list',
			'src/patterns/atoms/loader/loader',
			'src/patterns/atoms/lottie/lottie',
			'src/patterns/atoms/stage/stage',
			'src/patterns/molecules/example/example',
			'project/blueprints/pattern/$pattern$',
		];
		const examplePaths = [
			// paths only for this.options.exampleCode===true
			'project/routes/',
			'public/content/',
			'src/views/example/',
			'src/patterns/',
			'src/proto/',
			'src/shared/',
			'tests/cypress/cypress/integration/examples/'
		];
		const exampleIncludeAnyway = [
			// example file "parts" included for this.options.exampleCode===false
			'project/routes/readme.md',
			'src/patterns/readme.md',
			'src/proto/js/prototype.js',
			'src/proto/readme.md',
			'src/shared/readme.md',
			'.gitkeep',
		];
		const exporterFiles = [
			// files for this.options.exporter===true
			'config/default/exporter.js',
		];

		const templateData = {
			name: this.options.name,
			version: this._pkg.version,
			options: this.options,
		};

		files.forEach((file) => {

			// exclude ignores
			if (_.indexOf(ignores, file) !== -1) {
				return;
			}

			// exclude update ignores
			if (this._update) {
				if (_.indexOf(ignoresOnUpdate, file) !== -1) {
					return;
				}
			}

			// Client side templates only Files
			if (!this.options.clientTpl) {
				if (_.indexOf(clientTplFiles, file) !== -1) {
					return;
				}
			}

			// Example only Files
			if (!this.options.exampleCode) {
				if (
					examplePaths.some((v) => file.indexOf(v) >= 0) &&
					exampleIncludeAnyway.every((v) => { return file.indexOf(v) === -1; })
				) {
					return;
				}
			}

			// Exporter only Files
			if (!this.options.exporter) {
				if (_.indexOf(exporterFiles, file) !== -1) {
					return;
				}
			}

			const ext = path.extname(file).substring(1);
			const fileWithoutExt = file.substring(0, (file.length - ext.length - 1));
			const sourcePath = this.templatePath(file);
			let destinationPath = this.destinationPath(file);

			// check if it's a view file
			if (_.indexOf(viewFiles, fileWithoutExt) !== -1) {
				if (ext !== this.options.templateEngine) {
					// return view files with ext not matching the current templateEngine
					return;
				}
				if (this.options.viewExt !== this.options.templateEngine) {
					// sanity check for update case of old generated app's having viewExt other than hbs
					const targetExt = `.${this.options.viewExt !== 0 ? this.options.viewExt : this._viewExtOptions[0]}`;
					destinationPath = destinationPath.replace(path.extname(destinationPath), targetExt);
				}
			}

			if (_.indexOf(tplFiles, file) !== -1) {
				this.fs.copyTpl(sourcePath, destinationPath, templateData);
				return;
			}

			// rename CUTAWAY.gitignore to .gitignore
			if (destinationPath.indexOf('CUTAWAY') !== -1) {
				destinationPath = destinationPath.replace(/CUTAWAY/g, '');
			}

			this.fs.copy(sourcePath, destinationPath);
		}, this);
	}

	install() {
		this.installDependencies({
			npm: true,
			bower: false,
			yarn: false,
			skipInstall: this.options.skipInstall,
		});
	}

	end() {
		const filesToCopy = [
			{
				do: this.options.exporter,
				src: 'node_modules/@nitro/exporter/readme.md',
				srcWeb: 'https://raw.githubusercontent.com/namics/generator-nitro/master/packages/nitro-exporter/readme.md',
				dest: 'project/docs/nitro-exporter.md',
			},
			{
				do: true,
				src: 'node_modules/@nitro/webpack/readme.md',
				srcWeb: 'https://raw.githubusercontent.com/namics/generator-nitro/master/packages/nitro-webpack/readme.md',
				dest: 'project/docs/nitro-webpack.md',
			},
		];
		try {
			filesToCopy.forEach((file) => {
				if (file.do) {
					if (!this.options.skipInstall) {
						// get readme from current package version
						this.fs.copy(this.destinationPath(file.src), this.destinationPath(file.dest));
					} else {
						// get readme from github master branch
						request
							.get(file.srcWeb)
							.pipe(fs.createWriteStream(this.destinationPath(file.dest)));
					}
				}
			});
		} catch (e) {
			this.log(chalk.red(e.message));
		}

		if (this._update) {
			this.log(yosay(
				`All done – Check local changes and then\nrun \`npm install\` to update your project.`
			));
		} else {
			this.log(yosay(
				`All done –\nrun \`npm start\` to start ${chalk.cyan('Nitro')} in development mode.`
			));
		}
	}
};
<commit_msg>fix(generator): ignore example code on updates<commit_after>'use strict';

/* eslint-disable max-len, complexity, no-else-return, require-jsdoc */

const Generator = require('yeoman-generator');
const chalk = require('chalk');
const yosay = require('yosay');
const request = require('request');
const path = require('path');
const fs = require('fs');
const glob = require('glob');
const _ = require('lodash');

module.exports = class extends Generator {

	constructor(args, opts) {
		// Calling the super constructor
		super(args, opts);

		this._pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf8'));

		this._passedInOptions = {
			name: this.options.name,
			viewExt: this.options.viewExt,
			templateEngine: this.options.templateEngine,
			clientTpl: this.options.clientTpl,
			exampleCode: this.options.exampleCode,
			exporter: this.options.exporter,
		};

		this.option('name', {
			desc: 'the name of your app',
			type: String,
			defaults: this._passedInOptions.name || path.basename(process.cwd()),
		});
		this.options.name = _.kebabCase(this.options.name);

		this._templateEngineOptions = ['hbs', 'twig'];
		this.option('templateEngine', {
			desc: `your desired template engine [${this._templateEngineOptions.join('|')}]`,
			type: String,
			defaults: this._passedInOptions.templateEngine || this._templateEngineOptions[0],
		});

		this._viewExtOptions = ['hbs', 'twig'];
		this.option('viewExt', {
			desc: `your desired view file extension [${this._viewExtOptions.join('|')}]`,
			type: String,
			defaults: this._passedInOptions.viewExt || this._viewExtOptions[0],
		});

		this.option('clientTpl', {
			desc: 'do you need client side templates',
			type: Boolean,
			defaults: this._passedInOptions.clientTpl || false,
		});

		this.option('exampleCode', {
			desc: 'do you want to include the example code',
			type: Boolean,
			defaults: this._passedInOptions.exampleCode || false,
		});

		this.option('exporter', {
			desc: 'do you need static exporting functionalities',
			type: Boolean,
			defaults: this._passedInOptions.exporter || false,
		});

		this.option('skipQuestions', {
			desc: 'use default for not specified options and skip questions',
			type: Boolean,
			defaults: false,
		});

		this._skipQuestions = this.options.skipQuestions;
	}

	initializing() {}

	prompting() {

		this.log(yosay(
			`Welcome to the awe-inspiring ${chalk.cyan('Nitro')} generator!`
		));

		// check whether there is already a nitro application in place and we only have to update the application
		const json = this.fs.readJSON(this.destinationPath('.yo-rc.json'), { 'new': true });

		if (!json.new) {
			// update existing application
			return this.prompt([
				{
					name: 'update',
					type: 'confirm',
					message: `There is already a ${chalk.cyan('Nitro')} application in place! Should I serve you an update?`,
					default: true,
				},
			]).then((answers) => {
				this._update = answers.update;
				this.options.skipInstall = true;
				this.options.exampleCode = false;

				if (!this._update) {
					return;
				}

				const config = this.config.getAll();
				if (config) {
					this.options.name = config.name || this.options.name;
					this.options.viewExt = config.viewExtension || config.templateEngine ? config.templateEngine : this.options.viewExt;
					this.options.templateEngine = config.templateEngine || this.options.templateEngine;
					this.options.clientTpl = typeof config.clientTemplates === 'boolean' ? config.clientTemplates : this.options.clientTpl;
					this.options.exporter = typeof config.exporter === 'boolean' ? config.exporter : this.options.exporter;

					this.options.name = _.kebabCase(this.options.name);
				}
			});
		} else {
			// create new application
			return this.prompt([
				{
					name: 'name',
					message: 'What\'s the name of your app?',
					default: this.options.name,
					when: () => !this._skipQuestions && !this._passedInOptions.name,
				},
				{
					name: 'templateEngine',
					type: 'list',
					message: 'What\'s your desired template engine?',
					choices: this._templateEngineOptions,
					default: this.options.templateEngine,
					store: true,
					when: () => !this._skipQuestions && !this._passedInOptions.templateEngine,
				},
				{
					name: 'clientTpl',
					type: 'confirm',
					message: 'Would you like to include client side templates?',
					default: this.options.clientTpl,
					store: true,
					when: () => !this._skipQuestions && typeof this._passedInOptions.clientTpl !== 'boolean',
				},
				{
					name: 'exampleCode',
					type: 'confirm',
					message: 'Would you like to include the example code?',
					default: this.options.exampleCode,
					store: true,
					when: () => !this._skipQuestions && typeof this._passedInOptions.exampleCode !== 'boolean',
				},
				{
					name: 'exporter',
					type: 'confirm',
					message: 'Would you like to include static exporting functionalities?',
					default: this.options.exporter,
					store: true,
					when: () => !this._skipQuestions && typeof this._passedInOptions.exporter !== 'boolean',
				},
			]).then((answers) => {
				this.options.name = answers.name || this.options.name;
				this.options.templateEngine = answers.templateEngine || this.options.templateEngine;
				this.options.viewExt = this.options.templateEngine;
				this.options.clientTpl = answers.clientTpl !== undefined ? answers.clientTpl : this.options.clientTpl;
				this.options.exampleCode = answers.exampleCode !== undefined ? answers.exampleCode : this.options.exampleCode;
				this.options.exporter = answers.exporter !== undefined ? answers.exporter : this.options.exporter;

				this.options.name = _.kebabCase(this.options.name);

				this.config.set('name', this.options.name);
				this.config.set('templateEngine', this.options.templateEngine);
				this.config.set('clientTemplates', this.options.clientTpl);
				this.config.set('exampleCode', this.options.exampleCode);
				this.config.set('exporter', this.options.exporter);

				this.config.save();
			});
		}
	}

	writing() {

		this.log('Scaffolding your app');

		const files = glob.sync('**/*', { cwd: this.sourceRoot(), nodir: true, dot: true });

		const tplFiles = [
			// files to process with copyTpl
			'config/default.js',
			'config/webpack/options.js',
			'project/docs/nitro.md',
			'project/docs/client-templates.md',
			'project/helpers/readme.md',
			'src/patterns/molecules/example/example.hbs',
			'src/patterns/molecules/example/example.twig',
			'src/patterns/molecules/example/schema.json',
			'src/patterns/molecules/example/index.js',
			'src/proto/js/prototype.js',
			'src/views/index.hbs',
			'src/views/index.twig',
			'src/views/_partials/head.hbs',
			'src/views/_partials/head.twig',
			'src/ui.js',
			'src/proto.js',
			'tests/backstop/backstop.config.js',
			'docker-compose.yml',
			'docker-compose-dev.yml',
			'gulpfile.js',
			'package.json',
		];
		const ignores = [
			// files to ignore
			'.DS_Store',
			'.npmignore',
		];
		const ignoresOnUpdate = [
			// files to ignore on updating projects
			'config/local.js',
		];
		const clientTplFiles = [
			// files only for this.options.clientTpl===true
			'src/patterns/molecules/example/_data/example-template.json',
			'src/patterns/molecules/example/js/decorator/example-template.js',
			'src/patterns/molecules/example/template/example.hbs',
			'src/patterns/molecules/example/template/example.links.hbs',
			'src/patterns/molecules/example/template/partial/example.link.hbs',
			'project/docs/client-templates.md',
			'project/blueprints/pattern/template/$pattern$.hbs',
		];
		const viewFiles = [
			// all view files exists in different templateEngine variants
			'src/views/404',
			'src/views/index',
			'src/views/example/patterns',
			'src/views/_layouts/default',
			'src/views/_partials/foot',
			'src/views/_partials/head',
			'src/patterns/atoms/box/box',
			'src/patterns/atoms/button/button',
			'src/patterns/atoms/checkbox/checkbox',
			'src/patterns/atoms/cta/cta',
			'src/patterns/atoms/datepicker/datepicker',
			'src/patterns/atoms/gondel/gondel',
			'src/patterns/atoms/heading/heading',
			'src/patterns/atoms/icon/icon',
			'src/patterns/atoms/image/image',
			'src/patterns/atoms/list/list',
			'src/patterns/atoms/loader/loader',
			'src/patterns/atoms/lottie/lottie',
			'src/patterns/atoms/stage/stage',
			'src/patterns/molecules/example/example',
			'project/blueprints/pattern/$pattern$',
		];
		const examplePaths = [
			// paths only for this.options.exampleCode===true
			'project/routes/',
			'public/content/',
			'src/views/example/',
			'src/patterns/',
			'src/proto/',
			'src/shared/',
			'tests/cypress/cypress/integration/examples/'
		];
		const exampleIncludeAnyway = [
			// example file "parts" included for this.options.exampleCode===false
			'project/routes/readme.md',
			'src/patterns/readme.md',
			'src/proto/js/prototype.js',
			'src/proto/readme.md',
			'src/shared/readme.md',
			'.gitkeep',
		];
		const exporterFiles = [
			// files for this.options.exporter===true
			'config/default/exporter.js',
		];

		const templateData = {
			name: this.options.name,
			version: this._pkg.version,
			options: this.options,
		};

		files.forEach((file) => {

			// exclude ignores
			if (_.indexOf(ignores, file) !== -1) {
				return;
			}

			// exclude update ignores
			if (this._update) {
				if (_.indexOf(ignoresOnUpdate, file) !== -1) {
					return;
				}
			}

			// Client side templates only Files
			if (!this.options.clientTpl) {
				if (_.indexOf(clientTplFiles, file) !== -1) {
					return;
				}
			}

			// Example only Files
			if (!this.options.exampleCode) {
				if (
					examplePaths.some((v) => file.indexOf(v) >= 0) &&
					exampleIncludeAnyway.every((v) => { return file.indexOf(v) === -1; })
				) {
					return;
				}
			}

			// Exporter only Files
			if (!this.options.exporter) {
				if (_.indexOf(exporterFiles, file) !== -1) {
					return;
				}
			}

			const ext = path.extname(file).substring(1);
			const fileWithoutExt = file.substring(0, (file.length - ext.length - 1));
			const sourcePath = this.templatePath(file);
			let destinationPath = this.destinationPath(file);

			// check if it's a view file
			if (_.indexOf(viewFiles, fileWithoutExt) !== -1) {
				if (ext !== this.options.templateEngine) {
					// return view files with ext not matching the current templateEngine
					return;
				}
				if (this.options.viewExt !== this.options.templateEngine) {
					// sanity check for update case of old generated app's having viewExt other than hbs
					const targetExt = `.${this.options.viewExt !== 0 ? this.options.viewExt : this._viewExtOptions[0]}`;
					destinationPath = destinationPath.replace(path.extname(destinationPath), targetExt);
				}
			}

			if (_.indexOf(tplFiles, file) !== -1) {
				this.fs.copyTpl(sourcePath, destinationPath, templateData);
				return;
			}

			// rename CUTAWAY.gitignore to .gitignore
			if (destinationPath.indexOf('CUTAWAY') !== -1) {
				destinationPath = destinationPath.replace(/CUTAWAY/g, '');
			}

			this.fs.copy(sourcePath, destinationPath);
		}, this);
	}

	install() {
		this.installDependencies({
			npm: true,
			bower: false,
			yarn: false,
			skipInstall: this.options.skipInstall,
		});
	}

	end() {
		const filesToCopy = [
			{
				do: this.options.exporter,
				src: 'node_modules/@nitro/exporter/readme.md',
				srcWeb: 'https://raw.githubusercontent.com/namics/generator-nitro/master/packages/nitro-exporter/readme.md',
				dest: 'project/docs/nitro-exporter.md',
			},
			{
				do: true,
				src: 'node_modules/@nitro/webpack/readme.md',
				srcWeb: 'https://raw.githubusercontent.com/namics/generator-nitro/master/packages/nitro-webpack/readme.md',
				dest: 'project/docs/nitro-webpack.md',
			},
		];
		try {
			filesToCopy.forEach((file) => {
				if (file.do) {
					if (!this.options.skipInstall) {
						// get readme from current package version
						this.fs.copy(this.destinationPath(file.src), this.destinationPath(file.dest));
					} else {
						// get readme from github master branch
						request
							.get(file.srcWeb)
							.pipe(fs.createWriteStream(this.destinationPath(file.dest)));
					}
				}
			});
		} catch (e) {
			this.log(chalk.red(e.message));
		}

		if (this._update) {
			this.log(yosay(
				`All done – Check local changes and then\nrun \`npm install\` to update your project.`
			));
		} else {
			this.log(yosay(
				`All done –\nrun \`npm start\` to start ${chalk.cyan('Nitro')} in development mode.`
			));
		}
	}
};
<|endoftext|>


<commit_before>Package.describe({
  name: 'alon:lag-console',
  summary: 'A plugin for constellation that simulates network lag on your dev machine.',
  version: '1.0.0',
  git: 'https://github.com/MasterAM/meteor-lag-console',
  documentation: 'README.md',
  debugOnly: true
});

Package.onUse(function(api) {
  api.versionsFrom('1.0.1');
  api.use(['check', 'underscore'], 'server');
  api.use('alon:lag-methods@1.0.0');
  api.use('alon:lag-publications@1.0.0');
  api.use(['templating','reactive-dict', 'reactive-var', 'tracker'], 'client');
  api.use('underscore');
  api.use('mongo');
  api.use('constellation:console@1.2.1', 'client');

  api.addFiles(['lib/collection/lag_both.js'], ['client', 'server']);
  api.addFiles([
    'lib/client/config_formatter.js',
    'lib/collection/lag_client.js',
    'lib/template/header.html',
    'lib/template/header.js',
    'lib/template/header.css',
    'lib/template/menu.html',
    'lib/template/menu.js',
    'lib/template/menu.css',
    'lib/template/submenu/submenu.html',
    'lib/template/submenu/submenu.js',
    'lib/template/submenu/submenu.css',
    'lib/template/submenu/tab/tab.html',
    'lib/template/submenu/tab/tab.js',
    'lib/template/submenu/tab/tab.css',
    'lib/template/config/toggle_option.html',
    'lib/template/config/toggle_option.js',
    'lib/template/config/toggle_option.css',
    'lib/template/content/content.html',
    'lib/template/content/content.js',
    'lib/template/content/content.css',
    'lib/template/content/target/target.html',
    'lib/template/content/target/target.js',
    'lib/template/content/target/target.css',
    'lib/template/content/config/config.html',
    'lib/template/content/config/config.js',
    'lib/template/content/config/config.css',
    'lib/client/lag_console.js'
  ], 'client');
  api.addFiles([
    'lib/server/globals.js',
    'lib/collection/lag_server.js',
    'lib/server/methods.js',
    'lib/server/publish_as.js',
    'lib/server/publications.js',
    'lib/server/lag_console_setup.js'
  ], 'server');

  api.imply('constellation:console');

  api.export('configCollection', ['client', 'server']);
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.use('alon:lag-console');
  api.addFiles('tests/server/configs.js', 'server');
  api.addFiles('tests/server/server-test.js', 'server');
  api.addFiles('tests/client/client-test.js', 'client');
});
<commit_msg>Changed package description in package.js.<commit_after>Package.describe({
  name: 'alon:lag-console',
  summary: 'Network delay simulation for UX testing made clean and easy with a Constellation panel.',
  version: '1.0.0',
  git: 'https://github.com/MasterAM/meteor-lag-console',
  documentation: 'README.md',
  debugOnly: true
});

Package.onUse(function(api) {
  api.versionsFrom('1.0.1');
  api.use(['check', 'underscore'], 'server');
  api.use('alon:lag-methods@1.0.0');
  api.use('alon:lag-publications@1.0.0');
  api.use(['templating','reactive-dict', 'reactive-var', 'tracker'], 'client');
  api.use('underscore');
  api.use('mongo');
  api.use('constellation:console@1.2.1', 'client');

  api.addFiles(['lib/collection/lag_both.js'], ['client', 'server']);
  api.addFiles([
    'lib/client/config_formatter.js',
    'lib/collection/lag_client.js',
    'lib/template/header.html',
    'lib/template/header.js',
    'lib/template/header.css',
    'lib/template/menu.html',
    'lib/template/menu.js',
    'lib/template/menu.css',
    'lib/template/submenu/submenu.html',
    'lib/template/submenu/submenu.js',
    'lib/template/submenu/submenu.css',
    'lib/template/submenu/tab/tab.html',
    'lib/template/submenu/tab/tab.js',
    'lib/template/submenu/tab/tab.css',
    'lib/template/config/toggle_option.html',
    'lib/template/config/toggle_option.js',
    'lib/template/config/toggle_option.css',
    'lib/template/content/content.html',
    'lib/template/content/content.js',
    'lib/template/content/content.css',
    'lib/template/content/target/target.html',
    'lib/template/content/target/target.js',
    'lib/template/content/target/target.css',
    'lib/template/content/config/config.html',
    'lib/template/content/config/config.js',
    'lib/template/content/config/config.css',
    'lib/client/lag_console.js'
  ], 'client');
  api.addFiles([
    'lib/server/globals.js',
    'lib/collection/lag_server.js',
    'lib/server/methods.js',
    'lib/server/publish_as.js',
    'lib/server/publications.js',
    'lib/server/lag_console_setup.js'
  ], 'server');

  api.imply('constellation:console');

  api.export('configCollection', ['client', 'server']);
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.use('alon:lag-console');
  api.addFiles('tests/server/configs.js', 'server');
  api.addFiles('tests/server/server-test.js', 'server');
  api.addFiles('tests/client/client-test.js', 'client');
});
<|endoftext|>


<commit_before>import {Element} from 'chart.js';
import {isArray, toFontString, toRadians} from 'chart.js/helpers';
import {scaleValue, roundedRect, rotated} from '../helpers';

const PI = Math.PI;
const pointInLine = (p1, p2, t) => ({x: p1.x + t * (p2.x - p1.x), y: p1.y + t * (p2.y - p1.y)});
const interpolateX = (y, p1, p2) => pointInLine(p1, p2, Math.abs((y - p1.y) / (p2.y - p1.y))).x;
const interpolateY = (x, p1, p2) => pointInLine(p1, p2, Math.abs((x - p1.x) / (p2.x - p1.x))).y;
const toPercent = (s) => typeof s === 'string' && s.endsWith('%') && parseFloat(s) / 100;

export default class LineAnnotation extends Element {
  intersects(x, y, epsilon) {
    epsilon = epsilon || 0.001;
    const me = this;
    const p1 = {x: me.x, y: me.y};
    const p2 = {x: me.x2, y: me.y2};
    const dy = interpolateY(x, p1, p2);
    const dx = interpolateX(y, p1, p2);
    return (
      (!isFinite(dy) || Math.abs(y - dy) < epsilon) &&
			(!isFinite(dx) || Math.abs(x - dx) < epsilon)
    );
  }

  labelIsVisible() {
    const label = this.options.label;
    return label && label.enabled && label.content;
  }

  isOnLabel(mouseX, mouseY) {
    const {labelRect} = this;

    if (!labelRect) {
      return false;
    }

    const {x, y} = rotated({x: mouseX, y: mouseY}, labelRect, -labelRect.rotation);
    const w2 = labelRect.width / 2;
    const h2 = labelRect.height / 2;
    return x >= labelRect.x - w2 && x <= labelRect.x + w2 &&
      y >= labelRect.y - h2 && y <= labelRect.y + h2;
  }

  inRange(x, y) {
    const epsilon = this.options.borderWidth || 1;
    return this.intersects(x, y, epsilon) || this.isOnLabel(x, y);
  }

  getCenterPoint() {
    return {
      x: (this.x2 + this.x) / 2,
      y: (this.y2 + this.y) / 2
    };
  }

  draw(ctx) {
    const {x, y, x2, y2, options} = this;
    ctx.save();

    ctx.lineWidth = options.borderWidth;
    ctx.strokeStyle = options.borderColor;
    ctx.setLineDash(options.borderDash);
    ctx.lineDashOffset = options.borderDashOffset;

    // Draw
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x2, y2);
    ctx.stroke();

    ctx.restore();
  }

  drawLabel(ctx, chartArea) {
    if (this.labelIsVisible()) {
      ctx.save();
      drawLabel(ctx, this, chartArea);
      ctx.restore();
    }
  }

  resolveElementProperties(chart, options) {
    const scale = chart.scales[options.scaleID];
    let {top: y, left: x, bottom: y2, right: x2} = chart.chartArea;
    let min, max;

    if (scale) {
      min = scaleValue(scale, options.value, NaN);
      max = scaleValue(scale, options.endValue, min);
      if (scale.isHorizontal()) {
        x = min;
        x2 = max;
      } else {
        y = min;
        y2 = max;
      }
    } else {
      const xScale = chart.scales[options.xScaleID];
      const yScale = chart.scales[options.yScaleID];

      if (xScale) {
        x = scaleValue(xScale, options.xMin, x);
        x2 = scaleValue(xScale, options.xMax, x2);
      }

      if (yScale) {
        y = scaleValue(yScale, options.yMin, y);
        y2 = scaleValue(yScale, options.yMax, y2);
      }
    }
    return {
      x,
      y,
      x2,
      y2,
      width: x2 - x,
      height: y2 - y
    };
  }
}

LineAnnotation.id = 'lineAnnotation';
LineAnnotation.defaults = {
  display: true,
  borderWidth: 2,
  borderDash: [],
  borderDashOffset: 0,
  label: {
    backgroundColor: 'rgba(0,0,0,0.8)',
    drawTime: undefined,
    font: {
      family: undefined,
      lineHeight: undefined,
      size: undefined,
      style: 'bold',
      weight: undefined
    },
    color: '#fff',
    xPadding: 6,
    yPadding: 6,
    rotation: 0,
    cornerRadius: 6,
    position: 'center',
    xAdjust: 0,
    yAdjust: 0,
    textAlign: 'center',
    enabled: false,
    content: null
  },
  value: undefined,
  endValue: undefined,
  scaleID: undefined,
  xScaleID: 'x',
  xMin: undefined,
  xMax: undefined,
  yScaleID: 'y',
  yMin: undefined,
  yMax: undefined
};

LineAnnotation.defaultRoutes = {
  borderColor: 'color'
};

function calculateAutoRotation(line) {
  const {x, y, x2, y2} = line;
  const rotation = Math.atan2(y2 - y, x2 - x);
  // Flip the rotation if it goes > PI/2 or < -PI/2, so label stays upright
  return rotation > PI / 2 ? rotation - PI : rotation < PI / -2 ? rotation + PI : rotation;
}

function drawLabel(ctx, line, chartArea) {
  const label = line.options.label;

  ctx.font = toFontString(label.font);

  const {width, height} = measureLabel(ctx, label);
  const rect = line.labelRect = calculateLabelPosition(line, width, height, chartArea);

  ctx.translate(rect.x, rect.y);
  ctx.rotate(rect.rotation);

  ctx.fillStyle = label.backgroundColor;
  roundedRect(ctx, -(width / 2), -(height / 2), width, height, label.cornerRadius);
  ctx.fill();

  ctx.fillStyle = label.color;
  if (isArray(label.content)) {
    ctx.textAlign = label.textAlign;
    const x = calculateLabelXAlignment(label, width);
    let textYPosition = -(height / 2) + label.yPadding;
    for (let i = 0; i < label.content.length; i++) {
      ctx.textBaseline = 'top';
      ctx.fillText(
        label.content[i],
        x,
        textYPosition
      );
      textYPosition += label.font.size + label.yPadding;
    }
  } else if (label.content instanceof Image) {
    const x = -(width / 2) + label.xPadding;
    const y = -(height / 2) + label.yPadding;
    ctx.drawImage(label.content, x, y, width - (2 * label.xPadding), height - (2 * label.yPadding));
  } else {
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(label.content, 0, 0);
  }
}

function calculateLabelXAlignment(label, width) {
  const {textAlign, xPadding} = label;
  if (textAlign === 'start') {
    return -(width / 2) + xPadding;
  } else if (textAlign === 'end') {
    return +(width / 2) - xPadding;
  }
  return 0;
}

function getImageSize(size, value) {
  if (typeof value === 'number') {
    return value;
  } else if (typeof value === 'string') {
    return toPercent(value) * size;
  }
  return size;
}

const widthCache = new Map();
function measureLabel(ctx, label) {
  const content = label.content;
  if (content instanceof Image) {
    return {
      width: getImageSize(content.width, label.width) + 2 * label.xPadding,
      height: getImageSize(content.height, label.height) + 2 * label.yPadding
    };
  }
  const lines = isArray(content) ? content : [content];
  const count = lines.length;
  let width = 0;
  for (let i = 0; i < count; i++) {
    const text = lines[i];
    if (!widthCache.has(text)) {
      widthCache.set(text, ctx.measureText(text).width);
    }
    width = Math.max(width, widthCache.get(text));
  }
  width += 2 * label.xPadding;

  return {
    width,
    height: count * label.font.size + ((count + 1) * label.yPadding)
  };
}

function calculateLabelPosition(line, width, height, chartArea) {
  const label = line.options.label;
  const {xAdjust, yAdjust, xPadding, yPadding, position} = label;
  const p1 = {x: line.x, y: line.y};
  const p2 = {x: line.x2, y: line.y2};
  const rotation = label.rotation === 'auto' ? calculateAutoRotation(line) : toRadians(label.rotation);
  const size = rotatedSize(width, height, rotation);
  const t = calculateT(line, position, size, chartArea);
  const pt = pointInLine(p1, p2, t);
  const xCoordinateSizes = {size: size.w, min: chartArea.left, max: chartArea.right, padding: xPadding};
  const yCoordinateSizes = {size: size.h, min: chartArea.top, max: chartArea.bottom, padding: yPadding};

  return {
    x: adjustLabelCoordinate(pt.x, xCoordinateSizes) + xAdjust,
    y: adjustLabelCoordinate(pt.y, yCoordinateSizes) + yAdjust,
    width,
    height,
    rotation
  };
}

function rotatedSize(width, height, rotation) {
  const cos = Math.cos(rotation);
  const sin = Math.sin(rotation);
  return {
    w: Math.abs(width * cos) + Math.abs(height * sin),
    h: Math.abs(width * sin) + Math.abs(height * cos)
  };
}

function calculateT(line, position, rotSize, chartArea) {
  let t = 0.5;
  const space = spaceAround(line, chartArea);
  const label = line.options.label;
  if (position === 'start') {
    t = calculateTAdjust({w: line.x2 - line.x, h: line.y2 - line.y}, rotSize, label, space);
  } else if (position === 'end') {
    t = 1 - calculateTAdjust({w: line.x - line.x2, h: line.y - line.y2}, rotSize, label, space);
  }
  return t;
}

function calculateTAdjust(lineSize, labelSize, label, space) {
  const {xPadding, yPadding} = label;
  const lineW = lineSize.w * space.dx;
  const lineH = lineSize.h * space.dy;
  const x = (lineW > 0) && ((labelSize.w / 2 + xPadding - space.x) / lineW);
  const y = (lineH > 0) && ((labelSize.h / 2 + yPadding - space.y) / lineH);
  return Math.max(Math.min(Math.max(x, y), 0.25), 0);
}

function spaceAround(line, chartArea) {
  const {x, x2, y, y2} = line;
  const t = Math.min(y, y2) - chartArea.top;
  const l = Math.min(x, x2) - chartArea.left;
  const b = chartArea.bottom - Math.max(y, y2);
  const r = chartArea.right - Math.max(x, x2);
  return {
    x: Math.min(l, r),
    y: Math.min(t, b),
    dx: l < r ? 1 : -1,
    dy: t < b ? 1 : -1
  };
}

function adjustLabelCoordinate(coordinate, labelSizes) {
  const {size, min, max, padding} = labelSizes;
  const halfSize = size / 2;

  if (size > max - min) {
    // if it does not fit, display as much as possible
    return (max + min) / 2;
  }

  if (min >= (coordinate - padding - halfSize)) {
    coordinate = min + padding + halfSize;
  }

  if (max <= (coordinate + padding + halfSize)) {
    coordinate = max - padding - halfSize;
  }

  return coordinate;
}
<commit_msg>Restrict mouse events to where the line actually is (#403)<commit_after>import {Element} from 'chart.js';
import {isArray, toFontString, toRadians} from 'chart.js/helpers';
import {scaleValue, roundedRect, rotated} from '../helpers';

const PI = Math.PI;
const clamp = (x, from, to) => Math.min(to, Math.max(from, x));
const pointInLine = (p1, p2, t) => {
  t = clamp(t, 0, 1);
  return {x: p1.x + t * (p2.x - p1.x), y: p1.y + t * (p2.y - p1.y)};
};
const interpolateX = (y, p1, p2) => pointInLine(p1, p2, Math.abs((y - p1.y) / (p2.y - p1.y))).x;
const interpolateY = (x, p1, p2) => pointInLine(p1, p2, Math.abs((x - p1.x) / (p2.x - p1.x))).y;
const toPercent = (s) => typeof s === 'string' && s.endsWith('%') && parseFloat(s) / 100;

export default class LineAnnotation extends Element {
  intersects(x, y, epsilon) {
    epsilon = epsilon || 0.001;
    const me = this;
    const p1 = {x: me.x, y: me.y};
    const p2 = {x: me.x2, y: me.y2};
    const dy = interpolateY(x, p1, p2);
    const dx = interpolateX(y, p1, p2);
    return (
      (!isFinite(dy) || Math.abs(y - dy) < epsilon) &&
			(!isFinite(dx) || Math.abs(x - dx) < epsilon)
    );
  }

  labelIsVisible() {
    const label = this.options.label;
    return label && label.enabled && label.content;
  }

  isOnLabel(mouseX, mouseY) {
    const {labelRect} = this;

    if (!labelRect) {
      return false;
    }

    const {x, y} = rotated({x: mouseX, y: mouseY}, labelRect, -labelRect.rotation);
    const w2 = labelRect.width / 2;
    const h2 = labelRect.height / 2;
    return x >= labelRect.x - w2 && x <= labelRect.x + w2 &&
      y >= labelRect.y - h2 && y <= labelRect.y + h2;
  }

  inRange(x, y) {
    const epsilon = this.options.borderWidth || 1;
    return this.intersects(x, y, epsilon) || this.isOnLabel(x, y);
  }

  getCenterPoint() {
    return {
      x: (this.x2 + this.x) / 2,
      y: (this.y2 + this.y) / 2
    };
  }

  draw(ctx) {
    const {x, y, x2, y2, options} = this;
    ctx.save();

    ctx.lineWidth = options.borderWidth;
    ctx.strokeStyle = options.borderColor;
    ctx.setLineDash(options.borderDash);
    ctx.lineDashOffset = options.borderDashOffset;

    // Draw
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x2, y2);
    ctx.stroke();

    ctx.restore();
  }

  drawLabel(ctx, chartArea) {
    if (this.labelIsVisible()) {
      ctx.save();
      drawLabel(ctx, this, chartArea);
      ctx.restore();
    }
  }

  resolveElementProperties(chart, options) {
    const scale = chart.scales[options.scaleID];
    let {top: y, left: x, bottom: y2, right: x2} = chart.chartArea;
    let min, max;

    if (scale) {
      min = scaleValue(scale, options.value, NaN);
      max = scaleValue(scale, options.endValue, min);
      if (scale.isHorizontal()) {
        x = min;
        x2 = max;
      } else {
        y = min;
        y2 = max;
      }
    } else {
      const xScale = chart.scales[options.xScaleID];
      const yScale = chart.scales[options.yScaleID];

      if (xScale) {
        x = scaleValue(xScale, options.xMin, x);
        x2 = scaleValue(xScale, options.xMax, x2);
      }

      if (yScale) {
        y = scaleValue(yScale, options.yMin, y);
        y2 = scaleValue(yScale, options.yMax, y2);
      }
    }
    return {
      x,
      y,
      x2,
      y2,
      width: x2 - x,
      height: y2 - y
    };
  }
}

LineAnnotation.id = 'lineAnnotation';
LineAnnotation.defaults = {
  display: true,
  borderWidth: 2,
  borderDash: [],
  borderDashOffset: 0,
  label: {
    backgroundColor: 'rgba(0,0,0,0.8)',
    drawTime: undefined,
    font: {
      family: undefined,
      lineHeight: undefined,
      size: undefined,
      style: 'bold',
      weight: undefined
    },
    color: '#fff',
    xPadding: 6,
    yPadding: 6,
    rotation: 0,
    cornerRadius: 6,
    position: 'center',
    xAdjust: 0,
    yAdjust: 0,
    textAlign: 'center',
    enabled: false,
    content: null
  },
  value: undefined,
  endValue: undefined,
  scaleID: undefined,
  xScaleID: 'x',
  xMin: undefined,
  xMax: undefined,
  yScaleID: 'y',
  yMin: undefined,
  yMax: undefined
};

LineAnnotation.defaultRoutes = {
  borderColor: 'color'
};

function calculateAutoRotation(line) {
  const {x, y, x2, y2} = line;
  const rotation = Math.atan2(y2 - y, x2 - x);
  // Flip the rotation if it goes > PI/2 or < -PI/2, so label stays upright
  return rotation > PI / 2 ? rotation - PI : rotation < PI / -2 ? rotation + PI : rotation;
}

function drawLabel(ctx, line, chartArea) {
  const label = line.options.label;

  ctx.font = toFontString(label.font);

  const {width, height} = measureLabel(ctx, label);
  const rect = line.labelRect = calculateLabelPosition(line, width, height, chartArea);

  ctx.translate(rect.x, rect.y);
  ctx.rotate(rect.rotation);

  ctx.fillStyle = label.backgroundColor;
  roundedRect(ctx, -(width / 2), -(height / 2), width, height, label.cornerRadius);
  ctx.fill();

  ctx.fillStyle = label.color;
  if (isArray(label.content)) {
    ctx.textAlign = label.textAlign;
    const x = calculateLabelXAlignment(label, width);
    let textYPosition = -(height / 2) + label.yPadding;
    for (let i = 0; i < label.content.length; i++) {
      ctx.textBaseline = 'top';
      ctx.fillText(
        label.content[i],
        x,
        textYPosition
      );
      textYPosition += label.font.size + label.yPadding;
    }
  } else if (label.content instanceof Image) {
    const x = -(width / 2) + label.xPadding;
    const y = -(height / 2) + label.yPadding;
    ctx.drawImage(label.content, x, y, width - (2 * label.xPadding), height - (2 * label.yPadding));
  } else {
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(label.content, 0, 0);
  }
}

function calculateLabelXAlignment(label, width) {
  const {textAlign, xPadding} = label;
  if (textAlign === 'start') {
    return -(width / 2) + xPadding;
  } else if (textAlign === 'end') {
    return +(width / 2) - xPadding;
  }
  return 0;
}

function getImageSize(size, value) {
  if (typeof value === 'number') {
    return value;
  } else if (typeof value === 'string') {
    return toPercent(value) * size;
  }
  return size;
}

const widthCache = new Map();
function measureLabel(ctx, label) {
  const content = label.content;
  if (content instanceof Image) {
    return {
      width: getImageSize(content.width, label.width) + 2 * label.xPadding,
      height: getImageSize(content.height, label.height) + 2 * label.yPadding
    };
  }
  const lines = isArray(content) ? content : [content];
  const count = lines.length;
  let width = 0;
  for (let i = 0; i < count; i++) {
    const text = lines[i];
    if (!widthCache.has(text)) {
      widthCache.set(text, ctx.measureText(text).width);
    }
    width = Math.max(width, widthCache.get(text));
  }
  width += 2 * label.xPadding;

  return {
    width,
    height: count * label.font.size + ((count + 1) * label.yPadding)
  };
}

function calculateLabelPosition(line, width, height, chartArea) {
  const label = line.options.label;
  const {xAdjust, yAdjust, xPadding, yPadding, position} = label;
  const p1 = {x: line.x, y: line.y};
  const p2 = {x: line.x2, y: line.y2};
  const rotation = label.rotation === 'auto' ? calculateAutoRotation(line) : toRadians(label.rotation);
  const size = rotatedSize(width, height, rotation);
  const t = calculateT(line, position, size, chartArea);
  const pt = pointInLine(p1, p2, t);
  const xCoordinateSizes = {size: size.w, min: chartArea.left, max: chartArea.right, padding: xPadding};
  const yCoordinateSizes = {size: size.h, min: chartArea.top, max: chartArea.bottom, padding: yPadding};

  return {
    x: adjustLabelCoordinate(pt.x, xCoordinateSizes) + xAdjust,
    y: adjustLabelCoordinate(pt.y, yCoordinateSizes) + yAdjust,
    width,
    height,
    rotation
  };
}

function rotatedSize(width, height, rotation) {
  const cos = Math.cos(rotation);
  const sin = Math.sin(rotation);
  return {
    w: Math.abs(width * cos) + Math.abs(height * sin),
    h: Math.abs(width * sin) + Math.abs(height * cos)
  };
}

function calculateT(line, position, rotSize, chartArea) {
  let t = 0.5;
  const space = spaceAround(line, chartArea);
  const label = line.options.label;
  if (position === 'start') {
    t = calculateTAdjust({w: line.x2 - line.x, h: line.y2 - line.y}, rotSize, label, space);
  } else if (position === 'end') {
    t = 1 - calculateTAdjust({w: line.x - line.x2, h: line.y - line.y2}, rotSize, label, space);
  }
  return t;
}

function calculateTAdjust(lineSize, labelSize, label, space) {
  const {xPadding, yPadding} = label;
  const lineW = lineSize.w * space.dx;
  const lineH = lineSize.h * space.dy;
  const x = (lineW > 0) && ((labelSize.w / 2 + xPadding - space.x) / lineW);
  const y = (lineH > 0) && ((labelSize.h / 2 + yPadding - space.y) / lineH);
  return clamp(Math.max(x, y), 0, 0.25);
}

function spaceAround(line, chartArea) {
  const {x, x2, y, y2} = line;
  const t = Math.min(y, y2) - chartArea.top;
  const l = Math.min(x, x2) - chartArea.left;
  const b = chartArea.bottom - Math.max(y, y2);
  const r = chartArea.right - Math.max(x, x2);
  return {
    x: Math.min(l, r),
    y: Math.min(t, b),
    dx: l < r ? 1 : -1,
    dy: t < b ? 1 : -1
  };
}

function adjustLabelCoordinate(coordinate, labelSizes) {
  const {size, min, max, padding} = labelSizes;
  const halfSize = size / 2;

  if (size > max - min) {
    // if it does not fit, display as much as possible
    return (max + min) / 2;
  }

  if (min >= (coordinate - padding - halfSize)) {
    coordinate = min + padding + halfSize;
  }

  if (max <= (coordinate + padding + halfSize)) {
    coordinate = max - padding - halfSize;
  }

  return coordinate;
}
<|endoftext|>


<commit_before>module.exports = {
  plugins: [
    require("babel-plugin-transform-react-jsx"),
    require("babel-plugin-transform-flow-strip-types"),
    require("babel-plugin-syntax-flow"),
    require("babel-plugin-syntax-jsx"),
    require("babel-plugin-transform-react-display-name"),
  ],
  env: {
    development: {
      plugins: [
   //     require("babel-plugin-transform-react-jsx-source"),
        require("babel-plugin-transform-react-jsx-self")
      ]
    }
  }
};
<commit_msg>Remove jsx-self from react preset (#3552)<commit_after>module.exports = {
  plugins: [
    require("babel-plugin-transform-react-jsx"),
    require("babel-plugin-transform-flow-strip-types"),
    require("babel-plugin-syntax-flow"),
    require("babel-plugin-syntax-jsx"),
    require("babel-plugin-transform-react-display-name"),
  ],
  env: {
    development: {
      plugins: [
        // require("babel-plugin-transform-react-jsx-source"),
        // require("babel-plugin-transform-react-jsx-self")
      ]
    }
  }
};
<|endoftext|>