<commit_before>import React, { Component } from 'react'
import Chartist from 'chartist'
import uuid from 'node-uuid'

export default class ChartistAccessibility extends Component {
  getId () {
    const { elementId } = this.props
    return `ct-accessibility-table-${elementId || uuid.v4()}`
  }

  valueTransform (value) {
    const { valueTransform } = this.props
    const _valueTransform = typeof valueTransform === 'function' ? valueTransform : Chartist.noop
    return `${_valueTransform(value)}`
  }

  componentDidMount () {
    const { data } = this.props
    this.multiPoint = data.series.length > 1
  }

  render () {
    const { data, caption, seriesHeader, summary, elementId, visuallyHiddenStyles } = this.props
    console.log(data)
    return (

{caption || 'A  graphical chart'}

                  {seriesHeader}
                  {data.labels.map((l, i) => {l}	)}

                {this.multiPoint &&
                  data.series.map((s, i) => {
                    return (

                        {`${i + 1}. Series`}
                        {s.map((ss, ii) => {this.valueTransform(ss)}	)}

                    )
                  })
                }
                {!this.multiPoint &&

                     1. Series
                     {data.series[0].map((s, i) => {
                       return (
                         {this.valueTransform(s)}
                       )
                     })}

                }

    )
  }
}
<commit_msg>Add support for data notations: meta, classname, and other attributes. Now works with Pi charts<commit_after>import React, { Component } from 'react'
import Chartist from 'chartist'
import uuid from 'node-uuid'

export default class ChartistAccessibility extends Component {
  getId () {
    const { elementId } = this.props
    return `ct-accessibility-table-${elementId || uuid.v4()}`
  }

  valueTransform (value) {
    const { valueTransform } = this.props
    const _valueTransform = typeof valueTransform === 'function' ? valueTransform : Chartist.noop
    return `${_valueTransform(value)}`
  }

  stripAtrributes (data) {
    const { series, labels } = data
    const dataIsObj = series.every((element) => typeof element === 'object')
    const dataIsInt = series.every((element) => !isNaN(element))
    const dataIsString = series.every((element) => typeof element === 'string')
    return {
      labels,
      series: [series.map((s) => {
        if (dataIsObj && s.value) {
          return s.value
        } else if (dataIsInt || dataIsString) {
          return s
        }
      })]
    }
  }

  render () {
    const { data, caption, seriesHeader, summary, elementId, visuallyHiddenStyles } = this.props
    const multiPoint = data.series.length > 1
    const _data = this.stripAtrributes(data)
    return (

{caption || 'A  graphical chart'}

                  {seriesHeader}
                  {_data.labels.map((l, i) => {l}	)}

                {multiPoint &&
                  _data.series.map((s, i) => {
                    return (

                        {`${i + 1}. Series`}
                        {s.map((ss, ii) => {this.valueTransform(ss)}	)}

                    )
                  })
                }
                {!multiPoint &&

                     1. Series
                     {console.log(_data.series)}
                     {_data.series[0].map((s, i) => {
                       return (
                         {this.valueTransform(s)}
                       )
                     })}

                }

    )
  }
}
<|endoftext|>


<commit_before>const UserList = (function(){
  function UserList(sys){
    this.sys = sys;
    this.dom = sys.gui.initUserList();
    this.users = {};
  }

  UserList.prototype.show = function(){
    this.sys.gui.showUserContainer(this);
  };

  UserList.prototype.hide = function(){
    this.sys.gui.hideUserContainer(this);
  };

  UserList.prototype.remove = function(nick){
    if(typeof this.users[nick] === "undefined"){
      return false;
    }
    this.users[nick].remove(nick);
    delete this.users[nick];
    return true;
  };

  UserList.prototype.append = function(nick, avatar){
    this.users[nick] = new User(
      this.sys,
      this.sys.gui.appendUser(this.dom, avatar, nick),
      nick
    );
  };

  UserList.prototype.updateNick = function(old, news){
     if(typeof this.users[old] === "undefined"){
       return false;
     }

     this.users[old].updateNick(news);
     this.users[news] = this.users[old];
     delete this.users[old];
  };

  UserList.prototype.get = function(nick){
    if(typeof this.users[nick] === "undefined")
      return null;
    return this.users[nick];
  };

  return UserList;
})();
<commit_msg>Update userlist.js<commit_after>const UserList = (function(){
  function UserList(sys){
    this.sys = sys;
    this.dom = sys.gui.initUserList();
    this.users = {};
  }

  UserList.prototype.show = function(){
    this.sys.gui.showUserContainer(this);
  };

  UserList.prototype.hide = function(){
    this.sys.gui.hideUserContainer(this);
  };

  UserList.prototype.remove = function(nick){
    if(typeof this.users[nick] === "undefined"){
      return false;
    }
    this.users[nick].remove(nick);
    delete this.users[nick];
    return true;
  };

  UserList.prototype.append = function(nick, avatar){
    this.users[nick] = new User(
      this.sys,
      this.sys.gui.appendUser(this, this.dom, avatar, nick),
      nick
    );
  };

  UserList.prototype.updateNick = function(old, news){
     if(typeof this.users[old] === "undefined"){
       return false;
     }

     this.users[old].updateNick(news);
     this.users[news] = this.users[old];
     delete this.users[old];
  };

  UserList.prototype.get = function(nick){
    if(typeof this.users[nick] === "undefined")
      return null;
    return this.users[nick];
  };

  return UserList;
})();
<|endoftext|>


<commit_before>'use strict';

const u = require('./utils.js');
const fs = require('fs');
const electron = require('electron');
const file = (electron.app || electron.remote.app).getPath('userData')+'/config.json';

let config = {};

(electron.app || electron.remote.app).on('ready', () => {
  if(!u.exists(file)) {
    fs.writeFileSync(file, '{}');
  }

  config = JSON.parse(fs.readFileSync(file));
});

exports.file = function() {
  return file;
};

exports.has = function(key) {
  return u.search(config, key) !== undefined;
};

exports.set = function(key, value) {
  u.set(config, key)(value);
  u.sync(file, config);
};

exports.setBulk = function(items) {
  for (let key in items) {
    u.set(config, key)(items[key]);
  }
  u.sync(file, config);
};

exports.get = function(key, defaultValue)  {
  const value = u.search(config, key);
  return value === undefined ? defaultValue : value;
};

exports.keys = function(key) {
  return Object.keys((key) ? u.search(config, key) : config);
};

exports.all = function() {
  return config;
};

exports.delete = function(key) {
  u.remove(config, key)();
  u.sync(file, config);
};

exports.deleteBulk = function(keys) {
  for (let key of keys) {
    u.remove(config, key)();
  }
  u.sync(file, config);
};

exports.purge = function() {
  config = {};
  u.sync(file, config);
};
<commit_msg>Fix read file initializattion<commit_after>'use strict';

const u = require('./utils.js');
const fs = require('fs');
const electron = require('electron');
const file = (electron.app || electron.remote.app).getPath('userData')+'/config.json';

let config = {};

let readConfig = () => {
  if(!u.exists(file)) {
    fs.writeFileSync(file, '{}');
  }

  config = JSON.parse(fs.readFileSync(file));
};

if ((electron.app && electron.app.isReady()) || (electron.remote.app && electron.remote.app.isReady())) {
  readConfig();
} else {
  (electron.app || electron.remote.app).on('ready', () => {
    readConfig();
  });
}

exports.file = function() {
  return file;
};

exports.has = function(key) {
  return u.search(config, key) !== undefined;
};

exports.set = function(key, value) {
  u.set(config, key)(value);
  u.sync(file, config);
};

exports.setBulk = function(items) {
  for (let key in items) {
    u.set(config, key)(items[key]);
  }
  u.sync(file, config);
};

exports.get = function(key, defaultValue)  {
  const value = u.search(config, key);
  return value === undefined ? defaultValue : value;
};

exports.keys = function(key) {
  return Object.keys((key) ? u.search(config, key) : config);
};

exports.all = function() {
  return config;
};

exports.delete = function(key) {
  u.remove(config, key)();
  u.sync(file, config);
};

exports.deleteBulk = function(keys) {
  for (let key of keys) {
    u.remove(config, key)();
  }
  u.sync(file, config);
};

exports.purge = function() {
  config = {};
  u.sync(file, config);
};
<|endoftext|>


<commit_before>function findStations(callback) {
    $.ajax({
        type: 'GET',
        url: 'http://localhost:8765/mockdata/veturilo.xml',
        dataType: 'xml',
        success: function (xml) {
            var stations = [];
            $(xml).find('place').each(function () {
                var place = $(this);
                var station = {
                    name: place.attr('name'),
                    lat: place.attr('lat'),
                    lng: place.attr('lng'),
                    bikes: place.attr('lng'),
                    racks: place.attr('bike_racks')
                };
                stations.push(station);
            });
            callback(stations);
        }
    });
}

var distanceSquare = function(pointA, pointB) {
    var x = pointA.lat - pointB.lat;
    var y = pointA.lng - pointB.lng;
    return (x * x) + (y * y);
}

function findNearestStation(point, stations) {
    var nearest = null;
    var smallestDistanceSquare;
    $.each(stations, function (i, station) {
        var distance = distanceSquare(point, station);
        if ((nearest == null) || (smallestDistanceSquare > distance)) {
            nearest = station;
            smallestDistanceSquare = distance;
        }
    });
    return nearest;
}

<commit_msg>nearest station fixes<commit_after>function findStations(callback) {
    $.ajax({
        type: 'GET',
        url: 'http://localhost:8765/mockdata/veturilo.xml',
        dataType: 'xml',
        success: function (xml) {
            var stations = [];
            $(xml).find('place').each(function () {
                var place = $(this);
                var station = {
                    name: place.attr('name'),
                    lat: place.attr('lat'),
                    lng: place.attr('lng'),
                    bikes: place.attr('bikes'),
                    racks: place.attr('bike_racks')
                };
                stations.push(station);
            });
            callback(stations);
        }
    });
}

var distanceSquare = function (pointA, pointB) {
    var x = pointA.lat - pointB.lat;
    var y = pointA.lng - pointB.lng;
    return (x * x) + (y * y);
}

function findNearestStation(point, stations) {
    var nearest = null;
    var smallestDistanceSquare;
    $.each(stations, function (i, station) {
        var distance = distanceSquare(point, station);
        if ((nearest == null) || ((smallestDistanceSquare > distance) && (stations.bikes != '0'))) {
            nearest = station;
            smallestDistanceSquare = distance;
        }
    });
    return nearest;
}

<|endoftext|>


<commit_before>import { SmoothScrollbar } from './smooth_scrollbar';

import './apis/index';
import './events/index';
import './internals/index';

angular.module('SmoothScrollbar', [])
    .service('ScrollbarService', class ScrollbarService{
        static $inject = ['$q'];

        constructor($q) {
            this.scrollbarInstances = {};
            this.deferreds = {};
            this.$q = $q;
        }

        /**
         * @method
         * Get scrollbar instance
         * If instance isn't existed,
         * callback wiil be invoked after instance is created
         *
         * @param {String} name: scrollbar name
         * @param {Function} fn: callback with instance
         */
        getInstance(name) {
            let { deferreds, $q } = this;

            let deferred = deferreds[name] = deferreds[name] || $q.defer();

            return deferred.promise;
        }

        /**
         * @method
         * Create scrollbar instance
         *
         * @param {String} name: scrollbar name
         * @param {Element} elem: container element
         * @param {Object} options: as is explained in scrollbar constructor
         *
         * @return {Scrollbar} scrollbar instance
         */
        createInstance(name, elem, options) {
            let { scrollbarInstances, deferreds } = this;

            if (scrollbarInstances.hasOwnProperty(name)) {
                return scrollbarInstances[name];
            }

            let instance = scrollbarInstances[name] = new SmoothScrollbar(elem, options);

            if (deferreds.hasOwnProperty(name)) {
                deferreds[name].resolve(instance);
            }

            return instance;
        }

        /**
         * @method
         * Destroy scrollbar instance
         *
         * @param {String} name: scrollbar name
         */
        destroyInstance(name) {
            let { scrollbarInstances, deferreds } = this;
            let instance = scrollbarInstances[name];

            if (instance) {
                instance.destroy();
                delete scrollbarInstances[name];
                delete deferreds[name];
            }
        }
    })
    .directive('scrollbar', ['ScrollbarService', (ScrollbarService) => {
        return {
            restrict: 'AE',
            transclude: true,
            template: `

            `,
            scope: {
                name: '@scrollbar',
                speed: '@',
                stepLength: '@',
                easingDuration: '@',
                easingCurve: '@'
            },
            link(scope, elem) {
                let { name, speed, stepLength, easingDuration, easingCurve } = scope;
                if (!name) throw new Error('scrollbar name is required');

                // rebuild instance
                ScrollbarService.destroyInstance(scope.name);

                ScrollbarService.createInstance(name, elem[0], {
                    speed,
                    stepLength,
                    easingDuration,
                    easingCurve
                });
            }
        };
    }]);<commit_msg>update: destroy instance while scope is destroyed<commit_after>import { SmoothScrollbar } from './smooth_scrollbar';

import './apis/index';
import './events/index';
import './internals/index';

angular.module('SmoothScrollbar', [])
    .service('ScrollbarService', class ScrollbarService{
        static $inject = ['$q'];

        constructor($q) {
            this.scrollbarInstances = {};
            this.deferreds = {};
            this.$q = $q;
        }

        /**
         * @method
         * Get scrollbar instance
         * If instance isn't existed,
         * callback wiil be invoked after instance is created
         *
         * @param {String} name: scrollbar name
         * @param {Function} fn: callback with instance
         */
        getInstance(name) {
            let { deferreds, $q } = this;

            let deferred = deferreds[name] = deferreds[name] || $q.defer();

            return deferred.promise;
        }

        /**
         * @method
         * Create scrollbar instance
         *
         * @param {String} name: scrollbar name
         * @param {Element} elem: container element
         * @param {Object} options: as is explained in scrollbar constructor
         *
         * @return {Scrollbar} scrollbar instance
         */
        createInstance(name, elem, options) {
            let { scrollbarInstances, deferreds } = this;

            if (scrollbarInstances.hasOwnProperty(name)) {
                return scrollbarInstances[name];
            }

            let instance = scrollbarInstances[name] = new SmoothScrollbar(elem, options);

            if (deferreds.hasOwnProperty(name)) {
                deferreds[name].resolve(instance);
            }

            return instance;
        }

        /**
         * @method
         * Destroy scrollbar instance
         *
         * @param {String} name: scrollbar name
         */
        destroyInstance(name) {
            let { scrollbarInstances, deferreds } = this;
            let instance = scrollbarInstances[name];

            if (instance) {
                instance.destroy();
                delete scrollbarInstances[name];
                delete deferreds[name];
            }
        }
    })
    .directive('scrollbar', ['ScrollbarService', (ScrollbarService) => {
        return {
            restrict: 'AE',
            transclude: true,
            template: `

            `,
            scope: {
                name: '@scrollbar',
                speed: '@',
                stepLength: '@',
                easingDuration: '@',
                easingCurve: '@'
            },
            link(scope, elem) {
                let { name, speed, stepLength, easingDuration, easingCurve } = scope;
                if (!name) throw new Error('scrollbar name is required');

                ScrollbarService.createInstance(name, elem[0], {
                    speed,
                    stepLength,
                    easingDuration,
                    easingCurve
                });

                scope.$on('$destroy', () => {
                    ScrollbarService.destroyInstance(name);
                });
            }
        };
    }]);<|endoftext|>


<commit_before>'use strict';

import * as React from 'react';
import * as PropTypes from 'prop-types';

const UNKNOWN_PROPS = [
  'sources',
  'width',
  'height',
  'flexible',
  'fit',
  'fitFallback'
];
const POSITIVE_INTEGER_PATTERN = /^\d+$/;

/**
 * React component that render a image with object-fit and its fallback
 *
 * @class SuperImage
 */
export default class SuperImage extends React.Component {
  static propTypes = {
    src     : PropTypes.string.isRequired,
    sources : PropTypes.arrayOf(PropTypes.shape({
      srcSet : PropTypes.string,
      sizes  : PropTypes.string,
      media  : PropTypes.string,
      type   : PropTypes.string
    })),
    width       : PropTypes.string,
    height      : PropTypes.string,
    alt         : PropTypes.string,
    className   : PropTypes.string,
    fit         : PropTypes.oneOf(['contain', 'cover']),
    fitFallback : PropTypes.bool,
    flexible    : PropTypes.bool
  };

  static defaultProps = {
    sources     : [],
    width       : null,
    height      : null,
    alt         : '',
    className   : '',
    fit         : null,
    fitFallback : false,
    flexible    : false
  };

  renderImage() {
    const style = {};
    const props = {};

    if (this.props.fit) {
      style.objectFit = this.props.fit;
    }

    if (this.props.flexible) {
      style.width = '100%';
      style.height = '100%';
    } else {
      if (POSITIVE_INTEGER_PATTERN.test(this.props.width)) {
        style.width = `${this.props.width}px`;
      } else if (this.props.width) {
        style.width = this.props.width;
      }

      if (POSITIVE_INTEGER_PATTERN.test(this.props.height)) {
        style.height = `${this.props.height}px`;
      } else if (this.props.height) {
        style.height = this.props.height;
      }
    }

    // Props given to this Component is inherited <img /> in all
    Object.keys(this.props)
      .filter(key => UNKNOWN_PROPS.indexOf(key) === -1)
      .forEach(key => {
        props[key] = this.props[key];
      });

    // Render picture element if `sources` property exists
    if (this.props.sources.length > 0) {
      const pictureStyle = this.props.flexible ? {
        width  : '100%',
        height : '100%'
      } : {};

      /* eslint-disable react/no-array-index-key */
      const sources = this.props.sources.map((source, i) => {
        return <source key={i} {...source} />;
      });
      /* eslint-disable react/no-array-index-key */

      return (
        <picture style={pictureStyle}>
          {sources}
          <img
            src={this.props.src}
            alt={this.props.alt}
            style={style}
            {...props}
          />
        </picture>
      );
    }

    return (
      <img
        src={this.props.src}
        alt={this.props.alt}
        style={style}
        {...props}
      />
    );
  }

  renderImageWithObjectFitFallback() {
    const style = {
      display            : 'inline-block',
      backgroundImage    : `url(${this.props.src})`,
      backgroundRepeat   : 'no-repeat',
      backgroundPosition : 'center center'
    };

    if (this.props.flexible) {
      style.width = '100%';
      style.height = '100%';
    } else {
      if (POSITIVE_INTEGER_PATTERN.test(this.props.width)) {
        style.width = `${this.props.width}px`;
      } else if (this.props.width) {
        style.width = this.props.width;
      }

      if (POSITIVE_INTEGER_PATTERN.test(this.props.height)) {
        style.height = `${this.props.height}px`;
      } else if (this.props.height) {
        style.height = this.props.height;
      }
    }

    if (this.props.fit) {
      style.backgroundSize = this.props.fit;
    }

    return (
      <div
        role="img"
        aria-label={this.props.alt}
        className={this.props.className}
        style={style}
      />
    );
  }

  render() {
    if (this.props.fitFallback) {
      return this.renderImageWithObjectFitFallback();
    }

    return this.renderImage();
  }
}
<commit_msg>Accept number for width and height<commit_after>'use strict';

import * as React from 'react';
import * as PropTypes from 'prop-types';

const UNKNOWN_PROPS = [
  'sources',
  'width',
  'height',
  'flexible',
  'fit',
  'fitFallback'
];
const POSITIVE_INTEGER_PATTERN = /^\d+$/;

/**
 * React component that render a image with object-fit and its fallback
 *
 * @class SuperImage
 */
export default class SuperImage extends React.Component {
  static propTypes = {
    src     : PropTypes.string.isRequired,
    sources : PropTypes.arrayOf(PropTypes.shape({
      srcSet : PropTypes.string,
      sizes  : PropTypes.string,
      media  : PropTypes.string,
      type   : PropTypes.string
    })),
    width       : PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    height      : PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    alt         : PropTypes.string,
    className   : PropTypes.string,
    fit         : PropTypes.oneOf(['contain', 'cover']),
    fitFallback : PropTypes.bool,
    flexible    : PropTypes.bool
  };

  static defaultProps = {
    sources     : [],
    width       : null,
    height      : null,
    alt         : '',
    className   : '',
    fit         : null,
    fitFallback : false,
    flexible    : false
  };

  renderImage() {
    const style = {};
    const props = {};

    if (this.props.fit) {
      style.objectFit = this.props.fit;
    }

    if (this.props.flexible) {
      style.width = '100%';
      style.height = '100%';
    } else {
      if (POSITIVE_INTEGER_PATTERN.test(this.props.width)) {
        style.width = `${this.props.width}px`;
      } else if (this.props.width) {
        style.width = this.props.width;
      }

      if (POSITIVE_INTEGER_PATTERN.test(this.props.height)) {
        style.height = `${this.props.height}px`;
      } else if (this.props.height) {
        style.height = this.props.height;
      }
    }

    // Props given to this Component is inherited <img /> in all
    Object.keys(this.props)
      .filter(key => UNKNOWN_PROPS.indexOf(key) === -1)
      .forEach(key => {
        props[key] = this.props[key];
      });

    // Render picture element if `sources` property exists
    if (this.props.sources.length > 0) {
      const pictureStyle = this.props.flexible ? {
        width  : '100%',
        height : '100%'
      } : {};

      /* eslint-disable react/no-array-index-key */
      const sources = this.props.sources.map((source, i) => {
        return <source key={i} {...source} />;
      });
      /* eslint-disable react/no-array-index-key */

      return (
        <picture style={pictureStyle}>
          {sources}
          <img
            src={this.props.src}
            alt={this.props.alt}
            style={style}
            {...props}
          />
        </picture>
      );
    }

    return (
      <img
        src={this.props.src}
        alt={this.props.alt}
        style={style}
        {...props}
      />
    );
  }

  renderImageWithObjectFitFallback() {
    const style = {
      display            : 'inline-block',
      backgroundImage    : `url(${this.props.src})`,
      backgroundRepeat   : 'no-repeat',
      backgroundPosition : 'center center'
    };

    if (this.props.flexible) {
      style.width = '100%';
      style.height = '100%';
    } else {
      if (POSITIVE_INTEGER_PATTERN.test(this.props.width)) {
        style.width = `${this.props.width}px`;
      } else if (this.props.width) {
        style.width = this.props.width;
      }

      if (POSITIVE_INTEGER_PATTERN.test(this.props.height)) {
        style.height = `${this.props.height}px`;
      } else if (this.props.height) {
        style.height = this.props.height;
      }
    }

    if (this.props.fit) {
      style.backgroundSize = this.props.fit;
    }

    return (
      <div
        role="img"
        aria-label={this.props.alt}
        className={this.props.className}
        style={style}
      />
    );
  }

  render() {
    if (this.props.fitFallback) {
      return this.renderImageWithObjectFitFallback();
    }

    return this.renderImage();
  }
}
<|endoftext|>


<commit_before>/* jshint maxdepth: 5, maxparams: 6 */

(function(W, U) {
	'use strict';

	var reg = {
			args: /(\\?['"][^'"]+\\?['"]|[^,]+)/g,
			ext: /(.[^\(]+)(?:\((.*)\))?/,
			pair: /{{#(\S+?)(?:\|(.+?))?}}([\s\S]+?){{\/\1}}/g,
			partial: /{{\s*>(.+?)}}/g,
			short: /{{([^}]+) +\? ([^}]+)}}/g,
			single: /{{(.+?)}}/g,
			str: /^\\?("|')/,
			tags: /{{\s*(?:([#\/])([^#{\|\n\s]+)\s*(\|[^{\n]+)?|else)\s*}}/g
		},
		helpers = {
			is: function(a, b) {
				return a === (b !== U ? b : this.val);
			},
			not: function(a, b) {
				return ! helpers.is.call(this, a, b);
			},
			isEmpty: function(val) {
				return val !== U ? _isEmpty(val) : this.empty;
			},
			notEmpty: function(val) {
				return ! helpers.isEmpty.call(this, val);
			}
		},
		views = {},
		esc,

		/**
		 * Determine if value matches empty criteria
		 *
		 * @private
		 * @param {*} val
		 * @returns {boolean}
		 */
		_isEmpty = function(val) {
			return val === '' || val === false || val == null ||
				(typeof val == 'object' && ! Object.keys(val).length);
		},

		/**
		 * Make recursive partial replacements
		 *
		 * @private
		 * @param {string} temp
		 * @returns {string}
		 */
		_embed = function(temp) {
			temp = temp.replace(reg.partial, function(m, tag) {
				return views[tag.trim()] || '';
			});

			if (reg.partial.test(temp)) {
				temp = _embed(temp);
			}

			return temp;
		},

		/**
		 * Get specific object value
		 *
		 * @private
		 * @param {object} data
		 * @param {object} prev
		 * @param {string} key
		 * @param {string} fb
		 * @param {object} init
		 * @returns {*}
		 */
		_get = function(data, prev, key, fb, init) {
			key = key.trim();

			// Alter context
			if (key.substr(0, 6) == '$root.') {
				key = key.substr(6);
				data = init;
			} else if (key.substr(0, 3) == '../') {
				key = key.substr(3);
				data = prev;
			}

			var segs = key == '.' ? ['.'] : key.split('.'),
				orig = data,
				len = segs.length - 1,
				i = 0;

			// Loop through object segments
			for (; i <= len; i++) {
				key = segs[i];

				if (data && data.hasOwnProperty(key)) {
					data = data[key];

					// Return value on last segment
					if (i === len) {
						if (! _isEmpty(data)) {
							return data;
						}

						break;
					}
				} else {
					break;
				}
			}

			if (key == '.') {
				return data;
			}

			// Process fallback value
			if (fb && fb !== '') {
				return _string(fb) || _get(orig, prev, fb, '', init);
			}

			return fb || data;
		},

		/**
		 * Process value based on quote enclosure
		 *
		 * @private
		 * @param {string} val
		 * @param {boolean} [wrap=false]
		 * @returns {string}
		 */
		_string = function(val, wrap) {
			val = val.trim();
			var match = val.match(reg.str);

			if (match) {
				return val.replace(reg.str, '')
					.replace(new RegExp(match[0] + '$'), '');
			}

			if (wrap) {
				return '{{' + val + '}}';
			}
		},

		/**
		 * Parse helper arguments
		 *
		 * @private
		 * @param {string} str
		 * @param {object} data
		 * @param {object} prev
		 * @param {object} init
		 * @returns {*}
		 */
		_parseArgs = function(str, data, prev, init) {
			var args = str !== U ? str.match(reg.args) || [] : [];

			return args.map(function(arg) {
				arg = arg.trim();
				var match = arg.match(reg.str);

				if (match) {
					return arg.replace(reg.str, '')
						.replace(new RegExp(match[0] + '$'), '');
				}

				return arg == 'true' ? true :
					arg == 'false' ? false :
					arg == 'null' ? null :
					parseInt(arg).toString() == arg ? parseInt(arg) :
					_get(data, prev, arg, '', init);
			});
		},

		/**
		 * Parse template string
		 *
		 * @private
		 * @param {string} temp
		 * @param {object} data
		 * @param {object} prev
		 * @param {object} init
		 * @param {int} index
		 * @returns {string}
		 */
		_parse = function(temp, data, prev, init, index) {
			return temp.replace(reg.pair, function(m, t, helper, inner) {
				// Return escaped template tag pairs
				if (t == '!') {
					esc = true;
					return inner.replace(/{{/g, '{~');
				}

				var tag = t.replace(/%\d+/, ''),
					cond = inner.split('{{:' + t + '}}');
				inner = cond[0];

				var val = _get(data, prev, tag, U, init),
					empty = _isEmpty(val),
					help = [],
					each;

				// Parse helpers
				if (helper || empty) {
					var meth = helper ? helper.split('|') : [],
						sec = cond.length > 1 ? cond[1] : '',
						agg = [];

					// Check for root helpers
					if (empty) {
						var arg = meth[0] && meth[0][0] == '(';
						meth.unshift(tag + (arg ? meth[0] : '()'));

						if (arg) {
							meth.splice(1, 1);
						}
					}

					// Capture available aggregates and helpers
					meth.forEach(function(el) {
						var arr = el.match(reg.ext),
							name = arr[1].trim();

						// Check for each helper
						if (name == 'each') {
							each = true;
						} else if (helpers[name]) {
							el = [helpers[name], arr[2]];
							each ? help.push(el) : agg.push(el);
						}
					});

					// Process aggregates
					if (agg.length) {
						if (! agg.every(function(f) {
								var rv = f[0].apply({
									val: val,
									data: data,
									root: init,
									tag: tag,
									empty: empty,
									index: index
								}, _parseArgs(f[1], val, prev, init));

								if (rv === false) {
									return rv;
								}

								if (rv !== true) {
									val = rv;
									empty = _isEmpty(val);
								}

								return true;
							})) {
							return _parse(sec, data, prev, init, index);
						}
					} else if (empty) {
						return _parse(sec, data, prev, init, index);
					}
				}

				var isObject = typeof val == 'object';

				if (! each) {
					if (! isObject) {
						val = W.$extend({}, data, {
							'.': val,
							'#': 0,
							'##': 1
						});
					}

					return _parse(inner, val, data, init, index);
				}

				if (! empty) {
					// Loop through objects and arrays
					if (isObject) {
						var isPlainObject = W.$isObject(val),
							resp = '',
							i = 0;

						for (var key in val) {
							if (val.hasOwnProperty(key)) {
								// Merge default properties
								var el = val[key];
								empty = _isEmpty(el);

								// Process helpers
								if (! help.length ||
									help.every(function(f) {
										var rv = f[0].apply({
											val: el,
											data: data,
											root: init,
											tag: tag,
											empty: empty,
											index: i
										}, _parseArgs(f[1], el, prev, init));

										if (rv === false) {
											return rv;
										}

										if (rv !== true) {
											el = rv;
										}

										return true;
									})
								) {
									var item = W.$extend({}, W.$isObject(el) ?
											el :
											(isPlainObject ? val : {}),
										{
											$key: key,
											'.': el,
											'#': i,
											'##': i + 1
										});
									i++;

									resp += _parse(inner, item, data, init, i);
								}
							}
						}

						return resp;
					}

					return inner;
				}
			}).replace(reg.single, function(m, set) {
				var split = set.split('||'),
					fb = split[1],
					segs = split[0].split('|'),
					tag = segs[0].trim(),
					val = _get(data, prev, tag, fb, init),
					helps = segs.length > 1 ? segs.slice(1) : segs;

				// Process helpers
				helps.forEach(function(el, i) {
					var arr = el.match(reg.ext);
					helps[i] = el.trim();

					if (arr) {
						var helper = helpers[arr[1].trim()];

						if (helper && (segs.length > 1 ||
							! data.hasOwnProperty(tag))) {
							val = helper.apply({
								val: val,
								data: data,
								root: init,
								tag: tag,
								index: index,
								fallback: fb
							}, _parseArgs(arr[2], data, prev, init));
						}
					}
				});

				// Encode output by default
				if (val === U || typeof val == 'object') {
					val = '';
				} else if (typeof val == 'string') {
					// Recursively process injected tags
					if (val.indexOf('{{') > -1) {
						val = _render(val, data);
					}

					// Encode HTML characters
					if (helps.indexOf('raw') < 0) {
						val = val.replace(/&/g, '&')
							.replace(/&/g, '&')
							.replace(/</g, '<')
							.replace(/>/g, '>')
							.replace(/"/g, '"');
					}
				}

				return val;
			});
		},

		/**
		 * Render template string
		 *
		 * @private
		 * @param {string} temp
		 * @param {object} data
		 * @returns {string}
		 */
		_render = function(temp, data) {
			var tags = [],
				depth = [];

			// Make partial replacements
			temp = _embed(temp);

			// Match tag pairs
			temp = temp.replace(reg.short, function(m, cond, val) {
				cond = cond.trim() + '}}';
				var segs = val.split(' : '),
					resp = '{{#' + cond + _string(segs[0], true);

				if (segs.length > 1) {
					resp += '{{else}}' + _string(segs[1], true);
				}

				return resp + '{{/' + cond;
			}).replace(reg.tags, function(m, pre, tag, helper) {
				var resp = '{{';

				if (tag == '!') {
					esc = pre == '#';
					resp += pre + tag;
				} else if (esc) {
					return m;
				} else if (pre) {
					var segs = tag.split('('),
						root = segs[0],
						exists = tags.hasOwnProperty(tag);
					resp += pre + root + '%';

					if (pre == '#') {
						depth.push(root);

						if (exists) {
							tags[root].i++;
							tags[root].o.push(tags[root].i);
						} else {
							tags[root] = {
								i: 1,
								o: [1]
							};
						}

						if (segs.length > 1) {
							helper = '(' + segs.slice(1).join('(');
						}

						resp += tags[root].i + (helper || '');
					} else if (exists) {
						resp += tags[root].o.pop();
						tags[root].i--;
						depth.pop();
					}
				} else if (depth.length) {
					tag = depth.slice(-1)[0];
					resp += ':' + tag + '%' + tags[tag].i;
				}

				return resp + '}}';
			});

			// Parse template tags
			return _parse(temp, data, {}, data, 0);
		};

	W.app = {
		/**
		 * Application instance storage
		 */
		fn: {},

		/**
		 * Create an application
		 *
		 * @param {string} name
		 * @param {object} options
		 * @param {object} options.model
		 * @param {($|HTMLElement|string)} [options.target]
		 * @param {($|HTMLElement|string)} options.view
		 *
		 */
		make: function(name, options) {
			var sel = options.view,
				targ = options.target,
				model = options.model || {},
				views = W.$(targ || sel).map(function(el) {
					return [el, targ ? sel : el.outerHTML];
				}),
				fn = function(data) {
					views.forEach(function(view) {
						W.$setRef(
							W.view.diff(view[0], W.$parseHTML(
								W.view.render(view[1], data)
							), targ)
						);
					});
				},
				app = W.app;

			// Create a new application controller
			app.fn[name] = W._make(name, {}, {}, false, model);
			app[name] = new app.fn[name]();

			fn(model);

			W.$extend(app[name], {
				/**
				 * Destroy current application
				 */
				$destroy: function() {
					if (options._destruct) {
						options._destruct();
					}

					delete app[name];
				},

				/**
				 * Pause view updating
				 */
				$pause: function() {
					app[name].$unobserve('*');
				},

				/**
				 * Resume view updating
				 *
				 * @param {boolean} [update=false]
				 */
				$resume: function(update) {
					app[name].$observe('*', fn);

					if (update) {
						fn(app[name].$get());
					}
				}
			});

			// Initialize app observation
			app[name].$resume();

			return app[name];
		}
	};

	W.view = {
		/**
		 * Parse data into template string
		 *
		 * @param {string} template
		 * @param {object} [data]
		 * @returns {string}
		 */
		render: function(template, data) {
			esc = false;
			template = _render(views[template] || template, W.$extend(data));

			return esc ?
				template.replace(/{~/g, '{{') :
				template;
		},

		/**
		 * Add conditional template handler or tag data modifier
		 *
		 * @param {object|string} name
		 * @param {function} [fn]
		 */
		addHelper: function(name, fn) {
			W._extend(helpers, name, fn);
		},

		/**
		 * Add views to store for on-demand reference
		 *
		 * @param {object|string} name
		 * @param {string} [value]
		 */
		addView: function(name, value) {
			W._extend(views, name, value);
		}
	};
})(Wee, undefined);<commit_msg>Correct internal _get to return proper value<commit_after>/* jshint maxdepth: 5, maxparams: 6 */

(function(W, U) {
	'use strict';

	var reg = {
			args: /(\\?['"][^'"]+\\?['"]|[^,]+)/g,
			ext: /(.[^\(]+)(?:\((.*)\))?/,
			pair: /{{#(\S+?)(?:\|(.+?))?}}([\s\S]+?){{\/\1}}/g,
			partial: /{{\s*>(.+?)}}/g,
			short: /{{([^}]+) +\? ([^}]+)}}/g,
			single: /{{(.+?)}}/g,
			str: /^\\?("|')/,
			tags: /{{\s*(?:([#\/])([^#{\|\n\s]+)\s*(\|[^{\n]+)?|else)\s*}}/g
		},
		helpers = {
			is: function(a, b) {
				return a === (b !== U ? b : this.val);
			},
			not: function(a, b) {
				return ! helpers.is.call(this, a, b);
			},
			isEmpty: function(val) {
				return val !== U ? _isEmpty(val) : this.empty;
			},
			notEmpty: function(val) {
				return ! helpers.isEmpty.call(this, val);
			}
		},
		views = {},
		esc,

		/**
		 * Determine if value matches empty criteria
		 *
		 * @private
		 * @param {*} val
		 * @returns {boolean}
		 */
		_isEmpty = function(val) {
			return val === '' || val === false || val == null ||
				(typeof val == 'object' && ! Object.keys(val).length);
		},

		/**
		 * Make recursive partial replacements
		 *
		 * @private
		 * @param {string} temp
		 * @returns {string}
		 */
		_embed = function(temp) {
			temp = temp.replace(reg.partial, function(m, tag) {
				return views[tag.trim()] || '';
			});

			if (reg.partial.test(temp)) {
				temp = _embed(temp);
			}

			return temp;
		},

		/**
		 * Get specific object value
		 *
		 * @private
		 * @param {object} data
		 * @param {object} prev
		 * @param {string} key
		 * @param {string} fb
		 * @param {object} init
		 * @returns {*}
		 */
		_get = function(data, prev, key, fb, init) {
			key = key.trim();

			// Alter context
			if (key.substr(0, 6) == '$root.') {
				key = key.substr(6);
				data = init;
			} else if (key.substr(0, 3) == '../') {
				key = key.substr(3);
				data = prev;
			}

			var segs = key == '.' ? ['.'] : key.split('.'),
				orig = data,
				len = segs.length - 1,
				i = 0;

			// Loop through object segments
			for (; i <= len; i++) {
				key = segs[i];

				if (data && data.hasOwnProperty(key)) {
					data = data[key];

					// Return value on last segment
					if (i === len) {
						if (! _isEmpty(data)) {
							return data;
						}

						break;
					}
				} else {
					data = data ? data[key] : U;
					break;
				}
			}

			if (key == '.') {
				return data;
			}

			// Process fallback value
			if (fb && fb !== '') {
				return _string(fb) || _get(orig, prev, fb, '', init);
			}

			return fb || data;
		},

		/**
		 * Process value based on quote enclosure
		 *
		 * @private
		 * @param {string} val
		 * @param {boolean} [wrap=false]
		 * @returns {string}
		 */
		_string = function(val, wrap) {
			val = val.trim();
			var match = val.match(reg.str);

			if (match) {
				return val.replace(reg.str, '')
					.replace(new RegExp(match[0] + '$'), '');
			}

			if (wrap) {
				return '{{' + val + '}}';
			}
		},

		/**
		 * Parse helper arguments
		 *
		 * @private
		 * @param {string} str
		 * @param {object} data
		 * @param {object} prev
		 * @param {object} init
		 * @returns {*}
		 */
		_parseArgs = function(str, data, prev, init) {
			var args = str !== U ? str.match(reg.args) || [] : [];

			return args.map(function(arg) {
				arg = arg.trim();
				var match = arg.match(reg.str);

				if (match) {
					return arg.replace(reg.str, '')
						.replace(new RegExp(match[0] + '$'), '');
				}

				return arg == 'true' ? true :
					arg == 'false' ? false :
					arg == 'null' ? null :
					parseInt(arg).toString() == arg ? parseInt(arg) :
					_get(data, prev, arg, '', init);
			});
		},

		/**
		 * Parse template string
		 *
		 * @private
		 * @param {string} temp
		 * @param {object} data
		 * @param {object} prev
		 * @param {object} init
		 * @param {int} index
		 * @returns {string}
		 */
		_parse = function(temp, data, prev, init, index) {
			return temp.replace(reg.pair, function(m, t, helper, inner) {
				// Return escaped template tag pairs
				if (t == '!') {
					esc = true;
					return inner.replace(/{{/g, '{~');
				}

				var tag = t.replace(/%\d+/, ''),
					cond = inner.split('{{:' + t + '}}');
				inner = cond[0];

				var val = _get(data, prev, tag, U, init),
					empty = _isEmpty(val),
					help = [],
					each;

				// Parse helpers
				if (helper || empty) {
					var meth = helper ? helper.split('|') : [],
						sec = cond.length > 1 ? cond[1] : '',
						agg = [];

					// Check for root helpers
					if (empty) {
						var arg = meth[0] && meth[0][0] == '(';
						meth.unshift(tag + (arg ? meth[0] : '()'));

						if (arg) {
							meth.splice(1, 1);
						}
					}

					// Capture available aggregates and helpers
					meth.forEach(function(el) {
						var arr = el.match(reg.ext),
							name = arr[1].trim();

						// Check for each helper
						if (name == 'each') {
							each = true;
						} else if (helpers[name]) {
							el = [helpers[name], arr[2]];
							each ? help.push(el) : agg.push(el);
						}
					});

					// Process aggregates
					if (agg.length) {
						if (! agg.every(function(f) {
								var rv = f[0].apply({
									val: val,
									data: data,
									root: init,
									tag: tag,
									empty: empty,
									index: index
								}, _parseArgs(f[1], val, prev, init));

								if (rv === false) {
									return rv;
								}

								if (rv !== true) {
									val = rv;
									empty = _isEmpty(val);
								}

								return true;
							})) {
							return _parse(sec, data, prev, init, index);
						}
					} else if (empty) {
						return _parse(sec, data, prev, init, index);
					}
				}

				var isObject = typeof val == 'object';

				if (! each) {
					if (! isObject) {
						val = W.$extend({}, data, {
							'.': val,
							'#': 0,
							'##': 1
						});
					}

					return _parse(inner, val, data, init, index);
				}

				if (! empty) {
					// Loop through objects and arrays
					if (isObject) {
						var isPlainObject = W.$isObject(val),
							resp = '',
							i = 0;

						for (var key in val) {
							if (val.hasOwnProperty(key)) {
								// Merge default properties
								var el = val[key];
								empty = _isEmpty(el);

								// Process helpers
								if (! help.length ||
									help.every(function(f) {
										var rv = f[0].apply({
											val: el,
											data: data,
											root: init,
											tag: tag,
											empty: empty,
											index: i
										}, _parseArgs(f[1], el, prev, init));

										if (rv === false) {
											return rv;
										}

										if (rv !== true) {
											el = rv;
										}

										return true;
									})
								) {
									var item = W.$extend({}, W.$isObject(el) ?
											el :
											(isPlainObject ? val : {}),
										{
											$key: key,
											'.': el,
											'#': i,
											'##': i + 1
										});
									i++;

									resp += _parse(inner, item, data, init, i);
								}
							}
						}

						return resp;
					}

					return inner;
				}
			}).replace(reg.single, function(m, set) {
				var split = set.split('||'),
					fb = split[1],
					segs = split[0].split('|'),
					tag = segs[0].trim(),
					val = _get(data, prev, tag, fb, init),
					helps = segs.length > 1 ? segs.slice(1) : segs;

				// Process helpers
				helps.forEach(function(el, i) {
					var arr = el.match(reg.ext);
					helps[i] = el.trim();

					if (arr) {
						var helper = helpers[arr[1].trim()];

						if (helper && (segs.length > 1 ||
							! data.hasOwnProperty(tag))) {
							val = helper.apply({
								val: val,
								data: data,
								root: init,
								tag: tag,
								index: index,
								fallback: fb
							}, _parseArgs(arr[2], data, prev, init));
						}
					}
				});

				// Encode output by default
				if (val === U || typeof val == 'object') {
					val = '';
				} else if (typeof val == 'string') {
					// Recursively process injected tags
					if (val.indexOf('{{') > -1) {
						val = _render(val, data);
					}

					// Encode HTML characters
					if (helps.indexOf('raw') < 0) {
						val = val.replace(/&/g, '&')
							.replace(/&/g, '&')
							.replace(/</g, '<')
							.replace(/>/g, '>')
							.replace(/"/g, '"');
					}
				}

				return val;
			});
		},

		/**
		 * Render template string
		 *
		 * @private
		 * @param {string} temp
		 * @param {object} data
		 * @returns {string}
		 */
		_render = function(temp, data) {
			var tags = [],
				depth = [];

			// Make partial replacements
			temp = _embed(temp);

			// Match tag pairs
			temp = temp.replace(reg.short, function(m, cond, val) {
				cond = cond.trim() + '}}';
				var segs = val.split(' : '),
					resp = '{{#' + cond + _string(segs[0], true);

				if (segs.length > 1) {
					resp += '{{else}}' + _string(segs[1], true);
				}

				return resp + '{{/' + cond;
			}).replace(reg.tags, function(m, pre, tag, helper) {
				var resp = '{{';

				if (tag == '!') {
					esc = pre == '#';
					resp += pre + tag;
				} else if (esc) {
					return m;
				} else if (pre) {
					var segs = tag.split('('),
						root = segs[0],
						exists = tags.hasOwnProperty(tag);
					resp += pre + root + '%';

					if (pre == '#') {
						depth.push(root);

						if (exists) {
							tags[root].i++;
							tags[root].o.push(tags[root].i);
						} else {
							tags[root] = {
								i: 1,
								o: [1]
							};
						}

						if (segs.length > 1) {
							helper = '(' + segs.slice(1).join('(');
						}

						resp += tags[root].i + (helper || '');
					} else if (exists) {
						resp += tags[root].o.pop();
						tags[root].i--;
						depth.pop();
					}
				} else if (depth.length) {
					tag = depth.slice(-1)[0];
					resp += ':' + tag + '%' + tags[tag].i;
				}

				return resp + '}}';
			});

			// Parse template tags
			return _parse(temp, data, {}, data, 0);
		};

	W.app = {
		/**
		 * Application instance storage
		 */
		fn: {},

		/**
		 * Create an application
		 *
		 * @param {string} name
		 * @param {object} options
		 * @param {object} options.model
		 * @param {($|HTMLElement|string)} [options.target]
		 * @param {($|HTMLElement|string)} options.view
		 *
		 */
		make: function(name, options) {
			var sel = options.view,
				targ = options.target,
				model = options.model || {},
				views = W.$(targ || sel).map(function(el) {
					return [el, targ ? sel : el.outerHTML];
				}),
				fn = function(data) {
					views.forEach(function(view) {
						W.$setRef(
							W.view.diff(view[0], W.$parseHTML(
								W.view.render(view[1], data)
							), targ)
						);
					});
				},
				app = W.app;

			// Create a new application controller
			app.fn[name] = W._make(name, {}, {}, false, model);
			app[name] = new app.fn[name]();

			fn(model);

			W.$extend(app[name], {
				/**
				 * Destroy current application
				 */
				$destroy: function() {
					if (options._destruct) {
						options._destruct();
					}

					delete app[name];
				},

				/**
				 * Pause view updating
				 */
				$pause: function() {
					app[name].$unobserve('*');
				},

				/**
				 * Resume view updating
				 *
				 * @param {boolean} [update=false]
				 */
				$resume: function(update) {
					app[name].$observe('*', fn);

					if (update) {
						fn(app[name].$get());
					}
				}
			});

			// Initialize app observation
			app[name].$resume();

			return app[name];
		}
	};

	W.view = {
		/**
		 * Parse data into template string
		 *
		 * @param {string} template
		 * @param {object} [data]
		 * @returns {string}
		 */
		render: function(template, data) {
			esc = false;
			template = _render(views[template] || template, W.$extend(data));

			return esc ?
				template.replace(/{~/g, '{{') :
				template;
		},

		/**
		 * Add conditional template handler or tag data modifier
		 *
		 * @param {object|string} name
		 * @param {function} [fn]
		 */
		addHelper: function(name, fn) {
			W._extend(helpers, name, fn);
		},

		/**
		 * Add views to store for on-demand reference
		 *
		 * @param {object|string} name
		 * @param {string} [value]
		 */
		addView: function(name, value) {
			W._extend(views, name, value);
		}
	};
})(Wee, undefined);<|endoftext|>


<commit_before>import electron, { app } from 'electron'
import debugFactory from 'debug'
import appMenu from './menu'
import { START_PROXY } from './constants/ipcMessages'
import { createMainWindow, createProxyWindow, sendToProxyWindow } from './windows'

const debug = debugFactory('halland-proxy:main')

app.on('window-all-closed', () => {
  debug('All window closed...')
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

process.on('uncaughtException', (err) => {
  debug('Crashed...', err)
})

app.on('ready', () => {
  debug('App ready...')
  electron.Menu.setApplicationMenu(appMenu)

  createMainWindow()
  createProxyWindow().on('ready-to-show', () => sendToProxyWindow(START_PROXY))
})
<commit_msg>Show proxy window with dev tools if debug env exists<commit_after>import electron, { app } from 'electron'
import debugFactory from 'debug'
import appMenu from './menu'
import { START_PROXY } from './constants/ipcMessages'
import { createMainWindow, createProxyWindow, sendToProxyWindow } from './windows'

const debug = debugFactory('halland-proxy:main')

app.on('window-all-closed', () => {
  debug('All window closed...')
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

process.on('uncaughtException', (err) => {
  debug('Crashed...', err)
})

app.on('ready', () => {
  debug('App ready...')
  electron.Menu.setApplicationMenu(appMenu)

  createMainWindow()
  const proxyWindow = createProxyWindow()
  proxyWindow.on('ready-to-show', () => {
    sendToProxyWindow(START_PROXY)
    if (process.env['DEBUG']) {
      proxyWindow.show()
      proxyWindow.toggleDevTools()
    }
  })
})
<|endoftext|>


<commit_before>/**
 * App ID for the skill
 */
//var APP_ID = undefined; //OPTIONAL: replace with "amzn1.echo-sdk-ams.app.[your-unique-value-here]";

var APP_ID = "amzn1.ask.skill.69248e8b-2456-4937-9227-94773ceb34de";

// [http://www.chimet.co.uk/csg/chi.html]
// `22 January,6:50 am,6.4,7.4,051,3.90, 0.59,0.68,15,1.6,,1026,`
// Date, time, mean, gust, Wind Dir, tide hight, mean wave height, max wave height, wave period, air temp, sea temp, pressure, visibility

var URI = 'http://www.chimet.co.uk/csg/chi.html'
var http = require('http');
var chiData = [];
var chiDataTime = 0;

/**
 * The AlexaSkill prototype and helper functions
 */
var AlexaSkill = require('./AlexaSkill');

/**
 * SpaceGeek is a child of AlexaSkill.
 * To read more about inheritance in JavaScript, see the link below.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Inheritance
 */
var Chimet = function () {
    AlexaSkill.call(this, APP_ID);
};

// Extend AlexaSkill
Chimet.prototype = Object.create(AlexaSkill.prototype);
Chimet.prototype.constructor = Chimet;

Chimet.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
    //console.log("onSessionStarted requestId: " + sessionStartedRequest.requestId + ", sessionId: " + session.sessionId);
    // any initialization logic goes here
};

Chimet.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
    //console.log("onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
    handleNewFactRequest(response);
};

/**
 * Overridden to show that a subclass can override this function to teardown session state.
 */
Chimet.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
    //console.log("onSessionEnded requestId: " + sessionEndedRequest.requestId + ", sessionId: " + session.sessionId);
    // any cleanup logic goes here
};

Chimet.prototype.intentHandlers = {
    "GetChiMetIntent": function (intent, session, response) {
	    console.log("Chimet.prototype.intentHandlers: got here!");
		handleChiMetRequest(response);
    },

    "AMAZON.HelpIntent": function (intent, session, response) {
        response.ask("What can I help you with?");
    },

    "AMAZON.StopIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    },

    "AMAZON.CancelIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    }
};

/**
 * Gets a random new fact from the list and returns to the user.
 */

function handleChiMetRequest(response) {

  console.log('handleChiMetRequest: got here too');
  var speechOutput = '';
  var cardTitle = 'Chimet';

  console.time('http-request');

  http.get(URI, function (res) {
    var chiResponseString = '';
    console.log('handleChiMetRequest: HTTP response for Status Code: '+res.statusCode+', for: '+URI);

    // if for some reason we did not get a HTTP 200 OK
    if (res.statusCode != 200) {
      forecastResponseCallback(new Error("handleChiMetRequest: Non 200 Response for: "+URI));
      console.timeEnd('http-request');
    }

    // got some more data to append
    res.on('data', function (data) {
      chiResponseString += data;
    });

    // in theory finished!
    res.on('end', function () {
      // should have a sensible result
      chiDataTime = new Date().getTime();
      chiData = chiResponseString.split(',');
      console.log("handleChiMetRequest: res.on done");
      console.timeEnd('http-request');

      speechOutput = 'Chimet.  '+chiData[1]+'.  '+chiData[0]+'.  '
        +'Wind mean '+chiData[2]+', gusting '+chiData[3]+', direction '+chiData[4]+'.  '
        +'Tide height '+chiData[5]+'.  '
        +'Air temp '+chiData[9]+' degrees.';

	  console.log("handleChiMetRequest: speechOutput is: "+speechOutput);

    });
  }).on('error', function (e) {
    console.timeEnd('http-request');
    console.log("handleChiMetRequest: Communications error: " + e.message);
  });

  response.tellWithCard(speechOutput, cardTitle, speechOutput);
}

// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {
    var chimet = new Chimet();
    // Create an instance of the chimet skill.
    chimet.execute(event, context);
};

<commit_msg>build commit: 1485093540<commit_after>/**
 * App ID for the skill
 */
//var APP_ID = undefined; //OPTIONAL: replace with "amzn1.echo-sdk-ams.app.[your-unique-value-here]";

var APP_ID = "amzn1.ask.skill.69248e8b-2456-4937-9227-94773ceb34de";

// [http://www.chimet.co.uk/csg/chi.html]
// `22 January,6:50 am,6.4,7.4,051,3.90, 0.59,0.68,15,1.6,,1026,`
// Date, time, mean, gust, Wind Dir, tide hight, mean wave height, max wave height, wave period, air temp, sea temp, pressure, visibility

var URI = 'http://www.chimet.co.uk/csg/chi.html';
var http = require('http');
var chiData = [];
var chiDataTime = 0;

/**
 * The AlexaSkill prototype and helper functions
 */
var AlexaSkill = require('./AlexaSkill');

/**
 * SpaceGeek is a child of AlexaSkill.
 * To read more about inheritance in JavaScript, see the link below.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Inheritance
 */
var Chimet = function () {
    AlexaSkill.call(this, APP_ID);
};

// Extend AlexaSkill
Chimet.prototype = Object.create(AlexaSkill.prototype);
Chimet.prototype.constructor = Chimet;

Chimet.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
    //console.log("onSessionStarted requestId: " + sessionStartedRequest.requestId + ", sessionId: " + session.sessionId);
    // any initialization logic goes here
};

Chimet.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
    //console.log("onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
    handleNewFactRequest(response);
};

/**
 * Overridden to show that a subclass can override this function to teardown session state.
 */
Chimet.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
    //console.log("onSessionEnded requestId: " + sessionEndedRequest.requestId + ", sessionId: " + session.sessionId);
    // any cleanup logic goes here
};

Chimet.prototype.intentHandlers = {
    "GetChiMetIntent": function (intent, session, response) {
	    console.log("Chimet.prototype.intentHandlers: got here!");
		handleChiMetRequest(response);
    },

    "AMAZON.HelpIntent": function (intent, session, response) {
        response.ask("What can I help you with?");
    },

    "AMAZON.StopIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    },

    "AMAZON.CancelIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    }
};

/**
 * Gets a random new fact from the list and returns to the user.
 */

function handleChiMetRequest(response) {

  console.log('handleChiMetRequest: got here too');
  var speechOutput = '';
  var cardTitle = 'Chimet';

  console.time('http-request');

  http.get(URI, function (res) {
    var chiResponseString = '';
    console.log('handleChiMetRequest: HTTP response for Status Code: '+res.statusCode+', for: '+URI);

    // if for some reason we did not get a HTTP 200 OK
    if (res.statusCode != 200) {
      forecastResponseCallback(new Error("handleChiMetRequest: Non 200 Response for: "+URI));
      console.timeEnd('http-request');
    }

    // got some more data to append
    res.on('data', function (data) {
      chiResponseString += data;
    });

    // in theory finished!
    res.on('end', function () {
      // should have a sensible result
      chiDataTime = new Date().getTime();
      chiData = chiResponseString.split(',');
      console.log("handleChiMetRequest: res.on done");
      console.timeEnd('http-request');

      speechOutput = 'Chimet.  '+chiData[1]+'.  '+chiData[0]+'.  '
        +'Wind mean '+chiData[2]+', gusting '+chiData[3]+', direction '+chiData[4]+'.  '
        +'Tide height '+chiData[5]+'.  '
        +'Air temp '+chiData[9]+' degrees.';

	  console.log("handleChiMetRequest: speechOutput is: "+speechOutput);

    });
  }).on('error', function (e) {
    console.timeEnd('http-request');
    console.log("handleChiMetRequest: Communications error: " + e.message);
  });

  response.tellWithCard(speechOutput, cardTitle, speechOutput);
}

// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {
    var chimet = new Chimet();
    // Create an instance of the chimet skill.
    chimet.execute(event, context);
};

<|endoftext|>


<commit_before>import axis from 'axis.js'
import uglify from 'uglify-js'
import vm from 'vm'

function JasonettePlugin(options) {
  this.replacer = (key, value) => {
    if(axis.isFunction(value)) {
      const uglified = uglify.minify(`${String(value)}`, {fromString: true})
      const cleaned = uglified.code.replace('{{', '{ {').replace('}}', '} }')
      return `{{ ${cleaned};return ${value.name}() }}`
    } else if(axis.isObject(value) || axis.isArray(value)) {
      return value
    }
    return String(value)
  }
  const defaultOptions = {
    'replacer': this.replacer,
    'space': ''
  }

  this.options = Object.assign(defaultOptions, options)
}

JasonettePlugin.prototype.apply = function(compiler) {
  const options = this.options

  compiler.plugin("emit", (compilation, callback) => {
    Object.keys(compilation.assets).forEach((asset) => {
      const compiled = vm.runInThisContext(compilation.assets[asset].source())
      Object.keys(compiled).forEach((json) => {
        var src = JSON.stringify(compiled[json], options.replacer, options.space)
        const filename = ['default', 'jasonette'].indexOf(json) > -1 ? asset : `${json}.json`
        compilation.assets[filename] = {
          source: () => src,
          size: () => src.length
        }
      })
    })
    callback()
  })
}

export default JasonettePlugin
<commit_msg>avoid var keyword<commit_after>import axis from 'axis.js'
import uglify from 'uglify-js'
import vm from 'vm'

function JasonettePlugin(options) {
  this.replacer = (key, value) => {
    if(axis.isFunction(value)) {
      const uglified = uglify.minify(`${String(value)}`, {fromString: true})
      const cleaned = uglified.code.replace('{{', '{ {').replace('}}', '} }')
      return `{{ ${cleaned};return ${value.name}() }}`
    } else if(axis.isObject(value) || axis.isArray(value)) {
      return value
    }
    return String(value)
  }
  const defaultOptions = {
    'replacer': this.replacer,
    'space': ''
  }

  this.options = Object.assign(defaultOptions, options)
}

JasonettePlugin.prototype.apply = function(compiler) {
  const options = this.options

  compiler.plugin("emit", (compilation, callback) => {
    Object.keys(compilation.assets).forEach((asset) => {
      const compiled = vm.runInThisContext(compilation.assets[asset].source())
      Object.keys(compiled).forEach((json) => {
        const src = JSON.stringify(compiled[json], options.replacer, options.space)
        const filename = ['default', 'jasonette'].indexOf(json) > -1 ? asset : `${json}.json`
        compilation.assets[filename] = {
          source: () => src,
          size: () => src.length
        }
      })
    })
    callback()
  })
}

export default JasonettePlugin
<|endoftext|>


<commit_before>import {buildHtml} from "./buildhtml";
import {buildClientJs as buildBrowserify} from "./buildjs-browserify";
import {buildClientJs as buildRollup} from "./buildjs-rollup";

import * as rebuild from "rebuild-linked";

var modules = rebuild.getModules(process.cwd());
    /* Tools to be called from gulp when building a standard app */

var gulp = require('gulp');
var fs = require("fs-extra");
var path = require("path");

var extend = require("extend");

var chokidar = require('chokidar');

var async = require("async");

var tools = module.exports;
var cwd = process.cwd();

var sass = require('node-sass');

var resolve = require('resolve');

var options = {
    globals: {
        angular: "angular",
        jquery: "$",
        d3: "d3"
    },
    serverapp: {

    },
    sourceFolder: "./src",
    libFolder: "./lib",
    cssEntryPoint: "./css/index.scss",
    moduleMappings: {},
    customBrowserifyTransforms: [],
    additionalWatchPaths: [],
    buildfolder: "./build",
    cssVariations: {
        "ie": '$browserType: "ie";'
    },
    imageFolders: ["./src/images"],
    legacyBrowserError: {
        title: "App Error",
        message: "This app is designed for use in modern browsers."
    },
    templateData: {}
};

tools.init = function(opt) {
    rebuild.ensureModulesBuilt(process.cwd());
    extend(options, opt);
};

tools.test = function() {
    console.log("Test function");
};

tools.buildVariation = function(variation, env, watch, destFolder, onBuildComplete) {
    tools.buildVariations(variation,
        [{
            key: "index",
            title: variation,
            outputScriptName: "app",
            outputHtmlName: "index",
            additionalData: options.templateData || {}
        }].concat(options.subvariations || []),
        env, watch, destFolder, onBuildComplete);
};

tools.buildVariations = function(variationFolderName, subvariations, env, watch, destFolder, onBuildComplete) {
    console.log(subvariations);
    if (options.useRollup) {
        console.log("Building with Rollup");
    } else {
        console.log("Building with Browserify");
    }

    onBuildComplete = onBuildComplete || function(err) {
        if (!err) {
            console.log("Build completed successfully");
        } else {
            console.log(err);
        }
    };
    var debugMode = env != "prod"; //true;
    if (options.debug !== undefined) debugMode = options.debug;
    if (options[env] && options[env].debug !== undefined) debugMode = options[env].debug;
    console.log("Debug: " + debugMode);
    console.log("building " + variationFolderName + " for " + env);
    var buildfolder = path.resolve(cwd, options.buildfolder);
    var tempFolder = path.resolve(buildfolder, "temp-" + variationFolderName + "-" + env);
    var varFolder = path.resolve(buildfolder, env, variationFolderName);
    if (destFolder) varFolder = path.resolve(cwd, destFolder);

    fs.ensureDirSync(tempFolder);
    fs.ensureDirSync(varFolder);

    var hostSettings = {};
    extend(hostSettings, options.hostSettings);
    extend(hostSettings, options[env]);
    fs.writeFileSync(path.resolve(tempFolder, "hostsettings.js"), "module.exports=" + JSON.stringify(hostSettings), "utf-8");

    var sourceFolder = path.resolve(cwd, options.sourceFolder);
    var libFolder = path.resolve(cwd, options.libFolder);

    function buildClientJs(callback) {
        async.eachSeries(subvariations, function(subvariation, next) {
            if (!subvariation.outputScriptName) return next();
            if (subvariation.apps && subvariation.apps.indexOf(variationFolderName) < 0) return next();
            var opts = {
                options: options,
                debugMode: debugMode,
                tempFolder: tempFolder,
                src: path.resolve(sourceFolder, (subvariation.jsEntryPoint || variationFolderName) + ".js"),
                dest: path.resolve(varFolder, (subvariation.outputScriptName || "app") + ".js"),
                moduleMappings: options.moduleMappings
            };
            if (options.useRollup) {
                buildRollup(opts, next);
            }
            else {
                buildBrowserify(opts, next);
            }

            // For use with <script>$.getScript(window.atob ? "app.js" : "app-es3.js");</script>
            // no longer needed but kept for backward compatibility
            var statusReporter = require("browserify-build-status");
            fs.writeFileSync(path.resolve(varFolder, "app-es3.js"), statusReporter.getErrorScript(options.legacyBrowserError.title, options.legacyBrowserError.message));
        }, callback);

    }

    function copyHtml(callback) {
        console.log(subvariations);
        async.eachSeries(subvariations, function(subvariation, next) {
            if (!subvariation.outputHtmlName) return next();
            if (subvariation.apps && subvariation.apps.indexOf(variationFolderName) < 0) return next();
            var td = subvariation.additionalData || options.templateData || {};
            td.app = variationFolderName;
            td.env = env;
            td.variation = subvariation;
            td.options = options;
            var preloadCssPath = path.resolve(varFolder, "inline.css");
            if (fs.existsSync(preloadCssPath)) {
                td.inlineCss = fs.readFileSync(preloadCssPath, "utf-8");
            }
            else {
                td.inlineCss = "";
            }

            buildHtml(
                {
                    options: options,
                    sourceFolders: options.sourceFolders || [sourceFolder],
                    destFolder: varFolder,
                    fileMappings: subvariation.fileMappings || {
                        "index": subvariation.outputHtmlName,
                        "index-ie": subvariation.outputHtmlName + "-ie"
                    },
                    templateData: td
                },
                next);
        }, callback);
    }

    function copyLib(callback) {
        gulp.src(libFolder + '/*.*')
                .pipe(gulp.dest(varFolder + "/lib"))
                .on("end", callback);
    }

    function copyImages(callback) {
        var flatten = require('gulp-flatten');
        console.log("Copying images");
        var globs = [];
        for (let i = 0; i < options.imageFolders.length; i++) {
            var imgf = options.imageFolders[i];
            globs.push(imgf + "/**");
        }
        console.log(globs);
        try {
            var imagemin = require('gulp-imagemin');
            gulp.src(globs)
                    .pipe(flatten())
                    .pipe(imagemin({
                        progressive: true,
                        svgoPlugins: [{
                            removeViewBox: false
                        }]
                    }))
                    .pipe(gulp.dest(varFolder + "/images"))
                    .on("end", callback);
        } catch (ex) {
                // probably just imagemin not being installed - fall back to regular file copy
            console.log("Image optimization failed - copying images unmodified.");
            gulp.src(globs)
                    .pipe(flatten())
                    .pipe(gulp.dest(varFolder + "/images"))
                    .on("end", callback);

        }

    }

        //        function copyImages() {
        //            gulp.src(__dirname + '/apphtml/images/**/*')
        //                .pipe(gulp.dest(options.buildfolder + "/" + env + "/" + variation + "/images"))
        //                .on("end", function() {
        //                    gulp.src(process.cwd() + "/images/**/*")
        //                        .pipe(gulp.dest(options.buildfolder + "/" + env + "/" + variation + "/images"));
        //                });
        //        }

    function buildCssFile(inputFile, outputFile, fileBuilt) {
        sass.render({
            file: inputFile,
            outFile: varFolder + "/" + outputFile,
            sourceMap: true,
            outputStyle: debugMode ? "nested" : "compressed",
            importer: [function(url, prev) {

                    // first check if the file exists as specified
                var f = path.resolve(path.dirname(prev), url);
                if (fs.existsSync(f)) return { file: f };

                    // or with .scss added
                var f2 = path.dirname(f) + "/" + path.basename(f, ".scss") + ".scss";
                if (fs.existsSync(f2)) return { file: f2 };

                    // or with an underscore
                var f3 = path.dirname(f) + "/_" + path.basename(f, ".scss") + ".scss";
                if (fs.existsSync(f3)) return { file: f3 };

                    // try using node resolve
                var f4 = url;
                    // if it includes node_modules, remove it
                if (f4.indexOf("node_modules/") >= 0) {
                    f4 = f4.substr(f4.lastIndexOf("node_modules/") + 13);
                }

                    // resolve with require("resolve")
                try {
                    f4 = resolve.sync(f4, {
                        basedir: path.dirname(prev),
                        extensions: [".scss"]
                    });
                    return {file: f4 };
                }
                    catch (e) {
                        console.log(e);
                        // couldn't resolve it this way - ignore error and fall back to the default
                    }
                return null;
            }]
                // includePaths: ["."]
        }, function(err, result) {
            if (!err) {
                fs.writeFileSync(varFolder + "/" + outputFile, result.css);
                fs.writeFileSync(varFolder + "/" + outputFile + ".map", result.map);
                console.log("Completed sass build of " + inputFile);
            }
            if (fileBuilt) fileBuilt(err, result);
        });
    }

    function buildPreloadCss(onCssBuilt) {
        var cssEntryPoint = path.resolve(cwd, options.cssEntryPoint);
        var preloadCssPath = path.resolve(cssEntryPoint, "../inline.scss");
        console.log(preloadCssPath);
        if (!fs.existsSync(preloadCssPath)) return onCssBuilt && onCssBuilt();

        buildCssFile(preloadCssPath, "inline.css", onCssBuilt);

    }

    function buildCss(onCssBuilt) {
        console.log("Building CSS");
        var cssEntryPoint = path.resolve(cwd, options.cssEntryPoint);

        buildCssFile(cssEntryPoint, "app.css", function(err) {
            if (err) {
                return onCssBuilt && onCssBuilt(err);
            }

            var cssVariations = [];
            for (let k2 in options.cssVariations) {
                cssVariations.push({
                    key: k2,
                    settings: options.cssVariations[k2]
                });
            }

            async.eachSeries(cssVariations, function(v, next) {
                var iesrc = v.settings + '\n@import "' + (path.relative(tempFolder, cssEntryPoint).replace(/\\/ig, "/")) + '";';
                var ieCssFile = path.resolve(tempFolder, "index-" + v.key + ".scss");
                fs.writeFileSync(ieCssFile, iesrc);
                buildCssFile(ieCssFile, "app-" + v.key + ".css", next);
            }, function(err2) {
                if (err2) {
                    return onCssBuilt && onCssBuilt(err2);
                }
                buildPreloadCss(onCssBuilt);
            });

                // preloader

        });

    }

    function afterBuild(callback) {
        if (options.afterBrowserify) options.afterBrowserify(varFolder, env, variationFolderName);
        console.log("Build completed successfully");
        callback();
    }

    var fullBuild = [buildClientJs, buildCss, copyHtml, copyImages, copyLib, afterBuild];

    async.series(fullBuild, onBuildComplete);

    if (watch) {
        var paths = [sourceFolder].concat(options.additionalWatchPaths);

        // todo: assuming existence of src folder is not ideal. Unfortunately watching the whole module
        // folder causes severe performance issues.
        for (let i = 0; i < modules.length; i++) {
            var sf = path.resolve(modules[i].path, "src");
            if (fs.existsSync(sf)) paths.push(sf);
            sf = path.resolve(modules[i].path, "clientapp");
            if (fs.existsSync(sf)) paths.push(sf);
            sf = path.resolve(modules[i].path, "api");
            if (fs.existsSync(sf)) paths.push(sf);
        }
        //paths.push.apply(paths, modules.map(m => m.path));

        var cssFolder = path.dirname(path.resolve(cwd, options.cssEntryPoint));
        if (cssFolder.indexOf(sourceFolder) !== 0) paths.push(cssFolder);

        // watch image folders
        for (let i = 0; i < options.imageFolders.length; i++) {
            var imgf = options.imageFolders[i];
            if (imgf.indexOf(sourceFolder) !== 0) paths.push(imgf);
        }
        // watch tests
        if (options.browserTests) {
            paths.push(path.dirname(path.resolve(options.browserTests)));
        }
        console.log("Watching: ");
        console.log(paths);

        var watcher = chokidar.watch(paths, {
            ignored: [/[\/\\]\./, "node_modules", "build", "dist"],
            persistent: true,
            ignoreInitial: true
        });

        watcher.on("all", function(type, file) {
            console.log(type + " event for " + file);
            var ext = path.extname(file);
            if (ext == ".scss") {
                console.log("CSS needs rebuild");
                async.series([buildCss], function(err) {
                    if (err) {
                        console.log(err);
                    }
                });
            } else if (ext == ".js" || ext == ".html") {
                // if the changed file is .js or .html, need to run browserify
                console.log("Browserify package needs rebuild");
                async.series([buildClientJs, afterBuild], function() {});
            } else if (ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif") {
                    // src/images just needs to be copied if anything changes, and it can't contain anything used by browserify
                console.log("Updating images");
                async.series([copyImages], function() {});
            }
        });

    }
};

tools.buildTask = function(cb) {
    var args = process.argv.slice(3);
    if (args.length != 2 || args[0].indexOf("--") !== 0 || args[1].indexOf("--") !== 0) {
        console.log("Invalid arguments for build task");
        console.log("Usage: gulp build --web --dev");
        return;
    }
    var variation = args[0].substr(2);
    var env = args[1].substr(2);

    tools.buildVariation(variation, env, false, null, cb);
};
<commit_msg>watch debounce<commit_after>import {buildHtml} from "./buildhtml";
import {buildClientJs as buildBrowserify} from "./buildjs-browserify";
import {buildClientJs as buildRollup} from "./buildjs-rollup";

import * as rebuild from "rebuild-linked";

var modules = rebuild.getModules(process.cwd());
    /* Tools to be called from gulp when building a standard app */

var gulp = require('gulp');
var fs = require("fs-extra");
var path = require("path");

var extend = require("extend");

var chokidar = require('chokidar');

var async = require("async");

var tools = module.exports;
var cwd = process.cwd();

var sass = require('node-sass');

var resolve = require('resolve');

var options = {
    globals: {
        angular: "angular",
        jquery: "$",
        d3: "d3"
    },
    serverapp: {

    },
    sourceFolder: "./src",
    libFolder: "./lib",
    cssEntryPoint: "./css/index.scss",
    moduleMappings: {},
    customBrowserifyTransforms: [],
    additionalWatchPaths: [],
    buildfolder: "./build",
    cssVariations: {
        "ie": '$browserType: "ie";'
    },
    imageFolders: ["./src/images"],
    legacyBrowserError: {
        title: "App Error",
        message: "This app is designed for use in modern browsers."
    },
    templateData: {}
};

tools.init = function(opt) {
    rebuild.ensureModulesBuilt(process.cwd());
    extend(options, opt);
};

tools.test = function() {
    console.log("Test function");
};

tools.buildVariation = function(variation, env, watch, destFolder, onBuildComplete) {
    tools.buildVariations(variation,
        [{
            key: "index",
            title: variation,
            outputScriptName: "app",
            outputHtmlName: "index",
            additionalData: options.templateData || {}
        }].concat(options.subvariations || []),
        env, watch, destFolder, onBuildComplete);
};

tools.buildVariations = function(variationFolderName, subvariations, env, watch, destFolder, onBuildComplete) {
    console.log(subvariations);
    if (options.useRollup) {
        console.log("Building with Rollup");
    } else {
        console.log("Building with Browserify");
    }

    onBuildComplete = onBuildComplete || function(err) {
        if (!err) {
            console.log("Build of " + variationFolderName + " completed successfully");
        } else {
            console.log(err);
        }
    };
    var debugMode = env != "prod"; //true;
    if (options.debug !== undefined) debugMode = options.debug;
    if (options[env] && options[env].debug !== undefined) debugMode = options[env].debug;
    console.log("Debug: " + debugMode);
    console.log("building " + variationFolderName + " for " + env);
    var buildfolder = path.resolve(cwd, options.buildfolder);
    var tempFolder = path.resolve(buildfolder, "temp-" + variationFolderName + "-" + env);
    var varFolder = path.resolve(buildfolder, env, variationFolderName);
    if (destFolder) varFolder = path.resolve(cwd, destFolder);

    fs.ensureDirSync(tempFolder);
    fs.ensureDirSync(varFolder);

    var hostSettings = {};
    extend(hostSettings, options.hostSettings);
    extend(hostSettings, options[env]);
    fs.writeFileSync(path.resolve(tempFolder, "hostsettings.js"), "module.exports=" + JSON.stringify(hostSettings), "utf-8");

    var sourceFolder = path.resolve(cwd, options.sourceFolder);
    var libFolder = path.resolve(cwd, options.libFolder);

    function buildClientJs(callback) {
        async.eachSeries(subvariations, function(subvariation, next) {
            if (!subvariation.outputScriptName) return next();
            if (subvariation.apps && subvariation.apps.indexOf(variationFolderName) < 0) return next();
            var opts = {
                options: options,
                debugMode: debugMode,
                tempFolder: tempFolder,
                src: path.resolve(sourceFolder, (subvariation.jsEntryPoint || variationFolderName) + ".js"),
                dest: path.resolve(varFolder, (subvariation.outputScriptName || "app") + ".js"),
                moduleMappings: options.moduleMappings
            };
            if (options.useRollup) {
                buildRollup(opts, next);
            }
            else {
                buildBrowserify(opts, next);
            }

            // For use with <script>$.getScript(window.atob ? "app.js" : "app-es3.js");</script>
            // no longer needed but kept for backward compatibility
            var statusReporter = require("browserify-build-status");
            fs.writeFileSync(path.resolve(varFolder, "app-es3.js"), statusReporter.getErrorScript(options.legacyBrowserError.title, options.legacyBrowserError.message));
        }, callback);

    }

    function copyHtml(callback) {
        console.log(subvariations);
        async.eachSeries(subvariations, function(subvariation, next) {
            if (!subvariation.outputHtmlName) return next();
            if (subvariation.apps && subvariation.apps.indexOf(variationFolderName) < 0) return next();
            var td = subvariation.additionalData || options.templateData || {};
            td.app = variationFolderName;
            td.env = env;
            td.variation = subvariation;
            td.options = options;
            var preloadCssPath = path.resolve(varFolder, "inline.css");
            if (fs.existsSync(preloadCssPath)) {
                td.inlineCss = fs.readFileSync(preloadCssPath, "utf-8");
            }
            else {
                td.inlineCss = "";
            }

            buildHtml(
                {
                    options: options,
                    sourceFolders: options.sourceFolders || [sourceFolder],
                    destFolder: varFolder,
                    fileMappings: subvariation.fileMappings || {
                        "index": subvariation.outputHtmlName,
                        "index-ie": subvariation.outputHtmlName + "-ie"
                    },
                    templateData: td
                },
                next);
        }, callback);
    }

    function copyLib(callback) {
        gulp.src(libFolder + '/*.*')
                .pipe(gulp.dest(varFolder + "/lib"))
                .on("end", callback);
    }

    function copyImages(callback) {
        var flatten = require('gulp-flatten');
        console.log("Copying images");
        var globs = [];
        for (let i = 0; i < options.imageFolders.length; i++) {
            var imgf = options.imageFolders[i];
            globs.push(imgf + "/**");
        }
        console.log(globs);
        try {
            var imagemin = require('gulp-imagemin');
            gulp.src(globs)
                    .pipe(flatten())
                    .pipe(imagemin({
                        progressive: true,
                        svgoPlugins: [{
                            removeViewBox: false
                        }]
                    }))
                    .pipe(gulp.dest(varFolder + "/images"))
                    .on("end", callback);
        } catch (ex) {
                // probably just imagemin not being installed - fall back to regular file copy
            console.log("Image optimization failed - copying images unmodified.");
            gulp.src(globs)
                    .pipe(flatten())
                    .pipe(gulp.dest(varFolder + "/images"))
                    .on("end", callback);

        }

    }

        //        function copyImages() {
        //            gulp.src(__dirname + '/apphtml/images/**/*')
        //                .pipe(gulp.dest(options.buildfolder + "/" + env + "/" + variation + "/images"))
        //                .on("end", function() {
        //                    gulp.src(process.cwd() + "/images/**/*")
        //                        .pipe(gulp.dest(options.buildfolder + "/" + env + "/" + variation + "/images"));
        //                });
        //        }

    function buildCssFile(inputFile, outputFile, fileBuilt) {
        sass.render({
            file: inputFile,
            outFile: varFolder + "/" + outputFile,
            sourceMap: true,
            outputStyle: debugMode ? "nested" : "compressed",
            importer: [function(url, prev) {

                    // first check if the file exists as specified
                var f = path.resolve(path.dirname(prev), url);
                if (fs.existsSync(f)) return { file: f };

                    // or with .scss added
                var f2 = path.dirname(f) + "/" + path.basename(f, ".scss") + ".scss";
                if (fs.existsSync(f2)) return { file: f2 };

                    // or with an underscore
                var f3 = path.dirname(f) + "/_" + path.basename(f, ".scss") + ".scss";
                if (fs.existsSync(f3)) return { file: f3 };

                    // try using node resolve
                var f4 = url;
                    // if it includes node_modules, remove it
                if (f4.indexOf("node_modules/") >= 0) {
                    f4 = f4.substr(f4.lastIndexOf("node_modules/") + 13);
                }

                    // resolve with require("resolve")
                try {
                    f4 = resolve.sync(f4, {
                        basedir: path.dirname(prev),
                        extensions: [".scss"]
                    });
                    return {file: f4 };
                }
                    catch (e) {
                        console.log(e);
                        // couldn't resolve it this way - ignore error and fall back to the default
                    }
                return null;
            }]
                // includePaths: ["."]
        }, function(err, result) {
            if (!err) {
                fs.writeFileSync(varFolder + "/" + outputFile, result.css);
                fs.writeFileSync(varFolder + "/" + outputFile + ".map", result.map);
                console.log("Completed sass build of " + inputFile);
            }
            if (fileBuilt) fileBuilt(err, result);
        });
    }

    function buildPreloadCss(onCssBuilt) {
        var cssEntryPoint = path.resolve(cwd, options.cssEntryPoint);
        var preloadCssPath = path.resolve(cssEntryPoint, "../inline.scss");
        console.log(preloadCssPath);
        if (!fs.existsSync(preloadCssPath)) return onCssBuilt && onCssBuilt();

        buildCssFile(preloadCssPath, "inline.css", onCssBuilt);

    }

    function buildCss(onCssBuilt) {
        console.log("Building CSS");
        var cssEntryPoint = path.resolve(cwd, options.cssEntryPoint);

        buildCssFile(cssEntryPoint, "app.css", function(err) {
            if (err) {
                return onCssBuilt && onCssBuilt(err);
            }

            var cssVariations = [];
            for (let k2 in options.cssVariations) {
                cssVariations.push({
                    key: k2,
                    settings: options.cssVariations[k2]
                });
            }

            async.eachSeries(cssVariations, function(v, next) {
                var iesrc = v.settings + '\n@import "' + (path.relative(tempFolder, cssEntryPoint).replace(/\\/ig, "/")) + '";';
                var ieCssFile = path.resolve(tempFolder, "index-" + v.key + ".scss");
                fs.writeFileSync(ieCssFile, iesrc);
                buildCssFile(ieCssFile, "app-" + v.key + ".css", next);
            }, function(err2) {
                if (err2) {
                    return onCssBuilt && onCssBuilt(err2);
                }
                buildPreloadCss(onCssBuilt);
            });

                // preloader

        });

    }

    function afterBuild(callback) {
        if (options.afterBrowserify) options.afterBrowserify(varFolder, env, variationFolderName);
        console.log("Build completed successfully in " + varFolder);
        callback();
    }

    var fullBuild = [buildClientJs, buildCss, copyHtml, copyImages, copyLib, afterBuild];

    function setWatch(callback) {
        callback();
        if (!watch) return;

        var cssTimer,
            jsTimer,
            imageTimer;

        function cssChanged() {
            clearTimeout(cssTimer);
            cssTimer = setTimeout(function() {
                console.log("CSS needs rebuild");
                async.series([buildCss], function(err) {
                    if (err) {
                        console.log(err);
                    }
                });
            }, 3000);
        }

        function jsChanged() {
            clearTimeout(jsTimer);
            cssTimer = setTimeout(function() {
                console.log("Browserify package needs rebuild");
                async.series([buildClientJs, afterBuild], function() {});
            }, 3000);

        }

        function imageChanged() {
            clearTimeout(imageTimer);
            cssTimer = setTimeout(function() {
                console.log("Updating images");
                async.series([copyImages], function() {});
            }, 3000);
        }

        var paths = [sourceFolder].concat(options.additionalWatchPaths);

        // todo: assuming existence of src folder is not ideal. Unfortunately watching the whole module
        // folder causes severe performance issues.
        for (let i = 0; i < modules.length; i++) {
            var sf = path.resolve(modules[i].path, "src");
            if (fs.existsSync(sf)) paths.push(sf);
            sf = path.resolve(modules[i].path, "clientapp");
            if (fs.existsSync(sf)) paths.push(sf);
            sf = path.resolve(modules[i].path, "api");
            if (fs.existsSync(sf)) paths.push(sf);
        }
        //paths.push.apply(paths, modules.map(m => m.path));

        var cssFolder = path.dirname(path.resolve(cwd, options.cssEntryPoint));
        if (cssFolder.indexOf(sourceFolder) !== 0) paths.push(cssFolder);

        // watch image folders
        for (let i = 0; i < options.imageFolders.length; i++) {
            var imgf = options.imageFolders[i];
            if (imgf.indexOf(sourceFolder) !== 0) paths.push(imgf);
        }
        // watch tests
        if (options.browserTests) {
            paths.push(path.dirname(path.resolve(options.browserTests)));
        }
        console.log("Watching: ");
        console.log(paths);

        var watcher = chokidar.watch(paths, {
            ignored: [/[\/\\]\./, "node_modules", "build", "dist"],
            persistent: true,
            ignoreInitial: true
        });

        watcher.on("all", function(type, file) {
            console.log(type + " event for " + file);
            var ext = path.extname(file);
            if (ext == ".scss") {
                cssChanged();
            } else if (ext == ".js" || ext == ".html") {
                // if the changed file is .js or .html, need to run browserify
                jsChanged();
            } else if (ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif") {
                // src/images just needs to be copied if anything changes, and it can't contain anything used by browserify
                imageChanged();
            }
        });
    }

    async.series([...fullBuild, setWatch], onBuildComplete);

};

tools.buildTask = function(cb) {
    var args = process.argv.slice(3);
    if (args.length != 2 || args[0].indexOf("--") !== 0 || args[1].indexOf("--") !== 0) {
        console.log("Invalid arguments for build task");
        console.log("Usage: gulp build --web --dev");
        return;
    }
    var variation = args[0].substr(2);
    var env = args[1].substr(2);

    tools.buildVariation(variation, env, false, null, cb);
};
<|endoftext|>