<commit_before>var FS, Path, $, Client, TreeView, AddDialog, MoveDialog;

module.exports = {
	configDefaults: {
		hideLocalWhenDisplayed: false
	},

	treeView: null,
	client: null,

	activate: function (state) {
		if (!atom.project || !atom.project.path)
			return;

		var self = this;

		if (!FS) {
			FS = require('fs-plus');
			Path = require('path');
			$ = require('atom').$;

			Client = require('./client');
			TreeView = require('./views/tree-view');
		}

		atom.project.remoteftp = new Client();

		self.treeView = new TreeView();
		self.treeView.detach();
		setTimeout(function () {
			self.treeView.attach();
			self.treeView.hide();
		}, 1);

		FS.exists(atom.project.resolve('.ftpconfig'), function (exists) {
			if (exists)
				self.treeView.show();
		});

		atom.commands.add('atom-workspace', {

			'remote-ftp:create-ftp-config': function () {
				FS.writeFile(atom.project.resolve('.ftpconfig'), '{\n\
    "protocol": "ftp",\n\
	"host": "example.com",\n\
    "port": 21,\n\
    "user": "user",\n\
    "pass": "pass",\n\
    "remote": "/",\n\
    "secure": false,\n\
    "secureOptions": null,\n\
    "connTimeout": 10000,\n\
    "pasvTimeout": 10000,\n\
    "keepalive": 10000\n\
}'			, function (err) {
					if (!err)
						atom.workspace.open(atom.project.resolve('.ftpconfig'));
				});
			},

			'remote-ftp:create-sftp-config': function () {
				FS.writeFile(atom.project.resolve('.ftpconfig'), '{\n\
    "protocol": "sftp",\n\
	"host": "example.com",\n\
    "port": 22,\n\
    "user": "user",\n\
    "pass": "pass",\n\
    "remote": "/",\n\
	"agent": "",\n\
    "privatekey": "",\n\
	"passphrase": "",\n\
	"hosthash": "",\n\
	"ignorehost": true,\n\
	"connTimeout": 10000,\n\
	"keepalive": 10000\n\
}'			, function (err) {
					if (!err)
						atom.workspace.open(atom.project.resolve('.ftpconfig'));
				});
			},

			'remote-ftp:toggle': function () {
	            self.treeView.toggle();
	        },

	        'remote-ftp:connect': function () {
	            atom.project.remoteftp.readConfig(function (e) {
	                if (e) {
						throw "Could not read `.ftpconfig` file";
	                    return;
	                }
	                atom.project.remoteftp.connect();
	            });
	        },

	        'remote-ftp:disconnect': function () {
	            atom.project.remoteftp.disconnect();
	        },

	        'remote-ftp:add-file': function () {
	            var remotes = self.treeView.getSelected();

	            if (!AddDialog)
	                AddDialog = require('./dialogs/add-dialog');

	            var dialog = new AddDialog('');
	    		dialog.on('new-path', function (e, name) {
					dialog.close();

	                var remote = Path.join(remotes[0].remote, name).replace(/\\/g, '/');

	                atom.project.remoteftp.mkdir(remotes[0].remote, true, function (err) {
	                    atom.project.remoteftp.mkfile(remote, function (err) {

	                        remotes[0].open();

	                        if (!err)
	                            atom.workspace.open(atom.project.remoteftp.toLocal(remote));
	                    })
	                });
	    		});
	            dialog.attach();
	        },

	        'remote-ftp:add-folder': function () {
	            var remotes = self.treeView.getSelected();

	            if (!AddDialog)
	                AddDialog = require('./dialogs/add-dialog');

	            var dialog = new AddDialog('');
	            dialog.on('new-path', function (e, name) {
	                var remote = Path.join(remotes[0].remote, name).replace(/\\/g, '/');

	                atom.project.remoteftp.mkdir(remote, true, function (err) {
	                    dialog.close();

	                    remotes[0].open();
	                })
	            });
	            dialog.attach();
	        },

	        'remote-ftp:refresh-selected': function () {
	            var remotes = self.treeView.getSelected();

	            remotes.forEach(function (remote) {
	                remote.open();
	            });
	        },

	        'remote-ftp:move-selected': function () {
	            var remotes = self.treeView.getSelected();

	            if (!MoveDialog)
	                MoveDialog = require('./dialogs/move-dialog');

	            var dialog = new MoveDialog(remotes[0].remote);
	    		dialog.on('path-changed', function (e, newremote) {
	    			atom.project.remoteftp.rename(remotes[0].remote, newremote, function (error) {

	    				if (error) {
	    					dialog.close();
	    					return;
						}

	                    remotes[0].destroy();
	                    var parent = atom.project.remoteftp.resolve(Path.dirname(newremote).replace(/\\/g, '/'));
	                    if (parent)
	                        parent.open();
	    			});
	    		});
	    		dialog.attach();
	        },

	        'remote-ftp:delete-selected': function () {
	            var remotes = self.treeView.getSelected();

	            atom.confirm({
	    			message: "Are you sure you want to delete the selected item?",
	    			detailedMessage: "You are deleting:"+ remotes.map(function (item) { return "\n  " + item.remote; }),
	                buttons: {
	    				"Move to Trash": function () {
	    					remotes.forEach(function (item) {
	                             if (!item) return;

	                             atom.project.remoteftp.delete(item.remote, true, function (err, list) {
	                                 if (list)
	                                     list.forEach(function (item) {
	                                         var dir = Path.dirname(item.name).replace(/\\/g, '/'),
	                                             parent = atom.project.remoteftp.resolve(dir);

	                                         if (parent)
	                                             parent.open();
	                                     });
	                             });
	                         });
	    				},
	    				"Cancel": null
	    			}
	    		});
	        },

	       'remote-ftp:download-selected': function () {
	            var remotes = self.treeView.getSelected();

	            remotes.forEach(function (item) {
	                if (!item) return;

	                atom.project.remoteftp.download(item.remote, true, function (err) {

	                })
	            })
	        },

	        'remote-ftp:upload-selected': function () {
	            var locals = $('.tree-view .selected').map(function () {
	                return this.getPath ? this.getPath() : '';
	            }).get();

	            locals.forEach(function (local) {
	                if (!local) return;

	                atom.project.remoteftp.upload(local, function (err, list) {
						// TODO refresh parent ?
	                    /*if (list) {
	                        list.forEach(function (item) {
	                            var remote = atom.project.remoteftp.toRemote(item.name),
	                                dir = Path.join(remote, '..').replace(/\\/g, '/'),
	                                parent = atom.project.remoteftp.resolve(dir);

	                            if (parent)
	                                parent.open();
	                        });
						}*/
	                });
	            });
	        },

			'remote-ftp:abort-current': function () {
				atom.project.remoteftp.abort();
			}

		})

		atom.workspace.eachEditor(function (ed) {
			var buffer = ed.buffer;
			buffer.on('saved', self.fileSaved.bind(self));
		});
	},

	deactivate: function () {
		var self = this;
		atom.workspace.eachEditor(function (ed) {
			var buffer = ed.buffer;
			buffer.off('saved', self.fileSaved);
		});

		atom.project.remoteftp.disconnect();
	},

	fileSaved: function (text) {
		var self = this;

		//if (!atom.project.remoteftp.isConnected())
		//	return;

		var local = text.file.path;

		if (!atom.project.contains(local))
			return;

		if (local == atom.project.resolve('.ftpconfig'))
			return;

		atom.project.remoteftp.upload(local, function (err) {
			try {
				var remote = atom.project.remoteftp.toRemote(local),
					parent = atom.project.remoteftp.resolve(Path.dirname(remote).replace(/\\/g, '/'));
				if (parent)
					parent.open();
			} catch (e) {}
		});
	}
}
<commit_msg>fix #21<commit_after>var FS, Path, $, Client, TreeView, AddDialog, MoveDialog;

function hasProject () {
	return atom.project.path !== undefined;
}

function isConnected () {
	return atom.project.remoteftp ? atom.project.remoteftp.isConnected() : false;
}

module.exports = {
	configDefaults: {
		hideLocalWhenDisplayed: false
	},

	treeView: null,
	client: null,

	activate: function (state) {
		var self = this;

		//if (!atom.project || !atom.project.path)
		//	return;

		if (!FS) {
			FS = require('fs-plus');
			Path = require('path');
			$ = require('atom').$;

			Client = require('./client');
			TreeView = require('./views/tree-view');
		}

		atom.project.remoteftp = new Client();

		self.treeView = new TreeView();
		self.treeView.detach();
		setTimeout(function () {
			self.treeView.attach();
			self.treeView.hide();
		}, 1);

		if (hasProject()) {
			FS.exists(atom.project.resolve('.ftpconfig'), function (exists) {
				if (exists)
					self.treeView.show();
			});
		}

		atom.commands.add('atom-workspace', {

			'remote-ftp:create-ftp-config': function () {
				if (!hasProject()) return;

				FS.writeFile(atom.project.resolve('.ftpconfig'), '{\n\
    "protocol": "ftp",\n\
	"host": "example.com",\n\
    "port": 21,\n\
    "user": "user",\n\
    "pass": "pass",\n\
    "remote": "/",\n\
    "secure": false,\n\
    "secureOptions": null,\n\
    "connTimeout": 10000,\n\
    "pasvTimeout": 10000,\n\
    "keepalive": 10000\n\
}'			, function (err) {
					if (!err)
						atom.workspace.open(atom.project.resolve('.ftpconfig'));
				});
			},

			'remote-ftp:create-sftp-config': function () {
				if (!hasProject()) return;

				FS.writeFile(atom.project.resolve('.ftpconfig'), '{\n\
    "protocol": "sftp",\n\
	"host": "example.com",\n\
    "port": 22,\n\
    "user": "user",\n\
    "pass": "pass",\n\
    "remote": "/",\n\
	"agent": "",\n\
    "privatekey": "",\n\
	"passphrase": "",\n\
	"hosthash": "",\n\
	"ignorehost": true,\n\
	"connTimeout": 10000,\n\
	"keepalive": 10000\n\
}'			, function (err) {
					if (!err)
						atom.workspace.open(atom.project.resolve('.ftpconfig'));
				});
			},

			'remote-ftp:toggle': function () {
				if (!hasProject()) return;

	            self.treeView.toggle();
	        },

	        'remote-ftp:connect': function () {
				if (!hasProject()) return;

	            atom.project.remoteftp.readConfig(function (e) {
	                if (e) {
						throw "Could not read `.ftpconfig` file";
	                    return;
	                }
	                atom.project.remoteftp.connect();
	            });
	        },

	        'remote-ftp:disconnect': function () {
				if (!hasProject()) return;

	            atom.project.remoteftp.disconnect();
	        },

	        'remote-ftp:add-file': function () {
				if (!hasProject() || !isConnected()) return;

	            var remotes = self.treeView.getSelected();

	            if (!AddDialog)
	                AddDialog = require('./dialogs/add-dialog');

	            var dialog = new AddDialog('');
	    		dialog.on('new-path', function (e, name) {
					dialog.close();

	                var remote = Path.join(remotes[0].remote, name).replace(/\\/g, '/');

	                atom.project.remoteftp.mkdir(remotes[0].remote, true, function (err) {
	                    atom.project.remoteftp.mkfile(remote, function (err) {

	                        remotes[0].open();

	                        if (!err)
	                            atom.workspace.open(atom.project.remoteftp.toLocal(remote));
	                    })
	                });
	    		});
	            dialog.attach();
	        },

	        'remote-ftp:add-folder': function () {
				if (!hasProject() || !isConnected()) return;

	            var remotes = self.treeView.getSelected();

	            if (!AddDialog)
	                AddDialog = require('./dialogs/add-dialog');

	            var dialog = new AddDialog('');
	            dialog.on('new-path', function (e, name) {
	                var remote = Path.join(remotes[0].remote, name).replace(/\\/g, '/');

	                atom.project.remoteftp.mkdir(remote, true, function (err) {
	                    dialog.close();

	                    remotes[0].open();
	                })
	            });
	            dialog.attach();
	        },

	        'remote-ftp:refresh-selected': function () {
				if (!hasProject() || !isConnected()) return;

	            var remotes = self.treeView.getSelected();

	            remotes.forEach(function (remote) {
	                remote.open();
	            });
	        },

	        'remote-ftp:move-selected': function () {
				if (!hasProject() || !isConnected()) return;

	            var remotes = self.treeView.getSelected();

	            if (!MoveDialog)
	                MoveDialog = require('./dialogs/move-dialog');

	            var dialog = new MoveDialog(remotes[0].remote);
	    		dialog.on('path-changed', function (e, newremote) {
	    			atom.project.remoteftp.rename(remotes[0].remote, newremote, function (error) {

	    				if (error) {
	    					dialog.close();
	    					return;
						}

	                    remotes[0].destroy();
	                    var parent = atom.project.remoteftp.resolve(Path.dirname(newremote).replace(/\\/g, '/'));
	                    if (parent)
	                        parent.open();
	    			});
	    		});
	    		dialog.attach();
	        },

	        'remote-ftp:delete-selected': function () {
				if (!hasProject() || !isConnected()) return;

	            var remotes = self.treeView.getSelected();

	            atom.confirm({
	    			message: "Are you sure you want to delete the selected item?",
	    			detailedMessage: "You are deleting:"+ remotes.map(function (item) { return "\n  " + item.remote; }),
	                buttons: {
	    				"Move to Trash": function () {
	    					remotes.forEach(function (item) {
	                             if (!item) return;

	                             atom.project.remoteftp.delete(item.remote, true, function (err, list) {
	                                 if (list)
	                                     list.forEach(function (item) {
	                                         var dir = Path.dirname(item.name).replace(/\\/g, '/'),
	                                             parent = atom.project.remoteftp.resolve(dir);

	                                         if (parent)
	                                             parent.open();
	                                     });
	                             });
	                         });
	    				},
	    				"Cancel": null
	    			}
	    		});
	        },

	       'remote-ftp:download-selected': function () {
				if (!hasProject() || !isConnected()) return;

	            var remotes = self.treeView.getSelected();

	            remotes.forEach(function (item) {
	                if (!item) return;

	                atom.project.remoteftp.download(item.remote, true, function (err) {

	                })
	            })
	        },

	        'remote-ftp:upload-selected': function () {
				if (!hasProject() || !isConnected()) return;

	            var locals = $('.tree-view .selected').map(function () {
	                return this.getPath ? this.getPath() : '';
	            }).get();

	            locals.forEach(function (local) {
	                if (!local) return;

	                atom.project.remoteftp.upload(local, function (err, list) {
						// TODO refresh parent ?
	                    /*if (list) {
	                        list.forEach(function (item) {
	                            var remote = atom.project.remoteftp.toRemote(item.name),
	                                dir = Path.join(remote, '..').replace(/\\/g, '/'),
	                                parent = atom.project.remoteftp.resolve(dir);

	                            if (parent)
	                                parent.open();
	                        });
						}*/
	                });
	            });
	        },

			'remote-ftp:abort-current': function () {
				if (!hasProject()) return;

				atom.project.remoteftp.abort();
			}

		})

		atom.workspace.eachEditor(function (ed) {
			var buffer = ed.buffer;
			buffer.on('saved', self.fileSaved.bind(self));
		});
	},

	deactivate: function () {
		var self = this;
		atom.workspace.eachEditor(function (ed) {
			var buffer = ed.buffer;
			buffer.off('saved', self.fileSaved);
		});

		if (atom.project.remoteftp)
			atom.project.remoteftp.disconnect();
	},

	fileSaved: function (text) {
		if (!hasProject() || !isConnected()) return;

		var self = this;

		//if (!atom.project.remoteftp.isConnected())
		//	return;

		var local = text.file.path;

		if (!atom.project.contains(local))
			return;

		if (local == atom.project.resolve('.ftpconfig'))
			return;

		atom.project.remoteftp.upload(local, function (err) {
			try {
				var remote = atom.project.remoteftp.toRemote(local),
					parent = atom.project.remoteftp.resolve(Path.dirname(remote).replace(/\\/g, '/'));
				if (parent)
					parent.open();
			} catch (e) {}
		});
	}
}
<|endoftext|>


<commit_before>const path = require('path');
const childProcess = require('child_process');
const fsp = require('./fs-promise');
const promiseify = require('./promiseify');
const exec = promiseify(childProcess.exec);

const GET_REVISION = Symbol('GET_REVISION');
const GET_STORAGE = Symbol('GET_STORAGE');
const READ_FILE = Symbol('READ_FILE');

class Repository {

    /**
     * 仓库的变更观察者
     * @param   {string}    storagePath 版本记录文件地址
     * @param   {string}    type        仓库类型，支持 git 与 svn
     * @param   {string}    tableName   记录版本数据的字段前缀
     */
    constructor(storagePath, type = 'git', tableName = 'revision') {
        this.storagePath = storagePath;
        this.type = type.toLowerCase();
        this.tableName = tableName;
        this.dirname = path.dirname(storagePath);
        this.cache = {};
        this.storage = this[GET_STORAGE]();
    }

    getOldCommitId(target) {
        return this.storage.then(storage => storage[this.tableName][target]);
    }

    getNewCommitId(target) {
        let commitId = this.cache[target];
        if (commitId) {
            return Promise.resolve(commitId);
        } else {
            return this[GET_REVISION](target).then(commitId => {
                this.cache[target] = commitId;
                return commitId;
            });
        }
    }

    /**
     * 对比版本更改
     * @param   {string} target   目标
     * @return {Promise}
     */
    watch(target) {
        return Promise.all([this.getNewCommitId(target), this.getOldCommitId(target)]);
    }

    /**
     * 保存新的 git commit 到文件
     */
    save() {
        // 读取最新本地存储再写入，避免产生意外覆盖数据
        return this[READ_FILE]().then(data => {

            // 合并本地数据写入
            Object.assign(data[this.tableName], this.cache);

            // 将绝对路径转换为相对路径存储
            Object.keys(data[this.tableName]).forEach(target => {
                if (path.isAbsolute(target)) {
                    let commitId = data[this.tableName][target];
                    let relativePath = path.relative(this.dirname, target);
                    data[this.tableName][relativePath] = commitId;
                    delete data[this.tableName][target];
                }
            });
            return data;
        }).then(data => {
            let content = JSON.stringify(data, null, 2);
            return fsp.writeFile(this.storagePath, content, 'utf8');
        });
    }

    // 获取处理后的本地缓存
    [GET_STORAGE]() {
        return this[READ_FILE]().then(data => {

            // 将相对路径转换为绝对路径进行内部运算
            Object.keys(data[this.tableName]).forEach(target => {
                if (!path.isAbsolute(target)) {
                    let commitId = data[this.tableName][target];
                    let resolvePath = path.resolve(this.dirname, target);
                    data[this.tableName][resolvePath] = commitId;
                    delete data[this.tableName][target];
                }
            });

            return data;
        });
    }

    // 读取原始本地存储文件
    [READ_FILE]() {
        return fsp.readFile(this.storagePath, 'utf8')
            .then(json => JSON.parse(json))
            .catch(() => Promise.resolve({}))
            .then(data => {
                if (typeof data[this.tableName] !== 'object') {
                    data[this.tableName] = {};
                }
                return data;
            });
    }

    // 获取目标的修订 ID
    [GET_REVISION](target) {
        let type = this.type;
        let cwd = path.dirname(target);
        let basename = path.basename(target);
        let cmd;
        let runner;

        if (type === 'git') {
            cmd = `git log --pretty=format:"%h" -1 -- ${basename}`;
            runner = exec(cmd, {
                cwd
            }).then(stdout => stdout.toString().trim());
        } else if (type === 'svn') {
            cmd = `svn log --limit 1 --xml ${basename}`;
            runner = exec(cmd, {
                cwd
            }).then(stdout => {
                stdout = stdout.toString().trim();
                stdout = stdout.match(/revision="([^"]*?)"/)[1];
                return stdout;
            });
        } else {
            runner = Promise.reject(`does not support "${type}".`);
        }

        runner.catch(errors => {
            console.error(`"${target}": the file is not in the repository.`);
            return Promise.reject(errors);
        });

        return runner;
    }

}

module.exports = Repository;<commit_msg>Encode parameters<commit_after>const path = require('path');
const childProcess = require('child_process');
const fsp = require('./fs-promise');
const promiseify = require('./promiseify');
const exec = promiseify(childProcess.exec);

const GET_REVISION = Symbol('GET_REVISION');
const GET_STORAGE = Symbol('GET_STORAGE');
const READ_FILE = Symbol('READ_FILE');

class Repository {

    /**
     * 仓库的变更观察者
     * @param   {string}    storagePath 版本记录文件地址
     * @param   {string}    type        仓库类型，支持 git 与 svn
     * @param   {string}    tableName   记录版本数据的字段前缀
     */
    constructor(storagePath, type = 'git', tableName = 'revision') {
        this.storagePath = storagePath;
        this.type = type.toLowerCase();
        this.tableName = tableName;
        this.dirname = path.dirname(storagePath);
        this.cache = {};
        this.storage = this[GET_STORAGE]();
    }

    getOldCommitId(target) {
        return this.storage.then(storage => storage[this.tableName][target]);
    }

    getNewCommitId(target) {
        let commitId = this.cache[target];
        if (commitId) {
            return Promise.resolve(commitId);
        } else {
            return this[GET_REVISION](target).then(commitId => {
                this.cache[target] = commitId;
                return commitId;
            });
        }
    }

    /**
     * 对比版本更改
     * @param   {string} target   目标
     * @return {Promise}
     */
    watch(target) {
        return Promise.all([this.getNewCommitId(target), this.getOldCommitId(target)]);
    }

    /**
     * 保存新的 git commit 到文件
     */
    save() {
        // 读取最新本地存储再写入，避免产生意外覆盖数据
        return this[READ_FILE]().then(data => {

            // 合并本地数据写入
            Object.assign(data[this.tableName], this.cache);

            // 将绝对路径转换为相对路径存储
            Object.keys(data[this.tableName]).forEach(target => {
                if (path.isAbsolute(target)) {
                    let commitId = data[this.tableName][target];
                    let relativePath = path.relative(this.dirname, target);
                    data[this.tableName][relativePath] = commitId;
                    delete data[this.tableName][target];
                }
            });
            return data;
        }).then(data => {
            let content = JSON.stringify(data, null, 2);
            return fsp.writeFile(this.storagePath, content, 'utf8');
        });
    }

    // 获取处理后的本地缓存
    [GET_STORAGE]() {
        return this[READ_FILE]().then(data => {

            // 将相对路径转换为绝对路径进行内部运算
            Object.keys(data[this.tableName]).forEach(target => {
                if (!path.isAbsolute(target)) {
                    let commitId = data[this.tableName][target];
                    let resolvePath = path.resolve(this.dirname, target);
                    data[this.tableName][resolvePath] = commitId;
                    delete data[this.tableName][target];
                }
            });

            return data;
        });
    }

    // 读取原始本地存储文件
    [READ_FILE]() {
        return fsp.readFile(this.storagePath, 'utf8')
            .then(json => JSON.parse(json))
            .catch(() => Promise.resolve({}))
            .then(data => {
                if (typeof data[this.tableName] !== 'object') {
                    data[this.tableName] = {};
                }
                return data;
            });
    }

    // 获取目标的修订 ID
    [GET_REVISION](target) {
        let type = this.type;
        let cwd = path.dirname(target);
        let basename = path.basename(target);
        let cmd;
        let runner;

        if (type === 'git') {
            cmd = `git log --pretty=format:"%h" -1 -- ${JSON.stringify(basename)}`;
            runner = exec(cmd, {
                cwd
            }).then(stdout => stdout.toString().trim());
        } else if (type === 'svn') {
            cmd = `svn log --limit 1 --xml ${JSON.stringify(basename)}`;
            runner = exec(cmd, {
                cwd
            }).then(stdout => {
                stdout = stdout.toString().trim();
                stdout = stdout.match(/revision="([^"]*?)"/)[1];
                return stdout;
            });
        } else {
            runner = Promise.reject(`does not support "${type}".`);
        }

        runner.catch(errors => {
            console.error(`"${target}": the file is not in the repository.`);
            return Promise.reject(errors);
        });

        return runner;
    }

}

module.exports = Repository;<|endoftext|>


<commit_before>import React, { Component } from 'react'

class VoiceRecognition extends Component {
  constructor (props) {
    super(props)

    const SpeechRecognition = window.SpeechRecognition
      || window.webkitSpeechRecognition
      || window.mozSpeechRecognition
      || window.msSpeechRecognition
      || window.oSpeechRecognition

    if (SpeechRecognition != null) {
      this.recognition = this.createRecognition(SpeechRecognition)
    }
  }

  createRecognition = (SpeechRecognition) => {
    const defaults = {
      continuous: true,
      interimResults: false,
      lang: 'en-US'
    }

    const options = Object.assign({}, defaults, this.props)

    let recognition = new SpeechRecognition()

    recognition.continuous = options.continuous
    recognition.interimResults = options.interimResults
    recognition.lang = options.lang

    return recognition
  }

  bindResult = (event) => {
    let interimTranscript
    let finalTranscript

    for (let i = e.resultIndex; i < e.results.length; ++i) {
      if (event.results[i].isFinal) {
        finalTranscript += event.results[i][0].transcript
      } else {
        interimTranscript += event.results[i][0].transcript
      }
    }

    this.props.onResult({ interimTranscript, finalTranscript })
  }

  start = () => {
    this.recognition.start()
  }

  stop = () => {
    this.recognition.stop()
  }

  abort = () => {
    this.recognition.abort()
  }

  componentDidMount () {
    const events = [
      { name: 'start', action: this.props.onStart },
      { name: 'end', action: this.props.onEnd },
      { name: 'error', action: this.props.onError }
    ]

    events.forEach(event => {
      this.recognition.addEventListener(event.name, event.action)
    })

    this.recognition.addEventListener('result', this.bindResult)
  }

  componentWillUnmount () {
    this.abort()
  }

  render () {
    return null
  }
}

export default VoiceRecognition

<commit_msg>Start voice recognition<commit_after>import React, { Component } from 'react'

class VoiceRecognition extends Component {
  constructor (props) {
    super(props)

    const SpeechRecognition = window.SpeechRecognition
      || window.webkitSpeechRecognition
      || window.mozSpeechRecognition
      || window.msSpeechRecognition
      || window.oSpeechRecognition

    if (SpeechRecognition != null) {
      this.recognition = this.createRecognition(SpeechRecognition)
    }
  }

  createRecognition = (SpeechRecognition) => {
    const defaults = {
      continuous: true,
      interimResults: false,
      lang: 'en-US'
    }

    const options = Object.assign({}, defaults, this.props)

    let recognition = new SpeechRecognition()

    recognition.continuous = options.continuous
    recognition.interimResults = options.interimResults
    recognition.lang = options.lang

    return recognition
  }

  bindResult = (event) => {
    let interimTranscript = ''
    let finalTranscript = ''

    for (let i = event.resultIndex; i < event.results.length; ++i) {
      if (event.results[i].isFinal) {
        finalTranscript += event.results[i][0].transcript
      } else {
        interimTranscript += event.results[i][0].transcript
      }
    }

    this.props.onResult({ interimTranscript, finalTranscript })
  }

  start = () => {
    this.recognition.start()
  }

  stop = () => {
    this.recognition.stop()
  }

  abort = () => {
    this.recognition.abort()
  }

  componentDidMount () {
    const events = [
      { name: 'start', action: this.props.onStart },
      { name: 'end', action: this.props.onEnd },
      { name: 'error', action: this.props.onError }
    ]

    events.forEach(event => {
      this.recognition.addEventListener(event.name, event.action)
    })

    this.recognition.addEventListener('result', this.bindResult)

    this.start()
  }

  componentWillUnmount () {
    this.abort()
  }

  render () {
    return null
  }
}

export default VoiceRecognition

<|endoftext|>


<commit_before>const
  appPaths = require('../../app-paths'),
  PwaManifestPlugin = require('./plugin.pwa-manifest')

module.exports = function (chain, cfg) {
  // write manifest.json file
  chain.plugin('pwa-manifest')
    .use(PwaManifestPlugin, [ cfg ])

  let defaultOptions
  const
    WorkboxPlugin = require('workbox-webpack-plugin'),
    pluginMode = cfg.pwa.workboxPluginMode,
    log = require('../../helpers/logger')('app:workbox')

  if (pluginMode === 'GenerateSW') {
    const pkg = require(appPaths.resolve.app('package.json'))

    defaultOptions = {
      cacheId: pkg.name || 'quasar-pwa-app'
    }

    log('[GenerateSW] Will generate a service-worker file. Ignoring your custom written one.')
  }
  else {
    defaultOptions = {
      swSrc: appPaths.resolve.app(cfg.sourceFiles.serviceWorker)
    }

    log('[InjectManifest] Using your custom service-worker written file')
  }

  let opts = Object.assign(
    defaultOptions,
    cfg.pwa.workboxOptions
  )

  if (cfg.ctx.mode.ssr) {
    if (!opts.directoryIndex) {
      opts.directoryIndex = '/'
    }

    // if Object form:
    if (cfg.ssr.pwa && cfg.ssr.pwa !== true) {
      const merge = require('webpack-merge')
      opts = merge(opts, cfg.ssr.pwa)
    }

    if (pluginMode === 'GenerateSW') {
      opts.runtimeCaching = opts.runtimeCaching || []
      if (!opts.runtimeCaching.find(entry => entry.urlPattern === '/')) {
        opts.runtimeCaching.unshift({
          urlPattern: '/',
          handler: 'networkFirst'
        })
      }
    }
  }

  if (cfg.ctx.dev) {
    log('⚠  Forcing PWA into the network-first approach to not break Hot Module Replacement while developing.')
    // forcing network-first strategy
    opts.chunks = [ 'quasar-bogus-chunk' ]
    if (opts.excludeChunks) {
      delete opts.excludeChunks
    }

    if (pluginMode === 'GenerateSW') {
      opts.runtimeCaching = opts.runtimeCaching || []
      opts.runtimeCaching.push({
        urlPattern: /^http/,
        handler: 'networkFirst'
      })
    }
  }

  opts.swDest = 'service-worker.js'

  console.log('finalOptions', opts)

  chain.plugin('workbox')
    .use(WorkboxPlugin[pluginMode], [ opts ])

  if (!cfg.ctx.mode.ssr) {
    const HtmlPwaPlugin = require('./plugin.html-pwa').plugin
    chain.plugin('html-pwa')
      .use(HtmlPwaPlugin, [ cfg ])
  }
}
<commit_msg>chore: Remove debugging statement<commit_after>const
  appPaths = require('../../app-paths'),
  PwaManifestPlugin = require('./plugin.pwa-manifest')

module.exports = function (chain, cfg) {
  // write manifest.json file
  chain.plugin('pwa-manifest')
    .use(PwaManifestPlugin, [ cfg ])

  let defaultOptions
  const
    WorkboxPlugin = require('workbox-webpack-plugin'),
    pluginMode = cfg.pwa.workboxPluginMode,
    log = require('../../helpers/logger')('app:workbox')

  if (pluginMode === 'GenerateSW') {
    const pkg = require(appPaths.resolve.app('package.json'))

    defaultOptions = {
      cacheId: pkg.name || 'quasar-pwa-app'
    }

    log('[GenerateSW] Will generate a service-worker file. Ignoring your custom written one.')
  }
  else {
    defaultOptions = {
      swSrc: appPaths.resolve.app(cfg.sourceFiles.serviceWorker)
    }

    log('[InjectManifest] Using your custom service-worker written file')
  }

  let opts = Object.assign(
    defaultOptions,
    cfg.pwa.workboxOptions
  )

  if (cfg.ctx.mode.ssr) {
    if (!opts.directoryIndex) {
      opts.directoryIndex = '/'
    }

    // if Object form:
    if (cfg.ssr.pwa && cfg.ssr.pwa !== true) {
      const merge = require('webpack-merge')
      opts = merge(opts, cfg.ssr.pwa)
    }

    if (pluginMode === 'GenerateSW') {
      opts.runtimeCaching = opts.runtimeCaching || []
      if (!opts.runtimeCaching.find(entry => entry.urlPattern === '/')) {
        opts.runtimeCaching.unshift({
          urlPattern: '/',
          handler: 'networkFirst'
        })
      }
    }
  }

  if (cfg.ctx.dev) {
    log('⚠  Forcing PWA into the network-first approach to not break Hot Module Replacement while developing.')
    // forcing network-first strategy
    opts.chunks = [ 'quasar-bogus-chunk' ]
    if (opts.excludeChunks) {
      delete opts.excludeChunks
    }

    if (pluginMode === 'GenerateSW') {
      opts.runtimeCaching = opts.runtimeCaching || []
      opts.runtimeCaching.push({
        urlPattern: /^http/,
        handler: 'networkFirst'
      })
    }
  }

  opts.swDest = 'service-worker.js'

  chain.plugin('workbox')
    .use(WorkboxPlugin[pluginMode], [ opts ])

  if (!cfg.ctx.mode.ssr) {
    const HtmlPwaPlugin = require('./plugin.html-pwa').plugin
    chain.plugin('html-pwa')
      .use(HtmlPwaPlugin, [ cfg ])
  }
}
<|endoftext|>


<commit_before>var net = require('net');
var fs = require('fs');
var http = require('http');
var path = require('path');
var rules = require('./index');
var util = require('../util');
var config = require('../config');
var Storage = require('./storage');
var ROOT = config.DATA_DIR;
var rulesStorage = new Storage(path.join(ROOT, 'rules'));
var valuesStorage = new Storage(path.join(ROOT, 'values'));
var propertiesStorage = new Storage(path.join(ROOT, 'properties'));
var system = require('./system');
var oldData = require('./old-data');
var filter;

function setFilter(text) {
	if (!text || typeof text != 'string') {
		text = '';
	}
	text = text.substring(0, 128);
	propertiesStorage.setProperty('filterText', text);
	filter = util.toRegExp(text) || text;
}

exports.setFilter = setFilter;

setFilter(propertiesStorage.getProperty('filterText'));

exports.filterUrl = function filterUrl(url) {
	if (!url) {
		return false;
	}
	if (!filter) {
		return true;
	}
	if (filter.test) {
		return filter.test(url);
	}
	return url.indexOf(filter) != -1;
};

function syncData() {
	if (!oldData.exists) {
		return;
	}
	var syncedData;
	oldData.getRulesList().forEach(function(data) {
		if (!rulesStorage.existsFile(data.name)) {
			addRulesFile(data.name, data.value);
			data.selected && selectRulesFile(data.name);
			if (data.value) {
				syncedData = true;
			}
		}
	});

	oldData.getValuesList().forEach(function(data) {
		!valuesStorage.existsFile(data.name) && addValuesFile(data.name, data.value);
		if (data.value) {
			syncedData = true;
		}
	});
	if (!propertiesStorage.getProperty('_syncedData')) {
		var defalutRules = oldData.getDefaultRules();
		setDefaultRules(defalutRules.value);
		defalutRules.selected && enableDefaultRules();
		var rulesStyle = oldData.getRulesStyle();
		var valuesStyle = oldData.getValuesStyle();

		propertiesStorage.setProperty('theme', rulesStyle.fontSize);
		propertiesStorage.setProperty('fontSize', rulesStyle.fontSize);
		propertiesStorage.setProperty('showLineNumbers', rulesStyle.fontSize);

		propertiesStorage.setProperty('valuesTheme', valuesStyle.fontSize);
		propertiesStorage.setProperty('valuesFontSize', valuesStyle.fontSize);
		propertiesStorage.setProperty('valuesShowLineNumbers', valuesStyle.fontSize);
	} else {
		propertiesStorage.setProperty('_syncedData', true);
	}

	syncedData && oldData.drop();
}

process.nextTick(function() {
	syncData();
	parseRules();
});
/**
 * rules
 */

function parseHosts(text) {
	if (typeof text != 'string'
		|| !(text = text.trim())) {
		return '';
	}
	var result = [];
	text.split(/\n|\r\n|\r/g)
		.forEach(function(line) {
			var raw = line;
			line = line.replace(/#.*$/, '').trim();
			if (!line) {
				return;
			}
			line = line.split(/\s+/);
			var pattern = line[0];
			if (net.isIP(pattern)) {
				line.slice(1).forEach(function(matcher) {
					!/\//.test(matcher) && result.push(pattern + ' ' + matcher);
				});
			} else if (!/\//.test(pattern) && line[1] && net.isIP(line[1])) {
				result.push(line[1] + ' ' + pattern);
			}
		});

	return result.join('\r\n');
}

function parseRules(defaultRules) {
	var value = [];
	var hosts =  propertiesStorage.getProperty('syncWithSysHosts') ? [] : null;
	getAllRulesFile().forEach(function(file) {
		if (file.selected) {
			value.push(file.data);
			if (hosts) {
				var sysHosts = parseHosts(file.data);
				if (sysHosts) {
					hosts.push('#\r\n# ' + file.name + '\r\n#' + '\r\n' + sysHosts);
				}
			}
		}
	});

	if (typeof defaultRules == 'string') {
		setDefaultRules(defaultRules);
		value.push(defaultRules);
		rulesStorage.setProperty('disabledDefalutRules', false);
	}else if (!defaultRulesIsDisabled()) {
		defaultRules = getDefaultRules();
		value.push(defaultRules);
	}

	if (hosts && defaultRules) {
		var sysHosts = parseHosts(defaultRules);
		if (sysHosts) {
			hosts.push('#\r\n# Default\r\n#' + '\r\n' + sysHosts);
		}
	}

	rules.parse(value.join('\r\n'));
	if (hosts) {
		hosts = hosts.join('\r\n\r\n');
		system.setHosts(hosts, util.noop);
	}
}

exports.parseRules = parseRules;

function setDefaultRules(data) {
	data = typeof data != 'string' ? '' : data;
	rulesStorage.setProperty('defalutRules', data);
	parseRules();
}

function getDefaultRules() {
	return rulesStorage.getProperty('defalutRules');
}

function disableDefaultRules() {
	rulesStorage.setProperty('disabledDefalutRules', true);
	parseRules();
}

function enableDefaultRules() {
	rulesStorage.setProperty('disabledDefalutRules', false);
	parseRules();
}

function defaultRulesIsDisabled() {
	return rulesStorage.getProperty('disabledDefalutRules');
}

function selectRulesFile(file) {
	if (!rulesStorage.existsFile(file)) {
		return;
	}

	var selectedList = allowMultipleChoice() ? getSelectedRulesList() : [];
	if (selectedList.indexOf(file) == -1) {
		selectedList.push(file);
		rulesStorage.setProperty('selectedList', selectedList);
	}
	parseRules();
	return selectedList;
}

function unselectRulesFile(file) {
	var selectedList;

	if (allowMultipleChoice()) {
		selectedList = getSelectedRulesList();
		var index = selectedList.indexOf(file);
		if (index != -1) {
			selectedList.splice(index, 1);
			rulesStorage.setProperty('selectedList', selectedList);
		}
	} else {
		selectedList = [];
		rulesStorage.setProperty('selectedList', selectedList);
	}
	parseRules();

	return selectedList;
}

function allowMultipleChoice() {
	return propertiesStorage.getProperty('allowMultipleChoice');
}

function clearSelection() {
	rulesStorage.setProperty('selectedList', []);
	parseRules();
}

function getSelectedRulesList() {
	var selectedList = rulesStorage.getProperty('selectedList');
	if (!selectedList) {
		selectedList = [];
		rulesStorage.setProperty('selectedList', selectedList);
	}
	return selectedList;
}

function removeRulesFile(file) {
	unselectRulesFile(file);
	rulesStorage.removeFile(file);
}

function renameRulesFile(file, newFile) {
	if (!rulesStorage.renameFile(file, newFile)) {
		return;
	}

	var selectedList = getSelectedRulesList();
	var index = selectedList.indexOf(file);
	if (index != -1) {
		selectedList[index] = newFile;
		rulesStorage.setProperty('selectedList', selectedList);
	}
}

function addRulesFile(file, data) {
	rulesStorage.writeFile(file, data);
}

function getAllRulesFile() {
	var list = rulesStorage.getFileList();
	var selectedList = getSelectedRulesList();
	list.forEach(function(file) {
		file.selected = selectedList.indexOf(file.name) != -1;
	});
	return list;
}

exports.rules = {
		getSysHosts: system.getHosts,
		setSysHosts: system.setHosts,
		remove: removeRulesFile,
		add: addRulesFile,
		rename: renameRulesFile,
		select: selectRulesFile,
		unselect: unselectRulesFile,
		list: getAllRulesFile,
		getDefault: getDefaultRules,
		setDefault: setDefaultRules,
		enableDefault: enableDefaultRules,
		disableDefault: disableDefaultRules,
		defaultRulesIsDisabled: defaultRulesIsDisabled,
		parseRules: parseRules,
		clearSelection:clearSelection,
		getSelectedList: getSelectedRulesList
};

/**
 * values
 */

function addValuesFile(file, data) {
	valuesStorage.writeFile(file, data);
}

exports.values = {
	add: addValuesFile,
	get: function(file) {
		return valuesStorage.readFile(file);
	},
	remove: function remove(file) {
		valuesStorage.removeFile(file);
	},
	rename: function(file, newFile) {
		valuesStorage.renameFile(file, newFile);
	},
	list: function list() {
		var selectedFile = valuesStorage.getProperty('selectedFile');
		var list = valuesStorage.getFileList();
		if (selectedFile) {
			list.forEach(function(file) {
				file.selected = file.name == selectedFile;
			});
		}
		return list;
	},
	select: function(file) {
		typeof file == 'string' && valuesStorage.setProperty('selectedFile', file);
	},
	unselect: function() {
		valuesStorage.removeProperty('selectedFile');
	}
};

setTimeout(function getWhistleVersion() {
	http.get(config.registry, function(res) {
		res.setEncoding('utf8');
		var body = '';
		res.on('data', function(data) {
			body += data;
		});

		res.on('error', util.noop);
		res.on('end', function() {
			var ver = util.parseJSON(body);
			ver = ver['dist-tags'];
			if (ver = ver && ver['latest']) {
				propertiesStorage.setProperty('latestVersion', ver);
			}
		});
		setTimeout(getWhistleVersion, 1000 * 60 * 60 * 12);
	}).on('error', util.noop);
}, 1000); //等待package的信息配置更新完成

/**
 * properties
 */

exports.properties = {
		set: function(name, value) {
			typeof name == 'string' ? propertiesStorage.setProperty(name, value) :
				propertiesStorage.setProperties(name);
		},
		remove: function(name) {
			propertiesStorage.removeProperty(name);
		},
		get: function(name) {
			return propertiesStorage.getProperty(name);
		}
};

<commit_msg>drop data<commit_after>var net = require('net');
var fs = require('fs');
var http = require('http');
var path = require('path');
var rules = require('./index');
var util = require('../util');
var config = require('../config');
var Storage = require('./storage');
var ROOT = config.DATA_DIR;
var rulesStorage = new Storage(path.join(ROOT, 'rules'));
var valuesStorage = new Storage(path.join(ROOT, 'values'));
var propertiesStorage = new Storage(path.join(ROOT, 'properties'));
var system = require('./system');
var oldData = require('./old-data');
var filter;

function setFilter(text) {
	if (!text || typeof text != 'string') {
		text = '';
	}
	text = text.substring(0, 128);
	propertiesStorage.setProperty('filterText', text);
	filter = util.toRegExp(text) || text;
}

exports.setFilter = setFilter;

setFilter(propertiesStorage.getProperty('filterText'));

exports.filterUrl = function filterUrl(url) {
	if (!url) {
		return false;
	}
	if (!filter) {
		return true;
	}
	if (filter.test) {
		return filter.test(url);
	}
	return url.indexOf(filter) != -1;
};

function syncData() {
	if (!oldData.exists) {
		return;
	}
	var syncedData;
	var _syncedData = propertiesStorage.getProperty('_syncedData');
	oldData.getRulesList().forEach(function(data) {
		if (!rulesStorage.existsFile(data.name) && (data.value || !_syncedData)) {
			addRulesFile(data.name, data.value);
			data.selected && selectRulesFile(data.name);
			if (data.value) {
				syncedData = true;
			}
		}
	});

	oldData.getValuesList().forEach(function(data) {
		if (!valuesStorage.existsFile(data.name) && (data.value || !_syncedData)) {
			addValuesFile(data.name, data.value);
			if (data.value) {
				syncedData = true;
			}
		}
	});
	if (!_syncedData) {
		var defalutRules = oldData.getDefaultRules();
		setDefaultRules(defalutRules.value);
		defalutRules.selected && enableDefaultRules();
		var rulesStyle = oldData.getRulesStyle();
		var valuesStyle = oldData.getValuesStyle();

		propertiesStorage.setProperty('theme', rulesStyle.fontSize);
		propertiesStorage.setProperty('fontSize', rulesStyle.fontSize);
		propertiesStorage.setProperty('showLineNumbers', rulesStyle.fontSize);

		propertiesStorage.setProperty('valuesTheme', valuesStyle.fontSize);
		propertiesStorage.setProperty('valuesFontSize', valuesStyle.fontSize);
		propertiesStorage.setProperty('valuesShowLineNumbers', valuesStyle.fontSize);
	} else {
		propertiesStorage.setProperty('_syncedData', true);
	}

	syncedData && oldData.drop();
}

process.nextTick(function() {
	syncData();
	parseRules();
});
/**
 * rules
 */

function parseHosts(text) {
	if (typeof text != 'string'
		|| !(text = text.trim())) {
		return '';
	}
	var result = [];
	text.split(/\n|\r\n|\r/g)
		.forEach(function(line) {
			var raw = line;
			line = line.replace(/#.*$/, '').trim();
			if (!line) {
				return;
			}
			line = line.split(/\s+/);
			var pattern = line[0];
			if (net.isIP(pattern)) {
				line.slice(1).forEach(function(matcher) {
					!/\//.test(matcher) && result.push(pattern + ' ' + matcher);
				});
			} else if (!/\//.test(pattern) && line[1] && net.isIP(line[1])) {
				result.push(line[1] + ' ' + pattern);
			}
		});

	return result.join('\r\n');
}

function parseRules(defaultRules) {
	var value = [];
	var hosts =  propertiesStorage.getProperty('syncWithSysHosts') ? [] : null;
	getAllRulesFile().forEach(function(file) {
		if (file.selected) {
			value.push(file.data);
			if (hosts) {
				var sysHosts = parseHosts(file.data);
				if (sysHosts) {
					hosts.push('#\r\n# ' + file.name + '\r\n#' + '\r\n' + sysHosts);
				}
			}
		}
	});

	if (typeof defaultRules == 'string') {
		setDefaultRules(defaultRules);
		value.push(defaultRules);
		rulesStorage.setProperty('disabledDefalutRules', false);
	}else if (!defaultRulesIsDisabled()) {
		defaultRules = getDefaultRules();
		value.push(defaultRules);
	}

	if (hosts && defaultRules) {
		var sysHosts = parseHosts(defaultRules);
		if (sysHosts) {
			hosts.push('#\r\n# Default\r\n#' + '\r\n' + sysHosts);
		}
	}

	rules.parse(value.join('\r\n'));
	if (hosts) {
		hosts = hosts.join('\r\n\r\n');
		system.setHosts(hosts, util.noop);
	}
}

exports.parseRules = parseRules;

function setDefaultRules(data) {
	data = typeof data != 'string' ? '' : data;
	rulesStorage.setProperty('defalutRules', data);
	parseRules();
}

function getDefaultRules() {
	return rulesStorage.getProperty('defalutRules');
}

function disableDefaultRules() {
	rulesStorage.setProperty('disabledDefalutRules', true);
	parseRules();
}

function enableDefaultRules() {
	rulesStorage.setProperty('disabledDefalutRules', false);
	parseRules();
}

function defaultRulesIsDisabled() {
	return rulesStorage.getProperty('disabledDefalutRules');
}

function selectRulesFile(file) {
	if (!rulesStorage.existsFile(file)) {
		return;
	}

	var selectedList = allowMultipleChoice() ? getSelectedRulesList() : [];
	if (selectedList.indexOf(file) == -1) {
		selectedList.push(file);
		rulesStorage.setProperty('selectedList', selectedList);
	}
	parseRules();
	return selectedList;
}

function unselectRulesFile(file) {
	var selectedList;

	if (allowMultipleChoice()) {
		selectedList = getSelectedRulesList();
		var index = selectedList.indexOf(file);
		if (index != -1) {
			selectedList.splice(index, 1);
			rulesStorage.setProperty('selectedList', selectedList);
		}
	} else {
		selectedList = [];
		rulesStorage.setProperty('selectedList', selectedList);
	}
	parseRules();

	return selectedList;
}

function allowMultipleChoice() {
	return propertiesStorage.getProperty('allowMultipleChoice');
}

function clearSelection() {
	rulesStorage.setProperty('selectedList', []);
	parseRules();
}

function getSelectedRulesList() {
	var selectedList = rulesStorage.getProperty('selectedList');
	if (!selectedList) {
		selectedList = [];
		rulesStorage.setProperty('selectedList', selectedList);
	}
	return selectedList;
}

function removeRulesFile(file) {
	unselectRulesFile(file);
	rulesStorage.removeFile(file);
}

function renameRulesFile(file, newFile) {
	if (!rulesStorage.renameFile(file, newFile)) {
		return;
	}

	var selectedList = getSelectedRulesList();
	var index = selectedList.indexOf(file);
	if (index != -1) {
		selectedList[index] = newFile;
		rulesStorage.setProperty('selectedList', selectedList);
	}
}

function addRulesFile(file, data) {
	rulesStorage.writeFile(file, data);
}

function getAllRulesFile() {
	var list = rulesStorage.getFileList();
	var selectedList = getSelectedRulesList();
	list.forEach(function(file) {
		file.selected = selectedList.indexOf(file.name) != -1;
	});
	return list;
}

exports.rules = {
		getSysHosts: system.getHosts,
		setSysHosts: system.setHosts,
		remove: removeRulesFile,
		add: addRulesFile,
		rename: renameRulesFile,
		select: selectRulesFile,
		unselect: unselectRulesFile,
		list: getAllRulesFile,
		getDefault: getDefaultRules,
		setDefault: setDefaultRules,
		enableDefault: enableDefaultRules,
		disableDefault: disableDefaultRules,
		defaultRulesIsDisabled: defaultRulesIsDisabled,
		parseRules: parseRules,
		clearSelection:clearSelection,
		getSelectedList: getSelectedRulesList
};

/**
 * values
 */

function addValuesFile(file, data) {
	valuesStorage.writeFile(file, data);
}

exports.values = {
	add: addValuesFile,
	get: function(file) {
		return valuesStorage.readFile(file);
	},
	remove: function remove(file) {
		valuesStorage.removeFile(file);
	},
	rename: function(file, newFile) {
		valuesStorage.renameFile(file, newFile);
	},
	list: function list() {
		var selectedFile = valuesStorage.getProperty('selectedFile');
		var list = valuesStorage.getFileList();
		if (selectedFile) {
			list.forEach(function(file) {
				file.selected = file.name == selectedFile;
			});
		}
		return list;
	},
	select: function(file) {
		typeof file == 'string' && valuesStorage.setProperty('selectedFile', file);
	},
	unselect: function() {
		valuesStorage.removeProperty('selectedFile');
	}
};

setTimeout(function getWhistleVersion() {
	http.get(config.registry, function(res) {
		res.setEncoding('utf8');
		var body = '';
		res.on('data', function(data) {
			body += data;
		});

		res.on('error', util.noop);
		res.on('end', function() {
			var ver = util.parseJSON(body);
			ver = ver['dist-tags'];
			if (ver = ver && ver['latest']) {
				propertiesStorage.setProperty('latestVersion', ver);
			}
		});
		setTimeout(getWhistleVersion, 1000 * 60 * 60 * 12);
	}).on('error', util.noop);
}, 1000); //等待package的信息配置更新完成

/**
 * properties
 */

exports.properties = {
		set: function(name, value) {
			typeof name == 'string' ? propertiesStorage.setProperty(name, value) :
				propertiesStorage.setProperties(name);
		},
		remove: function(name) {
			propertiesStorage.removeProperty(name);
		},
		get: function(name) {
			return propertiesStorage.getProperty(name);
		}
};

<|endoftext|>


<commit_before>/*
 *  Copyright 2011 Rackspace
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

/* @fileOverview swiz is the serialization framework, built on Lucy's
 *   awesome python-esque version of things.... but for node.js
 *
 *  Major design goals are:
 *  * Allow us to support multiple formats (e.g. JSON & XML)
 *  * Be node.js-esque.
 *  * Not block especially frequently.
 *
 * Writing without a XML generator pimpy thingie because most of them
 * looked to be too much of a pain in the ass.
 *
 * Things that it doesn't presently do:
 * * Prevent you from using clearly-illegal names for things.
 * * Caching
 * * Pagination (this is regarded as a feature, not a bug)
 * * It doesn't try to remap returned arrays or hashes
 * * Probably some other things...
 */

// Required libs:
var async = require('async');

/**
 * The constructor for the swiz class
 * @constructor
 *
 * Notes about the data def.
 *
 * It's first a set of object type definitions.
 *
 * Each object type definition is a list of slots, which is a pair
 * of name and an object containing the metainformation.
 *
 * The metainformation is free-form.  In a DRY fashion, it'll assume
 * that the name is the name of the object's variable.  If it isn't, you
 * can use 'src' to retrieve something else.
 *
 * 'type' is the type (I use thrift's format), 'desc' means the description.
 * These are for making things self-describing down the road.
 *
 * @param {!Object} defs data def.
 */

function Swiz(defs) {
  this.defs = defs;
}

/** Controls if you want to use JSON or XML (or, for that matter, any other
  * weird serialization format people might invent to torment you with)
  *
  * @enum {number}
  */
exports.SERIALIZATION = {
  SERIALIZATION_JSON: 0,
  SERIALIZATION_XML: 1
};

/** Escape an XML string.
 *
 * @param {string} str string to be escaped.
 * @return {string} entity-replaced version of the string.
 */
Swiz.prototype.xmlEscapeString = function(str) {
  str = str.replace(/&/g, '&');
  str = str.replace(/</g, '<');
  str = str.replace(/>/g, '>');
  return str;
};

/**
 * Given a datastructure supported by Swiz, convert it into an Object that
 * can be serialized directly to JSON, or to XML using Swiz's serializeXml
 * method.
 *
 * @param {object} obj The datastructure to be converted.
 * @param {function} callback A callback fired with (err, result).
 */
Swiz.prototype.buildObject = function(obj, callback) {
  this._buildObject(null, obj, callback);
};

Swiz.prototype._buildObject = function(parent, obj, callback) {
  var self = this;
  var stype, def, result, keys;

  // Call the function and recurse on the value passed to the callback
  if (obj instanceof Function) {
    obj.call(parent, function(err, value) {
      if (err) {
        callback(err);
      } else {
        self._buildObject(null, value, callback);
      }
    });
  }

  // Recurse onto every element of an array
  else if (obj instanceof Array) {
    function iterArr(item, callback) {
      self._buildObject(null, item, callback);
    }

    async.map(obj, iterArr, callback);
  }

  // Recurse onto each property named in the definition
  else if (obj instanceof Object && obj.getSerializerType) {
    stype = obj.getSerializerType();
    def = this.defs[stype];
    result = {};
    Object.defineProperty(result, 'serializerType', {
      value: stype,
      enumerable: false
    });

    if (!def) {
      callback(new Error('No definition for this type; no way to serialize ' + stype));
      return;
    }

    function iterObj(item, callback) {
      var k;
      var prop = item[1];
      var dst = item[0];
      var src = prop.src || dst;

      if (prop.enumerated) {
        for (k in prop.enumerated) {
          if (prop.enumerated[k] === obj[src]) {
            result[dst] = k;
            callback();
            return;
          }
        }
      }

      self._buildObject(obj, obj[src], function(err, value) {
        result[dst] = value;
        callback(err);
      });
    }

    async.forEach(def, iterObj, function(err) {
      callback(err, result);
    });
  }

  // Treat it as a map, recurse onto each property
  else if (obj instanceof Object) {
    keys = Object.keys(obj);
    result = {};

    function iterMap(key, callback) {
      if (!obj.hasOwnProperty(key)) {
        callback();
        return;
      }

      self._buildObject(obj, obj[key], function(err, value) {
        result[key] = value;
        callback(err);
      });
    }

    async.forEach(keys, iterMap, function(err) {
      callback(err, result);
    });
  }

  // Simple value, pass it back
  else {
    callback(null, obj);
  }
};

Swiz.prototype._startTag = function(name) {
  if (name) {
    return '<' + name + '>';
  } else {
    return '';
  }
};

Swiz.prototype._endTag = function(name) {
  if (name) {
    return '</' + name + '>';
  } else {
    return '';
  }
};

Swiz.prototype._serializeXml = function(obj, key) {
  var i, def, stype, keys, item, src, result;

  // Treat each member of an array as a separate property with the same key
  if (obj instanceof Array) {
    result = '';
    for (i = 0; i < obj.length; i++) {
      result += this._serializeXml(obj[i], key);
    }
    return result;
  }

  // Look up object definitions, serialize each defined property
  else if (obj instanceof Object && obj.serializerType) {
    def = this.defs[obj.serializerType];
    if (!def) {
      throw new Error('No definition for this type; unable to serialize');
    }

    stype = this.xmlEscapeString(obj.serializerType);

    result = this._startTag(key) + this._startTag(stype);

    for (i = 0; i < def.length; i++) {
      item = def[i];
      src = item[0];
      result += this._serializeXml(obj[src], this.xmlEscapeString(src));
    }

    return result + this._endTag(stype) + this._endTag(key);
  }

  // Use all defined keys
  else if (obj instanceof Object) {
    keys = Object.keys(obj);
    result = this._startTag(key);

    for (i = 0; i < keys.length; i++) {
      if (obj.hasOwnProperty(keys[i])) {
        result += this._serializeXml(obj[keys[i]], this.xmlEscapeString(keys[i]));
      }
    }

    return result + this._endTag(key);
  }

  // Serialize individual values
  else {
    if (!obj) {
      return '';
    }
    return this._startTag(key) + this.xmlEscapeString(obj.toString()) + this._endTag(key);
  }
};

/**
 * Convert an "object" constructed by buildObject to JSON. Currently this
 * simply calls JSON.stringify() on the object.
 */
Swiz.prototype.serializeJson = function(obj) {
  return JSON.stringify(obj, null, 4);
};

/**
 * Convert an "object" constructed by buildObject to XML. If the object is an
 * Array it will be placed within <group>...</group> tags.
 *
 * @param {object|array} obj The object to be serialized.
 * @returns {string}
 */
Swiz.prototype.serializeXml = function(obj) {
  if (obj instanceof Array) {
    return '<?xml version="1.0" encoding="UTF-8"?>' +
        this._startTag('group') +
        this._serializeXml(obj, null) +
        this._endTag('group');
  } else {
    return '<?xml version="1.0" encoding="UTF-8"?>' +
        this._serializeXml(obj, null);
  }
};

/** Serialize function
  *
  * This is your primary API.  It will look through your pre-set
  * definition structure and try to "do the right thing" as necessary.
  *
  * Your object needs to have a getSerializerType() method so
  * it can know how to serialize it (so that any number of "node"
  * objects can be serialized as a Node).
  *
  * The individual slots (functions or variables) can be node-style
  * callbacks, single objects, arrays, or objects.  It will try to
  * "do the right thing"
  *
  * Version numbers are presently ignored.
  *
  * @param {enum} mode The mode of serialization.
  * @param {number} version The version number.
  * @param {Object|Array} obj The object to be serialized.
  * @param {function} callback The callback to use.
  */
Swiz.prototype.serialize = function(mode, version, obj, callback) {
  var self = this;

  this.buildObject(obj, function(err, result) {
    if (err) {
      callback(err);
      return;
    }

    if (mode === exports.SERIALIZATION.SERIALIZATION_XML) {
      callback(null, self.serializeXml(result));
    } else {
      callback(null, self.serializeJson(result));
    }
  });
};

/**
 * The swiz class
 */
exports.Swiz = Swiz;
<commit_msg>prune the null values from the serialized object<commit_after>/*
 *  Copyright 2011 Rackspace
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

/* @fileOverview swiz is the serialization framework, built on Lucy's
 *   awesome python-esque version of things.... but for node.js
 *
 *  Major design goals are:
 *  * Allow us to support multiple formats (e.g. JSON & XML)
 *  * Be node.js-esque.
 *  * Not block especially frequently.
 *
 * Writing without a XML generator pimpy thingie because most of them
 * looked to be too much of a pain in the ass.
 *
 * Things that it doesn't presently do:
 * * Prevent you from using clearly-illegal names for things.
 * * Caching
 * * Pagination (this is regarded as a feature, not a bug)
 * * It doesn't try to remap returned arrays or hashes
 * * Probably some other things...
 */

// Required libs:
var async = require('async');

/**
 * The constructor for the swiz class
 * @constructor
 *
 * Notes about the data def.
 *
 * It's first a set of object type definitions.
 *
 * Each object type definition is a list of slots, which is a pair
 * of name and an object containing the metainformation.
 *
 * The metainformation is free-form.  In a DRY fashion, it'll assume
 * that the name is the name of the object's variable.  If it isn't, you
 * can use 'src' to retrieve something else.
 *
 * 'type' is the type (I use thrift's format), 'desc' means the description.
 * These are for making things self-describing down the road.
 *
 * @param {!Object} defs data def.
 */

function Swiz(defs) {
  this.defs = defs;
}

/** Controls if you want to use JSON or XML (or, for that matter, any other
  * weird serialization format people might invent to torment you with)
  *
  * @enum {number}
  */
exports.SERIALIZATION = {
  SERIALIZATION_JSON: 0,
  SERIALIZATION_XML: 1
};

/** Escape an XML string.
 *
 * @param {string} str string to be escaped.
 * @return {string} entity-replaced version of the string.
 */
Swiz.prototype.xmlEscapeString = function(str) {
  str = str.replace(/&/g, '&');
  str = str.replace(/</g, '<');
  str = str.replace(/>/g, '>');
  return str;
};

/**
 * Given a datastructure supported by Swiz, convert it into an Object that
 * can be serialized directly to JSON, or to XML using Swiz's serializeXml
 * method.
 *
 * @param {object} obj The datastructure to be converted.
 * @param {function} callback A callback fired with (err, result).
 */
Swiz.prototype.buildObject = function(obj, callback) {
  this._buildObject(null, obj, callback);
};

Swiz.prototype._buildObject = function(parent, obj, callback) {
  var self = this;
  var stype, def, result, keys;

  // Call the function and recurse on the value passed to the callback
  if (obj instanceof Function) {
    obj.call(parent, function(err, value) {
      if (err) {
        callback(err);
      } else {
        self._buildObject(null, value, callback);
      }
    });
  }

  // Recurse onto every element of an array
  else if (obj instanceof Array) {
    function iterArr(item, callback) {
      self._buildObject(null, item, callback);
    }

    async.map(obj, iterArr, callback);
  }

  // Recurse onto each property named in the definition
  else if (obj instanceof Object && obj.getSerializerType) {
    stype = obj.getSerializerType();
    def = this.defs[stype];
    result = {};
    Object.defineProperty(result, 'serializerType', {
      value: stype,
      enumerable: false
    });

    if (!def) {
      callback(new Error('No definition for this type; no way to serialize ' + stype));
      return;
    }

    function iterObj(item, callback) {
      var k;
      var prop = item[1];
      var dst = item[0];
      var src = prop.src || dst;

      if (prop.enumerated) {
        for (k in prop.enumerated) {
          if (prop.enumerated[k] === obj[src]) {
            result[dst] = k;
            callback();
            return;
          }
        }
      }

      self._buildObject(obj, obj[src], function(err, value) {
        result[dst] = value;
        callback(err);
      });
    }

    async.forEach(def, iterObj, function(err) {
      callback(err, result);
    });
  }

  // Treat it as a map, recurse onto each property
  else if (obj instanceof Object) {
    keys = Object.keys(obj);
    result = {};

    function iterMap(key, callback) {
      if (!obj.hasOwnProperty(key)) {
        callback();
        return;
      }

      self._buildObject(obj, obj[key], function(err, value) {
        result[key] = value;
        callback(err);
      });
    }

    async.forEach(keys, iterMap, function(err) {
      callback(err, result);
    });
  }

  // Simple value, pass it back
  else {
    callback(null, obj);
  }
};

Swiz.prototype._startTag = function(name) {
  if (name) {
    return '<' + name + '>';
  } else {
    return '';
  }
};

Swiz.prototype._endTag = function(name) {
  if (name) {
    return '</' + name + '>';
  } else {
    return '';
  }
};

Swiz.prototype._serializeXml = function(obj, key) {
  var i, def, stype, keys, item, src, result;

  // Treat each member of an array as a separate property with the same key
  if (obj instanceof Array) {
    result = '';
    for (i = 0; i < obj.length; i++) {
      result += this._serializeXml(obj[i], key);
    }
    return result;
  }

  // Look up object definitions, serialize each defined property
  else if (obj instanceof Object && obj.serializerType) {
    def = this.defs[obj.serializerType];
    if (!def) {
      throw new Error('No definition for this type; unable to serialize');
    }

    stype = this.xmlEscapeString(obj.serializerType);

    result = this._startTag(key) + this._startTag(stype);

    for (i = 0; i < def.length; i++) {
      item = def[i];
      src = item[0];
      result += this._serializeXml(obj[src], this.xmlEscapeString(src));
    }

    return result + this._endTag(stype) + this._endTag(key);
  }

  // Use all defined keys
  else if (obj instanceof Object) {
    keys = Object.keys(obj);
    result = this._startTag(key);

    for (i = 0; i < keys.length; i++) {
      if (obj.hasOwnProperty(keys[i])) {
        if (obj[keys[i]]) {
          result += this._serializeXml(obj[keys[i]], this.xmlEscapeString(keys[i]));
        }
      }
    }

    return result + this._endTag(key);
  }

  // Serialize individual values
  else {
    if (!obj) {
      return '';
    }
    return this._startTag(key) + this.xmlEscapeString(obj.toString()) + this._endTag(key);
  }
};

function pruneNull(key, value) {
  return value ? value : undefined;
}

/**
 * Convert an "object" constructed by buildObject to JSON. Currently this
 * simply calls JSON.stringify() on the object.
 */
Swiz.prototype.serializeJson = function(obj) {
  return JSON.stringify(obj, pruneNull, 4);
};

/**
 * Convert an "object" constructed by buildObject to XML. If the object is an
 * Array it will be placed within <group>...</group> tags.
 *
 * @param {object|array} obj The object to be serialized.
 * @returns {string}
 */
Swiz.prototype.serializeXml = function(obj) {
  if (obj instanceof Array) {
    return '<?xml version="1.0" encoding="UTF-8"?>' +
        this._startTag('group') +
        this._serializeXml(obj, null) +
        this._endTag('group');
  } else {
    return '<?xml version="1.0" encoding="UTF-8"?>' +
        this._serializeXml(obj, null);
  }
};

/** Serialize function
  *
  * This is your primary API.  It will look through your pre-set
  * definition structure and try to "do the right thing" as necessary.
  *
  * Your object needs to have a getSerializerType() method so
  * it can know how to serialize it (so that any number of "node"
  * objects can be serialized as a Node).
  *
  * The individual slots (functions or variables) can be node-style
  * callbacks, single objects, arrays, or objects.  It will try to
  * "do the right thing"
  *
  * Version numbers are presently ignored.
  *
  * @param {enum} mode The mode of serialization.
  * @param {number} version The version number.
  * @param {Object|Array} obj The object to be serialized.
  * @param {function} callback The callback to use.
  */
Swiz.prototype.serialize = function(mode, version, obj, callback) {
  var self = this;

  this.buildObject(obj, function(err, result) {
    if (err) {
      callback(err);
      return;
    }

    if (mode === exports.SERIALIZATION.SERIALIZATION_XML) {
      callback(null, self.serializeXml(result));
    } else {
      callback(null, self.serializeJson(result));
    }
  });
};

/**
 * The swiz class
 */
exports.Swiz = Swiz;
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */
var fs = require('fs');
//express 基础框架
var express = require('express');
var routes = require('./routes');
var showlog = require('./routes/showlog');
var exportFile = require('./routes/export');
var hostFile = require('./routes/hostFile');
var http = require('http');
var path = require('path');
var flash = require('connect-flash');

var app = express();

// all environments
app.configure(function(){
	app.set('port', process.env.PORT || 3000);
	app.set('views', path.resolve(__dirname,'views'));
	app.set('view engine', 'ejs');
	app.use(express.favicon());
	app.use(express.json());
	app.use(express.urlencoded());
	//解析客户端请求，通常是通过post发过来的请求
	app.use(express.bodyParser());
	//用于支持定制的http方法
	app.use(express.methodOverride());
	//支持flash
	app.use(flash());
	//提供静态文件支持
	app.use(express['static'](path.resolve(__dirname,'public')));
	//提供路由支持
	app.use(app.router);
	// app.use(express.router(routes));
});

app.get('/', routes.index);
app.get('/index', routes.index);
app.get('/log', showlog.show);
app.get('/export.json', exportFile.show);
//app.post('/saveHosts', saveHosts.list);
app.post('/hostFile', hostFile.host);

app.get('/scope', routes.scope);
app.post('/scope', routes.save);
app.post('/removeHost', routes.removeHost);
app.post('/toggleHost', routes.toggleHost);
app.post('/removeGroup', routes.removeGroup);
app.post('/editProxy', routes.editProxy);
app.post('/editProxyGroup', routes.editProxyGroup);
app.post('/removeProxy', routes.removeProxy);
app.post('/disabledProxy', routes.disabledProxy);
app.post('/toggleOnlineProxy', routes.onlineProxy);

app.get('*', function(req, res){
    res.render('404', {
        title: 'No Found'
    });
});

//供外部调用打开端口
module.exports = app;
<commit_msg>add no-cache<commit_after>/**
 * Module dependencies.
 */
var fs = require('fs');
//express 基础框架
var express = require('express');
var routes = require('./routes');
var showlog = require('./routes/showlog');
var exportFile = require('./routes/export');
var hostFile = require('./routes/hostFile');
var http = require('http');
var path = require('path');
var flash = require('connect-flash');

var app = express();

// all environments
app.configure(function() {
	app.set('port', process.env.PORT || 3000);
	app.set('views', path.resolve(__dirname, 'views'));
	app.set('view engine', 'ejs');
	app.use(express.favicon());
	app.use(express.json());
	app.use(express.urlencoded());
	//解析客户端请求，通常是通过post发过来的请求
	app.use(express.bodyParser());
	//用于支持定制的http方法
	app.use(express.methodOverride());
	//支持flash
	app.use(flash());
	//提供静态文件支持
	app.use(express['static'](path.resolve(__dirname, 'public')));
	//提供路由支持
	app.use(function(req, res, next) {
		res.header('Cache-Control', 'no-cache');
		res.header('Expires', '-1');
		res.header('Pragma', 'no-cache');
		next();
	});
});

app.get('/', routes.index);
app.get('/index', routes.index);
app.get('/log', showlog.show);
app.get('/export.json', exportFile.show);
//app.post('/saveHosts', saveHosts.list);
app.post('/hostFile', hostFile.host);

app.get('/scope', routes.scope);
app.post('/scope', routes.save);
app.post('/removeHost', routes.removeHost);
app.post('/toggleHost', routes.toggleHost);
app.post('/removeGroup', routes.removeGroup);
app.post('/editProxy', routes.editProxy);
app.post('/editProxyGroup', routes.editProxyGroup);
app.post('/removeProxy', routes.removeProxy);
app.post('/disabledProxy', routes.disabledProxy);
app.post('/toggleOnlineProxy', routes.onlineProxy);

app.get('*', function(req, res) {
	res.render('404', {
		title: 'No Found'
	});
});

//供外部调用打开端口
module.exports = app;

<|endoftext|>


<commit_before>/**
 * @depend util/core.js
 * @depend stub.js
 * @depend mock.js
 * @depend sandbox.js
 */
/**
 * Test function, sandboxes fakes
 *
 * @author Christian Johansen (christian@cjohansen.no)
 * @license BSD
 *
 * Copyright (c) 2010-2013 Christian Johansen
 */
"use strict";

(function (sinon) {
    function makeApi(sinon) {
        function test(callback) {
            var type = typeof callback;

            if (type != "function") {
                throw new TypeError("sinon.test needs to wrap a test function, got " + type);
            }

            function sinonSandboxedTest() {
                var config = sinon.getConfig(sinon.config);
                config.injectInto = config.injectIntoThis && this || config.injectInto;
                var sandbox = sinon.sandbox.create(config);
                var exception, result;
                var doneIsWrapped = false;
                var argumentsCopy = Array.prototype.slice.call(arguments);
                if (argumentsCopy.length > 0 && typeof argumentsCopy[arguments.length - 1] == "function") {
                    var oldDone = argumentsCopy[arguments.length - 1];
                    argumentsCopy[arguments.length - 1] = function done(result) {
                        if (result) {
                            sandbox.restore();
                            throw exception;
                        } else {
                            sandbox.verifyAndRestore();
                        }
                        oldDone(result);
                    }
                    doneIsWrapped = true;
                }

                var args = argumentsCopy.concat(sandbox.args);

                try {
                    result = callback.apply(this, args);
                } catch (e) {
                    exception = e;
                }

                if (!doneIsWrapped) {
                    if (typeof exception !== "undefined") {
                        sandbox.restore();
                        throw exception;
                    } else {
                        sandbox.verifyAndRestore();
                    }
                }

                return result;
            };

            if (callback.length) {
                return function sinonAsyncSandboxedTest(callback) {
                    return sinonSandboxedTest.apply(this, arguments);
                };
            }

            return sinonSandboxedTest;
        }

        test.config = {
            injectIntoThis: true,
            injectInto: null,
            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
            useFakeTimers: true,
            useFakeServer: true
        };

        sinon.test = test;
        return test;
    }

    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;

    function loadDependencies(require, exports, module) {
        var sinon = require("./util/core");
        require("./sandbox");
        module.exports = makeApi(sinon);
    }

    if (isAMD) {
        define(loadDependencies);
    } else if (isNode) {
        loadDependencies(require, module.exports, module);
    } else if (!sinon) {
        return;
    } else {
        makeApi(sinon);
    }
}(typeof sinon == "object" && sinon || null));
<commit_msg>removed extraneous code<commit_after>/**
 * @depend util/core.js
 * @depend stub.js
 * @depend mock.js
 * @depend sandbox.js
 */
/**
 * Test function, sandboxes fakes
 *
 * @author Christian Johansen (christian@cjohansen.no)
 * @license BSD
 *
 * Copyright (c) 2010-2013 Christian Johansen
 */
"use strict";

(function (sinon) {
    function makeApi(sinon) {
        function test(callback) {
            var type = typeof callback;

            if (type != "function") {
                throw new TypeError("sinon.test needs to wrap a test function, got " + type);
            }

            function sinonSandboxedTest() {
                var config = sinon.getConfig(sinon.config);
                config.injectInto = config.injectIntoThis && this || config.injectInto;
                var sandbox = sinon.sandbox.create(config);
                var exception, result;
                var doneIsWrapped = false;
                var argumentsCopy = Array.prototype.slice.call(arguments);
                if (argumentsCopy.length > 0 && typeof argumentsCopy[arguments.length - 1] == "function") {
                    var oldDone = argumentsCopy[arguments.length - 1];
                    argumentsCopy[arguments.length - 1] = function done(result) {
                        if (result) {
                            sandbox.restore();
                            throw exception;
                        } else {
                            sandbox.verifyAndRestore();
                        }
                        oldDone(result);
                    }
                    doneIsWrapped = true;
                }

                var args = argumentsCopy.concat(sandbox.args);

                try {
                    result = callback.apply(this, args);
                } catch (e) {
                    exception = e;
                }

                if (!doneIsWrapped) {
                    if (typeof exception !== "undefined") {
                        sandbox.restore();
                        throw exception;
                    } else {
                        sandbox.verifyAndRestore();
                    }
                }

                return result;
            }

            if (callback.length) {
                return function sinonAsyncSandboxedTest() {
                    return sinonSandboxedTest.apply(this, arguments);
                };
            }

            return sinonSandboxedTest;
        }

        test.config = {
            injectIntoThis: true,
            injectInto: null,
            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
            useFakeTimers: true,
            useFakeServer: true
        };

        sinon.test = test;
        return test;
    }

    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;

    function loadDependencies(require, exports, module) {
        var sinon = require("./util/core");
        require("./sandbox");
        module.exports = makeApi(sinon);
    }

    if (isAMD) {
        define(loadDependencies);
    } else if (isNode) {
        loadDependencies(require, module.exports, module);
    } else if (sinon) {
        makeApi(sinon);
    }
}(typeof sinon == "object" && sinon || null));
<|endoftext|>