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

const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const BUILD_DIR = path.resolve(__dirname, 'out');
const APP_DIR = path.resolve(__dirname, 'src');

const config = {
  entry: {
    main: `${APP_DIR}/index.jsx`,
    vendor: ['react', 'react-dom', 'react-router', 'react-share'],
  },
  output: {
    path: BUILD_DIR,
    publicPath: '/',
    filename: '[chunkhash].[name].js',
  },
  module: {
    rules: [
      {
        test: /\.js?/,
        exclude: /node_modules/,
        use: 'babel-loader',
      },
      {
        test: /\.jsx?/,
        include: APP_DIR,
        use: 'babel-loader',
      },
      {
        test: /\.json$/,
        use: 'json-loader',
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: ExtractTextPlugin.extract({
          use: 'css-loader?sourceMap',
        }),
      },
    ],
  },
  devtool: 'source-map',
  performance: { hints: false },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production'),
      },
    }),
    new webpack.optimize.CommonsChunkPlugin({
      names: ['vendor', 'manifest'],
      minChunks: Infinity,
    }),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      chunks: ['main', 'vendor', 'manifest'],
      template: 'index.ejs',
    }),
    new HtmlWebpackPlugin({
      filename: '200.html',
      chunks: ['main', 'vendor', 'manifest'],
      template: 'index.ejs',
    }),
    new CopyWebpackPlugin([
      { from: 'sitemap.xml' },
      { from: '.htaccess' },
      { from: 'fines.html' },
      { from: 'data.csv' },
      { from: 'images/facebook.png', to: 'images/facebook.png' },
      { from: 'images/favicons' },
    ]),
    new ExtractTextPlugin({
      filename: 'bundle.css',
      disable: false,
      allChunks: true,
    }),
  ],
};

module.exports = config;
<commit_msg>Revert "Don't use babel on d3-bumps-chart"<commit_after>const webpack = require('webpack');
const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const BUILD_DIR = path.resolve(__dirname, 'out');
const APP_DIR = path.resolve(__dirname, 'src');

const config = {
  entry: {
    main: `${APP_DIR}/index.jsx`,
    vendor: ['react', 'react-dom', 'react-router', 'react-share'],
  },
  output: {
    path: BUILD_DIR,
    publicPath: '/',
    filename: '[chunkhash].[name].js',
  },
  module: {
    rules: [
      {
        test: /\.js?/,
        exclude: /node_modules\/(?!d3-bumps-chart)/,
        use: 'babel-loader',
      },
      {
        test: /\.jsx?/,
        include: APP_DIR,
        use: 'babel-loader',
      },
      {
        test: /\.json$/,
        use: 'json-loader',
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: ExtractTextPlugin.extract({
          use: 'css-loader?sourceMap',
        }),
      },
    ],
  },
  devtool: 'source-map',
  performance: { hints: false },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production'),
      },
    }),
    new webpack.optimize.CommonsChunkPlugin({
      names: ['vendor', 'manifest'],
      minChunks: Infinity,
    }),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      chunks: ['main', 'vendor', 'manifest'],
      template: 'index.ejs',
    }),
    new HtmlWebpackPlugin({
      filename: '200.html',
      chunks: ['main', 'vendor', 'manifest'],
      template: 'index.ejs',
    }),
    new CopyWebpackPlugin([
      { from: 'sitemap.xml' },
      { from: '.htaccess' },
      { from: 'fines.html' },
      { from: 'data.csv' },
      { from: 'images/facebook.png', to: 'images/facebook.png' },
      { from: 'images/favicons' },
    ]),
    new ExtractTextPlugin({
      filename: 'bundle.css',
      disable: false,
      allChunks: true,
    }),
  ],
};

module.exports = config;
<|endoftext|>


<commit_before>const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

// 使用 HtmlWebpackPlugin，将 bundle 好的 <script> 插入到 body。${__dirname} 为 ES6 语法对应的 __dirname
// const HtmlWebpackPlugin = require('html-webpack-plugin');
//
// const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
//   template: `${__dirname}/index.html`,
//   filename: 'indexbundle.html',
//   inject: 'body',
// });

module.exports = {
  devtool: 'eval-source-map',
  resolve: {
      extensions: [
          '',
          '.js',
          '.json',
          '.css',
      ],
  },
  entry: [
    './source/js/index.js',
  ],
  output: {
    path: `${__dirname}/bundle/`,
    filename: 'bundle.js',
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
          test: /\.css$/,
          loader: ExtractTextPlugin.extract(
              'style-loader',
              'css-loader?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]!postcss-loader?sourceMap'
          ),
      },
    ],
  },
  postcss: (webpack) => {
      return [
          require('postcss-import')({ addDependencyTo: webpack }),
          require('postcss-url')(),
          require('postcss-cssnext')({
              features: {
                  autoprefixer: { browsers: ['> 5%'] }
              }
          })
      ]
  },
  devServer: {
    inline: true,
    port: 8008,
  },
  plugins: [
    //   new webpack.optimize.CommonsChunkPlugin('common.js'),
      new ExtractTextPlugin('index.css')
  ],
};
<commit_msg>update<commit_after>const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

// 使用 HtmlWebpackPlugin，将 bundle 好的 <script> 插入到 body。${__dirname} 为 ES6 语法对应的 __dirname
// const HtmlWebpackPlugin = require('html-webpack-plugin');
//
// const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
//   template: `${__dirname}/index.html`,
//   filename: 'indexbundle.html',
//   inject: 'body',
// });

module.exports = {
  devtool: 'eval-source-map',
  resolve: {
      extensions: [
          '',
          '.js',
          '.json',
          '.css',
      ],
  },
  entry: [
    './source/js/index.js',
  ],
  output: {
    path: `${__dirname}/bundle/`,
    filename: 'bundle.js',
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
          test: /\.css$/,
          loader: ExtractTextPlugin.extract(
              'style-loader',
              'css-loader?sourceMap&modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]!postcss-loader'
          ),
      },
    ],
  },
  postcss: (webpack) => {
      return [
          require('postcss-import')({ addDependencyTo: webpack }),
          require('postcss-url')(),
          require('postcss-cssnext')({
              features: {
                  autoprefixer: { browsers: ['> 5%'] }
              }
          })
      ]
  },
  devServer: {
    inline: true,
    port: 8008,
  },
  plugins: [
    //   new webpack.optimize.CommonsChunkPlugin('common.js'),
      new ExtractTextPlugin('index.css')
  ],
};
<|endoftext|>


<commit_before>var path = require('path');
var process = require('process');
var webpack = require('webpack');

module.exports = {
  context: path.join(process.env.PWD, 'frontend'),
  entry: [
    "webpack-dev-server/client?http://localhost:8080",
    "webpack/hot/dev-server",
    "./index.js"
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'webpack.bundle.js',
    publicPath: "/assets/"
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV)
      }
    }),
    new webpack.HotModuleReplacementPlugin()
  ],
  module: {
    loaders: [
      { test: /\.js$/, loader: 'babel' },
      { test: /\.png$/, loader: 'url-loader?limit=20000' }
    ]
  }
};
<commit_msg>exclude node_modules, because surpress redux-devtools-log-monitor errors<commit_after>var path = require('path');
var process = require('process');
var webpack = require('webpack');

module.exports = {
  context: path.join(process.env.PWD, 'frontend'),
  entry: [
    "webpack-dev-server/client?http://localhost:8080",
    "webpack/hot/dev-server",
    "./index.js"
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'webpack.bundle.js',
    publicPath: "/assets/"
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV)
      }
    }),
    new webpack.HotModuleReplacementPlugin()
  ],
  module: {
    loaders: [
      { test: /\.js$/, loader: 'babel', exclude: /node_modules/ },
      { test: /\.png$/, loader: 'url-loader?limit=20000' }
    ]
  }
};
<|endoftext|>


<commit_before>'use strict';
angular.module('myApp.login', ['ngRoute', 'ng.deviceDetector'])
    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/login', {
            templateUrl: 'views/login/login.html',
            controller: 'LoginCtrl'
        });
    }])
    .controller('LoginCtrl', function ($scope, $http, $timeout, $window, $mdToast, deviceDetector) {
        var vm = this;
        vm.data = deviceDetector;
        var ip = $.getJSON('//freegeoip.net/json/?callback=?', function(data) {
            ip = JSON.stringify(data);
            console.log(ip);
        });

        console.log("userAgent: " + vm.data.raw.userAgent);
        $scope.loginData = {};
        $scope.doLogin = function () {
            console.log('Doing login', $scope.loginData);
            $scope.loginData.userAgent=vm.data.raw.userAgent;//aquí li afegin el userAgent al post del loginData
            $scope.loginData.os=vm.data.raw.os;
            $scope.loginData.browser=vm.data.raw.browser;
            $scope.loginData.device=vm.data.raw.device;
            $scope.loginData.os_version=vm.data.raw.os_version;
            $scope.loginData.ip = ip;
            $scope.loginData.browser_version=vm.data.raw.browser_version;
            $http({
                url: urlapi + $scope.loginData.role+ 's/login',
                method: "POST",
                data: $scope.loginData
            })
                .then(function (response) {
                        // success
                        console.log("response: ");
                        console.log(response.data);
                        if (response.data.success == true) {
                            localStorage.setItem("fs_web_token", response.data.token);
                            localStorage.setItem("fs_web_userdata", JSON.stringify(response.data.user));
                            window.location.reload();
                            /*$timeout(function () {
                             $window.location="#!/dashboard"; //peta pq fa la petició un cop al dashboard sense afegir el token, pq no ha afegit els httpProviders
                             }, 1000);*/
                        } else {
                            console.log("login failed");
                            $mdToast.show(
                                $mdToast.simple()
                                    .textContent('Account not found')
                                    .position("bottom right")
                                    .hideDelay(3000)
                            );
                            //$ionicLoading.show({ template: 'Login failed, user or password error.', noBackdrop: true, duration: 2000 });
                        }
                    },
                    function (response) { // optional
                        // failed
                        console.log(response);
                    });
        };/*
         $scope.logout = function () {
         localStorage.removeItem("fs_web_userdata");
         $timeout(function () {
         $window.location.reload(true);
         }, 1000);
         };*/
    });<commit_msg>No raw<commit_after>'use strict';
angular.module('myApp.login', ['ngRoute', 'ng.deviceDetector'])
    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/login', {
            templateUrl: 'views/login/login.html',
            controller: 'LoginCtrl'
        });
    }])
    .controller('LoginCtrl', function ($scope, $http, $timeout, $window, $mdToast, deviceDetector) {
        var vm = this;
        vm.data = deviceDetector;
        var ip = $.getJSON('//freegeoip.net/json/?callback=?', function(data) {
            ip = JSON.stringify(data);
            console.log(ip);
        });

        console.log("userAgent: " + vm.data.raw.userAgent);
        $scope.loginData = {};
        $scope.doLogin = function () {
            console.log('Doing login', $scope.loginData);
            $scope.loginData.userAgent=vm.data.raw.userAgent;//aquí li afegin el userAgent al post del loginData
            $scope.loginData.os=vm.data.os;
            $scope.loginData.browser=vm.data.browser;
            $scope.loginData.device=vm.data.device;
            $scope.loginData.os_version=vm.data.os_version;
            $scope.loginData.ip = ip;
            $scope.loginData.browser_version=vm.data.browser_version;
            $http({
                url: urlapi + $scope.loginData.role+ 's/login',
                method: "POST",
                data: $scope.loginData
            })
                .then(function (response) {
                        // success
                        console.log("response: ");
                        console.log(response.data);
                        if (response.data.success == true) {
                            localStorage.setItem("fs_web_token", response.data.token);
                            localStorage.setItem("fs_web_userdata", JSON.stringify(response.data.user));
                            window.location.reload();
                            /*$timeout(function () {
                             $window.location="#!/dashboard"; //peta pq fa la petició un cop al dashboard sense afegir el token, pq no ha afegit els httpProviders
                             }, 1000);*/
                        } else {
                            console.log("login failed");
                            $mdToast.show(
                                $mdToast.simple()
                                    .textContent('Account not found')
                                    .position("bottom right")
                                    .hideDelay(3000)
                            );
                            //$ionicLoading.show({ template: 'Login failed, user or password error.', noBackdrop: true, duration: 2000 });
                        }
                    },
                    function (response) { // optional
                        // failed
                        console.log(response);
                    });
        };/*
         $scope.logout = function () {
         localStorage.removeItem("fs_web_userdata");
         $timeout(function () {
         $window.location.reload(true);
         }, 1000);
         };*/
    });<|endoftext|>


<commit_before>/// <reference path='./typings/index.d.ts'/>

'use strict';

const assert = require('assert');

const isRelease = process.env.NODE_ENV === 'production';

function getParamFromEnv(env, name) {
    const value = env[name];

    assert.ok(!!value, `not found process.env.${name}`);
    console.log(`${name}: ${value}`);

    return value;
}

const KAREN_ENTRY_POINT = getParamFromEnv(process.env, 'KAREN_ENTRY_POINT');
const KAREN_CLIENT_DIST_DIR = getParamFromEnv(process.env, 'KAREN_CLIENT_DIST_DIR');

const babelPresets = [
];

let babelPlugins = [
    // es2016 level
    'babel-plugin-transform-exponentiation-operator',
    // es2017 level
    'babel-plugin-syntax-trailing-function-commas',
    'babel-plugin-transform-async-to-generator',

    // for React
    'syntax-jsx',
    'transform-react-jsx',

    // some utilitis
    'transform-inline-environment-variables',
    'transform-node-env-inline',
];

if (isRelease) {
    babelPlugins = babelPlugins.concat([
        'transform-react-constant-elements',
        'transform-react-inline-elements',
    ]);
}
else {
    babelPlugins = babelPlugins.concat([
        'transform-react-jsx-source',
    ]);
}

module.exports = {
    bail: true,

    devtool: isRelease ? '' : 'source-map',

    entry: {
        karen: KAREN_ENTRY_POINT,
    },

    output: {
        path: KAREN_CLIENT_DIST_DIR,
        filename: '[name].js',
    },

    externals: [
        {
            'moment': true,
        }
    ],

    resolve: {
        modules: ['node_modules'],
        extensions: ['.js', '.jsx'],
        alias: {},
    },

    module: {
        rules: [
            {
                test: /\.jsx?$/, // loader is applied to files which matches this extensions.
                exclude: /node_modules/, // don't transform under this path.
                loader: 'babel-loader',
                query: {
                    presets: babelPresets,
                    plugins: babelPlugins,
                }
            }
        ]
    },
};
<commit_msg>feat(babel): specify generatorOpts for client<commit_after>/// <reference path='./typings/index.d.ts'/>

'use strict';

const assert = require('assert');

const isRelease = process.env.NODE_ENV === 'production';

function getParamFromEnv(env, name) {
    const value = env[name];

    assert.ok(!!value, `not found process.env.${name}`);
    console.log(`${name}: ${value}`);

    return value;
}

const KAREN_ENTRY_POINT = getParamFromEnv(process.env, 'KAREN_ENTRY_POINT');
const KAREN_CLIENT_DIST_DIR = getParamFromEnv(process.env, 'KAREN_CLIENT_DIST_DIR');

const babelPresets = [
];

let babelPlugins = [
    // es2016 level
    'babel-plugin-transform-exponentiation-operator',
    // es2017 level
    'babel-plugin-syntax-trailing-function-commas',
    'babel-plugin-transform-async-to-generator',

    // for React
    'syntax-jsx',
    'transform-react-jsx',

    // some utilitis
    'transform-inline-environment-variables',
    'transform-node-env-inline',
];

if (isRelease) {
    babelPlugins = babelPlugins.concat([
        'transform-react-constant-elements',
        'transform-react-inline-elements',
    ]);
}
else {
    babelPlugins = babelPlugins.concat([
        'transform-react-jsx-source',
    ]);
}

const parserOpts = {};
const generatorOpts = {
    // retain the parentheses around an IIFE
    // see: https://github.com/nolanlawson/optimize-js
    retainFunctionParens: false,
};

module.exports = {
    bail: true,

    devtool: isRelease ? '' : 'source-map',

    entry: {
        karen: KAREN_ENTRY_POINT,
    },

    output: {
        path: KAREN_CLIENT_DIST_DIR,
        filename: '[name].js',
    },

    externals: [
        {
            'moment': true,
        }
    ],

    resolve: {
        modules: ['node_modules'],
        extensions: ['.js', '.jsx'],
        alias: {},
    },

    module: {
        rules: [
            {
                test: /\.jsx?$/, // loader is applied to files which matches this extensions.
                exclude: /node_modules/, // don't transform under this path.
                loader: 'babel-loader',
                query: {
                    presets: babelPresets,
                    plugins: babelPlugins,
                    parserOpts,
                    generatorOpts,
                }
            }
        ]
    },
};
<|endoftext|>


<commit_before>/*global angular */

/**
 * Services that persists and retrieves todos from localStorage or a backend API
 * if available.
 *
 * They both follow the same API, returning promises for all changes to the
 * model.
 */
angular.module('todomvc')
	.factory('todoStorage', function ($http, $injector) {
		'use strict';

		// Detect if an API backend is present. If so, return the API module, else
		// hand off the localStorage adapter
		return $http.get('/api')
			.then(function () {
				return $injector.get('api');
			}, function () {
				return $injector.get('localStorage');
			});
	})

	.factory('api', function ($http) {
		'use strict';

		var store = {
			todos: [],

			clearCompleted: function () {
				var originalTodos = store.todos.slice(0);

				var completeTodos = [], incompleteTodos = [];
				store.todos.forEach(function (todo) {
					if (todo.completed) {
						completeTodos.push(todo);
					} else {
						incompleteTodos.push(todo);
					}
				});

				angular.copy(incompleteTodos, store.todos);

				return $http.delete('/api/todos')
					.then(function success() {
						return store.todos;
					}, function error() {
						angular.copy(originalTodos, store.todos);
						return originalTodos;
					});
			},

			delete: function (todo) {
				var originalTodos = store.todos.slice(0);

				store.todos.splice(store.todos.indexOf(todo), 1);

				return $http.delete('/api/todos/' + todo.id)
					.then(function success() {
						return store.todos;
					}, function error() {
						angular.copy(originalTodos, store.todos);
						return originalTodos;
					});
			},

			get: function () {
				return $http.get('/api/todos')
					.then(function (resp) {
						angular.copy(resp.data, store.todos);
						return store.todos;
					});
			},

			insert: function (todo) {
				var originalTodos = store.todos.slice(0);

				return $http.post('/api/todos', todo)
					.then(function success(resp) {
						todo.id = resp.data.id;
						store.todos.push(todo);
						return store.todos;
					}, function error() {
						angular.copy(originalTodos, store.todos);
						return store.todos;
					});
			},

			put: function (todo) {
				var originalTodos = store.todos.slice(0);

				return $http.put('/api/todos/' + todo.id, todo)
					.then(function success() {
						return store.todos;
					}, function error() {
						angular.copy(originalTodos, store.todos);
						return originalTodos;
					});
			}
		};

		return store;
	})

	.factory('localStorage', function ($q) {
		'use strict';

		var STORAGE_ID = 'todos-angularjs';

		var store = {
			todos: [],

			_getFromLocalStorage: function () {
				return JSON.parse(localStorage.getItem(STORAGE_ID) || '[]');
			},

			_saveToLocalStorage: function (todos) {
				localStorage.setItem(STORAGE_ID, JSON.stringify(todos));
			},

			clearCompleted: function () {
				var deferred = $q.defer();

				var completeTodos = [], incompleteTodos = [];
				store.todos.forEach(function (todo) {
					if (todo.completed) {
						completeTodos.push(todo);
					} else {
						incompleteTodos.push(todo);
					}
				});

				angular.copy(incompleteTodos, store.todos);

				store._saveToLocalStorage(store.todos);
				deferred.resolve(store.todos);

				return deferred.promise;
			},

			delete: function (todo) {
				var deferred = $q.defer();

				store.todos.splice(store.todos.indexOf(todo), 1);

				store._saveToLocalStorage(store.todos);
				deferred.resolve(store.todos);

				return deferred.promise;
			},

			get: function () {
				var deferred = $q.defer();

				angular.copy(store._getFromLocalStorage(), store.todos);
				deferred.resolve(store.todos);

				return deferred.promise;
			},

			insert: function (todo) {
				var deferred = $q.defer();

				store.todos.push(todo);

				store._saveToLocalStorage(store.todos);
				deferred.resolve(store.todos);

				return deferred.promise;
			},

			put: function (todo, index) {
				var deferred = $q.defer();

				store.todos[index] = todo;

				store._saveToLocalStorage(store.todos);
				deferred.resolve(store.todos);

				return deferred.promise;
			}
		};

		return store;
	});
<commit_msg>Fix AngularJS JSCS issues<commit_after>/*global angular */

/**
 * Services that persists and retrieves todos from localStorage or a backend API
 * if available.
 *
 * They both follow the same API, returning promises for all changes to the
 * model.
 */
angular.module('todomvc')
	.factory('todoStorage', function ($http, $injector) {
		'use strict';

		// Detect if an API backend is present. If so, return the API module, else
		// hand off the localStorage adapter
		return $http.get('/api')
			.then(function () {
				return $injector.get('api');
			}, function () {
				return $injector.get('localStorage');
			});
	})

	.factory('api', function ($http) {
		'use strict';

		var store = {
			todos: [],

			clearCompleted: function () {
				var originalTodos = store.todos.slice(0);

				var completeTodos = [];
				var incompleteTodos = [];
				store.todos.forEach(function (todo) {
					if (todo.completed) {
						completeTodos.push(todo);
					} else {
						incompleteTodos.push(todo);
					}
				});

				angular.copy(incompleteTodos, store.todos);

				return $http.delete('/api/todos')
					.then(function success() {
						return store.todos;
					}, function error() {
						angular.copy(originalTodos, store.todos);
						return originalTodos;
					});
			},

			delete: function (todo) {
				var originalTodos = store.todos.slice(0);

				store.todos.splice(store.todos.indexOf(todo), 1);

				return $http.delete('/api/todos/' + todo.id)
					.then(function success() {
						return store.todos;
					}, function error() {
						angular.copy(originalTodos, store.todos);
						return originalTodos;
					});
			},

			get: function () {
				return $http.get('/api/todos')
					.then(function (resp) {
						angular.copy(resp.data, store.todos);
						return store.todos;
					});
			},

			insert: function (todo) {
				var originalTodos = store.todos.slice(0);

				return $http.post('/api/todos', todo)
					.then(function success(resp) {
						todo.id = resp.data.id;
						store.todos.push(todo);
						return store.todos;
					}, function error() {
						angular.copy(originalTodos, store.todos);
						return store.todos;
					});
			},

			put: function (todo) {
				var originalTodos = store.todos.slice(0);

				return $http.put('/api/todos/' + todo.id, todo)
					.then(function success() {
						return store.todos;
					}, function error() {
						angular.copy(originalTodos, store.todos);
						return originalTodos;
					});
			}
		};

		return store;
	})

	.factory('localStorage', function ($q) {
		'use strict';

		var STORAGE_ID = 'todos-angularjs';

		var store = {
			todos: [],

			_getFromLocalStorage: function () {
				return JSON.parse(localStorage.getItem(STORAGE_ID) || '[]');
			},

			_saveToLocalStorage: function (todos) {
				localStorage.setItem(STORAGE_ID, JSON.stringify(todos));
			},

			clearCompleted: function () {
				var deferred = $q.defer();

				var completeTodos = [];
				var incompleteTodos = [];
				store.todos.forEach(function (todo) {
					if (todo.completed) {
						completeTodos.push(todo);
					} else {
						incompleteTodos.push(todo);
					}
				});

				angular.copy(incompleteTodos, store.todos);

				store._saveToLocalStorage(store.todos);
				deferred.resolve(store.todos);

				return deferred.promise;
			},

			delete: function (todo) {
				var deferred = $q.defer();

				store.todos.splice(store.todos.indexOf(todo), 1);

				store._saveToLocalStorage(store.todos);
				deferred.resolve(store.todos);

				return deferred.promise;
			},

			get: function () {
				var deferred = $q.defer();

				angular.copy(store._getFromLocalStorage(), store.todos);
				deferred.resolve(store.todos);

				return deferred.promise;
			},

			insert: function (todo) {
				var deferred = $q.defer();

				store.todos.push(todo);

				store._saveToLocalStorage(store.todos);
				deferred.resolve(store.todos);

				return deferred.promise;
			},

			put: function (todo, index) {
				var deferred = $q.defer();

				store.todos[index] = todo;

				store._saveToLocalStorage(store.todos);
				deferred.resolve(store.todos);

				return deferred.promise;
			}
		};

		return store;
	});
<|endoftext|>


<commit_before>'use strict';

const
  nurl = require('url'),
  path = require('path'),
  request = require('request');

/* Globals */

const MESSAGE_TYPES = [
  'text', 'audio', 'voice', 'document', 'photo',
  'sticker', 'video', 'contact', 'location', 'query'
];

const ANSWER_METHODS = {
  addArticle: 'article', addPhoto: 'photo', addVideo: 'video',
  addGif: 'gif', addVideoGif: 'mpeg4_gif'
};

const REGEX = {
  cmd: /^\/([а-я\w\d]+)/,
  url: /^https?\:\/\/|www\./
};

/* Telegram Bot */

class TeleBot {
  constructor(cfg) {
    this.cfg = cfg;
    this.token = cfg.token;
    this.id = this.token.split(':')[0];
    this.api = 'https://api.telegram.org/bot' + this.token;
    this.fileLink = 'https://api.telegram.org/file/bot' + this.token + '/';
    this.limit = Number(cfg.limit) || 100;
    this.timeout = cfg.timeout >= 0 ? cfg.timeout : 0;
    this.retryTimeout = cfg.retryTimeout >= 0 ? cfg.retryTimeout : 5000;
    this.retry = false;
    this.pool = true;
    this.loopFn = null;
    this.looping = false;
    this.sleep = Number(cfg.sleep) || 1000;
    this.updateId = 0;
    this.eventList = {};
    this.modList = {};
  }
  /* Modules */
  use(fn) {
    return fn.call(this, this);
  }
  /* Keyboard */
  keyboard(keyboard, opt) {
    opt = opt || {};
    const markup = { keyboard };
    if (opt.resize === true) markup['resize_keyboard'] = true;
    if (opt.once === true) markup['one_time_keyboard'] = true;
    if (opt.selective) markup['selective'] = opt.selective;
    return JSON.stringify(markup);
  }
  /* Answer */
  answerList(id) {
    return answerList(id);
  }
  /* Actions */
  getMe() {
    this.event('getMe', arguments);
    return this.request('/getMe');
  }
  answerQuery(answers, opt) {
    this.event('answerQuery', arguments);
    return this.request('/answerInlineQuery', {
      inline_query_id: answers.id, results: answers.results(),
    });
  }
  getFile(fileId) {
    this.event('getFile', arguments);
    return this.request('/getFile', { file_id: fileId }).then(file => {
      const result = file.result;
      result.fileLink = this.fileLink + result.file_path;
      return result;
    });
  }
  forwardMessage(id, fromId, messageId) {
    this.event('forwardMessage', arguments);
    return this.request('/forwardMessage', {
      chat_id: id, from_chat_id: fromId, message_id: messageId
    });
  }
  getUserPhoto(id, opt) {
    this.event('getUserPhoto', arguments);
    opt = opt || {};
    const form = { user_id: id };
    if (opt.offset) form['offset'] = opt.offset;
    if (opt.limit) form['limit'] = opt.limit;
    return this.request('/getUserProfilePhotos', form);
  }
  sendAction(id, action) {
    this.event('sendAction', arguments);
    return this.request('/sendChatAction', { chat_id: id, action });
  }
  sendMessage(id, text, opt) {
    this.event('sendMessage', arguments);
    opt = opt || {};
    const form = props.call(this, { chat_id: id, text }, opt);
    if (opt.preview === false) form['disable_web_page_preview'] = true;
    return this.request('/sendMessage', form);
  }
  sendLocation(id, position, opt) {
    this.event('sendLocation', arguments);
    opt = opt || {};
    const form = props.call(this, {
      chat_id: id, latitude: position[0], longitude: position[1]
    }, opt);
    return this.request('/sendLocation', form);
  }
  sendPhoto(id, photo, opt) {
    return sendFile.call(this, 'photo', id,  photo, opt);
  }
  sendAudio(id, audio, opt) {
    return sendFile.call(this, 'audio', id, audio, opt);
  }
  sendVoice(id, voice, opt) {
    return sendFile.call(this, 'voice', id, voice, opt);
  }
  sendDocument(id, doc, opt) {
    return sendFile.call(this, 'document', id, doc, opt);
  }
  sendSticker(id, sticker, opt) {
    return sendFile.call(this, 'sticker', id, sticker, opt);
  }
  sendVideo(id, video, opt) {
    return sendFile.call(this, 'video', id, video, opt);
  }
  setWebhook(url, certificate) {
    this.event('setWebhook', arguments);
    return this.request('/setWebhook', { url, certificate });
  }
  /* Send request to server */
  request(url, form, data) {
    const options = { url: this.api + url, json: true };
    if (form) { options.form = form; } else { options.formData = data; };
    return new Promise((resolve, reject) => {
      request.post(options, (error, response, body) => {
        if (error || !body.ok || response.statusCode == 404) {
          return reject(error || body || 404);
        }
        return resolve(body);
      });
    });
  }
  /* Connection */
  connect() {
    this.looping = true;
    console.log('[info] bot started');
    this.event('connect');
    this.loopFn = setInterval(x => {
      if (!this.looping) clearInterval(this.loopFn);
      if (!this.pool) return;
      this.pool = false;
      this.getUpdate().then(x => {
        if (this.retry) {
          const now = Date.now();
          const diff = (now - this.retry) / 1000;
          console.log('[info.update] reconnected after ' + diff + ' seconds');
          this.event('reconnected', {
            startTime: this.retry, endTime: now, diffTime: diff
          });
          this.retry = false;
        }
        return this.event('tick');
      }).then(x => {
        this.pool = true;
      }).catch(error => {
        if (this.retry === false) this.retry = Date.now();
        console.error('[error.update]', error.stack || error);
        this.event('error', { error });
        return Promise.reject();
      }).catch(x => {
        const seconds = this.retryTimeout / 1000;
        console.log('[info.update] reconnecting in ' + seconds + ' seconds...');
        this.event('reconnecting');
        setTimeout(x => (this.pool = true), this.retryTimeout);
      });
    }, this.sleep);
  }
  disconnect(message) {
    this.looping = false;
    console.log('[info] bot disconnected' + (message ? ': ' + message : ''));
    this.event('disconnect', message);
  }
  /* Fetch updates */
  getUpdate() {
    // Request an update
    return this.request('/getUpdates', {
      offset: this.updateId, limit: this.limit, timeout: this.timeout
    }).then(body => {
      // Check for update
      var data = body.result;
      if (!data.length) return Promise.resolve();
      return new Promise((resolve, reject) => {
        this.event('update', data).then(output => {
          var me = extend({}, output);
          // Run update processors
          var temp = this.modRun('update', { data, me });
          data = temp.data, me = temp.me;
          // Check every message in update
          for (let update of data) {
            // Set update ID
            let nextId = ++update['update_id'];
            if (this.updateId < nextId) this.updateId = nextId;
            // Run message processors
            let temp = this.modRun('message', {
              me, msg:
                update['message'] || update['inline_query'] ||
                update['chosen_inline_result'] || {}
            });
            var msg = temp.msg, me = temp.me;
            for (let type of MESSAGE_TYPES) {
              // Check for Telegram API documented types
              if (!(type in msg)) continue;
              me.type = type;
              // Send type event
              this.event(['*', type], msg, me);
              // Check for command
              if (type == 'text') {
                const match = REGEX.cmd.exec(msg.text);
                if (!match) continue;
                // Command found
                me.cmd = msg.text.split(' ');
                this.event(['/*', '/' + match[1]], msg, me);
              }
            }
          }
        }).then(resolve).catch(reject);
      });
    });
  }
  get(url, json) {
    return new Promise((resolve, reject) => {
      request.get({ url, json: !!json }, (error, response, data) => {
        if (error || !data) return reject(response);
        return resolve(data);
      });
    });
  }
  mod(name, fn) {
    if (!this.modList[name]) this.modList[name] = [];
    if (this.modList[name].indexOf(fn) !== -1) return;
    this.modList[name].push(fn);
  }
  modRun(name, data) {
    const list = this.modList[name];
    if (!list || !list.length) return data;
    for (let fn of list) data = fn.call(this, data);
    return data;
  }
  /* Events */
  on(types, fn) {
    if (typeof types == 'string') types = [types];
    for (let type of types) {
      let event = this.eventList[type];
      if (!event) {
        this.eventList[type] = { fired: null, list: [] };
      } else if (event.fired) {
        const fired = event.fired;
        const out = fn.call(fired.self, fired.data, fired.details);
        if (out instanceof Promise) out.catch(error => {
          console.error('[error.event.fired]', error.stack || error);
          if (type != 'error')
            this.event('error', { error, data: fired.data });
        });
      }
      event = this.eventList[type].list;
      if (event.indexOf(fn) !== -1) return;
      event.push(fn);
    }
  }
  event(types, data, me) {
    const self = this, promises = [];
    if (typeof types == 'string') types = [types];
    for (let type of types) {
      let event = this.eventList[type];
      const details = { type, time: Date.now() };
      const props = { self: me, data, details };
      if (!event) {
        this.eventList[type] = { fired: props, list: [] };
        continue;
      }
      event.fired = props;
      event = event.list;
      for (let fn of event) {
        promises.push(new Promise((resolve, reject) => {
          try {
            fn = fn.call(me, data, details);
            if (fn instanceof Promise)
              return fn.then(resolve).catch(errorHandler);
            return resolve(fn);
          } catch(error) {
            return errorHandler(error);
          }
          function errorHandler(error) {
            console.error('[error.event]', error.stack || error);
            if (type != 'error')
              self.event('error', { error, data });
            return reject(error);
          }
        }));
      }
    }
    return Promise.all(promises);
  }
  clean(type) {
    if (!this.eventList.hasOwnProperty(type)) return;
    this.eventList[type].fired = null;
  }
  remove(type, fn) {
    if (!this.eventList.hasOwnProperty(type)) return;
    const event = this.eventList[type].list;
    const index = event.indexOf(fn);
    if (index === -1) return;
    event.splice(index, 1);
  }
  destroy(type) {
    if (!this.eventList.hasOwnProperty(type)) return;
    delete this.eventList[type];
  }
};

/* Answer List */

function answerList(queryId) {
  this.id = queryId;
  this.list = [];
};

answerList.prototype = {
  results() {
    return JSON.stringify(this.list);
  },
  add(type, set) {
    set = set || {};
    set.type = type;
    this.list.push(set);
    return set;
  }
};

// Add answer methods
{
  for (let prop in ANSWER_METHODS) {
    answerList.prototype[prop] = (name => {
      return function(set) {
        return this.add(name, set);
      };
    })(ANSWER_METHODS[prop]);
  }
}

/* Functions */

function props(form, opt) {
  opt = opt || {};
  form = form || {};
  // Reply to message
  if (opt.reply) form['reply_to_message_id'] = opt.reply;
  // Markdown/HTML support for message
  if (opt.parse) form['parse_mode'] = opt.parse;
  // User notification
  if (opt.notify === false) form['disable_notification'] = true;
  // Markup object
  if (opt.markup !== undefined) {
    if (opt.markup == 'hide' || opt.markup === false) {
      // Hide keyboard
      form['reply_markup'] = JSON.stringify({ hide_keyboard: true });
    } else if (opt.markup == 'reply') {
      // Fore reply
      form['reply_markup'] = JSON.stringify({ force_reply: true });
    } else {
      // JSON keyboard
      form['reply_markup'] = opt.markup;
    }
  }
  return (this.modRun('property', { form, options: opt })).form;
}

function sendFile(type, id, file, opt) {
  opt = opt || {};
  const form = props.call(this, { chat_id: id }, opt);
  let url = 'send' + type.charAt(0).toUpperCase() + type.slice(1);
  // Send bot action event
  this.event(url, [].slice.call(arguments).splice(0, 1));
  // Set file caption
  if (opt.caption) form.caption = opt.caption;
  url = '/' + url;
  if (typeof file == 'string' && REGEX.url.test(file)) {
    // If url, get blob and send to user
    return getBlob(file).then(data => {
      // Set file name
      if (!opt.fileName) {
        opt.fileName = path.basename(nurl.parse(file).pathname) || 'file';
      }
      // Data form
      form[type] = {
        value: data.buffer,
        options: { filename: opt.fileName, contentType: data.type }
      };
      return this.request(url, null, form);
    });
  } else {
    // String as 'file_id'
    form[type] = file;
    return this.request(url, null, form);
  }
}

function getBlob(url) {
  return new Promise((resolve, reject) => {
    request.get({ url, encoding: null }, (error, response, buffer) => {
      if (error || !buffer) return reject(error);
      return resolve({ buffer, type: response.headers['content-type'] });
    });
  });
}

function extend(me, input) {
  for (let obj of input) {
    for (let name in obj) {
      const key = me[name], value = obj[name];
      if (key !== undefined) {
        if (!Array.isArray(key)) me[name] = [key];
        me[name].push(value);
        continue;
      }
      me[name] = value;
    }
  }
  return me;
}

/* Exports */

module.exports = TeleBot;
<commit_msg>Improve "sendFile" function (add stream support)<commit_after>'use strict';

const
  fs = require('fs'),
  nurl = require('url'),
  path = require('path'),
  stream = require('stream'),
  request = require('request');

/* Globals */

const MESSAGE_TYPES = [
  'text', 'audio', 'voice', 'document', 'photo',
  'sticker', 'video', 'contact', 'location', 'query'
];

const ANSWER_METHODS = {
  addArticle: 'article', addPhoto: 'photo', addVideo: 'video',
  addGif: 'gif', addVideoGif: 'mpeg4_gif'
};

const REGEX = {
  cmd: /^\/([а-я\w\d]+)/,
  url: /^https?\:\/\/|www\./
};

/* Telegram Bot */

class TeleBot {
  constructor(cfg) {
    this.cfg = cfg;
    this.token = cfg.token;
    this.id = this.token.split(':')[0];
    this.api = 'https://api.telegram.org/bot' + this.token;
    this.fileLink = 'https://api.telegram.org/file/bot' + this.token + '/';
    this.limit = Number(cfg.limit) || 100;
    this.timeout = cfg.timeout >= 0 ? cfg.timeout : 0;
    this.retryTimeout = cfg.retryTimeout >= 0 ? cfg.retryTimeout : 5000;
    this.retry = false;
    this.pool = true;
    this.loopFn = null;
    this.looping = false;
    this.sleep = Number(cfg.sleep) || 1000;
    this.updateId = 0;
    this.eventList = {};
    this.modList = {};
  }
  /* Modules */
  use(fn) {
    return fn.call(this, this);
  }
  /* Keyboard */
  keyboard(keyboard, opt) {
    opt = opt || {};
    const markup = { keyboard };
    if (opt.resize === true) markup['resize_keyboard'] = true;
    if (opt.once === true) markup['one_time_keyboard'] = true;
    if (opt.selective) markup['selective'] = opt.selective;
    return JSON.stringify(markup);
  }
  /* Answer */
  answerList(id) {
    return answerList(id);
  }
  /* Actions */
  getMe() {
    this.event('getMe', arguments);
    return this.request('/getMe');
  }
  answerQuery(answers, opt) {
    this.event('answerQuery', arguments);
    return this.request('/answerInlineQuery', {
      inline_query_id: answers.id, results: answers.results(),
    });
  }
  getFile(fileId) {
    this.event('getFile', arguments);
    return this.request('/getFile', { file_id: fileId }).then(file => {
      const result = file.result;
      result.fileLink = this.fileLink + result.file_path;
      return result;
    });
  }
  forwardMessage(id, fromId, messageId) {
    this.event('forwardMessage', arguments);
    return this.request('/forwardMessage', {
      chat_id: id, from_chat_id: fromId, message_id: messageId
    });
  }
  getUserPhoto(id, opt) {
    this.event('getUserPhoto', arguments);
    opt = opt || {};
    const form = { user_id: id };
    if (opt.offset) form['offset'] = opt.offset;
    if (opt.limit) form['limit'] = opt.limit;
    return this.request('/getUserProfilePhotos', form);
  }
  sendAction(id, action) {
    this.event('sendAction', arguments);
    return this.request('/sendChatAction', { chat_id: id, action });
  }
  sendMessage(id, text, opt) {
    this.event('sendMessage', arguments);
    opt = opt || {};
    const form = props.call(this, { chat_id: id, text }, opt);
    if (opt.preview === false) form['disable_web_page_preview'] = true;
    return this.request('/sendMessage', form);
  }
  sendLocation(id, position, opt) {
    this.event('sendLocation', arguments);
    opt = opt || {};
    const form = props.call(this, {
      chat_id: id, latitude: position[0], longitude: position[1]
    }, opt);
    return this.request('/sendLocation', form);
  }
  sendPhoto(id, photo, opt) {
    return sendFile.call(this, 'photo', id,  photo, opt);
  }
  sendAudio(id, audio, opt) {
    return sendFile.call(this, 'audio', id, audio, opt);
  }
  sendVoice(id, voice, opt) {
    return sendFile.call(this, 'voice', id, voice, opt);
  }
  sendDocument(id, doc, opt) {
    return sendFile.call(this, 'document', id, doc, opt);
  }
  sendSticker(id, sticker, opt) {
    return sendFile.call(this, 'sticker', id, sticker, opt);
  }
  sendVideo(id, video, opt) {
    return sendFile.call(this, 'video', id, video, opt);
  }
  setWebhook(url, certificate) {
    this.event('setWebhook', arguments);
    return this.request('/setWebhook', { url, certificate });
  }
  /* Send request to server */
  request(url, form, data) {
    const options = { url: this.api + url, json: true };
    if (form) { options.form = form; } else { options.formData = data; };
    return new Promise((resolve, reject) => {
      request.post(options, (error, response, body) => {
        if (error || !body.ok || response.statusCode == 404) {
          return reject(error || body || 404);
        }
        return resolve(body);
      });
    });
  }
  /* Connection */
  connect() {
    this.looping = true;
    console.log('[info] bot started');
    this.event('connect');
    this.loopFn = setInterval(x => {
      if (!this.looping) clearInterval(this.loopFn);
      if (!this.pool) return;
      this.pool = false;
      this.getUpdate().then(x => {
        if (this.retry) {
          const now = Date.now();
          const diff = (now - this.retry) / 1000;
          console.log('[info.update] reconnected after ' + diff + ' seconds');
          this.event('reconnected', {
            startTime: this.retry, endTime: now, diffTime: diff
          });
          this.retry = false;
        }
        return this.event('tick');
      }).then(x => {
        this.pool = true;
      }).catch(error => {
        if (this.retry === false) this.retry = Date.now();
        console.error('[error.update]', error.stack || error);
        this.event('error', { error });
        return Promise.reject();
      }).catch(x => {
        const seconds = this.retryTimeout / 1000;
        console.log('[info.update] reconnecting in ' + seconds + ' seconds...');
        this.event('reconnecting');
        setTimeout(x => (this.pool = true), this.retryTimeout);
      });
    }, this.sleep);
  }
  disconnect(message) {
    this.looping = false;
    console.log('[info] bot disconnected' + (message ? ': ' + message : ''));
    this.event('disconnect', message);
  }
  /* Fetch updates */
  getUpdate() {
    // Request an update
    return this.request('/getUpdates', {
      offset: this.updateId, limit: this.limit, timeout: this.timeout
    }).then(body => {
      // Check for update
      var data = body.result;
      if (!data.length) return Promise.resolve();
      return new Promise((resolve, reject) => {
        this.event('update', data).then(output => {
          var me = extend({}, output);
          // Run update processors
          var temp = this.modRun('update', { data, me });
          data = temp.data, me = temp.me;
          // Check every message in update
          for (let update of data) {
            // Set update ID
            let nextId = ++update['update_id'];
            if (this.updateId < nextId) this.updateId = nextId;
            // Run message processors
            let temp = this.modRun('message', {
              me, msg:
                update['message'] || update['inline_query'] ||
                update['chosen_inline_result'] || {}
            });
            var msg = temp.msg, me = temp.me;
            for (let type of MESSAGE_TYPES) {
              // Check for Telegram API documented types
              if (!(type in msg)) continue;
              me.type = type;
              // Send type event
              this.event(['*', type], msg, me);
              // Check for command
              if (type == 'text') {
                const match = REGEX.cmd.exec(msg.text);
                if (!match) continue;
                // Command found
                me.cmd = msg.text.split(' ');
                this.event(['/*', '/' + match[1]], msg, me);
              }
            }
          }
        }).then(resolve).catch(reject);
      });
    });
  }
  get(url, json) {
    return new Promise((resolve, reject) => {
      request.get({ url, json: !!json }, (error, response, data) => {
        if (error || !data) return reject(response);
        return resolve(data);
      });
    });
  }
  mod(name, fn) {
    if (!this.modList[name]) this.modList[name] = [];
    if (this.modList[name].indexOf(fn) !== -1) return;
    this.modList[name].push(fn);
  }
  modRun(name, data) {
    const list = this.modList[name];
    if (!list || !list.length) return data;
    for (let fn of list) data = fn.call(this, data);
    return data;
  }
  /* Events */
  on(types, fn) {
    if (typeof types == 'string') types = [types];
    for (let type of types) {
      let event = this.eventList[type];
      if (!event) {
        this.eventList[type] = { fired: null, list: [] };
      } else if (event.fired) {
        const fired = event.fired;
        const out = fn.call(fired.self, fired.data, fired.details);
        if (out instanceof Promise) out.catch(error => {
          console.error('[error.event.fired]', error.stack || error);
          if (type != 'error')
            this.event('error', { error, data: fired.data });
        });
      }
      event = this.eventList[type].list;
      if (event.indexOf(fn) !== -1) return;
      event.push(fn);
    }
  }
  event(types, data, me) {
    const self = this, promises = [];
    if (typeof types == 'string') types = [types];
    for (let type of types) {
      let event = this.eventList[type];
      const details = { type, time: Date.now() };
      const props = { self: me, data, details };
      if (!event) {
        this.eventList[type] = { fired: props, list: [] };
        continue;
      }
      event.fired = props;
      event = event.list;
      for (let fn of event) {
        promises.push(new Promise((resolve, reject) => {
          try {
            fn = fn.call(me, data, details);
            if (fn instanceof Promise)
              return fn.then(resolve).catch(errorHandler);
            return resolve(fn);
          } catch(error) {
            return errorHandler(error);
          }
          function errorHandler(error) {
            console.error('[error.event]', error.stack || error);
            if (type != 'error')
              self.event('error', { error, data });
            return reject(error);
          }
        }));
      }
    }
    return Promise.all(promises);
  }
  clean(type) {
    if (!this.eventList.hasOwnProperty(type)) return;
    this.eventList[type].fired = null;
  }
  remove(type, fn) {
    if (!this.eventList.hasOwnProperty(type)) return;
    const event = this.eventList[type].list;
    const index = event.indexOf(fn);
    if (index === -1) return;
    event.splice(index, 1);
  }
  destroy(type) {
    if (!this.eventList.hasOwnProperty(type)) return;
    delete this.eventList[type];
  }
};

/* Answer List */

function answerList(queryId) {
  this.id = queryId;
  this.list = [];
};

answerList.prototype = {
  results() {
    return JSON.stringify(this.list);
  },
  add(type, set) {
    set = set || {};
    set.type = type;
    this.list.push(set);
    return set;
  }
};

// Add answer methods
{
  for (let prop in ANSWER_METHODS) {
    answerList.prototype[prop] = (name => {
      return function(set) {
        return this.add(name, set);
      };
    })(ANSWER_METHODS[prop]);
  }
}

/* Functions */

function props(form, opt) {
  opt = opt || {};
  form = form || {};
  // Reply to message
  if (opt.reply) form['reply_to_message_id'] = opt.reply;
  // Markdown/HTML support for message
  if (opt.parse) form['parse_mode'] = opt.parse;
  // User notification
  if (opt.notify === false) form['disable_notification'] = true;
  // Markup object
  if (opt.markup !== undefined) {
    if (opt.markup == 'hide' || opt.markup === false) {
      // Hide keyboard
      form['reply_markup'] = JSON.stringify({ hide_keyboard: true });
    } else if (opt.markup == 'reply') {
      // Fore reply
      form['reply_markup'] = JSON.stringify({ force_reply: true });
    } else {
      // JSON keyboard
      form['reply_markup'] = opt.markup;
    }
  }
  return (this.modRun('property', { form, options: opt })).form;
}

function sendFile(type, id, file, opt) {
  opt = opt || {};
  const form = props.call(this, { chat_id: id }, opt);
  let url = 'send' + type.charAt(0).toUpperCase() + type.slice(1);
  // Send bot action event
  this.event(url, [].slice.call(arguments).splice(0, 1));
  // Set file caption
  if (opt.caption) form.caption = opt.caption;
  url = '/' + url;
  if (file instanceof stream.Stream) {
    // File stream object
    if (!opt.fileName)
      opt.fileName = nurl.parse(path.basename(file.path)).pathname;
    form[type] = {
      value: file,
      options: { filename: opt.fileName }
    };
  } else if (Buffer.isBuffer(file)) {
    // File buffer
    if (!opt.fileName) opt.fileName = 'blob_file';
    form[type] = {
      value: file,
      options: { filename: opt.fileName }
    };
  } else if (REGEX.url.test(file)) {
    // File url
    if (!opt.fileName)
      opt.fileName = path.basename(nurl.parse(file).pathname) || 'file';
    form[type] = {
      value: request.get(file),
      options: { filename: opt.fileName }
    };
  } else if (fs.existsSync(file)) {
    // File location
    if (!opt.fileName) opt.fileName = path.basename(file);
    form[type] = {
      value: fs.createReadStream(file),
      options: { filename: opt.fileName }
    };
  } else {
    // File as 'file_id'
    form[type] = file;
  }
  return this.request(url, null, form);
}

function getBlob(url) {
  return new Promise((resolve, reject) => {
    request.get({ url, encoding: null }, (error, response, buffer) => {
      if (error || !buffer) return reject(error);
      return resolve({ buffer, type: response.headers['content-type'] });
    });
  });
}

function extend(me, input) {
  for (let obj of input) {
    for (let name in obj) {
      const key = me[name], value = obj[name];
      if (key !== undefined) {
        if (!Array.isArray(key)) me[name] = [key];
        me[name].push(value);
        continue;
      }
      me[name] = value;
    }
  }
  return me;
}

/* Exports */

module.exports = TeleBot;
<|endoftext|>


<commit_before>const decompress = require('decompress')
const request = require('request')
const ProgressBar = require('progress')
const tmpdir = require('os-tmpdir')
const mkdirp = require('mkdirp')
const path = require('path')
const fs = require('fs')
const checksum = require('checksum')
const rimraf = require('rimraf')

const tar = require('tar')
const zlib = require('zlib')

const config = {
  outputPath: path.join(__dirname, '..', 'git'),
  version: '2.11.0',
  build: '8',
  source: '',
  checksum: '',
  upstreamVersion: '',
  fileName: ''
}

function formatPlatform(platform) {
  // switching this to Ubuntu to ensure it's clear what we're installing here
  if (platform === 'linux') {
    return 'ubuntu'
  }
  return platform
}

config.fileName = `git-kitchen-sink-${formatPlatform(process.platform)}-v${config.version}-${config.build}.tgz`

// TODO: swap these out for official release URLs when we make the repository public

if (process.platform === 'darwin') {
  config.source = `https://www.dropbox.com/s/r5pqhg7ba6blpv4/${config.fileName}?dl=1`
  config.checksum = '4fcb5434e87d133339c308a4d9622c8c690d808f0b8b32a385d8178c1a4b0a24'
} else if (process.platform === 'win32') {
  config.source = `https://www.dropbox.com/s/yf33r47e3zby8mo/${config.fileName}?dl=1`
  config.checksum = '0aab55d5fbd9185052bd3f10292562d24650d44ce3e0b462cc8f1a53b5e70867'
} else if (process.platform === 'linux') {
  config.source = `https://www.dropbox.com/s/ofdvkkfq99nsab7/${config.fileName}?dl=1`
  config.checksum = '20b48a678ee7b717c8b7a7c6dafc9471c82e82e8ebe8edc2b0101d5d99ab53c8'
}
const fullUrl = config.source

function handleError (url, error) {
  if (!error) {
    return
  }

  const message = error.message || error
  console.error(`Downloading ${url} failed: ${message}`)
  process.exit(1)
}

function extract (source, callback) {
  if (path.extname(source) === '.zip') {
    const result = decompress(source, config.outputPath)
    result
      .then(() => {
        callback(null)
      })
      .catch(err => {
        callback(err)
      })

  } else {
    const extractor = tar.Extract({path: config.outputPath})
      .on('error', function (error) { callback(error) })
      .on('end', function () { callback() })

    fs.createReadStream(source)
      .on('error', function (error) { callback(error) })
      .pipe(zlib.Gunzip())
      .pipe(extractor)
  }
}

const dir = tmpdir()
const temporaryFile = path.join(dir, config.fileName)

const verifyFile = function (file, callback) {
  checksum.file(file, { algorithm: 'sha256' }, (_, hash) => {
    callback(hash === config.checksum)
  })
}

const unpackFile = function (file) {
  extract(file, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }
  })
}

const downloadCallback = function (error, response, body) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (response.statusCode !== 200) {
    return handleError(fullUrl, Error(`Non-200 response (${response.statusCode})`))
  }

  fs.createWriteStream(temporaryFile).write(body, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }

    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        console.log(`checksum verification failed, refusing to unpack...`)
        process.exit(1)
      }
    })
  })
}

const downloadAndUnpack = () => {
  console.log(`Downloading Git from: ${fullUrl}`)

  const req = request.get(fullUrl, { encoding: null }, downloadCallback)

  req.on('response', function (res) {
    const len = parseInt(res.headers['content-length'], 10)

    console.log()
    const bar = new ProgressBar('Downloading Git [:bar] :percent :etas', {
      complete: '=',
      incomplete: ' ',
      width: 50,
      total: len
    })

    res.on('data', function (chunk) {
      bar.tick(chunk.length)
    })

    res.on('end', function () {
      console.log('\n')
    })
  })
}

mkdirp(config.outputPath, function (error) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (fs.existsSync(config.outputPath)) {
    try {
      rimraf.sync(config.outputPath)
    } catch (err) {
      console.error(err)
      return
    }
  }

  if (fs.existsSync(temporaryFile)) {
    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        rimraf.sync(temporaryFile)
        downloadAndUnpack()
      }
    })
    return
  }

  downloadAndUnpack()
})
<commit_msg>update to new builds<commit_after>const decompress = require('decompress')
const request = require('request')
const ProgressBar = require('progress')
const tmpdir = require('os-tmpdir')
const mkdirp = require('mkdirp')
const path = require('path')
const fs = require('fs')
const checksum = require('checksum')
const rimraf = require('rimraf')

const tar = require('tar')
const zlib = require('zlib')

const config = {
  outputPath: path.join(__dirname, '..', 'git'),
  version: '2.11.0',
  build: '9',
  source: '',
  checksum: '',
  upstreamVersion: '',
  fileName: ''
}

function formatPlatform(platform) {
  // switching this to Ubuntu to ensure it's clear what we're installing here
  if (platform === 'linux') {
    return 'ubuntu'
  }
  return platform
}

config.fileName = `git-kitchen-sink-${formatPlatform(process.platform)}-v${config.version}-${config.build}.tgz`

// TODO: swap these out for official release URLs when we make the repository public

if (process.platform === 'darwin') {
  config.source = `https://www.dropbox.com/s/okgev1575noirnr/${config.fileName}?dl=1`
  config.checksum = 'd9c945060a1b356a160ae4ea20f833c2b15cdef16230e0f557d236c6a463f9ba'
} else if (process.platform === 'win32') {
  config.source = `https://www.dropbox.com/s/jyzqqag4co0ul54/${config.fileName}?dl=1`
  config.checksum = '449a4687b537cd32adcf000e8666b261ddd28e7390241373da213bc8c48d5675'
} else if (process.platform === 'linux') {
  config.source = `https://www.dropbox.com/s/i96j5b40h626f1l/${config.fileName}?dl=1`
  config.checksum = '7ed8a337b22b2d626b52c4a49f05f4cb867199912a929bc131b2e6fc5d86f8e3'
}
const fullUrl = config.source

function handleError (url, error) {
  if (!error) {
    return
  }

  const message = error.message || error
  console.error(`Downloading ${url} failed: ${message}`)
  process.exit(1)
}

function extract (source, callback) {
  if (path.extname(source) === '.zip') {
    const result = decompress(source, config.outputPath)
    result
      .then(() => {
        callback(null)
      })
      .catch(err => {
        callback(err)
      })

  } else {
    const extractor = tar.Extract({path: config.outputPath})
      .on('error', function (error) { callback(error) })
      .on('end', function () { callback() })

    fs.createReadStream(source)
      .on('error', function (error) { callback(error) })
      .pipe(zlib.Gunzip())
      .pipe(extractor)
  }
}

const dir = tmpdir()
const temporaryFile = path.join(dir, config.fileName)

const verifyFile = function (file, callback) {
  checksum.file(file, { algorithm: 'sha256' }, (_, hash) => {
    callback(hash === config.checksum)
  })
}

const unpackFile = function (file) {
  extract(file, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }
  })
}

const downloadCallback = function (error, response, body) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (response.statusCode !== 200) {
    return handleError(fullUrl, Error(`Non-200 response (${response.statusCode})`))
  }

  fs.createWriteStream(temporaryFile).write(body, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }

    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        console.log(`checksum verification failed, refusing to unpack...`)
        process.exit(1)
      }
    })
  })
}

const downloadAndUnpack = () => {
  console.log(`Downloading Git from: ${fullUrl}`)

  const req = request.get(fullUrl, { encoding: null }, downloadCallback)

  req.on('response', function (res) {
    const len = parseInt(res.headers['content-length'], 10)

    console.log()
    const bar = new ProgressBar('Downloading Git [:bar] :percent :etas', {
      complete: '=',
      incomplete: ' ',
      width: 50,
      total: len
    })

    res.on('data', function (chunk) {
      bar.tick(chunk.length)
    })

    res.on('end', function () {
      console.log('\n')
    })
  })
}

mkdirp(config.outputPath, function (error) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (fs.existsSync(config.outputPath)) {
    try {
      rimraf.sync(config.outputPath)
    } catch (err) {
      console.error(err)
      return
    }
  }

  if (fs.existsSync(temporaryFile)) {
    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        rimraf.sync(temporaryFile)
        downloadAndUnpack()
      }
    })
    return
  }

  downloadAndUnpack()
})
<|endoftext|>


<commit_before>/**
 * Created by ionagamed on 8/12/16.
 */

module.exports = {
    entry: [
        './munchkin/munchkin.js'
    ],
    output: {
        publicPath: '/client',
        filename: 'client/munchkin.js'
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                include: './munchkin',
                loader: 'babel-loader',
                query: {
                    presets: ['es2016']
                }
            }
        ]
    }
};<commit_msg>remove webpack separate config<commit_after><|endoftext|>


<commit_before>var Post = {
    init: function() {
        if(localStorage.getItem('share_url')) {
            Post_ajaxCreate();
            MovimTpl.showPanel();
        }
    },

    setEmbed: function() {
        if(localStorage.getItem('share_url')) {
            var embed = document.querySelector('input[name=embed]');
            embed.value = localStorage.getItem('share_url');
            embed.onpaste();
        }
    }
}

MovimWebsocket.attach(function() {
    Post.init();
});
<commit_msg>- Clear the shared url<commit_after>var Post = {
    init: function() {
        if(localStorage.getItem('share_url')) {
            Post_ajaxCreate();
            MovimTpl.showPanel();
        }
    },

    setEmbed: function() {
        if(localStorage.getItem('share_url')) {
            var embed = document.querySelector('input[name=embed]');
            embed.value = localStorage.getItem('share_url');
            embed.onpaste();
            localStorage.removeItem('share_url');
        }
    }
}

MovimWebsocket.attach(function() {
    Post.init();
});
<|endoftext|>


<commit_before>var httpProxy = require('http-proxy');
var url = require('url');
var net = require('net');
var path = require('path');

//
// Sample fake responses
//

var results_by_regex = {}
results_by_regex['test-html-200'] = {
    status: 200,
    text: 'Hello, world!',
    type: 'text/html'
}

results_by_regex['test-json-201'] = {
    status: 201,
    text: '{"created": true, "message": "Hello, world!", "value": 42}',
    type: 'application/json',
    headers: [{
        "name": "cache-control",
        "value": "no-cache"
    }, {
        "name": 'etag'
    }]
}

results_by_regex['test-error-500'] = {
    status: 500,
    text: 'Ooops! Something bad happend :(\n',
    type: 'application/text'
}

results_by_regex['test-error-599'] = {
    status: 599
}

//
// Simple rules management
//
var rules_handler = function(request, response) {
    var regex = request.url.substring(request.url.indexOf('rules') + 'rules'.length + 1);
    if (regex === undefined || regex.length == 0) {
        respond(response, 400, '{"error":"no regex specified in the path"}');
        return
    }

    if (request.method == 'POST') {
        parse_post(request, function(data){
            results_by_regex[regex] = JSON.parse(data);
            console.log('rule added for regex "%s": %s', regex, data);
            respond(response, 201, '{"regex":"'+regex+'", "result":"'+data+'"}');
        });
    } else if (request.method == 'DELETE') {
        if (results_by_regex[regex] != undefined) {
            delete results_by_regex[regex]
            console.log('rule added for regex "%s"', regex);
            respond(response, 200, '{"regex":"'+regex+'"}, "deleted":true}');
        } else {
            respond(response, 404);
        }
    } else {
        respond(response, 405);
    }
};

//
// The https faking filter
//

var https_filter = function(req, socket) {
    var result = find_result(req);
    if (!result || !is5xx(result)) {
        var serverUrl = url.parse('https://' + req.url);
        var srvSocket = net.connect(serverUrl.port, serverUrl.hostname, function() {
            socket.write(
                'HTTP/1.1 200 Connection Established\r\n' +
                'Proxy-agent: bimbo-proxy\r\n' +
                '\r\n');
            srvSocket.pipe(socket);
            socket.pipe(srvSocket);
        });
    } else {
        socket.write(
            'HTTP/1.1 '+result.status+' '+result.text+'\r\n' +
            'Proxy-agent: bimbo-proxy\r\n' +
            '\r\n');

        socket.destroy();
    }
}

//
// The http faking filter
//

var http_filter = function(proxyRes, request, response) {
    var content,
        _write = response.write;
    _writeHead = response.writeHead;

    var result = find_result(request);

    response.writeHead = function() {
        response.setHeader('x-bimbo-proxy', 'true');
        if (result) {
            console.log("Response will be faked to ", JSON.stringify(result))

            response.setHeader('x-bimbo-faked', 'true');
            delete_header(response, 'transfer-encoding');
            delete_header(response, 'content-encoding');

            if (result.text) {
                response.setHeader('Content-Length', result.text.length);
                response.setHeader('Content-Type', result.type + '; charset=utf-8')
            }

            headers = result.headers;
            if (headers) {
                headers.forEach(function(header) {
                    if (header.value) {
                        response.setHeader(header.name, header.value);
                    } else {
                        delete_header(response, header.name);
                    }
                });
            }

            _writeHead.apply(this, [result.status, {}]);
        } else {
            _writeHead.apply(this, arguments);
        }
    }

    response.write = function(data) {
        if (!result) {
            _write.apply(response, arguments);
        } else if (result.text) {
            _write.apply(response, [result.text.toString()]);
        }
    };
}

//
// Support functions
//

var respond = function(response, code, message) {
    response.statusCode = code;
    if (message != undefined) {
        response.setHeader('Content-type', 'application/json');
        response.write(message);
    }
    response.end();
}

var parse_post = function(request, callback) {
    var data = '';
    request.on('data', function(chunk) {
        data += chunk;
    });
    request.on('end', function() {
        callback(data);
    });
}

var is5xx = function(result) {
    return result.status >= 500 && result.status <= 599;
}

// TODO: we should make it work lowercase and maybe
// we do have a real function to do that, right?
var delete_header = function(response, name) {
    delete response._headers[name];
    delete response._headerNames[name];
}

var find_result = function(request) {
    for (var regex in results_by_regex) {
        if (results_by_regex.hasOwnProperty(regex)) {
            var found = new RegExp(regex).test(request.url);
            if (found) {
                return results_by_regex[regex];
            }
        }
    }

    return undefined;
};

//
// Exports!
//

exports.http_filter = http_filter;
exports.https_filter = https_filter;
exports.rules_handler = rules_handler;
<commit_msg>Fixed errors on HTTPS<commit_after>var httpProxy = require('http-proxy');
var url = require('url');
var net = require('net');
var path = require('path');

//
// Sample fake responses
//

var results_by_regex = {}
results_by_regex['test-html-200'] = {
    status: 200,
    text: 'Hello, world!',
    type: 'text/html'
}

results_by_regex['test-json-201'] = {
    status: 201,
    text: '{"created": true, "message": "Hello, world!", "value": 42}',
    type: 'application/json',
    headers: [{
        "name": "cache-control",
        "value": "no-cache"
    }, {
        "name": 'etag'
    }]
}

results_by_regex['test-error-500'] = {
    status: 500,
    text: 'Ooops! Something bad happend :(\n',
    type: 'application/text'
}

results_by_regex['test-error-599'] = {
    status: 599
}

//
// Simple rules management
//
var rules_handler = function(request, response) {
    var regex = request.url.substring(request.url.indexOf('rules') + 'rules'.length + 1);
    if (regex === undefined || regex.length == 0) {
        respond(response, 400, '{"error":"no regex specified in the path"}');
        return
    }

    if (request.method == 'POST') {
        parse_post(request, function(data){
            results_by_regex[regex] = JSON.parse(data);
            console.log('rule added for regex "%s": %s', regex, data);
            respond(response, 201, '{"regex":"'+regex+'", "result":"'+data+'"}');
        });
    } else if (request.method == 'DELETE') {
        if (results_by_regex[regex] != undefined) {
            delete results_by_regex[regex]
            console.log('rule removed for regex "%s"', regex);
            respond(response, 200, '{"regex":"'+regex+'"}, "deleted":true}');
        } else {
            respond(response, 404);
        }
    } else {
        respond(response, 405);
    }
};

//
// The https faking filter
//

var https_filter = function(req, socket) {
    var result = find_result(req);
    if (!result || !is5xx(result)) {
        var serverUrl = url.parse('https://' + req.url);
        var srvSocket = net.connect(serverUrl.port, serverUrl.hostname, function() {
            socket.write(
                'HTTP/1.1 200 Connection Established\r\n' +
                'Proxy-agent: bimbo-proxy\r\n' +
                '\r\n');
            srvSocket.pipe(socket);
            socket.pipe(srvSocket);
        });
    } else {
        console.log("Response to %s will be faked to %s", req.url, JSON.stringify(result))
        // socket.write("HTTP/" + req.httpVersion + " 500 Connection error\r\n\r\n");
        // socket.end();
        socket.write('HTTP/' + req.httpVersion + ' '+result.status+' '+result.text+'\r\n');
        socket.write('Proxy-agent: bimbo-proxy\r\n');

        if (result.headers) {
            result.headers.forEach(function(header) {
                socket.write(header.name+': '+header.value+'\r\n');
            });
        }

        socket.write('\r\n');
        socket.end();
    }
}

//
// The http faking filter
//

var http_filter = function(proxyRes, request, response) {
    var content,
        _write = response.write;
    _writeHead = response.writeHead;

    var result = find_result(request);

    response.writeHead = function() {
        response.setHeader('x-bimbo-proxy', 'true');
        if (result) {
            console.log("Response to %s will be faked to %s", request.url, JSON.stringify(result))

            response.setHeader('x-bimbo-faked', 'true');
            delete_header(response, 'transfer-encoding');
            delete_header(response, 'content-encoding');

            if (result.text) {
                response.setHeader('Content-Length', result.text.length);
                response.setHeader('Content-Type', result.type + '; charset=utf-8')
            }

            var headers = result.headers;
            if (headers) {
                headers.forEach(function(header) {
                    if (header.value) {
                        response.setHeader(header.name, header.value);
                    } else {
                        delete_header(response, header.name);
                    }
                });
            }

            _writeHead.apply(this, [result.status, {}]);
        } else {
            _writeHead.apply(this, arguments);
        }
    }

    response.write = function(data) {
        if (!result) {
            _write.apply(response, arguments);
        } else if (result.text) {
            _write.apply(response, [result.text.toString()]);
        }
    };
}

//
// Support functions
//

var respond = function(response, code, message) {
    response.statusCode = code;
    if (message != undefined) {
        response.setHeader('Content-type', 'application/json');
        response.write(message);
    }
    response.end();
}

var parse_post = function(request, callback) {
    var data = '';
    request.on('data', function(chunk) {
        data += chunk;
    });
    request.on('end', function() {
        callback(data);
    });
}

var is5xx = function(result) {
    return result.status >= 500 && result.status <= 599;
}

// TODO: we should make it work lowercase and maybe
// we do have a real function to do that, right?
var delete_header = function(response, name) {
    delete response._headers[name];
    delete response._headerNames[name];
}

var find_result = function(request) {
    for (var regex in results_by_regex) {
        if (results_by_regex.hasOwnProperty(regex)) {
            var found = new RegExp(regex).test(request.url);
            if (found) {
                return results_by_regex[regex];
            }
        }
    }

    return undefined;
};

//
// Exports!
//

exports.http_filter = http_filter;
exports.https_filter = https_filter;
exports.rules_handler = rules_handler;
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

const path = require('path');
const archiver = require('archiver');
const fs = require('fs');

const { name, version } = require('../package.json');
const src = path.resolve(__dirname, '../dist');
const dst = path.join(path.resolve(__dirname, '..'), `${name}-${version}`);

const createArchive = (archive, src, compressedFile) =>
	new Promise((resolve, reject) => {
		const output = fs.createWriteStream(compressedFile);
		output.on('close', () => resolve());

		archive.on('error', (err) => reject(err));
		archive.pipe(output);
		archive.directory(src, '');
		archive.finalize();
	});

const createDistTar = () => createArchive(
	archiver('tar', { gzip: true, gzipOptions: { level: 9 } }),
	src,
	`${dst}.tar.gz`
);

const createDistZip = () => createArchive(
	archiver('zip', { level: 9 }),
	src,
	`${dst}.zip`
);

Promise.resolve()
	.then(createDistTar)
	.then(createDistZip)
	.catch(err =>
	{
		console.log(err);
		process.exit(1);
	});
<commit_msg>Add es6 archive generation<commit_after>#!/usr/bin/env node
'use strict';

const path = require('path');
const archiver = require('archiver');
const fs = require('fs-extra');

const { name, version } = require('../package.json');
const src = path.resolve(__dirname, '../dist');
const dst = path.join(path.resolve(__dirname, '..'), `${name}-${version}`);

const createArchive = (archive, src, compressedFile) =>
	new Promise((resolve, reject) => {
		const output = fs.createWriteStream(compressedFile);
		output.on('close', () => resolve());

		archive.on('error', (err) => reject(err));
		archive.pipe(output);
		archive.directory(src, '');
		archive.finalize();
	});

const createTarArchive = (archiveSrc, archiveDest) => createArchive(
	archiver('tar', { gzip: true, gzipOptions: { level: 9 } }),
	archiveSrc,
	archiveDest
);

const createZipArchive = (archiveSrc, archiveDest) => createArchive(
	archiver('zip', { level: 9 }),
	archiveSrc,
	archiveDest
);

Promise.resolve()
	.then(() => createTarArchive(src, `${dst}.tar.gz`))
	.then(() => createZipArchive(src, `${dst}.zip`))
	.then(() => createZipArchive(path.join(src, 'es6'), path.join(src, `${name}-${version}-es6.zip`)))
	.then(() => fs.remove(path.join(src, 'es6')))
	.catch(err =>
	{
		console.log(err);
		process.exit(1);
	});
<|endoftext|>


<commit_before>let webpack = require('webpack');
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');

let distFolder = path.resolve(__dirname, 'dist');
let indexFile = path.resolve(__dirname, 'index.html');

const config = {
    entry: {
        app: './src/app.js',
        vendors: ['./node_modules/angular/angular.js']
    },
    output: {
        filename: '[name].[hash].bundle.js',
        path: distFolder
    },
    devtool: 'source-map',
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: 'babel-loader'
            },
            {
                test: /\.html$/,
                exclude: indexFile,
                loader: "ng-cache-loader?prefix=[dir]/[dir]"
            }
        ]
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendors',
            minChunks: Infinity
        }),
        new HtmlWebpackPlugin({
            template: indexFile,
            inject: 'body'
        })
    ]
};

module.exports = config;<commit_msg>Uses clean-webpack-plugin to delete dist directory when bundling<commit_after>let webpack = require('webpack');
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
let CleanWebpackPlugin = require('clean-webpack-plugin');

let distFolder = path.resolve(__dirname, 'dist');
let indexFile = path.resolve(__dirname, 'index.html');

const config = {
    entry: {
        app: './src/app.js',
        vendors: ['./node_modules/angular/angular.js']
    },
    output: {
        filename: '[name].[hash].bundle.js',
        path: distFolder
    },
    devtool: 'source-map',
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: 'babel-loader'
            },
            {
                test: /\.html$/,
                exclude: indexFile,
                loader: "ng-cache-loader?prefix=[dir]/[dir]"
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin([distFolder]),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendors',
            minChunks: Infinity
        }),
        new HtmlWebpackPlugin({
            template: indexFile,
            inject: 'body'
        })
    ]
};

module.exports = config;<|endoftext|>


<commit_before>/*! build 2014-09-01 08:09:11 */
/*! Pew.js */
/*! Copyright Francois Lajoie */
/*! MIT License */
"use strict";var Pew=function(){function a(a){var b={title:"My Project",fps:60,resources:[],vars:{}};return this.conf=Pew.utils.extend({},b,a),this.scenes={},this.layers={},this.animationFrame=new AnimationFrame(this.conf.fps),this}function b(a){var b=a||{};return this.full=b.full||!0,this.autoresize=b.autoresize||!0,this.width=b.width||"480",this.height=b.height||"320",this.canvas=b.canvas||null,this.ctx=b.ctx||null,this.init(),this}function c(a,b){return this.fn=b||function(){},function(){this._name=a,this._fid=0,this._status="idle",this.is=function(a){return this._status===a?!0:!1},this.requestAnim=function(a){var a=a||this.draw;this._fid=Pew.project().animationFrame.request(a),this._status="playing"},this.cancelAnim=function(){Pew.project().animationFrame.cancel(this._fid),this._status="idle"},this.toggleAnim=function(a){if(this.is("idle")){var a=a||this.draw;a()}else this.cancelAnim()}}.apply(this.fn),this}{var d;!function(){var a=1e3;return{get:function(){return++a}}}()}return{Project:a,Scene:c,Layer:b,project:function(){return d},createProject:function(b){return d=new a(b)}}}();Pew.Project.prototype.createLayer=function(a,b){var c=new Pew.Layer(b);return this.layers[a]=c,c},Pew.Project.prototype.start=function(a){var b=this.scenes[a].fn;b.init&&b.init(),b.draw()},Pew.Project.prototype.createScene=function(a,b){return this.scenes[a]=new Pew.Scene(a,b),this.scenes[a]},Pew.Layer.prototype.init=function(){if(null==this.canvas&&(this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),document.body.appendChild(this.canvas)),this.canvas.style.display="block",this.canvas.style.position="absolute",this.canvas.style.zIndex=this._zi.get(),this.full?this.fullscreen():(this.canvas.width=this.width,this.canvas.height=this.height),this.autoresize){window.onresize=window.onresize||function(){for(var a in Pew.project().layers)Pew.project().layers[a].autoresize&&Pew.project().layers[a].fullscreen()}}},Pew.Layer.prototype.fullscreen=function(){this.canvas.width=window.innerWidth,this.canvas.height=window.innerHeight,this.width=this.canvas.width,this.height=this.canvas.height},Pew.Layer.prototype.clear=function(a,b,c,d){var a=a||0,b=b||0,c=c||this.canvas.width,d=d||this.canvas.height;this.ctx.clearRect(a,b,c,d)},Pew.Layer.prototype._zi=function(){var a=0;return{get:function(){return++a}}}(),Pew.utils=function(){},Pew.utils.deepExtend=function(a){a=a||{};for(var b=1;b<arguments.length;b++){var c=arguments[b];if(c)for(var d in c)c.hasOwnProperty(d)&&("object"==typeof c[d]?Pew.utils.extend(a[d],c[d]):a[d]=c[d])}return a},Pew.utils.extend=function(a){a=a||{};for(var b=1;b<arguments.length;b++){var c=arguments[b];if(c)for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}return a},Pew.utils.rand=function(a,b,c){return void 0===c&&(c=1),Math.round((Math.floor(Math.random()*(b-a+1))+a)/c)*c},Pew.utils.randIndex=function(a){return a[this.rand(1,a.length)-1]},Pew.utils.range=function(a,b,c){arguments.length<=1&&(b=a||0,a=0),c=arguments[2]||1;for(var d=Math.max(Math.ceil((b-a)/c),0),e=0,f=new Array(d);d>e;)f[e++]=a,a+=c;return f},Pew.Project.prototype.mouse=function(){function a(a){for(var b=a.offsetLeft,c=a.offsetTop,d=a.offsetParent;null!==d;)b=parseInt(b)+parseInt(d.offsetLeft),c=parseInt(c)+parseInt(d.offsetTop),d=d.offsetParent;return new Array(b,c)}function b(b){var b=b||null;null!=b&&(b.addEventListener("click",function(){c.click=!0,d.click&&d.click(),c.click=!1}),b.addEventListener("dblclick",function(){c.dblclick=!0,d.dblclick&&d.dblclick(),c.dblclick=!1}),b.addEventListener("mousemove",function(c){var d=a(b);e.x=c.clientX-d[0],e.y=c.clientY-d[1]}))}var c=[],d=[],e={x:0,y:0};return{init:b,cursor:e,x:function(a){return e.x=a||e.x,e.x},y:function(a){return e.y=a||e.y,e.y},on:function(a,b){d[a]=b},off:function(a){d.splice(a,1)}}}(),Pew.Project.prototype.keyboard=function(){function a(){document.body.addEventListener("keydown",function(a){f[a.keyCode]=!0;var c=h(a,e(a.keyCode));c!==!1&&g[a.keyCode]&&(b(a.keyCode),a.preventDefault())}),document.body.addEventListener("keyup",function(a){f[a.keyCode]=!1})}function b(a){var b=c(a);g[b]&&g[b](e(b))}function c(a){if(isNaN(a)){var a=i[a.toUpperCase()]||a;isNaN(a)&&(a=a.toUpperCase().charCodeAt(0))}return a}function d(a){if(isNaN(a))return a;for(var b in i)if(i[b]==a)return b;return String.fromCharCode(a)}function e(a){return{"char":d(a).toLowerCase(),code:a}}for(var f=[],g={},h=function(){},i={SHIFT:16,TAB:9,CTRL:17,ALT:18,SPACE:32,BACKSPACE:8,ENTER:13,ESC:27,LEFT:37,RIGHT:39,UP:38,DOWN:40},j=1;13>j;++j)i["F"+j]=111+j;return{init:a,toKeyCode:c,toKeyChar:d,trigger:b,key:function(a){return a=c(a),void 0===f[a]&&(f[a]=!1),f[a]},keys:function(){var a=[];for(var b in f)0!=f[b]&&a.push(b);return a},on:function(a,b){if("[object Array]"===Object.prototype.toString.call(a))for(var d in a)g[c(a[d])]=b;else g[c(a)]=b},off:function(a){if(void 0!==a)if("[object Array]"===Object.prototype.toString.call(a))for(var b in a)delete g[c(a[b])];else delete g[c(a)];else for(var a in g)delete g[a]},onAll:function(a){h=a},offAll:function(){h=function(){}}}}(),Pew.Project.prototype.resources=function(){function a(a,b){this.url=a,this.rid=b,this.ready=!1,this.el=!1;var c=a.split(".");this.ext=1===c.length||""===c[0]&&2===c.length?"":c.pop()}function b(b,c,d){c=c||function(){},d=d||function(){},g.push(c);var h=g.length-1;b instanceof Array&&(d(e(h)),b.forEach(function(b){var e=new a(b,h);if("image"===e.type())e.el=new Image;else{if("audio"!==e.type())return;e.el=new Audio}e.onLoad(c,d),e.el.src=b,f[b]=e}))}function c(a){return f[a].el}function d(a){var b=!0;for(var c in f)f[c].ready===!1&&f[c].rid===a&&(b=!1);return b}function e(a){var b=0,c=0;for(var d in f)f[d].rid===a&&(f[d].ready===!1?++c:++b);return{total:b+c,ready:b,not_ready:c,progress:Math.round(100*b/(b+c))||0}}var f={},g=[],h={audio:["mp3","m4a","ogg","oga","webma","wav"],image:["jpg","jpeg","png","gif"]};return a.prototype.type=function(){for(property in h)for(var a in h[property])if(h[property][a]===this.ext)return property},a.prototype.onLoad=function(a,b){var c=this;this.el.addEventListener("load",function(){c.ready=!0;var f=e(c.rid);d(c.rid)?(b(f),a(),g[c.rid]=function(){}):b(f)})},{load:b,get:c}}(),Pew.Project.prototype.fpsmeter=function(){function a(a){a||(a={}),this.updateRate=a.updateRate||1e3,this._tickCounter=0,this._updateTimeoutId=null,this.current=0}var b=Date.now||function(){return(new Date).getTime()};return a.prototype.start=function(a){var c=this;return a=a||function(){},this._startTime=b(),this._tickCounter=0,this._updateTimeoutId=setTimeout(function(){c._tickCounter&&(c.current=Math.round(1e3/((b()-c._startTime)/c._tickCounter)),a(c.current)),c.start(a)},this.updateRate),this},a.prototype.stop=function(){return clearTimeout(this._updateTimeoutId),this},a.prototype.tick=function(){return++this._tickCounter,this},new a}(),function(a){function b(a){return this instanceof b?(a||(a={}),"number"==typeof a&&(a={frameRate:a}),null!=a.useNative||(a.useNative=!0),this.options=a,this.frameRate=a.frameRate||b.FRAME_RATE,this._frameLength=1e3/this.frameRate,this._isCustomFrameRate=this.frameRate!==b.FRAME_RATE,this._timeoutId=null,this._callbacks={},this._lastTickTime=0,void(this._tickCounter=0)):new b(a)}var c,d;!function(){var e,f,g=["webkit","moz","ms","o"];try{a.top.name,f=a.top}catch(h){f=a}for(c=f.requestAnimationFrame,d=f.cancelAnimationFrame||f.cancelRequestAnimationFrame,e=0;e<g.length&&!c;e++)c=f[g[e]+"RequestAnimationFrame"],d=f[g[e]+"CancelAnimationFrame"]||f[g[e]+"CancelRequestAnimationFrame"];c&&c(function(){b.hasNative=!0})}(),b.FRAME_RATE=60,b.shim=function(c){var d=new b(c);return a.requestAnimationFrame=function(a){return d.request(a)},a.cancelAnimationFrame=function(a){return d.cancel(a)},d},b.now=Date.now||function(){return(new Date).getTime()},b.navigationStart=b.now(),b.perfNow=function(){return a.performance&&a.performance.now?a.performance.now():b.now()-b.navigationStart},b.hasNative=!1,b.prototype.request=function(d){var e,f=this;if(++this._tickCounter,b.hasNative&&f.options.useNative&&!this._isCustomFrameRate)return c(d);if(!d)throw new TypeError("Not enough arguments");return null==this._timeoutId&&(e=this._frameLength+this._lastTickTime-b.now(),0>e&&(e=0),this._timeoutId=a.setTimeout(function(){var a;f._lastTickTime=b.now(),f._timeoutId=null,++f._tickCounter;for(a in f._callbacks)f._callbacks[a]&&(b.hasNative&&f.options.useNative?c(f._callbacks[a]):f._callbacks[a](b.perfNow()),delete f._callbacks[a])},e)),this._callbacks[this._tickCounter]=d,this._tickCounter},b.prototype.cancel=function(a){b.hasNative&&this.options.useNative&&d(a),delete this._callbacks[a]},"object"==typeof exports&&"object"==typeof module?module.exports=b:"function"==typeof define&&define.amd?define(function(){return b}):a.AnimationFrame=b}(window);<commit_msg>updated build<commit_after>/*! build 2014-09-01 08:09:29 */
/*! Pew.js */
/*! Copyright Francois Lajoie */
/*! MIT License */
"use strict";var Pew=function(){function a(a){var b={title:"My Project",fps:60,resources:[],vars:{}};return this.conf=Pew.utils.extend({},b,a),this.scenes={},this.layers={},this.animationFrame=new AnimationFrame(this.conf.fps),this}function b(a){var b=a||{};return this.full=b.full||!0,this.autoresize=b.autoresize||!0,this.width=b.width||"480",this.height=b.height||"320",this.canvas=b.canvas||null,this.ctx=b.ctx||null,this.init(),this}function c(a,b){return this.fn=b||function(){},function(){this._name=a,this._fid=0,this._status="idle",this.is=function(a){return this._status===a?!0:!1},this.requestAnim=function(a){var a=a||this.draw;this._fid=Pew.project().animationFrame.request(a),this._status="playing"},this.cancelAnim=function(){Pew.project().animationFrame.cancel(this._fid),this._status="idle"},this.toggleAnim=function(a){if(this.is("idle")){var a=a||this.draw;a()}else this.cancelAnim()}}.apply(this.fn),this}{var d;!function(){var a=1e3;return{get:function(){return++a}}}()}return{Project:a,Scene:c,Layer:b,project:function(){return d},createProject:function(b){return d=new a(b)}}}();Pew.Project.prototype.createLayer=function(a,b){var c=new Pew.Layer(b);return this.layers[a]=c,c},Pew.Project.prototype.start=function(a){var b=this.scenes[a].fn;b.init&&b.init(),b.draw()},Pew.Project.prototype.createScene=function(a,b){return this.scenes[a]=new Pew.Scene(a,b),this.scenes[a]},Pew.Layer.prototype.init=function(){if(null==this.canvas&&(this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),document.body.appendChild(this.canvas)),this.canvas.style.display="block",this.canvas.style.position="absolute",this.canvas.style.zIndex=this._zi.get(),this.full?this.fullscreen():(this.canvas.width=this.width,this.canvas.height=this.height),this.autoresize){window.onresize=window.onresize||function(){for(var a in Pew.project().layers)Pew.project().layers[a].autoresize&&Pew.project().layers[a].fullscreen()}}},Pew.Layer.prototype.fullscreen=function(){this.canvas.width=window.innerWidth,this.canvas.height=window.innerHeight,this.width=this.canvas.width,this.height=this.canvas.height},Pew.Layer.prototype.clear=function(a,b,c,d){var a=a||0,b=b||0,c=c||this.canvas.width,d=d||this.canvas.height;this.ctx.clearRect(a,b,c,d)},Pew.Layer.prototype._zi=function(){var a=0;return{get:function(){return++a}}}(),Pew.utils=function(){},Pew.utils.deepExtend=function(a){a=a||{};for(var b=1;b<arguments.length;b++){var c=arguments[b];if(c)for(var d in c)c.hasOwnProperty(d)&&("object"==typeof c[d]?Pew.utils.extend(a[d],c[d]):a[d]=c[d])}return a},Pew.utils.extend=function(a){a=a||{};for(var b=1;b<arguments.length;b++){var c=arguments[b];if(c)for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}return a},Pew.utils.rand=function(a,b,c){return void 0===c&&(c=1),Math.round((Math.floor(Math.random()*(b-a+1))+a)/c)*c},Pew.utils.randIndex=function(a){return a[this.rand(1,a.length)-1]},Pew.utils.range=function(a,b,c){arguments.length<=1&&(b=a||0,a=0),c=arguments[2]||1;for(var d=Math.max(Math.ceil((b-a)/c),0),e=0,f=new Array(d);d>e;)f[e++]=a,a+=c;return f},Pew.Project.prototype.mouse=function(){function a(a){for(var b=a.offsetLeft,c=a.offsetTop,d=a.offsetParent;null!==d;)b=parseInt(b)+parseInt(d.offsetLeft),c=parseInt(c)+parseInt(d.offsetTop),d=d.offsetParent;return new Array(b,c)}function b(b){var b=b||null;null!=b&&(b.addEventListener("click",function(){c.click=!0,d.click&&d.click(),c.click=!1}),b.addEventListener("dblclick",function(){c.dblclick=!0,d.dblclick&&d.dblclick(),c.dblclick=!1}),b.addEventListener("mousemove",function(c){var d=a(b);e.x=c.clientX-d[0],e.y=c.clientY-d[1]}))}var c=[],d=[],e={x:0,y:0};return{init:b,cursor:e,x:function(a){return e.x=a||e.x,e.x},y:function(a){return e.y=a||e.y,e.y},on:function(a,b){d[a]=b},off:function(a){d.splice(a,1)}}}(),Pew.Project.prototype.keyboard=function(){function a(){document.body.addEventListener("keydown",function(a){f[a.keyCode]=!0;var c=h(a,e(a.keyCode));c!==!1&&g[a.keyCode]&&(b(a.keyCode),a.preventDefault())}),document.body.addEventListener("keyup",function(a){f[a.keyCode]=!1})}function b(a){var b=c(a);g[b]&&g[b](e(b))}function c(a){if(isNaN(a)){var a=i[a.toUpperCase()]||a;isNaN(a)&&(a=a.toUpperCase().charCodeAt(0))}return a}function d(a){if(isNaN(a))return a;for(var b in i)if(i[b]==a)return b;return String.fromCharCode(a)}function e(a){return{"char":d(a).toLowerCase(),code:a}}for(var f=[],g={},h=function(){},i={SHIFT:16,TAB:9,CTRL:17,ALT:18,SPACE:32,BACKSPACE:8,ENTER:13,ESC:27,LEFT:37,RIGHT:39,UP:38,DOWN:40},j=1;13>j;++j)i["F"+j]=111+j;return{init:a,toKeyCode:c,toKeyChar:d,trigger:b,key:function(a){return a=c(a),void 0===f[a]&&(f[a]=!1),f[a]},keys:function(){var a=[];for(var b in f)0!=f[b]&&a.push(b);return a},on:function(a,b){if("[object Array]"===Object.prototype.toString.call(a))for(var d in a)g[c(a[d])]=b;else g[c(a)]=b},off:function(a){if(void 0!==a)if("[object Array]"===Object.prototype.toString.call(a))for(var b in a)delete g[c(a[b])];else delete g[c(a)];else for(var a in g)delete g[a]},onAll:function(a){h=a},offAll:function(){h=function(){}}}}(),Pew.Project.prototype.resources=function(){function a(a,b){this.url=a,this.rid=b,this.ready=!1,this.el=!1;var c=a.split(".");this.ext=1===c.length||""===c[0]&&2===c.length?"":c.pop()}function b(b,c,d){c=c||function(){},d=d||function(){},g.push(c);var h=g.length-1;b instanceof Array&&(d(e(h)),b.forEach(function(b){var e=new a(b,h);if("image"===e.type())e.el=new Image;else{if("audio"!==e.type())return;e.el=new Audio}e.onLoad(c,d),e.el.src=b,f[b]=e}))}function c(a){return f[a].el}function d(a){var b=!0;for(var c in f)f[c].ready===!1&&f[c].rid===a&&(b=!1);return b}function e(a){var b=0,c=0;for(var d in f)f[d].rid===a&&(f[d].ready===!1?++c:++b);return{total:b+c,ready:b,not_ready:c,progress:Math.round(100*b/(b+c))||0}}var f={},g=[],h={audio:["mp3","m4a","ogg","oga","webma","wav"],image:["jpg","jpeg","png","gif"]};return a.prototype.type=function(){for(property in h)for(var a in h[property])if(h[property][a]===this.ext)return property},a.prototype.onLoad=function(a,b){var c=this;this.el.addEventListener("load",function(){c.ready=!0;var f=e(c.rid);d(c.rid)?(b(f),a(),g[c.rid]=function(){}):b(f)})},{load:b,get:c}}(),Pew.Project.prototype.fpsmeter=function(){function a(a){a||(a={}),this.updateRate=a.updateRate||1e3,this._tickCounter=0,this._updateTimeoutId=null,this.current=0}var b=Date.now||function(){return(new Date).getTime()};return a.prototype.start=function(a){var c=this;return a=a||function(){},this._startTime=b(),this._tickCounter=0,this._updateTimeoutId=setTimeout(function(){c._tickCounter&&(c.current=Math.round(1e3/((b()-c._startTime)/c._tickCounter)),a(c.current)),c.start(a)},this.updateRate),this},a.prototype.stop=function(){return clearTimeout(this._updateTimeoutId),this},a.prototype.tick=function(){return++this._tickCounter,this},new a}(),function(a){function b(a){return this instanceof b?(a||(a={}),"number"==typeof a&&(a={frameRate:a}),null!=a.useNative||(a.useNative=!0),this.options=a,this.frameRate=a.frameRate||b.FRAME_RATE,this._frameLength=1e3/this.frameRate,this._isCustomFrameRate=this.frameRate!==b.FRAME_RATE,this._timeoutId=null,this._callbacks={},this._lastTickTime=0,void(this._tickCounter=0)):new b(a)}var c,d;!function(){var e,f,g=["webkit","moz","ms","o"];try{a.top.name,f=a.top}catch(h){f=a}for(c=f.requestAnimationFrame,d=f.cancelAnimationFrame||f.cancelRequestAnimationFrame,e=0;e<g.length&&!c;e++)c=f[g[e]+"RequestAnimationFrame"],d=f[g[e]+"CancelAnimationFrame"]||f[g[e]+"CancelRequestAnimationFrame"];c&&c(function(){b.hasNative=!0})}(),b.FRAME_RATE=60,b.shim=function(c){var d=new b(c);return a.requestAnimationFrame=function(a){return d.request(a)},a.cancelAnimationFrame=function(a){return d.cancel(a)},d},b.now=Date.now||function(){return(new Date).getTime()},b.navigationStart=b.now(),b.perfNow=function(){return a.performance&&a.performance.now?a.performance.now():b.now()-b.navigationStart},b.hasNative=!1,b.prototype.request=function(d){var e,f=this;if(++this._tickCounter,b.hasNative&&f.options.useNative&&!this._isCustomFrameRate)return c(d);if(!d)throw new TypeError("Not enough arguments");return null==this._timeoutId&&(e=this._frameLength+this._lastTickTime-b.now(),0>e&&(e=0),this._timeoutId=a.setTimeout(function(){var a;f._lastTickTime=b.now(),f._timeoutId=null,++f._tickCounter;for(a in f._callbacks)f._callbacks[a]&&(b.hasNative&&f.options.useNative?c(f._callbacks[a]):f._callbacks[a](b.perfNow()),delete f._callbacks[a])},e)),this._callbacks[this._tickCounter]=d,this._tickCounter},b.prototype.cancel=function(a){b.hasNative&&this.options.useNative&&d(a),delete this._callbacks[a]},"object"==typeof exports&&"object"==typeof module?module.exports=b:"function"==typeof define&&define.amd?define(function(){return b}):a.AnimationFrame=b}(window);<|endoftext|>