<commit_before>var Twitter = require('node-tweet-stream');

var isValidTweet = function (tweet, config) {
  var validTweet = true;

  //
  // Check that track keywords are part of tweet's text
  //
  var trackKeywords = config.application.trackKeywords.replace(',','|');
  var trackKeywordsRegex = new RegExp(trackKeywords, 'gim');

  if (! tweet.text.match(trackKeywordsRegex)) {
    validTweet = false;
  }

  // Validate tweet with filters
  config.application.filters.forEach(function (filter) {
    if (validTweet) {
      validTweet = require('../filters/' + filter).isValid(tweet);
    }
  });

  return validTweet;
};

module.exports = function (config, handleTweet) {
  var TWITTER_CONSUMER_KEY = config.twitter.api.consumerKey;
  var TWITTER_CONSUMER_SECRET = config.twitter.api.consumerSecret;
  var TWITTER_ACCESS_TOKEN_KEY = config.twitter.api.accessTokenKey;
  var TWITTER_ACCESS_TOKEN_SECRET = config.twitter.api.accessTokenSecret;
  var TWITTER_PICTURE_TRACK_KEYWORD = "pic twitter com";

  var keywords = [TWITTER_PICTURE_TRACK_KEYWORD, config.application.trackKeywords].join(' ');

  var twitter = new Twitter({
    consumer_key: TWITTER_CONSUMER_KEY,
    consumer_secret: TWITTER_CONSUMER_SECRET,
    token: TWITTER_ACCESS_TOKEN_KEY,
    token_secret: TWITTER_ACCESS_TOKEN_SECRET
  });

  twitter.on('tweet', function (tweet) {
    if (isValidTweet(tweet, config)) {
      handleTweet(tweet);
    }
  });

  twitter.on('error', function (error) {
    console.error('[Snapkite][Error] ' + error);
  })

  twitter.track(keywords);
};
<commit_msg>Bugfix<commit_after>var Twitter = require('node-tweet-stream');

var isValidTweet = function (tweet, config) {
  var validTweet = true;

  //
  // Check that track keywords are part of tweet's text
  //
  var trackKeywords = config.application.trackKeywords.replace(',','|');
  var trackKeywordsRegex = new RegExp('[' + trackKeywords + ']', 'gim');

  if (! tweet.text.match(trackKeywordsRegex)) {
    validTweet = false;
  }

  // Validate tweet with filters
  config.application.filters.forEach(function (filter) {
    if (validTweet) {
      validTweet = require('../filters/' + filter).isValid(tweet);
    }
  });

  return validTweet;
};

module.exports = function (config, handleTweet) {
  var TWITTER_CONSUMER_KEY = config.twitter.api.consumerKey;
  var TWITTER_CONSUMER_SECRET = config.twitter.api.consumerSecret;
  var TWITTER_ACCESS_TOKEN_KEY = config.twitter.api.accessTokenKey;
  var TWITTER_ACCESS_TOKEN_SECRET = config.twitter.api.accessTokenSecret;
  var TWITTER_PICTURE_TRACK_KEYWORD = "pic twitter com";

  var keywords = [TWITTER_PICTURE_TRACK_KEYWORD, config.application.trackKeywords].join(' ');

  var twitter = new Twitter({
    consumer_key: TWITTER_CONSUMER_KEY,
    consumer_secret: TWITTER_CONSUMER_SECRET,
    token: TWITTER_ACCESS_TOKEN_KEY,
    token_secret: TWITTER_ACCESS_TOKEN_SECRET
  });

  twitter.on('tweet', function (tweet) {
    if (isValidTweet(tweet, config)) {
      handleTweet(tweet);
    }
  });

  twitter.on('error', function (error) {
    console.error('[Snapkite][Error] ' + error);
  })

  twitter.track(keywords);
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

"use strict";

var fs = require("fs");
var path = require("path");
var child_process = require("child_process");
var optimist = require("optimist");

var argv = optimist
    .usage("Usage: nodebug script.js [options]")
    .options("help",       { alias: "h", describe: "Show this help" })
    .options("web-host",   { "default": "127.0.0.1", describe: "Web host used by node-inspector" })
    .options("web-port",   { "default": 8080, describe: "Web port used by node-inspector" })
    .options("debug-port", { "default": 5858, describe: "Debug port used by node" })
    .options("debug-brk",  { "default": true, describe: "Break on first line of script" })
    .options("keep-alive", { "default": false, describe: "Keep child processes alive after exit" })
    .argv;

if (argv["help"]) {
    showHelp();
}

if (!argv["_"].length) {
    showError("script required", true);
}

try {
    var scriptProcess = executeScript();
    var inspectorProcess = startInspector();
    var browserProcess = launchBrowser();
} catch (error) {
    showError(error.message, false);
}

process.on("exit", function () {
    if (!argv["keep-alive"]) {
        if (scriptProcess) {
            scriptProcess.kill();
        }

        if (inspectorProcess) {
            inspectorProcess.kill();
        }

        if (browserProcess) {
            browserProcess.kill();
        }
    }
});

/* Shows the help message and exits with success code */
function showHelp() {
    var help = optimist.help().trim();
    console.log(help);
    process.exit(0);
}

/* Shows an error message and exits with failure code */
function showError(message, includeHelp) {
    if (includeHelp) {
        var help = optimist.help().trim();
        console.error("Error: " + message + "\n" + help);
    } else {
        console.error("Error: " + message);
    }

    process.exit(1);
}

/* Executes the node script */
function executeScript() {
    var nodePath = process.execPath;
    var nodeArgs = [];

    if (argv["debug-brk"]) {
        nodeArgs.push("--debug-brk=" + argv["debug-port"]);
    } else {
        nodeArgs.push("--debug=" + argv["debug-port"]);
    }

    nodeArgs = nodeArgs.concat(argv["_"]);

    return child_process.spawn(nodePath, nodeArgs, { stdio: "inherit" }).on("exit", process.exit);
}

/* Starts node-inspector */
function startInspector() {
    var searchPaths = [];

    switch (process.platform) {
        case "win32":
            searchPaths.push(path.join(__dirname, "..", "node_modules", ".bin", "node-inspector.cmd"));
            break;

        default:
            searchPaths.push(path.join(__dirname, "..", "node_modules", ".bin", "node-inspector"));
            break;
    }

    var inspectorPath = firstExistingPath(searchPaths);
    var inspectorArgs = [];

    inspectorArgs.push("--web-host=" + argv["web-host"]);
    inspectorArgs.push("--web-port=" + argv["web-port"]);

    return child_process.execFile(inspectorPath, inspectorArgs);
}

/* Launches a web browser (i.e. Chrome) */
function launchBrowser() {
    var searchPaths = [];

    switch (process.platform) {
        case "win32":
            searchPaths.push(path.join(process.env["LocalAppData"], "Google", "Chrome", "Application", "chrome.exe"));
            searchPaths.push(path.join(process.env["ProgramFiles"], "Google", "Chrome", "Application", "chrome.exe"));
            searchPaths.push(path.join(process.env["ProgramFiles(x86)"], "Google", "Chrome", "Application", "chrome.exe"));
            break;

        case "darwin":
            searchPaths.push(path.join("/", "Applications", "Google Chrome.app", "Contents", "MacOS", "Google Chrome"));
            break;

        default:
            searchPaths.push(path.join("/", "opt", "google", "chrome", "google-chrome"));
            break;
    }

    var browserPath = firstExistingPath(searchPaths);
    var browserArgs = [];

    browserArgs.push("--app=http://" + argv["web-host"] + ":" + argv["web-port"] + "/debug?port=" + argv["debug-port"]);
    browserArgs.push("--user-data-dir=" + path.join(__dirname, "..", "ChromeProfile"));

    return child_process.execFile(browserPath, browserArgs);
}

/* Searches an array of paths for the first one that exists */
function firstExistingPath(paths) {
    for (var i = 0; i < paths.length; i++) {
        if (fs.existsSync(paths[i])) {
            return paths[i];
        }
    }

    throw "file not found: " + path.basename(paths[0]);
}<commit_msg>Fixed error handling when chrome or node-inspector is not found<commit_after>#!/usr/bin/env node

"use strict";

var fs = require("fs");
var path = require("path");
var child_process = require("child_process");
var optimist = require("optimist");

var argv = optimist
    .usage("Usage: nodebug script.js [options]")
    .options("help",       { alias: "h", describe: "Show this help" })
    .options("web-host",   { "default": "127.0.0.1", describe: "Web host used by node-inspector" })
    .options("web-port",   { "default": 8080, describe: "Web port used by node-inspector" })
    .options("debug-port", { "default": 5858, describe: "Debug port used by node" })
    .options("debug-brk",  { "default": true, describe: "Break on first line of script" })
    .options("keep-alive", { "default": false, describe: "Keep child processes alive after exit" })
    .argv;

if (argv["help"]) {
    showHelp();
}

if (!argv["_"].length) {
    showError("script required", true);
}

try {
    var inspectorProcess = startInspector();
    var browserProcess = launchBrowser();
    var scriptProcess = executeScript();
} catch (error) {
    showError(error.message, false);
}

process.on("exit", function () {
    if (!argv["keep-alive"]) {
        if (scriptProcess) {
            scriptProcess.kill();
        }

        if (inspectorProcess) {
            inspectorProcess.kill();
        }

        if (browserProcess) {
            browserProcess.kill();
        }
    }
});

/* Shows the help message and exits with success code */
function showHelp() {
    var help = optimist.help().trim();
    console.log(help);
    process.exit(0);
}

/* Shows an error message and exits with failure code */
function showError(message, includeHelp) {
    if (includeHelp) {
        var help = optimist.help().trim();
        console.error("Error: " + message + "\n" + help);
    } else {
        console.error("Error: " + message);
    }

    process.exit(1);
}

/* Executes the node script */
function executeScript() {
    var nodePath = process.execPath;
    var nodeArgs = [];

    if (argv["debug-brk"]) {
        nodeArgs.push("--debug-brk=" + argv["debug-port"]);
    } else {
        nodeArgs.push("--debug=" + argv["debug-port"]);
    }

    nodeArgs = nodeArgs.concat(argv["_"]);

    return child_process.spawn(nodePath, nodeArgs, { stdio: "inherit" }).on("exit", process.exit);
}

/* Starts node-inspector */
function startInspector() {
    var searchPaths = [];

    switch (process.platform) {
        case "win32":
            searchPaths.push(path.join(__dirname, "..", "node_modules", ".bin", "node-inspector.cmd"));
            break;

        default:
            searchPaths.push(path.join(__dirname, "..", "node_modules", ".bin", "node-inspector"));
            break;
    }

    var inspectorPath = firstExistingPath("node-inspector", searchPaths);
    var inspectorArgs = [];

    inspectorArgs.push("--web-host=" + argv["web-host"]);
    inspectorArgs.push("--web-port=" + argv["web-port"]);

    return child_process.execFile(inspectorPath, inspectorArgs);
}

/* Launches a web browser (i.e. Chrome) */
function launchBrowser() {
    var searchPaths = [];

    switch (process.platform) {
        case "win32":
            searchPaths.push(path.join(process.env["LocalAppData"], "Google", "Chrome", "Application", "chrome.exe"));
            searchPaths.push(path.join(process.env["ProgramFiles"], "Google", "Chrome", "Application", "chrome.exe"));
            searchPaths.push(path.join(process.env["ProgramFiles(x86)"], "Google", "Chrome", "Application", "chrome.exe"));
            break;

        case "darwin":
            searchPaths.push(path.join("/", "Applications", "Google Chrome.app", "Contents", "MacOS", "Google Chrome"));
            break;

        default:
            searchPaths.push(path.join("/", "opt", "google", "chrome", "google-chrome"));
            break;
    }

    var browserPath = firstExistingPath("chrome", searchPaths);
    var browserArgs = [];

    browserArgs.push("--app=http://" + argv["web-host"] + ":" + argv["web-port"] + "/debug?port=" + argv["debug-port"]);
    browserArgs.push("--user-data-dir=" + path.join(__dirname, "..", "ChromeProfile"));

    return child_process.execFile(browserPath, browserArgs);
}

/* Searches an array of paths for the first one that exists */
function firstExistingPath(description, paths) {
    for (var i = 0; i < paths.length; i++) {
        if (fs.existsSync(paths[i])) {
            return paths[i];
        }
    }

    throw new Error(description + " not found");
}<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { node, string, object, bool } from 'prop-types'

export const combineHeaders = (searchParams = {}) => {
  return Object.keys(searchParams)
    .map(key => `${key}=${encodeURIComponent(searchParams[key])}`)
    .join('&')
}

export const createContactLink = (tel, sms, facetime, email, headers) => {
  let link
  if (email) {
    link = `mailto:${email}`
    if (headers) {
      link += `?${combineHeaders(headers)}`
    }
  } else if (tel) {
    link = `tel:${tel}`
  } else if (sms) {
    link = `sms:${sms}`
  } else if (facetime) {
    link = `facetime:${facetime}`
  }
  return link
}

class Obfuscate extends Component {
  render() {
    return this.props.obfuscate
      ? this.renderObfuscatedLink()
      : this.renderLink()
  }

  renderLink() {
    const {
      tel,
      sms,
      facetime,
      email,
      obfuscate,
      headers,
      children,
      ...others
    } = this.props
    return (
      <a
        href={createContactLink(tel, sms, facetime, email, headers)}
        {...others}
      >
        {children || tel || sms || facetime || email}
      </a>
    )
  }

  reverse(s) {
    return s
      .split('')
      .reverse()
      .join('')
  }

  renderObfuscatedLink() {
    const {
      tel,
      sms,
      facetime,
      email,
      obfuscate,
      headers,
      children,
      style,
      ...others
    } = this.props

    const obsStyle = {
      ...(style || {}),
      unicodeBidi: 'bidi-override',
    };

    if (!children) {
      obsStyle.direction = 'rtl';
    }

    return (
      <a
        onClick={this.handleClick.bind(this)}
        href="obfuscated"
        {...others}
        style={obsStyle}
      >
        {
          children ||
          this.reverse(tel || sms || facetime || email)
            .replace('(', ')')
            .replace(')', '(')
        }
      </a>
    )
  }

  handleClick(event) {
    event.preventDefault()
    const { tel, sms, facetime, email, headers } = this.props
    window.location.href = createContactLink(tel, sms, facetime, email, headers)
  }
}

Obfuscate.propTypes = {
  children: node,
  tel: string,
  sms: string,
  facetime: string,
  email: string,
  headers: object,
  obfuscate: bool,
  style: object,
}

Obfuscate.defaultProps = {
  obfuscate: true,
}

export default Obfuscate
<commit_msg>Format code<commit_after>import React, { Component } from 'react'
import { node, string, object, bool } from 'prop-types'

export const combineHeaders = (searchParams = {}) => {
  return Object.keys(searchParams)
    .map(key => `${key}=${encodeURIComponent(searchParams[key])}`)
    .join('&')
}

export const createContactLink = (tel, sms, facetime, email, headers) => {
  let link
  if (email) {
    link = `mailto:${email}`
    if (headers) {
      link += `?${combineHeaders(headers)}`
    }
  } else if (tel) {
    link = `tel:${tel}`
  } else if (sms) {
    link = `sms:${sms}`
  } else if (facetime) {
    link = `facetime:${facetime}`
  }
  return link
}

class Obfuscate extends Component {
  render() {
    return this.props.obfuscate
      ? this.renderObfuscatedLink()
      : this.renderLink()
  }

  renderLink() {
    const {
      tel,
      sms,
      facetime,
      email,
      obfuscate,
      headers,
      children,
      ...others
    } = this.props
    return (
      <a
        href={createContactLink(tel, sms, facetime, email, headers)}
        {...others}
      >
        {children || tel || sms || facetime || email}
      </a>
    )
  }

  reverse(s) {
    return s
      .split('')
      .reverse()
      .join('')
  }

  renderObfuscatedLink() {
    const {
      tel,
      sms,
      facetime,
      email,
      obfuscate,
      headers,
      children,
      style,
      ...others
    } = this.props

    const obsStyle = {
      ...(style || {}),
      unicodeBidi: 'bidi-override',
    }

    if (!children) {
      obsStyle.direction = 'rtl'
    }

    return (
      <a
        onClick={this.handleClick.bind(this)}
        href="obfuscated"
        {...others}
        style={obsStyle}
      >
        {children ||
          this.reverse(tel || sms || facetime || email)
            .replace('(', ')')
            .replace(')', '(')}
      </a>
    )
  }

  handleClick(event) {
    event.preventDefault()
    const { tel, sms, facetime, email, headers } = this.props
    window.location.href = createContactLink(tel, sms, facetime, email, headers)
  }
}

Obfuscate.propTypes = {
  children: node,
  tel: string,
  sms: string,
  facetime: string,
  email: string,
  headers: object,
  obfuscate: bool,
  style: object,
}

Obfuscate.defaultProps = {
  obfuscate: true,
}

export default Obfuscate
<|endoftext|>


<commit_before>/*
 * This file is part of the Spludo Framework.
 * Copyright (c) 2009 DracoBlue, http://dracoblue.net/
 *
 * Licensed under the terms of MIT License. For the full copyright and license
 * information, please see the LICENSE file in the root folder.
 */

/**
 * @class The manager for all registered sessions.
 *
 * @extends Logging
 *
 * @since 0.1
 * @author DracoBlue
 */
SessionManager = function(options) {
    options = options || {};

    var engine = options.engine || MemoryStorage;
    this.storage = new engine("session_manager", options.engine_options || {});
};

process.mixin(true, SessionManager.prototype, Logging.prototype);

SessionManager.prototype.removeSession = function(session_id) {
    this.storage.remove(session_id);
    this.info("removeSession: " + session_id);
};

SessionManager.prototype.getSession = function(session_id) {
    var session = this.storage.get(session_id) || null;

    if (session === null) {
        throw new Error("Session for id " + session_id + " not found!");
    }

    return JSON.parse(session);
};

SessionManager.prototype.setSession = function(session_id, session) {
    this.storage.set(session_id, JSON.stringify(session));
};

SessionManager.prototype.createSession = function(session) {
    var session_id = null;

    /*
     * FIXME: This is an ugly solution. Guess what happens if we have lots
     * of session. We need some way better function here.
     */
    while (session_id === null) {
        session_id = new String(Math.floor(Math.random()*999999999));
        if (this.storage.has(session_id)) {
            session_id = null;
        }
    }

    this.storage.set(session_id, JSON.stringify(session));

    return session_id;
};
<commit_msg>Added createSession info.<commit_after>/*
 * This file is part of the Spludo Framework.
 * Copyright (c) 2009 DracoBlue, http://dracoblue.net/
 *
 * Licensed under the terms of MIT License. For the full copyright and license
 * information, please see the LICENSE file in the root folder.
 */

/**
 * @class The manager for all registered sessions.
 *
 * @extends Logging
 *
 * @since 0.1
 * @author DracoBlue
 */
SessionManager = function(options) {
    options = options || {};

    var engine = options.engine || MemoryStorage;
    this.storage = new engine("session_manager", options.engine_options || {});
};

process.mixin(true, SessionManager.prototype, Logging.prototype);

SessionManager.prototype.removeSession = function(session_id) {
    this.storage.remove(session_id);
    this.info("removeSession: " + session_id);
};

SessionManager.prototype.getSession = function(session_id) {
    var session = this.storage.get(session_id) || null;

    if (session === null) {
        throw new Error("Session for id " + session_id + " not found!");
    }

    return JSON.parse(session);
};

SessionManager.prototype.setSession = function(session_id, session) {
    this.storage.set(session_id, JSON.stringify(session));
};

SessionManager.prototype.createSession = function(session) {
    var session_id = null;

    /*
     * FIXME: This is an ugly solution. Guess what happens if we have lots
     * of session. We need some way better function here.
     */
    while (session_id === null) {
        session_id = new String(Math.floor(Math.random()*999999999));
        if (this.storage.has(session_id)) {
            session_id = null;
        }
    }

    this.storage.set(session_id, JSON.stringify(session));

    this.info("createSession: " + session_id);

    return session_id;
};
<|endoftext|>


<commit_before>import util from '../../util';
import Parser from '../parser';

/**
 * 分解字符串函数参数
 * @param   {String}  funcString
 * @return  {Object}
 */
function stringToParams (funcString) {
	var args, func;
	var exp = util.removeSpace(funcString);
	var matches = exp.match(/(\(.*\))/);
	var result = matches && matches[0];

	// 有函数名和参数
	if (result) {
		func = exp.substr(0, exp.indexOf(result));
		args = '[' + result.substr(1, result.length - 2) + ']';
	} else {
		func = exp;
	}

	return {
		'func': func,
		'args': args
	}
}

/**
 * 字符 json 转为键值对象
 * @param   {String}  jsonString
 * @return  {Object}
 */
function convertJson (jsonString) {
	var json, string = jsonString.trim();

	if (/^\{.*\}$/.test(string)) {
		json = {};
		let leng = string.length;
		string = string.substr(1, leng - 2).replace(/\s/g, '');
		let props = string.match(/[^,]+:[^:]+((?=,[^:]+:)|$)/g);

		util.each(props, function (prop) {
			var vals = util.getKeyValue(prop, true);
			var name = vals[0], value = vals[1];
			if (name && value) {
				name = name.replace(/(^'*)|('*$)|(^"*)|("*$)/g, '');
				json[name] = value;
			}
		});
	}

	return json;
}

/**
 * v-on 指令解析模块
 */
function Von (vm) {
	this.vm = vm;
	Parser.call(this);
}
var von = Von.prototype = Object.create(Parser.prototype);

/**
 * 解析 v-on 指令
 * @param   {Object}      fors        [vfor 数据]
 * @param   {DOMElement}  node        [指令节点]
 * @param   {String}      expression  [指令表达式]
 * @param   {String}      directive   [指令名称]
 */
von.parse = function (fors, node, expression, directive) {
	// 单个事件
	if (directive.indexOf(':') > -1) {
		this.parseSingle.apply(this, arguments);
	}
	// 多个事件
	else {
		this.parseJson.apply(this, arguments);
	}
}

/**
 * 解析单个 v-on:type
 */
von.parseSingle = function (fors, node, expression, directive) {
	// 事件信息
	var info = stringToParams(expression);
	// 事件类型
	var type = util.getKeyValue(directive);
	// 事件取值字段名称
	var field = info.func;
	// 参数字符串
	var paramString = info.args;

	// 获取事件函数
	var deps = this.getDeps(fors, field);
	var scope = this.getScope(fors, field);
	var getter = this.getEval(fors, field);
	var func = getter.call(scope, scope);

	// 绑定事件 & 参数求值
	this.bindEvent(fors, node, field, type, func, paramString);

	// 监测依赖变化，绑定新回调，旧回调将被移除
	this.vm.watcher.watch(deps, function (path, lastCallback, oldCallback) {
		// 解除绑定
		this.update(node, type, oldCallback, false, true);
		// 绑定新回调
		this.bindEvent(fors, node, path, type, lastCallback, paramString);
	}, this);
}

/**
 * 解析多个 v-on=eventJson
 */
von.parseJson = function (fors, node, expression) {
	util.each(convertJson(expression), function (exp, type) {
		this.parseSingle(fors, node, exp, type);
	}, this);
}

/**
 * 绑定一个事件
 * @param   {Object}      fors
 * @param   {DOMElement}  node
 * @param   {String}      field
 * @param   {String}      evt
 * @param   {Function}    func
 * @param   {String}      paramString
 */
von.bindEvent = function (fors, node, field, evt, func, paramString) {
	var self, stop, prevent, keyCode, capture = false;

	// 支持 4 种事件修饰符 .self .stop .prevent .capture
	if (evt.indexOf('.') > -1) {
		let modals = evt.split('.');
		evt = modals.shift();
		self = modals && modals.indexOf('self') > -1;
		stop = modals && modals.indexOf('stop') > -1;
		prevent = modals && modals.indexOf('prevent') > -1;
		capture = modals && modals.indexOf('capture') > -1;
		keyCode = evt.indexOf('key') === 0 ? +modals[0] : null;
	}

	// 处理回调参数以及依赖监测
	var args = [];
	if (paramString) {
		// 取值依赖
		let deps = this.getDeps(fors, paramString);
		// 别名映射
		let maps = fors && util.copy(fors.maps);
		// 取值域
		let scope = this.getScope(fors, paramString);
		// 添加别名标记
		util.defRec(scope, '$event', '$event');
		// 取值函数
		let getter = this.getEval(fors, paramString);
		// 事件参数
		args = getter.call(scope, scope);

		this.vm.watcher.watch(deps, function () {
			scope = this.updateScope(scope, maps, deps, arguments);
			args = getter.call(scope, scope);
		}, this);
	}

	// 事件代理函数
	var eventProxy = function _eventProxy (e) {
		// 是否限定只能在当前节点触发事件
		if (self && e.target !== node) {
			return;
		}

		// 是否指定按键触发
		if (keyCode && keyCode !== e.keyCode) {
			return;
		}

		// 未指定参数，则原生事件对象作为唯一参数
		if (!args.length) {
			args.push(e);
		} else {
			// 更新/替换事件对象
			util.each(args, function (param, index) {
				if (param === '$event' || param instanceof Event) {
					args[index] = e;
				}
			});
		}

		// 是否阻止冒泡
		if (stop) {
			e.stopPropagation();
		}

		// 是否阻止默认事件
		if (prevent) {
			e.preventDefault();
		}

		func.apply(this, args);
	}

	// 添加绑定
	this.update(node, evt, eventProxy, capture);
}

/**
 * 更新绑定事件
 * @param   {DOMElement}   node
 * @param   {String}       evt
 * @param   {Function}     callback
 * @param   {Boolean}      capture
 */
von.update = function () {
	var updater = this.vm.updater;
	updater.updateEvent.apply(updater, arguments);
}

export default Von;
<commit_msg>Extract regular expression from some functions.<commit_after>import util from '../../util';
import Parser from '../parser';

const regBigBrackets = /^\{.*\}$/;
const regSmallBrackets = /(\(.*\))/;
const regQuotes = /(^'*)|('*$)|(^"*)|("*$)/g;
const regJsonFormat = /[^,]+:[^:]+((?=,[^:]+:)|$)/g;

/**
 * 分解字符串函数参数
 * @param   {String}  funcString
 * @return  {Object}
 */
function stringToParams (funcString) {
	var args, func;
	var exp = util.removeSpace(funcString);
	var matches = exp.match(regSmallBrackets);
	var result = matches && matches[0];

	// 有函数名和参数
	if (result) {
		func = exp.substr(0, exp.indexOf(result));
		args = '[' + result.substr(1, result.length - 2) + ']';
	} else {
		func = exp;
	}

	return { func, args };
}

/**
 * 字符 json 转为键值对象
 * @param   {String}  jsonString
 * @return  {Object}
 */
function convertJson (jsonString) {
	var json, string = jsonString.trim();

	if (regBigBrackets.test(string)) {
		json = {};
		let leng = string.length;
		string = string.substr(1, leng - 2).replace(/\s/g, '');
		let props = string.match(regJsonFormat);

		util.each(props, function (prop) {
			var vals = util.getKeyValue(prop, true);
			var name = vals[0], value = vals[1];
			if (name && value) {
				name = name.replace(regQuotes, '');
				json[name] = value;
			}
		});
	}

	return json;
}

/**
 * v-on 指令解析模块
 */
function Von (vm) {
	this.vm = vm;
	Parser.call(this);
}
var von = Von.prototype = Object.create(Parser.prototype);

/**
 * 解析 v-on 指令
 * @param   {Object}      fors        [vfor 数据]
 * @param   {DOMElement}  node        [指令节点]
 * @param   {String}      expression  [指令表达式]
 * @param   {String}      directive   [指令名称]
 */
von.parse = function (fors, node, expression, directive) {
	// 单个事件
	if (directive.indexOf(':') > -1) {
		this.parseSingle.apply(this, arguments);
	}
	// 多个事件
	else {
		this.parseJson.apply(this, arguments);
	}
}

/**
 * 解析单个 v-on:type
 */
von.parseSingle = function (fors, node, expression, directive) {
	// 事件信息
	var info = stringToParams(expression);
	// 事件类型
	var type = util.getKeyValue(directive);
	// 事件取值字段名称
	var field = info.func;
	// 参数字符串
	var paramString = info.args;

	// 获取事件函数
	var deps = this.getDeps(fors, field);
	var scope = this.getScope(fors, field);
	var getter = this.getEval(fors, field);
	var func = getter.call(scope, scope);

	// 绑定事件 & 参数求值
	this.bindEvent(fors, node, field, type, func, paramString);

	// 监测依赖变化，绑定新回调，旧回调将被移除
	this.vm.watcher.watch(deps, function (path, lastCallback, oldCallback) {
		// 解除绑定
		this.update(node, type, oldCallback, false, true);
		// 绑定新回调
		this.bindEvent(fors, node, path, type, lastCallback, paramString);
	}, this);
}

/**
 * 解析多个 v-on=eventJson
 */
von.parseJson = function (fors, node, expression) {
	util.each(convertJson(expression), function (exp, type) {
		this.parseSingle(fors, node, exp, type);
	}, this);
}

/**
 * 绑定一个事件
 * @param   {Object}      fors
 * @param   {DOMElement}  node
 * @param   {String}      field
 * @param   {String}      evt
 * @param   {Function}    func
 * @param   {String}      paramString
 */
von.bindEvent = function (fors, node, field, evt, func, paramString) {
	var self, stop, prevent, keyCode, capture = false;

	// 支持 4 种事件修饰符 .self .stop .prevent .capture
	if (evt.indexOf('.') > -1) {
		let modals = evt.split('.');
		evt = modals.shift();
		self = modals && modals.indexOf('self') > -1;
		stop = modals && modals.indexOf('stop') > -1;
		prevent = modals && modals.indexOf('prevent') > -1;
		capture = modals && modals.indexOf('capture') > -1;
		keyCode = evt.indexOf('key') === 0 ? +modals[0] : null;
	}

	// 处理回调参数以及依赖监测
	var args = [];
	if (paramString) {
		// 取值依赖
		let deps = this.getDeps(fors, paramString);
		// 别名映射
		let maps = fors && util.copy(fors.maps);
		// 取值域
		let scope = this.getScope(fors, paramString);
		// 添加别名标记
		util.defRec(scope, '$event', '$event');
		// 取值函数
		let getter = this.getEval(fors, paramString);
		// 事件参数
		args = getter.call(scope, scope);

		this.vm.watcher.watch(deps, function () {
			scope = this.updateScope(scope, maps, deps, arguments);
			args = getter.call(scope, scope);
		}, this);
	}

	// 事件代理函数
	var eventProxy = function _eventProxy (e) {
		// 是否限定只能在当前节点触发事件
		if (self && e.target !== node) {
			return;
		}

		// 是否指定按键触发
		if (keyCode && keyCode !== e.keyCode) {
			return;
		}

		// 未指定参数，则原生事件对象作为唯一参数
		if (!args.length) {
			args.push(e);
		} else {
			// 更新/替换事件对象
			util.each(args, function (param, index) {
				if (param === '$event' || param instanceof Event) {
					args[index] = e;
				}
			});
		}

		// 是否阻止冒泡
		if (stop) {
			e.stopPropagation();
		}

		// 是否阻止默认事件
		if (prevent) {
			e.preventDefault();
		}

		func.apply(this, args);
	}

	// 添加绑定
	this.update(node, evt, eventProxy, capture);
}

/**
 * 更新绑定事件
 * @param   {DOMElement}   node
 * @param   {String}       evt
 * @param   {Function}     callback
 * @param   {Boolean}      capture
 */
von.update = function () {
	var updater = this.vm.updater;
	updater.updateEvent.apply(updater, arguments);
}

export default Von;
<|endoftext|>


<commit_before>#!/usr/bin/env node

/**
 * Builds app binaries for OS X, Linux, and Windows.
 */

var config = require('../config')
var cp = require('child_process')
var electronPackager = require('electron-packager')
var fs = require('fs')
var path = require('path')
var pkg = require('../package.json')

var BUILD_NAME = config.APP_NAME + '-v' + config.APP_VERSION

function build () {
  var platform = process.argv[2]
  if (platform === '--darwin') {
    buildDarwin(printDone)
  } else if (platform === '--win32') {
    buildWin32(printDone)
  } else if (platform === '--linux') {
    buildLinux(printDone)
  } else {
    buildDarwin(function (err, buildPath) {
      printDone(err, buildPath)
      buildWin32(function (err, buildPath) {
        printDone(err, buildPath)
        buildLinux(printDone)
      })
    })
  }
}

var all = {
  // Build 64 bit binaries only.
  arch: 'x64',

  // The application source directory.
  dir: config.ROOT_PATH,

  // The release version of the application. Maps to the `ProductVersion` metadata
  // property on Windows, and `CFBundleShortVersionString` on OS X.
  'app-version': pkg.version,

  // Package the application's source code into an archive, using Electron's archive
  // format. Mitigates issues around long path names on Windows and slightly speeds up
  // require().
  asar: true,

  // A glob expression, that unpacks the files with matching names to the
  // "app.asar.unpacked" directory.
  'asar-unpack': 'WebTorrent*',

  // The build version of the application. Maps to the FileVersion metadata property on
  // Windows, and CFBundleVersion on OS X. We're using the short git hash (e.g. 'e7d837e')
  // Windows requires the build version to start with a number :/ so we stick on a prefix
  'build-version': '0-' + cp.execSync('git rev-parse --short HEAD').toString().replace('\n', ''),

  // Pattern which specifies which files to ignore when copying files to create the
  // package(s).
  ignore: /^\/dist|\/(appveyor.yml|AUTHORS|CONTRIBUTORS|bench|benchmark|benchmark\.js|bin|bower\.json|component\.json|coverage|doc|docs|docs\.mli|dragdrop\.min\.js|example|examples|example\.html|example\.js|externs|ipaddr\.min\.js|Makefile|min|minimist|perf|rusha|simplepeer\.min\.js|simplewebsocket\.min\.js|static\/screenshot\.png|test|tests|test\.js|tests\.js|webtorrent\.min\.js|\.[^\/]*|.*\.md|.*\.markdown)$/,

  // The application name.
  name: config.APP_NAME,

  // The base directory where the finished package(s) are created.
  out: path.join(config.ROOT_PATH, 'dist'),

  // Replace an already existing output directory.
  overwrite: true,

  // Runs `npm prune --production` which remove the packages specified in
  // "devDependencies" before starting to package the app.
  prune: true,

  // The Electron version with which the app is built (without the leading 'v')
  version: pkg.devDependencies['electron-prebuilt']
}

var darwin = {
  platform: 'darwin',

  // The bundle identifier to use in the application's plist (OS X only).
  'app-bundle-id': 'io.webtorrent.app',

  // The application category type, as shown in the Finder via "View" -> "Arrange by
  // Application Category" when viewing the Applications directory (OS X only).
  'app-category-type': 'public.app-category.utilities',

  // The bundle identifier to use in the application helper's plist (OS X only).
  'helper-bundle-id': 'io.webtorrent.app.helper',

  // Application icon.
  icon: config.APP_ICON + '.icns'
}

var win32 = {
  platform: 'win32',

  // Object hash of application metadata to embed into the executable (Windows only)
  'version-string': {

    // Company that produced the file.
    CompanyName: config.APP_NAME,

    // Copyright notices that apply to the file.
    LegalCopyright: config.APP_COPYRIGHT,

    // Name of the program, displayed to users
    FileDescription: config.APP_NAME,

    // Original name of the file, not including a path. This information enables an
    // application to determine whether a file has been renamed by a user. The format of
    // the name depends on the file system for which the file was created.
    OriginalFilename: 'WebTorrent.exe',

    // Name of the product with which the file is distributed.
    ProductName: config.APP_NAME,

    // Internal name of the file, if one exists, for example, a module name if the file
    // is a dynamic-link library. If the file has no internal name, this string should be
    // the original filename, without extension. This string is required.
    InternalName: config.APP_NAME
  },

  // Application icon.
  icon: config.APP_ICON + '.ico'
}

var linux = {
  platform: 'linux'

  // Note: Application icon for Linux is specified via the BrowserWindow `icon` option.
}

build()

function buildDarwin (cb) {
  var appDmg = require('appdmg')
  var plist = require('plist')
  var sign = require('electron-osx-sign')

  electronPackager(Object.assign({}, all, darwin), function (err, buildPath) {
    if (err) return cb(err)

    var appPath = path.join(buildPath[0], config.APP_NAME + '.app')
    var contentsPath = path.join(appPath, 'Contents')
    var resourcesPath = path.join(contentsPath, 'Resources')
    var infoPlistPath = path.join(contentsPath, 'Info.plist')
    var infoPlist = plist.parse(fs.readFileSync(infoPlistPath, 'utf8'))

    infoPlist.CFBundleDocumentTypes = [
      {
        CFBundleTypeExtensions: [ 'torrent' ],
        CFBundleTypeIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleTypeName: 'BitTorrent Document',
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSItemContentTypes: [ 'org.bittorrent.torrent' ]
      },
      {
        CFBundleTypeName: 'Any',
        CFBundleTypeOSTypes: [ '****' ],
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSTypeIsPackage: false
      }
    ]

    infoPlist.CFBundleURLTypes = [
      {
        CFBundleTypeRole: 'Editor',
        CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleURLName: 'BitTorrent Magnet URL',
        CFBundleURLSchemes: [ 'magnet' ]
      }
    ]

    infoPlist.NSHumanReadableCopyright = config.APP_COPYRIGHT

    fs.writeFileSync(infoPlistPath, plist.build(infoPlist))

    // Copy torrent file icon into app bundle
    cp.execSync(`cp ${config.APP_FILE_ICON + '.icns'} ${resourcesPath}`)

    if (process.platform === 'darwin') {
      /*
       * Sign the app with Apple Developer ID certificate. We sign the app for 2 reasons:
       *   - So the auto-updater (Squirrrel.Mac) can check that app updates are signed by
       *     the same author as the current version.
       *   - So users will not a see a warning about the app coming from an "Unidentified
       *     Developer" when they open it for the first time (OS X Gatekeeper).
       *
       * To sign an OS X app for distribution outside the App Store, the following are
       * required:
       *   - Xcode
       *   - Xcode Command Line Tools (xcode-select --install)
       *   - Membership in the Apple Developer Program
       */
      var signOpts = {
        app: appPath,
        platform: 'darwin',
        verbose: true
      }

      sign(signOpts, function (err) {
        if (err) return cb(err)

        // Create .zip file (used by the auto-updater)
        var zipPath = path.join(buildPath[0], BUILD_NAME + '.zip')
        cp.execSync(`pushd ${buildPath[0]} && zip -r -y ${zipPath} ${config.APP_NAME + '.app'} && popd`)

        // Create a .dmg (OS X disk image) file, for easy user installation.
        var dmgOpts = {
          basepath: config.ROOT_PATH,
          target: path.join(buildPath[0], BUILD_NAME + '.dmg'),
          specification: {
            title: config.APP_NAME,
            icon: config.APP_ICON + '.icns',
            background: path.join(config.STATIC_PATH, 'appdmg.png'),
            'icon-size': 128,
            contents: [
              { x: 122, y: 240, type: 'file', path: appPath },
              { x: 380, y: 240, type: 'link', path: '/Applications' },
              // Hide hidden icons out of view, for users who have hidden files shown.
              // https://github.com/LinusU/node-appdmg/issues/45#issuecomment-153924954
              { x: 50, y: 500, type: 'position', path: '.background' },
              { x: 100, y: 500, type: 'position', path: '.DS_Store' },
              { x: 150, y: 500, type: 'position', path: '.Trashes' },
              { x: 200, y: 500, type: 'position', path: '.VolumeIcon.icns' }
            ]
          }
        }

        var dmg = appDmg(dmgOpts)
        dmg.on('error', cb)
        dmg.on('progress', function (info) {
          if (info.type === 'step-begin') console.log(info.title + '...')
        })
        dmg.on('finish', function (info) {
          cb(null, buildPath)
        })
      })
    }
  })
}

function buildWin32 (cb) {
  electronPackager(Object.assign({}, all, win32), cb)
}

function buildLinux (cb) {
  electronPackager(Object.assign({}, all, linux), cb)
}

function printDone (err, buildPath) {
  if (err) console.error(err.message || err)
  else console.log('Built ' + buildPath[0])
}
<commit_msg>OS X: pick a better bundle ID<commit_after>#!/usr/bin/env node

/**
 * Builds app binaries for OS X, Linux, and Windows.
 */

var config = require('../config')
var cp = require('child_process')
var electronPackager = require('electron-packager')
var fs = require('fs')
var path = require('path')
var pkg = require('../package.json')

var BUILD_NAME = config.APP_NAME + '-v' + config.APP_VERSION

function build () {
  var platform = process.argv[2]
  if (platform === '--darwin') {
    buildDarwin(printDone)
  } else if (platform === '--win32') {
    buildWin32(printDone)
  } else if (platform === '--linux') {
    buildLinux(printDone)
  } else {
    buildDarwin(function (err, buildPath) {
      printDone(err, buildPath)
      buildWin32(function (err, buildPath) {
        printDone(err, buildPath)
        buildLinux(printDone)
      })
    })
  }
}

var all = {
  // Build 64 bit binaries only.
  arch: 'x64',

  // The application source directory.
  dir: config.ROOT_PATH,

  // The release version of the application. Maps to the `ProductVersion` metadata
  // property on Windows, and `CFBundleShortVersionString` on OS X.
  'app-version': pkg.version,

  // Package the application's source code into an archive, using Electron's archive
  // format. Mitigates issues around long path names on Windows and slightly speeds up
  // require().
  asar: true,

  // A glob expression, that unpacks the files with matching names to the
  // "app.asar.unpacked" directory.
  'asar-unpack': 'WebTorrent*',

  // The build version of the application. Maps to the FileVersion metadata property on
  // Windows, and CFBundleVersion on OS X. We're using the short git hash (e.g. 'e7d837e')
  // Windows requires the build version to start with a number :/ so we stick on a prefix
  'build-version': '0-' + cp.execSync('git rev-parse --short HEAD').toString().replace('\n', ''),

  // Pattern which specifies which files to ignore when copying files to create the
  // package(s).
  ignore: /^\/dist|\/(appveyor.yml|AUTHORS|CONTRIBUTORS|bench|benchmark|benchmark\.js|bin|bower\.json|component\.json|coverage|doc|docs|docs\.mli|dragdrop\.min\.js|example|examples|example\.html|example\.js|externs|ipaddr\.min\.js|Makefile|min|minimist|perf|rusha|simplepeer\.min\.js|simplewebsocket\.min\.js|static\/screenshot\.png|test|tests|test\.js|tests\.js|webtorrent\.min\.js|\.[^\/]*|.*\.md|.*\.markdown)$/,

  // The application name.
  name: config.APP_NAME,

  // The base directory where the finished package(s) are created.
  out: path.join(config.ROOT_PATH, 'dist'),

  // Replace an already existing output directory.
  overwrite: true,

  // Runs `npm prune --production` which remove the packages specified in
  // "devDependencies" before starting to package the app.
  prune: true,

  // The Electron version with which the app is built (without the leading 'v')
  version: pkg.devDependencies['electron-prebuilt']
}

var darwin = {
  platform: 'darwin',

  // The bundle identifier to use in the application's plist (OS X only).
  'app-bundle-id': 'io.webtorrent.webtorrent',

  // The application category type, as shown in the Finder via "View" -> "Arrange by
  // Application Category" when viewing the Applications directory (OS X only).
  'app-category-type': 'public.app-category.utilities',

  // The bundle identifier to use in the application helper's plist (OS X only).
  'helper-bundle-id': 'io.webtorrent.webtorrent-helper',

  // Application icon.
  icon: config.APP_ICON + '.icns'
}

var win32 = {
  platform: 'win32',

  // Object hash of application metadata to embed into the executable (Windows only)
  'version-string': {

    // Company that produced the file.
    CompanyName: config.APP_NAME,

    // Copyright notices that apply to the file.
    LegalCopyright: config.APP_COPYRIGHT,

    // Name of the program, displayed to users
    FileDescription: config.APP_NAME,

    // Original name of the file, not including a path. This information enables an
    // application to determine whether a file has been renamed by a user. The format of
    // the name depends on the file system for which the file was created.
    OriginalFilename: 'WebTorrent.exe',

    // Name of the product with which the file is distributed.
    ProductName: config.APP_NAME,

    // Internal name of the file, if one exists, for example, a module name if the file
    // is a dynamic-link library. If the file has no internal name, this string should be
    // the original filename, without extension. This string is required.
    InternalName: config.APP_NAME
  },

  // Application icon.
  icon: config.APP_ICON + '.ico'
}

var linux = {
  platform: 'linux'

  // Note: Application icon for Linux is specified via the BrowserWindow `icon` option.
}

build()

function buildDarwin (cb) {
  var appDmg = require('appdmg')
  var plist = require('plist')
  var sign = require('electron-osx-sign')

  electronPackager(Object.assign({}, all, darwin), function (err, buildPath) {
    if (err) return cb(err)

    var appPath = path.join(buildPath[0], config.APP_NAME + '.app')
    var contentsPath = path.join(appPath, 'Contents')
    var resourcesPath = path.join(contentsPath, 'Resources')
    var infoPlistPath = path.join(contentsPath, 'Info.plist')
    var infoPlist = plist.parse(fs.readFileSync(infoPlistPath, 'utf8'))

    infoPlist.CFBundleDocumentTypes = [
      {
        CFBundleTypeExtensions: [ 'torrent' ],
        CFBundleTypeIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleTypeName: 'BitTorrent Document',
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSItemContentTypes: [ 'org.bittorrent.torrent' ]
      },
      {
        CFBundleTypeName: 'Any',
        CFBundleTypeOSTypes: [ '****' ],
        CFBundleTypeRole: 'Editor',
        LSHandlerRank: 'Owner',
        LSTypeIsPackage: false
      }
    ]

    infoPlist.CFBundleURLTypes = [
      {
        CFBundleTypeRole: 'Editor',
        CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
        CFBundleURLName: 'BitTorrent Magnet URL',
        CFBundleURLSchemes: [ 'magnet' ]
      }
    ]

    infoPlist.NSHumanReadableCopyright = config.APP_COPYRIGHT

    fs.writeFileSync(infoPlistPath, plist.build(infoPlist))

    // Copy torrent file icon into app bundle
    cp.execSync(`cp ${config.APP_FILE_ICON + '.icns'} ${resourcesPath}`)

    if (process.platform === 'darwin') {
      /*
       * Sign the app with Apple Developer ID certificate. We sign the app for 2 reasons:
       *   - So the auto-updater (Squirrrel.Mac) can check that app updates are signed by
       *     the same author as the current version.
       *   - So users will not a see a warning about the app coming from an "Unidentified
       *     Developer" when they open it for the first time (OS X Gatekeeper).
       *
       * To sign an OS X app for distribution outside the App Store, the following are
       * required:
       *   - Xcode
       *   - Xcode Command Line Tools (xcode-select --install)
       *   - Membership in the Apple Developer Program
       */
      var signOpts = {
        app: appPath,
        platform: 'darwin',
        verbose: true
      }

      sign(signOpts, function (err) {
        if (err) return cb(err)

        // Create .zip file (used by the auto-updater)
        var zipPath = path.join(buildPath[0], BUILD_NAME + '.zip')
        cp.execSync(`pushd ${buildPath[0]} && zip -r -y ${zipPath} ${config.APP_NAME + '.app'} && popd`)

        // Create a .dmg (OS X disk image) file, for easy user installation.
        var dmgOpts = {
          basepath: config.ROOT_PATH,
          target: path.join(buildPath[0], BUILD_NAME + '.dmg'),
          specification: {
            title: config.APP_NAME,
            icon: config.APP_ICON + '.icns',
            background: path.join(config.STATIC_PATH, 'appdmg.png'),
            'icon-size': 128,
            contents: [
              { x: 122, y: 240, type: 'file', path: appPath },
              { x: 380, y: 240, type: 'link', path: '/Applications' },
              // Hide hidden icons out of view, for users who have hidden files shown.
              // https://github.com/LinusU/node-appdmg/issues/45#issuecomment-153924954
              { x: 50, y: 500, type: 'position', path: '.background' },
              { x: 100, y: 500, type: 'position', path: '.DS_Store' },
              { x: 150, y: 500, type: 'position', path: '.Trashes' },
              { x: 200, y: 500, type: 'position', path: '.VolumeIcon.icns' }
            ]
          }
        }

        var dmg = appDmg(dmgOpts)
        dmg.on('error', cb)
        dmg.on('progress', function (info) {
          if (info.type === 'step-begin') console.log(info.title + '...')
        })
        dmg.on('finish', function (info) {
          cb(null, buildPath)
        })
      })
    }
  })
}

function buildWin32 (cb) {
  electronPackager(Object.assign({}, all, win32), cb)
}

function buildLinux (cb) {
  electronPackager(Object.assign({}, all, linux), cb)
}

function printDone (err, buildPath) {
  if (err) console.error(err.message || err)
  else console.log('Built ' + buildPath[0])
}
<|endoftext|>


<commit_before>"use strict";
//Config loggin level
var logger = require('winston');
logger.remove(logger.transports.Console);
logger.add(logger.transports.Console, {
	level: 'debug',
	colorize: true,
	timestamp: true
});

var path = require('path');
var fs = require('fs');
var request = require('request');
var https = require('https');
var exec = require('child_process').exec;

var CONFIG_PATH = path.join(process.cwd(), 'crowdin.json');
var crowdin = require(CONFIG_PATH);

/******* PRIVATE METHODS *******/
function refreshTranslations(callback) {
	logger.debug("Refreshing translation.");
	var opts = {
		uri: 'https://crowdin.com/api/project/' + crowdin.projectId + '/export',
		qs: {
			key: crowdin.apiKey
		}
	};
	request(opts, function(error, response) {
		if (!error && response.statusCode == 200) {
			logger.info("Translations refreshed.");
		} else {
			logger.error("Fail to refresh translation.");
		}
		callback(error);
	});
}

function downloadTranslations(callback) {
	logger.debug("Downloading translation.");
	var options = {
		hostname: 'crowdin.com',
		port: 443,
		path: '/api/project/' + crowdin.projectId + '/download/all.zip?key=' + crowdin.apiKey,
		method: 'GET'
	};

	var req = https.request(options, function(res) {
		res.on('data', function(chunk) {
			fs.appendFileSync('./all.zip', chunk);
		});
		res.on('end', function(error) {
			if (!error) {
				logger.info("Translations Dowloaded.");
			}
			callback(error);
		});
	});
	req.on('error', function(e) {
		logger.error('problem with request: ' + e.message);
	});
	req.end();
}

function uploadKeys(fileName, realFileName, callback) {
	logger.debug('Uploading traductions...');
	var formData = {};
	formData['files[' + fileName + ']'] = fs.createReadStream('./i18n/' + realFileName);

	request.post({
		url: 'https://crowdin.com/api/project/' + crowdin.projectId + '/add-file?key=' + crowdin.apiKey,
		formData: formData
	}, function(err) {
		if (err) {
			logger.error('Upload failed.', err);
		} else {
			logger.info('Traductions uploaded successfully!');
		}
		callback(err);
	});
}

function upgradeKeys(fileName, realFileName, callback) {
	logger.debug('Uploading traductions...');
	var formData = {};
	formData['files[' + fileName + ']'] = fs.createReadStream('./i18n/' + realFileName);

	request.post({
		url: 'https://crowdin.com/api/project/' + crowdin.projectId + '/update-file?key=' + crowdin.apiKey,
		formData: formData
	}, function(err) {
		if (err) {
			logger.error('Upload failed.', err);
		} else {
			logger.info('Traductions uploaded successfully!');
		}
		callback(err);
	});
}

function mergeTranslations(srcFile, outputFile, callback) {
	logger.info('Merging transalations.');
	exec("msgcat ./i18n/" + srcFile + " ./i18n/es-AR/" + srcFile + " -o ./i18n/" + outputFile, callback);
}

function initPaths(fileName) {
	logger.info('Initializing...');
	if (!fs.existsSync('./i18n')) {
		fs.mkdirSync('./i18n');
	}
	if (fs.existsSync('./i18n/' + fileName)) {
		fs.truncateSync('./i18n/' + fileName, 0);
	} else {
		fs.writeFileSync('./i18n/' + fileName, ' ');
	}
}

function removeDirectory(path) {
	exec('rm -rf ' + path, function(err) {
		if (err) {
			logger.warn("Error removing " + path + ". " + err);
		}
	});
}

function cleanOldTranslations(callback) {
	fs.unlink('./all.zip', function(error) {
		if (!error || error.code === 'ENOENT') {
			var files = fs.readdirSync('./i18n');
			files.map(function(file) {
				return path.join('./i18n', file);
			}).forEach(function(file) {
				var stats = fs.statSync(file);
				if (stats.isDirectory()) {
					removeDirectory(file);
				}
			});
			callback();
		} else {
			callback(error);
		}
	});
}

function unzipTranslations(callback) {
	logger.debug("Unziping.");
	exec('unzip ./all.zip -d i18n',
		function(error) {
			if (error !== null) {
				logger.error('exec error: ' + error);
			}
			callback();
		});
}

function scanDirectory(directory, fileName, callback) {
	logger.debug("Scaning " + directory + " for keys.");
	exec('find ' + directory + ' -iname "*.js" | xargs xgettext -j --from-code=UTF-8 --force-po --no-wrap -ktr:1 -ktrd:1 -ktrn:1,2 -ktrnd:1,2 -o i18n/' + fileName + ' -LJavaScript',
		function(error) {
			if (error !== null) {
				logger.warn("Error scaning directory " + directory);
			}
			callback(error);
		});
}

function gerateTranslationFile(fileName, callback) {
	initPaths(fileName);
	scanDirectory(crowdin.srcPath, fileName, callback);
}

/*******************************/
var createCrowdin = function(callback) {
	gerateTranslationFile(crowdin.filename, function(error) {
		if (!error) {
			uploadKeys(crowdin.filename, crowdin.filename, callback);
		}
	});
};

var downloadCrowdin = function(callback) {
	if (!fs.existsSync('./i18n')) {
		fs.mkdirSync('./i18n');
	}
	cleanOldTranslations(function(error) {
		if (error) {
			logger.error("Error cleaning up old translations.");
			callback(error);
		} else {
			refreshTranslations(function(error) {
				if (error) {
					logger.error("Error refreshing translations.");
					callback(error);
				} else {
					downloadTranslations(function(error) {
						if (error) {
							logger.error("Error dowloading translations.");
							callback(error);
						} else {
							unzipTranslations(function(error) {
								if (error) {
									logger.error("Error Unziping translations.");
								} else {
									logger.info("Tranlations updated sucessfull!");
								}
								callback(error);
							});
						}
					});
				}
			});
		}
	});
};

var uploadCrowdin = function(merge, callback) {
	gerateTranslationFile(crowdin.filename, function(error) {
		if (merge) {
			downloadCrowdin(function(error) {
				if (!error) {
					mergeTranslations(crowdin.filename, 'merged_' + crowdin.filename, function(error) {
						if (error) {
							logger.error('Error merging translations.');
							callback(error);
						} else {
							upgradeKeys(crowdin.filename, 'merged_' + crowdin.filename, callback);
						}
					});
				} else {
					callback(error);
				}
			});
		} else {
			if (error) {
				callback(error);
			} else {
				upgradeKeys(crowdin.filename, crowdin.filename, callback);
			}
		}
	});
};

module.exports.createCrowdin = createCrowdin;
module.exports.downloadCrowdin = downloadCrowdin;
module.exports.uploadCrowdin = uploadCrowdin;
module.exports.generateFile = gerateTranslationFile;
module.exports.defaultFileName = crowdin.filename;<commit_msg>oppening to all file type to look for new keys<commit_after>"use strict";
//Config loggin level
var logger = require('winston');
logger.remove(logger.transports.Console);
logger.add(logger.transports.Console, {
	level: 'debug',
	colorize: true,
	timestamp: true
});

var path = require('path');
var fs = require('fs');
var request = require('request');
var https = require('https');
var exec = require('child_process').exec;

var CONFIG_PATH = path.join(process.cwd(), 'crowdin.json');
var crowdin = require(CONFIG_PATH);

/******* PRIVATE METHODS *******/
function refreshTranslations(callback) {
	logger.debug("Refreshing translation.");
	var opts = {
		uri: 'https://crowdin.com/api/project/' + crowdin.projectId + '/export',
		qs: {
			key: crowdin.apiKey
		}
	};
	request(opts, function(error, response) {
		if (!error && response.statusCode == 200) {
			logger.info("Translations refreshed.");
		} else {
			logger.error("Fail to refresh translation.");
		}
		callback(error);
	});
}

function downloadTranslations(callback) {
	logger.debug("Downloading translation.");
	var options = {
		hostname: 'crowdin.com',
		port: 443,
		path: '/api/project/' + crowdin.projectId + '/download/all.zip?key=' + crowdin.apiKey,
		method: 'GET'
	};

	var req = https.request(options, function(res) {
		res.on('data', function(chunk) {
			fs.appendFileSync('./all.zip', chunk);
		});
		res.on('end', function(error) {
			if (!error) {
				logger.info("Translations Dowloaded.");
			}
			callback(error);
		});
	});
	req.on('error', function(e) {
		logger.error('problem with request: ' + e.message);
	});
	req.end();
}

function uploadKeys(fileName, realFileName, callback) {
	logger.debug('Uploading traductions...');
	var formData = {};
	formData['files[' + fileName + ']'] = fs.createReadStream('./i18n/' + realFileName);

	request.post({
		url: 'https://crowdin.com/api/project/' + crowdin.projectId + '/add-file?key=' + crowdin.apiKey,
		formData: formData
	}, function(err) {
		if (err) {
			logger.error('Upload failed.', err);
		} else {
			logger.info('Traductions uploaded successfully!');
		}
		callback(err);
	});
}

function upgradeKeys(fileName, realFileName, callback) {
	logger.debug('Uploading traductions...');
	var formData = {};
	formData['files[' + fileName + ']'] = fs.createReadStream('./i18n/' + realFileName);

	request.post({
		url: 'https://crowdin.com/api/project/' + crowdin.projectId + '/update-file?key=' + crowdin.apiKey,
		formData: formData
	}, function(err) {
		if (err) {
			logger.error('Upload failed.', err);
		} else {
			logger.info('Traductions uploaded successfully!');
		}
		callback(err);
	});
}

function mergeTranslations(srcFile, outputFile, callback) {
	logger.info('Merging transalations.');
	exec("msgcat ./i18n/" + srcFile + " ./i18n/es-AR/" + srcFile + " -o ./i18n/" + outputFile, callback);
}

function initPaths(fileName) {
	logger.info('Initializing...');
	if (!fs.existsSync('./i18n')) {
		fs.mkdirSync('./i18n');
	}
	if (fs.existsSync('./i18n/' + fileName)) {
		fs.truncateSync('./i18n/' + fileName, 0);
	} else {
		fs.writeFileSync('./i18n/' + fileName, ' ');
	}
}

function removeDirectory(path) {
	exec('rm -rf ' + path, function(err) {
		if (err) {
			logger.warn("Error removing " + path + ". " + err);
		}
	});
}

function cleanOldTranslations(callback) {
	fs.unlink('./all.zip', function(error) {
		if (!error || error.code === 'ENOENT') {
			var files = fs.readdirSync('./i18n');
			files.map(function(file) {
				return path.join('./i18n', file);
			}).forEach(function(file) {
				var stats = fs.statSync(file);
				if (stats.isDirectory()) {
					removeDirectory(file);
				}
			});
			callback();
		} else {
			callback(error);
		}
	});
}

function unzipTranslations(callback) {
	logger.debug("Unziping.");
	exec('unzip ./all.zip -d i18n',
		function(error) {
			if (error !== null) {
				logger.error('exec error: ' + error);
			}
			callback();
		});
}

function scanDirectory(directory, fileName, callback) {
	logger.debug("Scaning " + directory + " for keys.");
	exec('find ' + directory + ' -iname "*.*" | xargs xgettext -j --from-code=UTF-8 --force-po --no-wrap -ktr:1 -ktrd:1 -ktrn:1,2 -ktrnd:1,2 -o i18n/' + fileName + ' -LJavaScript',
		function(error) {
			if (error !== null) {
				logger.warn("Error scaning directory " + directory);
			}
			callback(error);
		});
}

function gerateTranslationFile(fileName, callback) {
	initPaths(fileName);
	scanDirectory(crowdin.srcPath, fileName, callback);
}

/*******************************/
var createCrowdin = function(callback) {
	gerateTranslationFile(crowdin.filename, function(error) {
		if (!error) {
			uploadKeys(crowdin.filename, crowdin.filename, callback);
		}
	});
};

var downloadCrowdin = function(callback) {
	if (!fs.existsSync('./i18n')) {
		fs.mkdirSync('./i18n');
	}
	cleanOldTranslations(function(error) {
		if (error) {
			logger.error("Error cleaning up old translations.");
			callback(error);
		} else {
			refreshTranslations(function(error) {
				if (error) {
					logger.error("Error refreshing translations.");
					callback(error);
				} else {
					downloadTranslations(function(error) {
						if (error) {
							logger.error("Error dowloading translations.");
							callback(error);
						} else {
							unzipTranslations(function(error) {
								if (error) {
									logger.error("Error Unziping translations.");
								} else {
									logger.info("Tranlations updated sucessfull!");
								}
								callback(error);
							});
						}
					});
				}
			});
		}
	});
};

var uploadCrowdin = function(merge, callback) {
	gerateTranslationFile(crowdin.filename, function(error) {
		if (merge) {
			downloadCrowdin(function(error) {
				if (!error) {
					mergeTranslations(crowdin.filename, 'merged_' + crowdin.filename, function(error) {
						if (error) {
							logger.error('Error merging translations.');
							callback(error);
						} else {
							upgradeKeys(crowdin.filename, 'merged_' + crowdin.filename, callback);
						}
					});
				} else {
					callback(error);
				}
			});
		} else {
			if (error) {
				callback(error);
			} else {
				upgradeKeys(crowdin.filename, crowdin.filename, callback);
			}
		}
	});
};

module.exports.createCrowdin = createCrowdin;
module.exports.downloadCrowdin = downloadCrowdin;
module.exports.uploadCrowdin = uploadCrowdin;
module.exports.generateFile = gerateTranslationFile;
module.exports.defaultFileName = crowdin.filename;<|endoftext|>


<commit_before>#!/usr/bin/env node

/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var path = require("path");
// Local version replace global one
try {
	var localWebpack = require.resolve(path.join(process.cwd(), "node_modules", "webpack", "bin", "webpack.js"));
	if(__filename != localWebpack) {
		return require(localWebpack);
	}
} catch(e) {}
var fs = require("fs");
var util = require("util");
var optimist = require("optimist")
	.usage("webpack " + require("../package.json").version + "\n" +
		"Usage: http://webpack.github.io/docs/cli.html")

require("./config-optimist")(optimist);

optimist

	.boolean("json").alias("json", "j").describe("json")

	.boolean("colors").alias("colors", "c").describe("colors")

	.string("sort-modules-by").describe("sort-modules-by")

	.string("sort-chunks-by").describe("sort-chunks-by")

	.string("sort-assets-by").describe("sort-assets-by")

	.boolean("hide-modules").describe("hide-modules")

	.string("display-exclude").describe("display-exclude")

	.boolean("display-modules").describe("display-modules")

	.boolean("display-chunks").describe("display-chunks")

	.boolean("display-error-details").describe("display-error-details")

	.boolean("display-origins").describe("display-origins")

	.boolean("display-cached").describe("display-cached")

	.boolean("display-cached-assets").describe("display-cached-assets")

	.boolean("display-reasons").alias("display-reasons", "verbose").alias("display-reasons", "v").describe("display-reasons");

var argv = optimist.argv;

var options = require("./convert-argv")(optimist, argv);

function ifArg(name, fn, init) {
	if(Array.isArray(argv[name])) {
		if(init) init();
		argv[name].forEach(fn);
	} else if(typeof argv[name] != "undefined") {
		if(init) init();
		fn(argv[name], -1);
	}
}

var outputOptions = {
	cached: false,
	cachedAssets: false,
	context: options.context
};

ifArg("json", function(bool) {
	outputOptions.json = bool;
});

outputOptions.colors = require("supports-color");

ifArg("sort-modules-by", function(value) {
	outputOptions.modulesSort = value;
});

ifArg("sort-chunks-by", function(value) {
	outputOptions.chunksSort = value;
});

ifArg("sort-assets-by", function(value) {
	outputOptions.assetsSort = value;
});

ifArg("display-exclude", function(value) {
	outputOptions.exclude = value;
});

if(!outputOptions.json) {
	ifArg("display-chunks", function(bool) {
		outputOptions.modules = !bool;
		outputOptions.chunks = bool;
	});

	ifArg("display-reasons", function(bool) {
		outputOptions.reasons = bool;
	});

	ifArg("display-error-details", function(bool) {
		outputOptions.errorDetails = bool;
	});

	ifArg("display-origins", function(bool) {
		outputOptions.chunkOrigins = bool;
	});

	ifArg("display-cached", function(bool) {
		if(bool)
			outputOptions.cached = true;
	});

	ifArg("display-cached-assets", function(bool) {
		if(bool)
			outputOptions.cachedAssets = true;
	});

	if(!outputOptions.exclude && !argv["display-modules"])
		outputOptions.exclude = ["node_modules", "bower_components", "jam", "components"];
} else {
	outputOptions.chunks = true;
	outputOptions.modules = true;
	outputOptions.chunkModules = true;
	outputOptions.reasons = true;
	outputOptions.cached = true;
	outputOptions.cachedAssets = true;
}

ifArg("hide-modules", function(bool) {
	if(bool) {
		outputOptions.modules = false;
		outputOptions.chunkModules = false;
	}
});

var webpack = require("../lib/webpack.js");

Error.stackTrackLimit = 30;
var lastHash = null;
var compiler = webpack(options, function(err, stats) {
	if(!options.watch) {
		// Do not keep cache anymore
		compiler.purgeInputFileSystem();
	}
	if(err) {
		lastHash = null;
		console.error(err.stack || err);
		if(err.details) console.error(err.details);
		if(!options.watch) {
			process.on("exit", function() {
				process.exit(1);
			});
		}
		return;
	}
	if(outputOptions.json) {
		process.stdout.write(JSON.stringify(stats.toJson(outputOptions), null, 2) + "\n");
	} else if(stats.hash !== lastHash) {
		lastHash = stats.hash;
		process.stdout.write(stats.toString(outputOptions) + "\n");
	}
});
<commit_msg>report exit code on Errors<commit_after>#!/usr/bin/env node

/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var path = require("path");
// Local version replace global one
try {
	var localWebpack = require.resolve(path.join(process.cwd(), "node_modules", "webpack", "bin", "webpack.js"));
	if(__filename != localWebpack) {
		return require(localWebpack);
	}
} catch(e) {}
var fs = require("fs");
var util = require("util");
var optimist = require("optimist")
	.usage("webpack " + require("../package.json").version + "\n" +
		"Usage: http://webpack.github.io/docs/cli.html")

require("./config-optimist")(optimist);

optimist

	.boolean("json").alias("json", "j").describe("json")

	.boolean("colors").alias("colors", "c").describe("colors")

	.string("sort-modules-by").describe("sort-modules-by")

	.string("sort-chunks-by").describe("sort-chunks-by")

	.string("sort-assets-by").describe("sort-assets-by")

	.boolean("hide-modules").describe("hide-modules")

	.string("display-exclude").describe("display-exclude")

	.boolean("display-modules").describe("display-modules")

	.boolean("display-chunks").describe("display-chunks")

	.boolean("display-error-details").describe("display-error-details")

	.boolean("display-origins").describe("display-origins")

	.boolean("display-cached").describe("display-cached")

	.boolean("display-cached-assets").describe("display-cached-assets")

	.boolean("display-reasons").alias("display-reasons", "verbose").alias("display-reasons", "v").describe("display-reasons");

var argv = optimist.argv;

var options = require("./convert-argv")(optimist, argv);

function ifArg(name, fn, init) {
	if(Array.isArray(argv[name])) {
		if(init) init();
		argv[name].forEach(fn);
	} else if(typeof argv[name] != "undefined") {
		if(init) init();
		fn(argv[name], -1);
	}
}

var outputOptions = {
	cached: false,
	cachedAssets: false,
	context: options.context
};

ifArg("json", function(bool) {
	outputOptions.json = bool;
});

outputOptions.colors = require("supports-color");

ifArg("sort-modules-by", function(value) {
	outputOptions.modulesSort = value;
});

ifArg("sort-chunks-by", function(value) {
	outputOptions.chunksSort = value;
});

ifArg("sort-assets-by", function(value) {
	outputOptions.assetsSort = value;
});

ifArg("display-exclude", function(value) {
	outputOptions.exclude = value;
});

if(!outputOptions.json) {
	ifArg("display-chunks", function(bool) {
		outputOptions.modules = !bool;
		outputOptions.chunks = bool;
	});

	ifArg("display-reasons", function(bool) {
		outputOptions.reasons = bool;
	});

	ifArg("display-error-details", function(bool) {
		outputOptions.errorDetails = bool;
	});

	ifArg("display-origins", function(bool) {
		outputOptions.chunkOrigins = bool;
	});

	ifArg("display-cached", function(bool) {
		if(bool)
			outputOptions.cached = true;
	});

	ifArg("display-cached-assets", function(bool) {
		if(bool)
			outputOptions.cachedAssets = true;
	});

	if(!outputOptions.exclude && !argv["display-modules"])
		outputOptions.exclude = ["node_modules", "bower_components", "jam", "components"];
} else {
	outputOptions.chunks = true;
	outputOptions.modules = true;
	outputOptions.chunkModules = true;
	outputOptions.reasons = true;
	outputOptions.cached = true;
	outputOptions.cachedAssets = true;
}

ifArg("hide-modules", function(bool) {
	if(bool) {
		outputOptions.modules = false;
		outputOptions.chunkModules = false;
	}
});

var webpack = require("../lib/webpack.js");

Error.stackTrackLimit = 30;
var lastHash = null;
var compiler = webpack(options, function(err, stats) {
	if(!options.watch) {
		// Do not keep cache anymore
		compiler.purgeInputFileSystem();
	}
	if(err) {
		lastHash = null;
		console.error(err.stack || err);
		if(err.details) console.error(err.details);
		if(!options.watch) {
			process.on("exit", function() {
				process.exit(1);
			});
		}
		return;
	}
	if(outputOptions.json) {
		process.stdout.write(JSON.stringify(stats.toJson(outputOptions), null, 2) + "\n");
	} else if(stats.hash !== lastHash) {
		lastHash = stats.hash;
		process.stdout.write(stats.toString(outputOptions) + "\n");
	}
	if(!options.watch && stats.hasErrors()) {
		process.on("exit", function() {
			process.exit(2);
		});
	}
});
<|endoftext|>


<commit_before>require("./patch");

var estraverse = require("estraverse");
var traverse   = require("./traverse");
var acorn      = require("acorn-6to5");
var path       = require("path");
var util       = require("util");
var fs         = require("fs");
var t          = require("./types");
var _          = require("lodash");

exports.inherits = util.inherits;

exports.resolve = function (loc) {
  try {
    return require.resolve(loc);
  } catch (err) {
    return null;
  }
};

exports.list = function (val) {
  return val ? val.split(",") : [];
};

exports.getUid = function (parent, file) {
  var node;

  if (t.isAssignmentExpression(parent)) {
    node = parent.left;
  } else if (t.isVariableDeclarator(parent)) {
    node = parent.id;
  }

  var id = "ref";

  if (t.isIdentifier(node)) id = node.name;

  return t.identifier(file.generateUid(id));
};

exports.isAbsolute = function (loc) {
  if (!loc) return false;
  if (loc[0] === "/") return true; // unix
  if (loc[1] === ":" && loc[2] === "\\") return true; // windows
  return false;
};

exports.canCompile = function (filename) {
  var ext = path.extname(filename);
  return _.contains([".js", ".es6"], ext);
};

exports.sourceMapToComment = function (map) {
  var json = JSON.stringify(map);
  var base64 = new Buffer(json).toString("base64");
  return "//# sourceMappingURL=data:application/json;base64," + base64;
};

exports.pushMutatorMap = function (mutatorMap, key, kind, method) {
  var alias;

  if (t.isIdentifier(key)) {
    alias = key.name;
    if (method.computed) alias = "computed:" + alias;
  } else if (t.isLiteral(key)) {
    alias = String(key.value);
  } else {
    alias = JSON.stringify(traverse.removeProperties(_.cloneDeep(key)));
  }

  var map;
  if (_.has(mutatorMap, alias)) {
    map = mutatorMap[alias];
  } else {
    map = {};
  }
  mutatorMap[alias] = map;

  map._key = key;
  if (method.computed) {
    map._computed = true;
  }

  map[kind] = method;
};

exports.buildDefineProperties = function (mutatorMap) {
  var objExpr = t.objectExpression([]);

  _.each(mutatorMap, function (map) {
    var mapNode = t.objectExpression([]);

    var propNode = t.property("init", map._key, mapNode, map._computed);

    _.each(map, function (node, key) {
      if (key[0] === "_") return;

      node = _.clone(node);
      if (t.isMethodDefinition(node)) node = node.value;
      mapNode.properties.push(t.property("init", t.identifier(key), node));
    });

    objExpr.properties.push(propNode);
  });

  return objExpr;
};

exports.template = function (name, nodes, keepExpression) {
  var template = exports.templates[name];
  if (!template) throw new ReferenceError("unknown template " + name);

  template = _.cloneDeep(template);

  var inherits = false;
  if (nodes) {
    inherits = nodes.inherits;
    delete nodes.inherits;

    if (!_.isEmpty(nodes)) {
      traverse(template, function (node) {
        if (t.isIdentifier(node) && _.has(nodes, node.name)) {
          var newNode = nodes[node.name];
          if (_.isString(newNode)) {
            node.name = newNode;
          } else {
            return newNode;
          }
        }
      });
    }
  }

  var node = template.body[0];

  if (!keepExpression && t.isExpressionStatement(node)) {
    node = node.expression;

    if (t.isParenthesizedExpression(node)) node = node.expression;
  }

  if (inherits) {
    node = t.inherits(node, inherits);
  }

  return node;
};

exports.codeFrame = function (lines, lineNumber, colNumber) {
  colNumber = Math.max(colNumber, 0);

  lines = lines.split("\n");

  var start = Math.max(lineNumber - 3, 0);
  var end   = Math.min(lines.length, lineNumber + 3);
  var width = (end + "").length;

  if (!lineNumber && !colNumber) {
    start = 0;
    end = lines.length;
  }

  return "\n" + lines.slice(start, end).map(function (line, i) {
    var curr = i + start + 1;

    var gutter = curr === lineNumber ? "> " : "  ";

    var sep = curr + exports.repeat(width + 1);
    gutter += sep + "| ";

    var str = gutter + line;

    if (colNumber && curr === lineNumber) {
      str += "\n";
      str += exports.repeat(gutter.length - 2);
      str += "|" + exports.repeat(colNumber) + "^";
    }

    return str;
  }).join("\n");
};

exports.repeat = function (width, cha) {
  cha = cha || " ";
  return new Array(width + 1).join(cha);
};

exports.parse = function (opts, code, callback) {
  try {
    var comments = [];
    var tokens   = [];

    var ast = acorn.parse(code, {
      preserveParens: true,
      ecmaVersion:    Infinity,
      strictMode:     true,
      onComment:      comments,
      locations:      true,
      onToken:        tokens,
      ranges:         true
    });

    estraverse.attachComments(ast, comments, tokens);

    ast = t.file(ast, comments, tokens);

    traverse(ast, function (node, parent) {
      node._parent = parent;
    });

    if (callback) {
      return callback(ast);
    } else {
      return ast;
    }
  } catch (err) {
    if (!err._6to5) {
      err._6to5 = true;
      var message = opts.filename + ": " + err.message;

      var loc = err.loc;
      if (loc) {
        var frame = exports.codeFrame(code, loc.line, loc.column);
        message += frame;
      }

      if (err.stack) err.stack = err.stack.replace(err.message, message);
      err.message = message;
    }

    throw err;
  }
};

exports.parseNoProperties = function (loc, code) {
  var ast = exports.parse({ filename: loc }, code).program;
  return traverse.removeProperties(ast);
};

var loadTemplates = function () {
  var templates = {};

  var templatesLoc = __dirname + "/templates";
  if (!fs.existsSync(templatesLoc)) {
    throw new Error("no templates directory - this is most likely the " +
                    "result of a broken `npm publish`. Please report to " +
                    "https://githut.com/sebmck/6to5/issues");
  }

  _.each(fs.readdirSync(templatesLoc), function (name) {
    if (name[0] === ".") return;

    var key  = path.basename(name, path.extname(name));
    var loc  = templatesLoc + "/" + name;
    var code = fs.readFileSync(loc, "utf8");

    templates[key] = exports.parseNoProperties(loc, code);
  });

  return templates;
};

try {
  return require("../../templates.json");
} catch (err) {
  if (err.code !== "MODULE_NOT_FOUND") throw err;

  Object.defineProperty(exports, "templates", {
    get: function () {
      return exports.templates = loadTemplates();
    }
  });
}
<commit_msg>fix cached templates exporting<commit_after>require("./patch");

var estraverse = require("estraverse");
var traverse   = require("./traverse");
var acorn      = require("acorn-6to5");
var path       = require("path");
var util       = require("util");
var fs         = require("fs");
var t          = require("./types");
var _          = require("lodash");

exports.inherits = util.inherits;

exports.resolve = function (loc) {
  try {
    return require.resolve(loc);
  } catch (err) {
    return null;
  }
};

exports.list = function (val) {
  return val ? val.split(",") : [];
};

exports.getUid = function (parent, file) {
  var node;

  if (t.isAssignmentExpression(parent)) {
    node = parent.left;
  } else if (t.isVariableDeclarator(parent)) {
    node = parent.id;
  }

  var id = "ref";

  if (t.isIdentifier(node)) id = node.name;

  return t.identifier(file.generateUid(id));
};

exports.isAbsolute = function (loc) {
  if (!loc) return false;
  if (loc[0] === "/") return true; // unix
  if (loc[1] === ":" && loc[2] === "\\") return true; // windows
  return false;
};

exports.canCompile = function (filename) {
  var ext = path.extname(filename);
  return _.contains([".js", ".es6"], ext);
};

exports.sourceMapToComment = function (map) {
  var json = JSON.stringify(map);
  var base64 = new Buffer(json).toString("base64");
  return "//# sourceMappingURL=data:application/json;base64," + base64;
};

exports.pushMutatorMap = function (mutatorMap, key, kind, method) {
  var alias;

  if (t.isIdentifier(key)) {
    alias = key.name;
    if (method.computed) alias = "computed:" + alias;
  } else if (t.isLiteral(key)) {
    alias = String(key.value);
  } else {
    alias = JSON.stringify(traverse.removeProperties(_.cloneDeep(key)));
  }

  var map;
  if (_.has(mutatorMap, alias)) {
    map = mutatorMap[alias];
  } else {
    map = {};
  }
  mutatorMap[alias] = map;

  map._key = key;
  if (method.computed) {
    map._computed = true;
  }

  map[kind] = method;
};

exports.buildDefineProperties = function (mutatorMap) {
  var objExpr = t.objectExpression([]);

  _.each(mutatorMap, function (map) {
    var mapNode = t.objectExpression([]);

    var propNode = t.property("init", map._key, mapNode, map._computed);

    _.each(map, function (node, key) {
      if (key[0] === "_") return;

      node = _.clone(node);
      if (t.isMethodDefinition(node)) node = node.value;
      mapNode.properties.push(t.property("init", t.identifier(key), node));
    });

    objExpr.properties.push(propNode);
  });

  return objExpr;
};

exports.template = function (name, nodes, keepExpression) {
  var template = exports.templates[name];
  if (!template) throw new ReferenceError("unknown template " + name);

  template = _.cloneDeep(template);

  var inherits = false;
  if (nodes) {
    inherits = nodes.inherits;
    delete nodes.inherits;

    if (!_.isEmpty(nodes)) {
      traverse(template, function (node) {
        if (t.isIdentifier(node) && _.has(nodes, node.name)) {
          var newNode = nodes[node.name];
          if (_.isString(newNode)) {
            node.name = newNode;
          } else {
            return newNode;
          }
        }
      });
    }
  }

  var node = template.body[0];

  if (!keepExpression && t.isExpressionStatement(node)) {
    node = node.expression;

    if (t.isParenthesizedExpression(node)) node = node.expression;
  }

  if (inherits) {
    node = t.inherits(node, inherits);
  }

  return node;
};

exports.codeFrame = function (lines, lineNumber, colNumber) {
  colNumber = Math.max(colNumber, 0);

  lines = lines.split("\n");

  var start = Math.max(lineNumber - 3, 0);
  var end   = Math.min(lines.length, lineNumber + 3);
  var width = (end + "").length;

  if (!lineNumber && !colNumber) {
    start = 0;
    end = lines.length;
  }

  return "\n" + lines.slice(start, end).map(function (line, i) {
    var curr = i + start + 1;

    var gutter = curr === lineNumber ? "> " : "  ";

    var sep = curr + exports.repeat(width + 1);
    gutter += sep + "| ";

    var str = gutter + line;

    if (colNumber && curr === lineNumber) {
      str += "\n";
      str += exports.repeat(gutter.length - 2);
      str += "|" + exports.repeat(colNumber) + "^";
    }

    return str;
  }).join("\n");
};

exports.repeat = function (width, cha) {
  cha = cha || " ";
  return new Array(width + 1).join(cha);
};

exports.parse = function (opts, code, callback) {
  try {
    var comments = [];
    var tokens   = [];

    var ast = acorn.parse(code, {
      preserveParens: true,
      ecmaVersion:    Infinity,
      strictMode:     true,
      onComment:      comments,
      locations:      true,
      onToken:        tokens,
      ranges:         true
    });

    estraverse.attachComments(ast, comments, tokens);

    ast = t.file(ast, comments, tokens);

    traverse(ast, function (node, parent) {
      node._parent = parent;
    });

    if (callback) {
      return callback(ast);
    } else {
      return ast;
    }
  } catch (err) {
    if (!err._6to5) {
      err._6to5 = true;
      var message = opts.filename + ": " + err.message;

      var loc = err.loc;
      if (loc) {
        var frame = exports.codeFrame(code, loc.line, loc.column);
        message += frame;
      }

      if (err.stack) err.stack = err.stack.replace(err.message, message);
      err.message = message;
    }

    throw err;
  }
};

exports.parseNoProperties = function (loc, code) {
  var ast = exports.parse({ filename: loc }, code).program;
  return traverse.removeProperties(ast);
};

var loadTemplates = function () {
  var templates = {};

  var templatesLoc = __dirname + "/templates";
  if (!fs.existsSync(templatesLoc)) {
    throw new Error("no templates directory - this is most likely the " +
                    "result of a broken `npm publish`. Please report to " +
                    "https://githut.com/sebmck/6to5/issues");
  }

  _.each(fs.readdirSync(templatesLoc), function (name) {
    if (name[0] === ".") return;

    var key  = path.basename(name, path.extname(name));
    var loc  = templatesLoc + "/" + name;
    var code = fs.readFileSync(loc, "utf8");

    templates[key] = exports.parseNoProperties(loc, code);
  });

  return templates;
};

try {
  exports.templates = require("../../templates.json");
} catch (err) {
  if (err.code !== "MODULE_NOT_FOUND") throw err;

  Object.defineProperty(exports, "templates", {
    get: function () {
      return exports.templates = loadTemplates();
    }
  });
}
<|endoftext|>