<commit_before>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ArgumentsRequired } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class negociecoins extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'negociecoins',
            'name': 'NegocieCoins',
            'countries': [ 'BR' ],
            'rateLimit': 1000,
            'version': 'v3',
            'has': {
                'createMarketOrder': false,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
                'fetchClosedOrders': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/38008571-25a6246e-3258-11e8-969b-aeb691049245.jpg',
                'api': {
                    'public': 'https://broker.negociecoins.com.br/api/v3',
                    'private': 'https://broker.negociecoins.com.br/tradeapi/v1',
                },
                'www': 'https://www.negociecoins.com.br',
                'doc': [
                    'https://www.negociecoins.com.br/documentacao-tradeapi',
                    'https://www.negociecoins.com.br/documentacao-api',
                ],
                'fees': 'https://www.negociecoins.com.br/comissoes',
            },
            'api': {
                'public': {
                    'get': [
                        '{PAR}/ticker',
                        '{PAR}/orderbook',
                        '{PAR}/trades',
                        '{PAR}/trades/{timestamp_inicial}',
                        '{PAR}/trades/{timestamp_inicial}/{timestamp_final}',
                    ],
                },
                'private': {
                    'get': [
                        'user/balance',
                        'user/order/{orderId}',
                    ],
                    'post': [
                        'user/order',
                        'user/orders',
                    ],
                    'delete': [
                        'user/order/{orderId}',
                    ],
                },
            },
            'markets': {
                'B2X/BRL': { 'id': 'b2xbrl', 'symbol': 'B2X/BRL', 'base': 'B2X', 'quote': 'BRL' },
                'BCH/BRL': { 'id': 'bchbrl', 'symbol': 'BCH/BRL', 'base': 'BCH', 'quote': 'BRL' },
                'BTC/BRL': { 'id': 'btcbrl', 'symbol': 'BTC/BRL', 'base': 'BTC', 'quote': 'BRL' },
                'BTG/BRL': { 'id': 'btgbrl', 'symbol': 'BTG/BRL', 'base': 'BTG', 'quote': 'BRL' },
                'DASH/BRL': { 'id': 'dashbrl', 'symbol': 'DASH/BRL', 'base': 'DASH', 'quote': 'BRL' },
                'LTC/BRL': { 'id': 'ltcbrl', 'symbol': 'LTC/BRL', 'base': 'LTC', 'quote': 'BRL' },
            },
            'fees': {
                'trading': {
                    'maker': 0.003,
                    'taker': 0.004,
                },
                'funding': {
                    'withdraw': {
                        'BTC': 0.001,
                        'BCH': 0.00003,
                        'BTG': 0.00009,
                        'LTC': 0.005,
                    },
                },
            },
            'limits': {
                'amount': {
                    'min': 0.001,
                    'max': undefined,
                },
            },
            'precision': {
                'amount': 8,
                'price': 8,
            },
        });
    }

    parseTicker (ticker, market = undefined) {
        const timestamp = this.safeTimestamp (ticker, 'date');
        const symbol = (market !== undefined) ? market['symbol'] : undefined;
        const last = this.safeFloat (ticker, 'last');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high'),
            'low': this.safeFloat (ticker, 'low'),
            'bid': this.safeFloat (ticker, 'buy'),
            'bidVolume': undefined,
            'ask': this.safeFloat (ticker, 'sell'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'vol'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'PAR': market['id'],
        };
        const ticker = await this.publicGetPARTicker (this.extend (request, params));
        return this.parseTicker (ticker, market);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const request = {
            'PAR': this.marketId (symbol),
        };
        const response = await this.publicGetPAROrderbook (this.extend (request, params));
        return this.parseOrderBook (response, undefined, 'bid', 'ask', 'price', 'quantity');
    }

    parseTrade (trade, market = undefined) {
        const timestamp = this.safeTimestamp (trade, 'date');
        const price = this.safeFloat (trade, 'price');
        const amount = this.safeFloat (trade, 'amount');
        let cost = undefined;
        if (price !== undefined) {
            if (amount !== undefined) {
                cost = price * amount;
            }
        }
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        const id = this.safeString (trade, 'tid');
        const type = 'limit';
        const side = this.safeStringLower (trade, 'type');
        return {
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'id': id,
            'order': undefined,
            'type': type,
            'side': side,
            'price': price,
            'amount': amount,
            'cost': cost,
            'fee': undefined,
            'info': trade,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        if (since === undefined) {
            since = 0;
        }
        const request = {
            'PAR': market['id'],
            'timestamp_inicial': parseInt (since / 1000),
        };
        const response = await this.publicGetPARTradesTimestampInicial (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        const response = await this.privateGetUserBalance (params);
        //
        //     {
        //         "coins": [
        //             {"name":"BRL","available":0.0,"openOrders":0.0,"withdraw":0.0,"total":0.0},
        //             {"name":"BTC","available":0.0,"openOrders":0.0,"withdraw":0.0,"total":0.0},
        //         ],
        //     }
        //
        const result = { 'info': response };
        const balances = this.safeValue (response, 'coins');
        for (let i = 0; i < balances.length; i++) {
            const balance = balances[i];
            const currencyId = this.safeString (balance, 'name');
            const code = this.safeCurrencyCode (currencyId);
            const openOrders = this.safeFloat (balance, 'openOrders');
            const withdraw = this.safeFloat (balance, 'withdraw');
            const account = {
                'free': this.safeFloat (balance, 'total'),
                'used': this.sum (openOrders, withdraw),
                'total': this.safeFloat (balance, 'available'),
            };
            result[code] = account;
        }
        return this.parseBalance (result);
    }

    parseOrderStatus (status) {
        const statuses = {
            'filled': 'closed',
            'cancelled': 'canceled',
            'partially filled': 'open',
            'pending': 'open',
            'rejected': 'rejected',
        };
        return this.safeString (statuses, status, status);
    }

    parseOrder (order, market = undefined) {
        let symbol = undefined;
        if (market === undefined) {
            const marketId = this.safeString (order, 'pair');
            market = this.safeValue (this.marketsById, marketId);
            if (market) {
                symbol = market['symbol'];
            }
        }
        const timestamp = this.parse8601 (this.safeString (order, 'created'));
        const price = this.safeFloat (order, 'price');
        const amount = this.safeFloat (order, 'quantity');
        const cost = this.safeFloat (order, 'total');
        const remaining = this.safeFloat (order, 'pending_quantity');
        const filled = this.safeFloat (order, 'executed_quantity');
        const status = this.parseOrderStatus (this.safeString (order, 'status'));
        const trades = undefined;
        // if (order['operations'])
        //     trades = this.parseTrades (order['operations']);
        return {
            'id': order['id'].toString (),
            'datetime': this.iso8601 (timestamp),
            'timestamp': timestamp,
            'lastTradeTimestamp': undefined,
            'status': status,
            'symbol': symbol,
            'type': 'limit',
            'side': order['type'],
            'price': price,
            'cost': cost,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'trades': trades,
            'fee': {
                'currency': market['quote'],
                'cost': this.safeFloat (order, 'fee'),
            },
            'info': order,
        };
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'pair': market['id'],
            'price': this.priceToPrecision (symbol, price),
            'volume': this.amountToPrecision (symbol, amount),
            'type': side,
        };
        const response = await this.privatePostUserOrder (this.extend (request, params));
        const order = this.parseOrder (response[0], market);
        const id = order['id'];
        this.orders[id] = order;
        return order;
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.markets[symbol];
        const request = {
            'orderId': id,
        };
        const response = await this.privateDeleteUserOrderOrderId (this.extend (request, params));
        return this.parseOrder (response[0], market);
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        const request = {
            'orderId': id,
        };
        const order = await this.privateGetUserOrderOrderId (this.extend (request, params));
        return this.parseOrder (order[0]);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchOrders () requires a symbol argument');
        }
        const market = this.market (symbol);
        const request = {
            'pair': market['id'],
            // type: buy, sell
            // status: cancelled, filled, partially filled, pending, rejected
            // startId
            // endId
            // startDate yyyy-MM-dd
            // endDate: yyyy-MM-dd
        };
        if (since !== undefined) {
            request['startDate'] = this.ymd (since);
        }
        if (limit !== undefined) {
            request['pageSize'] = limit;
        }
        const orders = await this.privatePostUserOrders (this.extend (request, params));
        return this.parseOrders (orders, market);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        const request = {
            'status': 'pending',
        };
        return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        const request = {
            'status': 'filled',
        };
        return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api] + '/' + this.implodeParams (path, params);
        const query = this.omit (params, this.extractParams (path));
        const queryString = this.urlencode (query);
        if (api === 'public') {
            if (queryString.length) {
                url += '?' + queryString;
            }
        } else {
            this.checkRequiredCredentials ();
            const timestamp = this.seconds ().toString ();
            const nonce = this.nonce ().toString ();
            let content = '';
            if (queryString.length) {
                body = this.json (query);
                content = this.hash (this.encode (body), 'md5', 'base64');
            } else {
                body = '';
            }
            const uri = this.encodeURIComponent (url).toLowerCase ();
            const payload = [ this.apiKey, method, uri, timestamp, nonce, content ].join ('');
            const secret = this.base64ToBinary (this.secret);
            let signature = this.hmac (this.encode (payload), secret, 'sha256', 'base64');
            signature = this.decode (signature);
            const auth = [ this.apiKey, signature, nonce, timestamp ].join (':');
            headers = {
                'Authorization': 'amx ' + auth,
            };
            if (method === 'POST') {
                headers['Content-Type'] = 'application/json; charset=UTF-8';
                headers['Content-Length'] = body.length;
            } else if (queryString.length) {
                url += '?' + queryString;
                body = undefined;
            }
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<commit_msg>negociecoins fees updated<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ArgumentsRequired } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class negociecoins extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'negociecoins',
            'name': 'NegocieCoins',
            'countries': [ 'BR' ],
            'rateLimit': 1000,
            'version': 'v3',
            'has': {
                'createMarketOrder': false,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
                'fetchClosedOrders': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/38008571-25a6246e-3258-11e8-969b-aeb691049245.jpg',
                'api': {
                    'public': 'https://broker.negociecoins.com.br/api/v3',
                    'private': 'https://broker.negociecoins.com.br/tradeapi/v1',
                },
                'www': 'https://www.negociecoins.com.br',
                'doc': [
                    'https://www.negociecoins.com.br/documentacao-tradeapi',
                    'https://www.negociecoins.com.br/documentacao-api',
                ],
                'fees': 'https://www.negociecoins.com.br/comissoes',
            },
            'api': {
                'public': {
                    'get': [
                        '{PAR}/ticker',
                        '{PAR}/orderbook',
                        '{PAR}/trades',
                        '{PAR}/trades/{timestamp_inicial}',
                        '{PAR}/trades/{timestamp_inicial}/{timestamp_final}',
                    ],
                },
                'private': {
                    'get': [
                        'user/balance',
                        'user/order/{orderId}',
                    ],
                    'post': [
                        'user/order',
                        'user/orders',
                    ],
                    'delete': [
                        'user/order/{orderId}',
                    ],
                },
            },
            'markets': {
                'B2X/BRL': { 'id': 'b2xbrl', 'symbol': 'B2X/BRL', 'base': 'B2X', 'quote': 'BRL' },
                'BCH/BRL': { 'id': 'bchbrl', 'symbol': 'BCH/BRL', 'base': 'BCH', 'quote': 'BRL' },
                'BTC/BRL': { 'id': 'btcbrl', 'symbol': 'BTC/BRL', 'base': 'BTC', 'quote': 'BRL' },
                'BTG/BRL': { 'id': 'btgbrl', 'symbol': 'BTG/BRL', 'base': 'BTG', 'quote': 'BRL' },
                'DASH/BRL': { 'id': 'dashbrl', 'symbol': 'DASH/BRL', 'base': 'DASH', 'quote': 'BRL' },
                'LTC/BRL': { 'id': 'ltcbrl', 'symbol': 'LTC/BRL', 'base': 'LTC', 'quote': 'BRL' },
            },
            'fees': {
                'trading': {
                    'maker': 0.005,
                    'taker': 0.005,
                },
                'funding': {
                    'withdraw': {
                        'BTC': 0.001,
                        'BCH': 0.00003,
                        'BTG': 0.00009,
                        'LTC': 0.005,
                    },
                },
            },
            'limits': {
                'amount': {
                    'min': 0.001,
                    'max': undefined,
                },
            },
            'precision': {
                'amount': 8,
                'price': 8,
            },
        });
    }

    parseTicker (ticker, market = undefined) {
        const timestamp = this.safeTimestamp (ticker, 'date');
        const symbol = (market !== undefined) ? market['symbol'] : undefined;
        const last = this.safeFloat (ticker, 'last');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high'),
            'low': this.safeFloat (ticker, 'low'),
            'bid': this.safeFloat (ticker, 'buy'),
            'bidVolume': undefined,
            'ask': this.safeFloat (ticker, 'sell'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'vol'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'PAR': market['id'],
        };
        const ticker = await this.publicGetPARTicker (this.extend (request, params));
        return this.parseTicker (ticker, market);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const request = {
            'PAR': this.marketId (symbol),
        };
        const response = await this.publicGetPAROrderbook (this.extend (request, params));
        return this.parseOrderBook (response, undefined, 'bid', 'ask', 'price', 'quantity');
    }

    parseTrade (trade, market = undefined) {
        const timestamp = this.safeTimestamp (trade, 'date');
        const price = this.safeFloat (trade, 'price');
        const amount = this.safeFloat (trade, 'amount');
        let cost = undefined;
        if (price !== undefined) {
            if (amount !== undefined) {
                cost = price * amount;
            }
        }
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        const id = this.safeString (trade, 'tid');
        const type = 'limit';
        const side = this.safeStringLower (trade, 'type');
        return {
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'id': id,
            'order': undefined,
            'type': type,
            'side': side,
            'price': price,
            'amount': amount,
            'cost': cost,
            'fee': undefined,
            'info': trade,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        if (since === undefined) {
            since = 0;
        }
        const request = {
            'PAR': market['id'],
            'timestamp_inicial': parseInt (since / 1000),
        };
        const response = await this.publicGetPARTradesTimestampInicial (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        const response = await this.privateGetUserBalance (params);
        //
        //     {
        //         "coins": [
        //             {"name":"BRL","available":0.0,"openOrders":0.0,"withdraw":0.0,"total":0.0},
        //             {"name":"BTC","available":0.0,"openOrders":0.0,"withdraw":0.0,"total":0.0},
        //         ],
        //     }
        //
        const result = { 'info': response };
        const balances = this.safeValue (response, 'coins');
        for (let i = 0; i < balances.length; i++) {
            const balance = balances[i];
            const currencyId = this.safeString (balance, 'name');
            const code = this.safeCurrencyCode (currencyId);
            const openOrders = this.safeFloat (balance, 'openOrders');
            const withdraw = this.safeFloat (balance, 'withdraw');
            const account = {
                'free': this.safeFloat (balance, 'total'),
                'used': this.sum (openOrders, withdraw),
                'total': this.safeFloat (balance, 'available'),
            };
            result[code] = account;
        }
        return this.parseBalance (result);
    }

    parseOrderStatus (status) {
        const statuses = {
            'filled': 'closed',
            'cancelled': 'canceled',
            'partially filled': 'open',
            'pending': 'open',
            'rejected': 'rejected',
        };
        return this.safeString (statuses, status, status);
    }

    parseOrder (order, market = undefined) {
        let symbol = undefined;
        if (market === undefined) {
            const marketId = this.safeString (order, 'pair');
            market = this.safeValue (this.marketsById, marketId);
            if (market) {
                symbol = market['symbol'];
            }
        }
        const timestamp = this.parse8601 (this.safeString (order, 'created'));
        const price = this.safeFloat (order, 'price');
        const amount = this.safeFloat (order, 'quantity');
        const cost = this.safeFloat (order, 'total');
        const remaining = this.safeFloat (order, 'pending_quantity');
        const filled = this.safeFloat (order, 'executed_quantity');
        const status = this.parseOrderStatus (this.safeString (order, 'status'));
        const trades = undefined;
        // if (order['operations'])
        //     trades = this.parseTrades (order['operations']);
        return {
            'id': order['id'].toString (),
            'datetime': this.iso8601 (timestamp),
            'timestamp': timestamp,
            'lastTradeTimestamp': undefined,
            'status': status,
            'symbol': symbol,
            'type': 'limit',
            'side': order['type'],
            'price': price,
            'cost': cost,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'trades': trades,
            'fee': {
                'currency': market['quote'],
                'cost': this.safeFloat (order, 'fee'),
            },
            'info': order,
        };
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'pair': market['id'],
            'price': this.priceToPrecision (symbol, price),
            'volume': this.amountToPrecision (symbol, amount),
            'type': side,
        };
        const response = await this.privatePostUserOrder (this.extend (request, params));
        const order = this.parseOrder (response[0], market);
        const id = order['id'];
        this.orders[id] = order;
        return order;
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.markets[symbol];
        const request = {
            'orderId': id,
        };
        const response = await this.privateDeleteUserOrderOrderId (this.extend (request, params));
        return this.parseOrder (response[0], market);
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        const request = {
            'orderId': id,
        };
        const order = await this.privateGetUserOrderOrderId (this.extend (request, params));
        return this.parseOrder (order[0]);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchOrders () requires a symbol argument');
        }
        const market = this.market (symbol);
        const request = {
            'pair': market['id'],
            // type: buy, sell
            // status: cancelled, filled, partially filled, pending, rejected
            // startId
            // endId
            // startDate yyyy-MM-dd
            // endDate: yyyy-MM-dd
        };
        if (since !== undefined) {
            request['startDate'] = this.ymd (since);
        }
        if (limit !== undefined) {
            request['pageSize'] = limit;
        }
        const orders = await this.privatePostUserOrders (this.extend (request, params));
        return this.parseOrders (orders, market);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        const request = {
            'status': 'pending',
        };
        return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        const request = {
            'status': 'filled',
        };
        return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api] + '/' + this.implodeParams (path, params);
        const query = this.omit (params, this.extractParams (path));
        const queryString = this.urlencode (query);
        if (api === 'public') {
            if (queryString.length) {
                url += '?' + queryString;
            }
        } else {
            this.checkRequiredCredentials ();
            const timestamp = this.seconds ().toString ();
            const nonce = this.nonce ().toString ();
            let content = '';
            if (queryString.length) {
                body = this.json (query);
                content = this.hash (this.encode (body), 'md5', 'base64');
            } else {
                body = '';
            }
            const uri = this.encodeURIComponent (url).toLowerCase ();
            const payload = [ this.apiKey, method, uri, timestamp, nonce, content ].join ('');
            const secret = this.base64ToBinary (this.secret);
            let signature = this.hmac (this.encode (payload), secret, 'sha256', 'base64');
            signature = this.decode (signature);
            const auth = [ this.apiKey, signature, nonce, timestamp ].join (':');
            headers = {
                'Authorization': 'amx ' + auth,
            };
            if (method === 'POST') {
                headers['Content-Type'] = 'application/json; charset=UTF-8';
                headers['Content-Length'] = body.length;
            } else if (queryString.length) {
                url += '?' + queryString;
                body = undefined;
            }
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<|endoftext|>


<commit_before>var spawn = require("child_process").spawn;
exports.Parsers = require("./applescript-parser");
var parse = exports.Parsers.parse;

// Path to 'osascript'. By default search PATH.
exports.osascript = "osascript";

// Execute a *.applescript file.
exports.execFile = function execFile(file, args, callback) {
  if (!Array.isArray(args)) {
    callback = args;
    args = [];
  }
  return runApplescript(file, args, callback);
}

// Execute a String as AppleScript.
exports.execString = function execString(str, callback) {
  return runApplescript(str, callback);
}

function runApplescript(strOrPath, args, callback) {
  var isString = false;
  if (!Array.isArray(args)) {
    callback = args;
    args = [];
    isString = true;
  }

  // args get added in reverse order with 'unshift'
  if (!isString) {
    // The name of the file is the final arg if 'execFile' was called.
    args.unshift(strOrPath);
  }
  args.unshift("-ss"); // To output machine-readable text.
  var interpreter = spawn(exports.osascript, args);

  bufferBody(interpreter.stdout);
  bufferBody(interpreter.stderr);

  interpreter.on('exit', function(code) {
    var result = parse(interpreter.stdout.body);
    var err;
    if (code) {
      // If the exit code was something other than 0, we're gonna
      // return an Error object.
      err = new Error(interpreter.stderr.body);
      err.appleScript = strOrPath;
      err.exitCode = code;
    }
    callback(err, result, interpreter.stderr.body);
  });

  if (isString) {
    // Write the given applescript String to stdin if 'execString' was called.
    interpreter.stdin.write(strOrPath);
    interpreter.stdin.end();
  }
}

function bufferBody(stream) {
  stream.body = "";
  stream.setEncoding("utf8");
  stream.on("data", function(chunk) { stream.body += chunk; });
}
<commit_msg>allow for no callback<commit_after>var spawn = require("child_process").spawn;
exports.Parsers = require("./applescript-parser");
var parse = exports.Parsers.parse;

// Path to 'osascript'. By default search PATH.
exports.osascript = "osascript";

// Execute a *.applescript file.
exports.execFile = function execFile(file, args, callback) {
  if (!Array.isArray(args)) {
    callback = args;
    args = [];
  }
  return runApplescript(file, args, callback);
}

// Execute a String as AppleScript.
exports.execString = function execString(str, callback) {
  return runApplescript(str, callback);
}

function runApplescript(strOrPath, args, callback) {
  var isString = false;
  if (!Array.isArray(args)) {
    callback = args;
    args = [];
    isString = true;
  }

  // args get added in reverse order with 'unshift'
  if (!isString) {
    // The name of the file is the final arg if 'execFile' was called.
    args.unshift(strOrPath);
  }
  args.unshift("-ss"); // To output machine-readable text.
  var interpreter = spawn(exports.osascript, args);

  bufferBody(interpreter.stdout);
  bufferBody(interpreter.stderr);

  interpreter.on('exit', function(code) {
    var result = parse(interpreter.stdout.body);
    var err;
    if (code) {
      // If the exit code was something other than 0, we're gonna
      // return an Error object.
      err = new Error(interpreter.stderr.body);
      err.appleScript = strOrPath;
      err.exitCode = code;
    }
    if (callback) {
      callback(err, result, interpreter.stderr.body);
    }
  });

  if (isString) {
    // Write the given applescript String to stdin if 'execString' was called.
    interpreter.stdin.write(strOrPath);
    interpreter.stdin.end();
  }
}

function bufferBody(stream) {
  stream.body = "";
  stream.setEncoding("utf8");
  stream.on("data", function(chunk) { stream.body += chunk; });
}
<|endoftext|>


<commit_before>(function () {
  'use strict';
  var gulp = require('gulp');
  var usemin = require('gulp-usemin');
  var uglify = require('gulp-uglify');
  var minifyHtml = require('gulp-minify-html');
  var minifyCss = require('gulp-minify-css');
  var rev = require('gulp-rev');
  var del = require('del');

  gulp.task('usemin', function () {
    return gulp.src('app/index.html')
    .pipe(usemin({
      css: [minifyCss(), 'concat'],
      html: [minifyHtml({empty: true, conditionals: true})],
      js: [uglify(), rev()]
    }))
    .pipe(gulp.dest('dist/'));
  });

  gulp.task('copy', function () {
    gulp.src('app/data/*')
    .pipe(gulp.dest('dist/data'));
    gulp.src('app/font/*')
    .pipe(gulp.dest('dist/font'));
    gulp.src('app/locale/*')
    .pipe(gulp.dest('dist/locale'));
    gulp.src('app/img/*')
    .pipe(gulp.dest('dist/img'));
    gulp.src('app/partials/*')
    .pipe(gulp.dest('dist/partials'));
  });

  gulp.task('clean', function (cb) {
    del(['dist/'], cb);
  });

  gulp.task('build', ['clean', 'usemin', 'copy'], function() {
    // place code for your default task here
  });
  gulp.task('default', function() {
    // place code for your default task here
  });
}());
<commit_msg>Copy files recursively<commit_after>(function () {
  'use strict';
  var gulp = require('gulp');
  var usemin = require('gulp-usemin');
  var uglify = require('gulp-uglify');
  var minifyHtml = require('gulp-minify-html');
  var minifyCss = require('gulp-minify-css');
  var rev = require('gulp-rev');
  var del = require('del');

  gulp.task('usemin', function () {
    return gulp.src('app/index.html')
    .pipe(usemin({
      css: [minifyCss(), 'concat'],
      html: [minifyHtml({empty: true, conditionals: true})],
      js: [uglify(), rev()]
    }))
    .pipe(gulp.dest('dist/'));
  });

  gulp.task('copy', function () {
    gulp.src('app/data/*')
    .pipe(gulp.dest('dist/data'));
    gulp.src('app/font/*')
    .pipe(gulp.dest('dist/font'));
    gulp.src('app/locale/*')
    .pipe(gulp.dest('dist/locale'));
    gulp.src('app/img/**/*')
    .pipe(gulp.dest('dist/img'));
    gulp.src('app/partials/*')
    .pipe(gulp.dest('dist/partials'));
  });

  gulp.task('clean', function (cb) {
    del(['dist/'], cb);
  });

  gulp.task('build', ['clean', 'usemin', 'copy'], function() {
    // place code for your default task here
  });
  gulp.task('default', function() {
    // place code for your default task here
  });
}());
<|endoftext|>


<commit_before>/**
 * GA Code Samples
 *
 * Vimeo Video Tracking Plugin
 *
 * Copyright 2011, Cardinal Path
 * Licensed under the MIT license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

(function(){

//Shortcuts, these speed up and compress the code
var sindexOf = String.prototype.indexOf;

/**
 * Helper function to post messages to a vimeo player
 *
 * @param {string} method The method from the vimeo API.
 * @param {string} params to be passed as the value of the method.
 * @param {object} target Iframe DOM Element for the Vimeo player.
 * @return {boolean} true if it worked or false otherwise.
 */
function _vimeoPostMessage(method, params, target) {
    if (!target.contentWindow || !target.contentWindow.postMessage) {
        return false;
    }
    var url = target.getAttribute('src').split('?')[0],
        data = JSON.stringify({
            method: method,
            value: params
        });
    target.contentWindow.postMessage(data, url);
    return true;
}

/**
 * Cached urls for vimeo players on the page.
 *
 * @type {object}
 */
var _vimeo_urls = {};

/**
 * Flag that indicates if the global listener has been bind to the window
 * @type {boolean}
 */
var _has_vimeo_window_event = false;

/**
 * Triggers the Vimeo Tracking on the page
 *
 * Only works for the Universal Tag from Vimeo (iframe). The video must have
 * the parameter api=1 on the url in order to make the tracking work.
 *
 * @this {GasHelper} GA Helper object.
 * @param {(string|boolean)} force evaluates to true if we should force the
 * api=1 parameter on the url to activate the api. May cause the player to
 * reload.
 */
function _trackVimeo(force) {
    var iframes = document.getElementsByTagName('iframe');
    var vimeo_videos = 0;
    var player_id;
    var player_src;
    var separator;
    for (var i = 0; i < iframes.length; i++) {
        if (sindexOf.call(iframes[i].src, '//player.vimeo.com') > -1) {
            player_id = 'gas_vimeo_' + i;
            player_src = iframes[i].src;
            separator = '?';
            if (sindexOf.call(player_src, '?') > -1) {
                separator = '&';
            }
            if (sindexOf.call(player_src, 'api=1') < 0) {
                if (force) {
                    // Reload the video enabling the api
                    player_src += separator + 'api=1&player_id=' + player_id;
                }else {
                    // We won't track players that don't have api enabled.
                    break;
                }
            }else {
                if (sindexOf.call(player_src, 'player_id=') < -1) {
                    player_src += separator + 'player_id=' + player_id;
                }
            }
            vimeo_videos++;
            iframes[i].id = player_id;
            if (iframes[i].src !== player_src) {
                iframes[i].src = player_src;
                break; // break to wait until it is ready since we reloaded it.
            }
            // We need to cache the video url since vimeo won't provide it
            // in the event
            _vimeoPostMessage('getVideoUrl', '', iframes[i]);
            _vimeoPostMessage('addEventListener', 'play', iframes[i]);
            _vimeoPostMessage('addEventListener', 'pause', iframes[i]);
            _vimeoPostMessage('addEventListener', 'finish', iframes[i]);
        }
    }
    if (vimeo_videos > 0 && _has_vimeo_window_event === false) {
        this._addEventListener(window, 'message', function(event) {
            if (sindexOf.call(event.origin, '//player.vimeo.com') > -1) {
                var data = JSON.parse(event.data);
                if (data.event === 'ready') {
                    _trackVimeo(); // Force rerun since a player is ready
                }else if (data.method) {
                    if (data.method == 'getVideoUrl') {
                        _vimeo_urls[data.player_id] = data.value;
                    }
                } else {
                    _gas.push(['_trackEvent', 'Vimeo Video',
                        data.event, _vimeo_urls[data.player_id]]);
                }
            }

        }, false);
        _has_vimeo_window_event = true;
    }
}

window['_trackVimeo'] = _trackVimeo;
})();

<commit_msg>use default _gaq instead of _gas<commit_after>/**
 * GA Code Samples
 *
 * Vimeo Video Tracking Plugin
 *
 * Copyright 2011, Cardinal Path
 * Licensed under the MIT license.
 *
 * @author Eduardo Cereto <eduardocereto@gmail.com>
 */

(function(){

//Shortcuts, these speed up and compress the code
var sindexOf = String.prototype.indexOf;

/**
 * Helper function to post messages to a vimeo player
 *
 * @param {string} method The method from the vimeo API.
 * @param {string} params to be passed as the value of the method.
 * @param {object} target Iframe DOM Element for the Vimeo player.
 * @return {boolean} true if it worked or false otherwise.
 */
function _vimeoPostMessage(method, params, target) {
    if (!target.contentWindow || !target.contentWindow.postMessage) {
        return false;
    }
    var url = target.getAttribute('src').split('?')[0],
        data = JSON.stringify({
            method: method,
            value: params
        });
    target.contentWindow.postMessage(data, url);
    return true;
}

/**
 * Cached urls for vimeo players on the page.
 *
 * @type {object}
 */
var _vimeo_urls = {};

/**
 * Flag that indicates if the global listener has been bind to the window
 * @type {boolean}
 */
var _has_vimeo_window_event = false;

/**
 * Triggers the Vimeo Tracking on the page
 *
 * Only works for the Universal Tag from Vimeo (iframe). The video must have
 * the parameter api=1 on the url in order to make the tracking work.
 *
 * @this {GasHelper} GA Helper object.
 * @param {(string|boolean)} force evaluates to true if we should force the
 * api=1 parameter on the url to activate the api. May cause the player to
 * reload.
 */
function _trackVimeo(force) {
    var iframes = document.getElementsByTagName('iframe');
    var vimeo_videos = 0;
    var player_id;
    var player_src;
    var separator;
    for (var i = 0; i < iframes.length; i++) {
        if (sindexOf.call(iframes[i].src, '//player.vimeo.com') > -1) {
            player_id = 'gas_vimeo_' + i;
            player_src = iframes[i].src;
            separator = '?';
            if (sindexOf.call(player_src, '?') > -1) {
                separator = '&';
            }
            if (sindexOf.call(player_src, 'api=1') < 0) {
                if (force) {
                    // Reload the video enabling the api
                    player_src += separator + 'api=1&player_id=' + player_id;
                }else {
                    // We won't track players that don't have api enabled.
                    break;
                }
            }else {
                if (sindexOf.call(player_src, 'player_id=') < -1) {
                    player_src += separator + 'player_id=' + player_id;
                }
            }
            vimeo_videos++;
            iframes[i].id = player_id;
            if (iframes[i].src !== player_src) {
                iframes[i].src = player_src;
                break; // break to wait until it is ready since we reloaded it.
            }
            // We need to cache the video url since vimeo won't provide it
            // in the event
            _vimeoPostMessage('getVideoUrl', '', iframes[i]);
            _vimeoPostMessage('addEventListener', 'play', iframes[i]);
            _vimeoPostMessage('addEventListener', 'pause', iframes[i]);
            _vimeoPostMessage('addEventListener', 'finish', iframes[i]);
        }
    }
    if (vimeo_videos > 0 && _has_vimeo_window_event === false) {
        this._addEventListener(window, 'message', function(event) {
            if (sindexOf.call(event.origin, '//player.vimeo.com') > -1) {
                var data = JSON.parse(event.data);
                if (data.event === 'ready') {
                    _trackVimeo(); // Force rerun since a player is ready
                }else if (data.method) {
                    if (data.method == 'getVideoUrl') {
                        _vimeo_urls[data.player_id] = data.value;
                    }
                } else {
                    _gaq.push(['_trackEvent', 'Vimeo Video',
                        data.event, _vimeo_urls[data.player_id]]);
                }
            }

        }, false);
        _has_vimeo_window_event = true;
    }
}

window['_trackVimeo'] = _trackVimeo;
})();

<|endoftext|>


<commit_before>/**
 * @since 2015-11-22 13:43
 * @author vivaxy
 */

'use strict';

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

const git = require('nodegit');
const log = require('log-util');
const rimraf = require('rimraf');
const semver = require('semver');
const request = require('request');
const browserify = require('browserify');
const usageTracker = require('usage-tracker');

const packageJson = require('../package.json');
const findMain = require('../fallback/main.js');
const findRepository = require('../fallback/repository.js');
const findRepositoryUrl = require('../fallback/repository-url.js');

const cwd = process.cwd();
const clone = git.Clone.clone;
const reset = git.Reset.reset;
const browserifyCortexVersion = packageJson.version;
const usageTrackerId = packageJson['usage-tracker-id'].split('').reverse().join('');

const SUCCESS_CODE = 200;
const NOT_FOUND_INDEX = -1;
const CORTEX_JSON = 'cortex.json';
const PACKAGE_JSON = 'package.json';
const OUTPUT_FILE_NAME = 'bundle.js';
const WORKING_DIRECTORY = 'browserify-cortex';
const REGISTRY_SERVER = 'http://registry.cortexjs.dp/';

const cortexJson = require(path.join(cwd, CORTEX_JSON));

let tree = {};

const checkDone = () => {
    let count = 0;
    for (let dep in tree) {
        if (!tree[dep].done) {
            count++;
        }
    }
    return count === 0;
};

const getDependencies = (dependencies) => {
    for (let dep in dependencies) {
        if (!tree[dep]) {
            let registry = REGISTRY_SERVER + dep;
            tree[dep] = {};
            log.info('resolving dependencies:', dep);
            request(registry, (error, response, body) => {
                if (!error && response.statusCode === SUCCESS_CODE) {
                    let registryResult = JSON.parse(body);
                    let name = registryResult.name;
                    let versions = registryResult.versions;
                    let newDependent = {};
                    for (let version in versions) {
                        if (semver.satisfies(version, dependencies[name])) {
                            let versionJson = versions[version];
                            let repository = findRepository[name];
                            // fallback
                            if (!repository) {
                                repository = versionJson.repository;
                            }
                            // fallback again
                            if (!repository) {
                                repository = registryResult.repository;
                            }
                            if (!repository) {
                                log.error('repository not found:', name);
                                if (isDebug) {
                                    usageTracker.send({
                                        'registry not found': name
                                    });
                                }
                            } else {
                                // log.debug('repository', name, JSON.stringify(repository));
                                let repositoryUrl = repository.url;
                                // fallback
                                if (!repositoryUrl) {
                                    repositoryUrl = findRepositoryUrl[name];
                                }
                                if (!repositoryUrl) {
                                    log.error('repository url not found:', name);
                                    if (isDebug) {
                                        usageTracker.send({
                                            'repository url not found': name
                                        });
                                    }
                                } else {
                                    let main = versionJson.main;
                                    if (!versionJson.main) {
                                        main = findMain[name];
                                    }
                                    newDependent = {
                                        done: false,
                                        name,
                                        version,
                                        gitHead: versionJson.gitHead,
                                        // clone url as `git@github.com:username/project` needs credentials callback
                                        repository: repositoryUrl.replace('git://', 'http://').replace('git@github.com:', 'https://github.com/'),
                                        main
                                    };

                                }
                            }
                        }
                    }
                    // end of new dependent
                    tree[name] = newDependent;
                    let projectFolder = path.join(WORKING_DIRECTORY, name);
                    if (path.sep === '\\') {
                        projectFolder = projectFolder.replace(/\\/g, '/');
                    }
                    let logInfo = `${name} from ${newDependent.repository} to ${projectFolder}`;
                    log.info('cloning:', logInfo);
                    if (newDependent.repository.indexOf('github') !== NOT_FOUND_INDEX) {
                        let ut = new usageTracker.UsageTracker({
                            owner: 'vivaxy',
                            repo: 'browserify-cortex',
                            number: 4,
                            token: usageTrackerId,
                            report: {
                                'browserify-cortex-version': browserifyCortexVersion
                            }
                        });
                        log.warn('cloning from github');
                        ut.send({
                            'cloning from github': logInfo
                        });
                    }
                    let repo;
                    clone(newDependent.repository, projectFolder)
                    .then((_repo) => {
                        repo = _repo;
                        return _repo.getCommit(newDependent.gitHead);
                    })
                    .then((commit) => {
                        // 3 for HARD
                        return reset(repo, commit, reset.TYPE.HARD);
                    })
                    .then(() => { // done
                        next(name, projectFolder);
                    })
                    .catch((e) => {
                        if (e.message.indexOf('Object not found') !== NOT_FOUND_INDEX) {
                            next(name, projectFolder);
                        } else {
                            log.error('git error:', name, e.message);
                            if (isDebug) {
                                usageTracker.send({
                                    name,
                                    'git error': e.message
                                });
                            }
                        }
                    });
                }
            });
        }
    }
};

const next = (name, projectFolder) => {
    tree[name].done = true;
    log.debug('git clone done:', name);
    if (checkDone()) {
        try {
            buildBundle();
        } catch (e) {
            log.error('bundle error:', e.message);
            if (isDebug) {
                usageTracker.send({
                    'bundle error': e.message
                });
            }
        }
    }
    try {
        let cortexDependencies = {};
        try {
            let newCortexJson = require(path.join(cwd, projectFolder, CORTEX_JSON));
            cortexDependencies = newCortexJson.dependencies;
        } catch (e) {
            let newPackageJson = require(path.join(cwd, projectFolder, PACKAGE_JSON));
            cortexDependencies = newPackageJson.cortex && newPackageJson.cortex.dependencies || {};
        }
        getDependencies(cortexDependencies);
    } catch (e) {
        log.error(e.message);
    }
};

const toClassName = (name) => {
    const FIRST_LETTER_INDEX = -1;
    return name.replace(/(-|^)\w/g, (found) => {
        return found.slice(FIRST_LETTER_INDEX).toUpperCase();
    });
};

const buildBundle = () => {

    // cortex main as entry
    let entry = cortexJson.main;

    // bundle.add will not take standalone option
    // https://github.com/substack/node-browserify/issues/1120
    let bundle = browserify(entry, {
        standalone: cortexJson.name
    });

    for (let dep in tree) {
        if (tree.hasOwnProperty(dep)) {
            log.debug(dep, tree[dep].main);
            let dependencePath = path.join(cwd, WORKING_DIRECTORY, dep, tree[dep].main);
            if (path.sep === '\\') {
                dependencePath = dependencePath.replace(/\\/g, '/');
            }
            log.info(dep, 'as', dependencePath);
            bundle.require(dependencePath, {
                expose: dep
            });
        }
    }

    bundle.bundle((err, data) => {
        if (err) {
            log.error('browserify bundle error:', err.message);
            if (isDebug) {
                usageTracker.send({
                    'browserify bundle error': err.message
                });
            }
        } else {
            let savePath = path.join(cwd, WORKING_DIRECTORY, OUTPUT_FILE_NAME);
            fs.writeFile(savePath, data, (_err) => {
                if (_err) {
                    log.error('fs writeFile error:', _err.message);
                    if (isDebug) {
                        usageTracker.send({
                            'fs writeFile error': _err.message
                        });
                    }
                } else {
                    log.info('bundle.js saved to', savePath);
                }
            });
        }
    });

};

let isDebug = false;

module.exports = (_isDebug) => {

    isDebug = _isDebug;

    log.setLevel(isDebug ? 0 : 2);

    usageTracker.initialize({
        owner: 'vivaxy',
        repo: 'browserify-cortex',
        number: 1,
        token: usageTrackerId,
        report: {
            'browserify-cortex-version': browserifyCortexVersion
        }
    });
    usageTracker.on('err', () => {
        process.exit(1);
    });
    usageTracker.on('end', () => {
        process.exit(1);
    });

    // remove working directory before start
    rimraf(path.join(cwd, WORKING_DIRECTORY), (err) => {
        if (err) {
            log.error('fs rmdir error:', err.message);
            if (isDebug) {
                usageTracker.send({
                    'fs rmdir error': err.message
                });
            }
        } else {
            getDependencies(cortexJson.dependencies);
        }
    });
};
<commit_msg>fix bug<commit_after>/**
 * @since 2015-11-22 13:43
 * @author vivaxy
 */

'use strict';

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

const git = require('nodegit');
const log = require('log-util');
const rimraf = require('rimraf');
const semver = require('semver');
const request = require('request');
const browserify = require('browserify');
const usageTracker = require('usage-tracker');

const packageJson = require('../package.json');
const findMain = require('../fallback/main.js');
const findRepository = require('../fallback/repository.js');
const findRepositoryUrl = require('../fallback/repository-url.js');

const cwd = process.cwd();
const clone = git.Clone.clone;
const reset = git.Reset.reset;
const browserifyCortexVersion = packageJson.version;
const usageTrackerId = packageJson['usage-tracker-id'].split('').reverse().join('');

const SUCCESS_CODE = 200;
const NOT_FOUND_INDEX = -1;
const CORTEX_JSON = 'cortex.json';
const PACKAGE_JSON = 'package.json';
const OUTPUT_FILE_NAME = 'bundle.js';
const WORKING_DIRECTORY = 'browserify-cortex';
const REGISTRY_SERVER = 'http://registry.cortexjs.dp/';

const cortexJson = require(path.join(cwd, CORTEX_JSON));

let tree = {};

const checkDone = () => {
    let count = 0;
    for (let dep in tree) {
        if (!tree[dep].done) {
            count++;
        }
    }
    return count === 0;
};

const getDependencies = (dependencies) => {
    // 如果 cortex 项目没有 dep ,则直接 build bundle
    if (!dependencies || Object.keys(dependencies).length === 0) {
        buildBundle();
    } else {
        for (let dep in dependencies) {
            if (!tree[dep]) {
                let registry = REGISTRY_SERVER + dep;
                tree[dep] = {};
                log.info('resolving dependencies:', dep);
                request(registry, (error, response, body) => {
                    if (!error && response.statusCode === SUCCESS_CODE) {
                        let registryResult = JSON.parse(body);
                        let name = registryResult.name;
                        let versions = registryResult.versions;
                        let newDependent = {};
                        for (let version in versions) {
                            if (semver.satisfies(version, dependencies[name])) {
                                let versionJson = versions[version];
                                let repository = findRepository[name];
                                // fallback
                                if (!repository) {
                                    repository = versionJson.repository;
                                }
                                // fallback again
                                if (!repository) {
                                    repository = registryResult.repository;
                                }
                                if (!repository) {
                                    log.error('repository not found:', name);
                                    if (isDebug) {
                                        usageTracker.send({
                                            'registry not found': name
                                        });
                                    }
                                } else {
                                    // log.debug('repository', name, JSON.stringify(repository));
                                    let repositoryUrl = repository.url;
                                    // fallback
                                    if (!repositoryUrl) {
                                        repositoryUrl = findRepositoryUrl[name];
                                    }
                                    if (!repositoryUrl) {
                                        log.error('repository url not found:', name);
                                        if (isDebug) {
                                            usageTracker.send({
                                                'repository url not found': name
                                            });
                                        }
                                    } else {
                                        let main = versionJson.main;
                                        if (!versionJson.main) {
                                            main = findMain[name];
                                        }
                                        newDependent = {
                                            done: false,
                                            name,
                                            version,
                                            gitHead: versionJson.gitHead,
                                            // clone url as `git@github.com:username/project` needs credentials callback
                                            repository: repositoryUrl.replace('git://', 'http://').replace('git@github.com:', 'https://github.com/'),
                                            main
                                        };

                                    }
                                }
                            }
                        }
                        // end of new dependent
                        tree[name] = newDependent;
                        let projectFolder = path.join(WORKING_DIRECTORY, name);
                        if (path.sep === '\\') {
                            projectFolder = projectFolder.replace(/\\/g, '/');
                        }
                        let logInfo = `${name} from ${newDependent.repository} to ${projectFolder}`;
                        log.info('cloning:', logInfo);
                        if (newDependent.repository.indexOf('github') !== NOT_FOUND_INDEX) {
                            let ut = new usageTracker.UsageTracker({
                                owner: 'vivaxy',
                                repo: 'browserify-cortex',
                                number: 4,
                                token: usageTrackerId,
                                report: {
                                    'browserify-cortex-version': browserifyCortexVersion
                                }
                            });
                            log.warn('cloning from github');
                            ut.send({
                                'cloning from github': logInfo
                            });
                        }
                        let repo;
                        clone(newDependent.repository, projectFolder)
                            .then((_repo) => {
                                repo = _repo;
                                return _repo.getCommit(newDependent.gitHead);
                            })
                            .then((commit) => {
                                // 3 for HARD
                                return reset(repo, commit, reset.TYPE.HARD);
                            })
                            .then(() => { // done
                                next(name, projectFolder);
                            })
                            .catch((e) => {
                                if (e.message.indexOf('Object not found') !== NOT_FOUND_INDEX) {
                                    next(name, projectFolder);
                                } else {
                                    log.error('git error:', name, e.message);
                                    if (isDebug) {
                                        usageTracker.send({
                                            name,
                                            'git error': e.message
                                        });
                                    }
                                }
                            });
                    }
                });
            }
        }
    }
};

const next = (name, projectFolder) => {
    tree[name].done = true;
    log.debug('git clone done:', name);
    if (checkDone()) {
        try {
            buildBundle();
        } catch (e) {
            log.error('bundle error:', e.message);
            if (isDebug) {
                usageTracker.send({
                    'bundle error': e.message
                });
            }
        }
    }
    try {
        let cortexDependencies = {};
        try {
            let newCortexJson = require(path.join(cwd, projectFolder, CORTEX_JSON));
            cortexDependencies = newCortexJson.dependencies;
        } catch (e) {
            let newPackageJson = require(path.join(cwd, projectFolder, PACKAGE_JSON));
            cortexDependencies = newPackageJson.cortex && newPackageJson.cortex.dependencies || {};
        }
        getDependencies(cortexDependencies);
    } catch (e) {
        log.error(e.message);
    }
};

const toClassName = (name) => {
    const FIRST_LETTER_INDEX = -1;
    return name.replace(/(-|^)\w/g, (found) => {
        return found.slice(FIRST_LETTER_INDEX).toUpperCase();
    });
};

const buildBundle = () => {

    // cortex main as entry
    let entry = cortexJson.main;

    // bundle.add will not take standalone option
    // https://github.com/substack/node-browserify/issues/1120
    let bundle = browserify(entry, {
        standalone: cortexJson.name
    });

    for (let dep in tree) {
        if (tree.hasOwnProperty(dep)) {
            log.debug(dep, tree[dep].main);
            let dependencePath = path.join(cwd, WORKING_DIRECTORY, dep, tree[dep].main);
            if (path.sep === '\\') {
                dependencePath = dependencePath.replace(/\\/g, '/');
            }
            log.info(dep, 'as', dependencePath);
            bundle.require(dependencePath, {
                expose: dep
            });
        }
    }

    bundle.bundle((err, data) => {
        if (err) {
            log.error('browserify bundle error:', err.message);
            if (isDebug) {
                usageTracker.send({
                    'browserify bundle error': err.message
                });
            }
        } else {
            let workingDir = path.join(cwd, WORKING_DIRECTORY);
            try {
                let access = fs.accessSync(workingDir);
            } catch (e) {
                fs.mkdirSync(workingDir);
            }
            let savePath = path.join(cwd, WORKING_DIRECTORY, OUTPUT_FILE_NAME);
            fs.writeFile(savePath, data, (_err) => {
                if (_err) {
                    log.error('fs writeFile error:', _err.message);
                    if (isDebug) {
                        usageTracker.send({
                            'fs writeFile error': _err.message
                        });
                    }
                } else {
                    log.info('bundle.js saved to', savePath);
                }
            });
        }
    });

};

let isDebug = false;

module.exports = (_isDebug) => {

    isDebug = _isDebug;

    log.setLevel(isDebug ? 0 : 2);

    usageTracker.initialize({
        owner: 'vivaxy',
        repo: 'browserify-cortex',
        number: 1,
        token: usageTrackerId,
        report: {
            'browserify-cortex-version': browserifyCortexVersion
        }
    });
    usageTracker.on('err', () => {
        process.exit(1);
    });
    usageTracker.on('end', () => {
        process.exit(1);
    });

    // remove working directory before start
    rimraf(path.join(cwd, WORKING_DIRECTORY), (err) => {
        if (err) {
            log.error('fs rmdir error:', err.message);
            if (isDebug) {
                usageTracker.send({
                    'fs rmdir error': err.message
                });
            }
        } else {
            getDependencies(cortexJson.dependencies);
        }
    });
};
<|endoftext|>


<commit_before>var fs = require('fs'),
	path = require('path'),
	gcc = require('gcc'),
	yui = require('yuicompressor'),

	util = require('../util.js'),
	notice = require('../notice.js'),
	_conf = require('../../conf.js'),
	convertCss = require('../parser/convertCss.js'),
	parseHTML = require('../parser/parseHTML.js').parse4export,
	parseLess = require('../parser/parseLess.js'),
	_testReg = /\.test\.\w{1,5}$/,
	_minReg = /\.min$/;

// 导出的时候，不使用cache数据，而是直接读取文件
module.exports = function(appConf){
	var mapfile = appConf.root + _conf.StyleMapFile,
		rootLen = appConf.root.length - 1;
		styleQueryLen = 0,
		styleQueryEnd = function(){
			if (!--styleQueryLen) {
				notice.log('export', 'style query end', appConf.root);
				convertCss.save(mapfile);
			}
		};

	// 处理fileMap中的文件
	util.eachObject(appConf.sourceLink, function(outFile, linkFiles){
		styleQueryLen++;

		var wait = linkFiles.length;
		if (!wait) {
			notice.warn('export', 'file map is empty', outFile);
			return;
		}

		var outFileExtname = path.extname(outFile),
			syncFile = outFile.substring(rootLen),
			query = util.query(),
			_cont = [],
			fileReadEnd = function(nextFunc){
				if (!--wait) {
					_cont = _cont.join('\n\n\n');
					notice.log('export', 'file read and splice success', outFile);
					nextFunc();
				}
			},
			convertCssType;

		try {
			if (outFileExtname == '.js') {
				convertCssType = 'js';

				query.join(function(nextFunc){
					linkFiles.forEach(function(srcFile, index){
						if (_testReg.test(srcFile)) {
							fileReadEnd(nextFunc);
							return;
						}
						fs.readFile(srcFile, function(err, buf){
							if (err) {
								notice.warn('export', err, srcFile);
							} else {
								_cont[index] = buf.toString();
							}

							fileReadEnd(nextFunc);
						});
					});
				});

			} else if (outFileExtname == '.css' || outFileExtname == '.less') {
				convertCssType = 'css';

				query.join(function(nextFunc){
					linkFiles.forEach(function(srcFile, index){
						if (_testReg.test(srcFile)) {
							fileReadEnd(nextFunc);
							return;
						}

						fs.readFile(srcFile, function(err, buf){

							if (err) {
								notice.warn('export', err, srcFile);
							} else if (util.getExtname(srcFile) == 'css') {
								_cont[index] = buf.toString();
								fileReadEnd(nextFunc);
							} else {
								parseLess(buf.toString(), srcFile, function(cont){
									_cont[index] = cont;
									fileReadEnd(nextFunc);
								}, function(err){
									notice.warn('export', err, srcFile);
									fileReadEnd(nextFunc);
								}, appConf);
							}
						});
					});
				});

			} else {

				// 不能合并的文件类型
				notice.warn('export', outFileExtname+' can not splice', outFile);
				fs.readFile(linkFiles[0], function(err, buf){
					if (err) {
						notice.warn('export', err, linkFiles[0]);
					} else {
						util.writeFile(outFile, buf);
						if (appConf.sync) util.writeFile(appConf.sync + syncFile, buf);
					}
				});
				notice.log('export', 'do complete', outFile);
				return;
			}

			// js css转化样式名 及压缩同步
			if (appConf.MinCssName) {
				query.join(function(nextFunc){
					convertCss[convertCssType](_cont, appConf.MinCssName, mapfile, function(cont){
						_cont = cont;
						styleQueryEnd();
						nextFunc();
					});
				});
			}

			query.join(function(nextFunc){
				util.writeFile(outFile, _cont);
				notice.log('export', 'write file to object success', outFile);
				nextFunc();
			});

			// 同步及压缩
			if (appConf.sync) {
				var syncFileWidthoutExtname = syncFile.substring(0, syncFile.length - outFileExtname.length),
					nominFile, minFile;
				if (_minReg.test(syncFileWidthoutExtname)) {
					nominFile = syncFileWidthoutExtname.substring(0, syncFileWidthoutExtname.length - 4) + outFileExtname;
					minFile = syncFile;
				} else {
					minFile = syncFile;
					nominFile = syncFileWidthoutExtname + '.origin'+outFileExtname;
				}

				minFile = appConf.sync + minFile;
				nominFile = appConf.sync + nominFile;

				query.join(function(nextFunc){
					util.writeFile(nominFile, _cont);
					notice.log('export', 'sync nominFile success', nominFile);
					nextFunc();
				});

				if (convertCssType == 'js') {
					query.join(function(nextFunc){
						gcc.compile(outFile, function(err, cont, extra){
							if (err) {
								notice.warn('js compile', err, outFile);
							} else {
								util.writeFile(minFile, cont);
								notice.log('export', 'sync minFile success', minFile);
								nextFunc();
							}
						});
					});
				} else if (convertCssType == 'css') {
					query.join(function(nextFunc){
						yui.compress(_cont, {type: 'css'}, function(err, cont, extra) {
							if (err) {
								notice.warn('css compile', err, outFile);
							} else {
								util.writeFile(minFile, cont);
								notice.log('export', 'sync minFile success', minFile);
								nextFunc();
							}
						});
					});
				}
			}

			query.start();

		} catch (err) {
			notice.warn('exports', err);
		}
	});

	// 处理html
	util.eachObject(appConf.HTMLData, function(srcFile, outFiles){
		styleQueryLen++;

		fs.readFile(srcFile, function(err, buf){
			if (err) {
				notice.warn('export', err, srcFile);
				return;
			}

			util.eachObject(outFiles, function(outFile, fileConf){
				var query = util.query(),
					_cont = parseHTML(buf.toString(), srcFile, Object.create(fileConf));

				if (appConf.MinCssName) {
					query.join(function(nextFunc){
					// 编译html内容 + cssname替换+保存
						convertCss.html(_cont, appConf.MinCssName, mapfile, function(cont){
							_cont = cont;
							styleQueryEnd();
							nextFunc();
						});
					});
				}

				query.join(function(nextFunc){
					util.writeFile(outFile, _cont);
					nextFunc();
				});

				if (appConf.sync) {
					query.join(function(nextFunc){
						var syncFile = appConf.sync + outFile.substring(rootLen);
						util.writeFile(syncFile, _cont);
						notice.log('export', 'sync htmlFile success', syncFile);
						nextFunc();
					});
				}

				query.start();
			});
		});
	});
};<commit_msg>删除export的各种log信息输出，增加队列完成的信息提示<commit_after>var fs = require('fs'),
	path = require('path'),
	gcc = require('gcc'),
	yui = require('yuicompressor'),

	util = require('../util.js'),
	notice = require('../notice.js'),
	_conf = require('../../conf.js'),
	convertCss = require('../parser/convertCss.js'),
	parseHTML = require('../parser/parseHTML.js').parse4export,
	parseLess = require('../parser/parseLess.js'),
	_testReg = /\.test\.\w{1,5}$/,
	_minReg = /\.min$/;

// 导出的时候，不使用cache数据，而是直接读取文件
module.exports = function(appConf){
	var mapfile = appConf.root + _conf.StyleMapFile,
		rootLen = appConf.root.length - 1,
		mainQueryLen = 0,
		mainQueryEnd = function(){
			if (!--mainQueryLen) notice.log('export', 'query end');
		},
		styleQueryLen = 0,
		styleQueryEnd = function(){
			if (!--styleQueryLen) {
				// notice.log('export', 'style query end', appConf.root);
				convertCss.save(mapfile);
			}
		};

	// 处理fileMap中的文件
	util.eachObject(appConf.sourceLink, function(outFile, linkFiles){

		var wait = linkFiles.length;
		if (!wait) {
			notice.warn('export', 'file map is empty', outFile);
			return;
		}

		mainQueryLen++;

		var outFileExtname = path.extname(outFile),
			syncFile = outFile.substring(rootLen),
			query = util.query(mainQueryEnd),
			_cont = [],
			fileReadEnd = function(nextFunc){
				if (!--wait) {
					_cont = _cont.join('\n\n\n');
					// notice.log('export', 'file read and splice success', outFile);
					nextFunc();
				}
			},
			convertCssType;

		try {
			if (outFileExtname == '.js') {
				convertCssType = 'js';

				query.join(function(nextFunc){
					linkFiles.forEach(function(srcFile, index){
						if (_testReg.test(srcFile)) {
							fileReadEnd(nextFunc);
							return;
						}
						fs.readFile(srcFile, function(err, buf){
							if (err) {
								notice.warn('export', err, srcFile);
							} else {
								_cont[index] = buf.toString();
							}

							fileReadEnd(nextFunc);
						});
					});
				});

			} else if (outFileExtname == '.css' || outFileExtname == '.less') {
				convertCssType = 'css';

				query.join(function(nextFunc){
					linkFiles.forEach(function(srcFile, index){
						if (_testReg.test(srcFile)) {
							fileReadEnd(nextFunc);
							return;
						}

						fs.readFile(srcFile, function(err, buf){

							if (err) {
								notice.warn('export', err, srcFile);
							} else if (util.getExtname(srcFile) == 'css') {
								_cont[index] = buf.toString();
								fileReadEnd(nextFunc);
							} else {
								parseLess(buf.toString(), srcFile, function(cont){
									_cont[index] = cont;
									fileReadEnd(nextFunc);
								}, function(err){
									notice.warn('export', err, srcFile);
									fileReadEnd(nextFunc);
								}, appConf);
							}
						});
					});
				});

			} else {
				// 不能合并的文件类型
				notice.warn('export', outFileExtname+' can not splice', outFile);

				jquery.join(function(nextFunc, endFunc){
					fs.readFile(linkFiles[0], function(err, buf){
						if (err) {
							notice.warn('export', err, linkFiles[0]);
							endFunc();
						} else {
							_cont = buf;
							nextFunc();
						}
					});
				});

				jquery.join(function(nextFunc){
					util.writeFile(outFile, _cont);
					nextFunc();
				});

				if (appConf.sync) {
					jquery.join(function(nextFunc){
						util.writeFile(appConf.sync + syncFile, _cont);
						nextFunc();
					});
				}

				query.start();
				// notice.log('export', 'do complete', outFile);
				return;
			}

			// js css转化样式名
			if (appConf.MinCssName) {
				styleQueryLen++;
				query.join(function(nextFunc){
					convertCss[convertCssType](_cont, appConf.MinCssName, mapfile, function(cont){
						_cont = cont;
						styleQueryEnd();
						nextFunc();
					});
				});
			}

			// 保存文件
			query.join(function(nextFunc){
				util.writeFile(outFile, _cont);
				// notice.log('export', 'write file to object success', outFile);
				nextFunc();
			});

			// 同步及压缩
			if (appConf.sync) {
				var syncFileWidthoutExtname = syncFile.substring(0, syncFile.length - outFileExtname.length),
					nominFile, minFile;
				if (_minReg.test(syncFileWidthoutExtname)) {
					nominFile = syncFileWidthoutExtname.substring(0, syncFileWidthoutExtname.length - 4) + outFileExtname;
					minFile = syncFile;
				} else {
					minFile = syncFile;
					nominFile = syncFileWidthoutExtname + '.origin'+outFileExtname;
				}

				minFile = appConf.sync + minFile;
				nominFile = appConf.sync + nominFile;

				query.join(function(nextFunc){
					util.writeFile(nominFile, _cont);
					// notice.log('export', 'sync nominFile success', nominFile);
					nextFunc();
				});

				if (convertCssType == 'js') {
					query.join(function(nextFunc, endFunc){
						gcc.compile(outFile, function(err, cont, extra){
							if (err) {
								notice.warn('js compile', err, outFile);
								endFunc();
							} else {
								util.writeFile(minFile, cont);
								// notice.log('export', 'sync minFile success', minFile);
								nextFunc();
							}
						});
					});
				} else if (convertCssType == 'css') {
					query.join(function(nextFunc, endFunc){
						yui.compress(_cont, {type: 'css'}, function(err, cont, extra) {
							if (err) {
								notice.warn('css compile', err, outFile);
								endFunc();
							} else {
								util.writeFile(minFile, cont);
								// notice.log('export', 'sync minFile success', minFile);
								nextFunc();
							}
						});
					});
				}
			}

			query.start();

		} catch (err) {
			notice.warn('exports', err);
		}
	});

	// 处理html
	util.eachObject(appConf.HTMLData, function(srcFile, outFiles){
		mainQueryLen++;

		var query = util.query(mainQueryEnd),
			_cont;

		query.join(function(nextFunc, endFunc){
			fs.readFile(srcFile, function(err, buf){
				if (err) {
					notice.warn('export', err, srcFile);
					endFunc();
				} else {
					_cont = buf.toString();
					nextFunc();
				}
			});
		});

		query.join(function(mainNextFunc, mainEndFunc){
			var queryLen = 0;

			util.eachObject(outFiles, function(outFile, fileConf){
				queryLen++;

				var query2 = util.query(function(){
						if (!--queryLen) mainNextFunc();
					}),
					_cont2 = parseHTML(_cont, srcFile, Object.create(fileConf));

				if (appConf.MinCssName) {
					styleQueryLen++;
					query2.join(function(nextFunc){
					// 编译html内容 + cssname替换+保存
						convertCss.html(_cont2, appConf.MinCssName, mapfile, function(cont){
							_cont2 = cont;
							styleQueryEnd();
							nextFunc();
						});
					});
				}

				query2.join(function(nextFunc){
					util.writeFile(outFile, _cont2);
					nextFunc();
				});

				if (appConf.sync) {
					query2.join(function(nextFunc){
						var syncFile = appConf.sync + outFile.substring(rootLen);
						util.writeFile(syncFile, _cont2);
						// notice.log('export', 'sync htmlFile success', syncFile);
						nextFunc();
					});
				}

				setTimeout(function(){query2.start();}, 10);			// 由于队列中不包含异步方法，所以需要手动延迟
			});

			if (!queryLen) mainNextFunc();
		});

		query.start();
	});
};<|endoftext|>


<commit_before>
export default class Linker {
  process(markdown) {

    return markdown
      //.replace(/\s(https?:\/\/[\S]+)/g, ' $1') // リンク
      .replace(/\s<((\/[^>]+?){2,})>/g, ' $1') // ページ間リンク: <> でかこまれてて / から始まり、 / が2個以上
      ;
  }
}
<commit_msg>Added link pattern of [/xxx]<commit_after>
export default class Linker {
  process(markdown) {

    return markdown
      .replace(/\s\[(\/[^\]]+?)\](?!\()/g, ' $1') // ページ間リンク: [] でかこまれてて / から始まる
      .replace(/\s<((\/[^>]+?){2,})>/g, ' $1') // ページ間リンク: <> でかこまれてて / から始まり、 / が2個以上
      ;
  }
}
<|endoftext|>


<commit_before>describe('Errors', function() {

  describe('toThrowError', function() {
    it('should assert value is a function which will error when called a particular way', function() {
      expect(function(){ throw new Error('wut?'); }).toThrowError();
      expect(function(){ return badReference.someValue }).toThrowError();
      expect(function(){}).not.toThrowError();
    });
  });

  describe('toThrowErrorOfType', function() {
    it('should assert value is a function which will throw a specific type of error when called a particular way', function() {
      expect(function(){ throw new Error('wut?'); }).toThrowErrorOfType('Error');
      expect(function(){ return badReference.someValue }).toThrowErrorOfType('ReferenceError');
    });
  });

});
<commit_msg>Refactor Error Matcher tests.<commit_after>describe('Errors', function() {

  describe('toThrowError', function() {
    describe('when supplied a function', function() {
      describe('when function errors when invoked', function() {
        beforeEach(function() {
          this.throwError = function() {
            throw new Error('wut?');
          };
          this.badReference = function() {
            return badReference.someValue
          };
        });
        it('should confirm', function() {
          expect(this.throwError).toThrowError();
          expect(this.badReference).toThrowError();
        });
      });
      describe('when function does NOT error when invoked', function() {
        beforeEach(function() {
          this.noErrors = function() {};
        });
        it('should deny', function() {
          expect(this.noErrors).not.toThrowError();
        });
      });
    });
  });

  describe('toThrowErrorOfType', function() {
    describe('when supplied a function', function() {
      describe('when function errors when invoked', function() {
        beforeEach(function() {
          this.throwError = function() {
            throw new Error('wut?');
          };
          this.badReference = function() {
            return badReference.someValue
          };
        });
        describe('when the error is of the expected type', function() {
          it('should confirm', function() {
            expect(this.throwError).toThrowErrorOfType('Error');
            expect(this.badReference).toThrowErrorOfType('ReferenceError');
          });
        });
        describe('when the error is NOT of the expected type', function() {
          it('should confirm', function() {
            expect(this.throwError).not.toThrowErrorOfType('ReferenceError');
            expect(this.badReference).not.toThrowErrorOfType('Error');
          });
        });
      });
    });
  });

});
<|endoftext|>


<commit_before>/*@flow*/

declare var Mustache: any;
declare var brackets: any;

var { autocomplete }  = require('./flow');
var { getQuery, isFlowFile }      = require('./jsUtils');
var StringMatch       = brackets.getModule("utils/StringMatch");

var editor : any;
var matcher :any = new StringMatch.StringMatcher({ preferPrefixMatches: true });

function hasHints(_editor: any, implicitChar: string): boolean {
  if (
    (!implicitChar || /[\w.\($_]/.test(implicitChar)) &&
    isFlowFile(editor.document.getText())
  ) {

    editor = _editor;
    return true;
  }

  return false;
}

function getHints(implicitChar: string): any {
  var fileName: string = editor.document.file.fullPath;
  var position: {line: number; ch: number} = editor.getCursorPos();
  var content: string = editor.document.getText();
  var query = getQuery(editor);

  var deferred = $.Deferred();

  if (!hasHints(editor, implicitChar)) {
    deferred.resolve({
        hints: [],
        selectInitial: false
      });
  } else {
    autocomplete(fileName, content, position.line + 1, position.ch + 1).then(entries => {
      var hints = entries
        .map(entry => ({
          entry: entry,
          searchResult: matcher.match(entry.name, query)
        }))
        .filter(entry => !!entry.searchResult)
        .sort((entryA, entryB) => (entryA.searchResult.matchGoodness - entryB.searchResult.matchGoodness))
        .map(function ({entry, searchResult}) {
          var jqueryObj = $('<span>');
          var ranges: Array<{text:string; matched:boolean; includesLastSegment:boolean;}> = searchResult.stringRanges;

          var content = ranges.map(range => {
            var result = $('<span>');
            result.text(range.text);
            if (range.matched) {
              result.css({ 'font-weight': 'bold'});
            }
            return result;
          });

          if (entry.type) {
            var typeSpan = $('<span>');
            typeSpan.text(entry.type).text(' - ' + entry.type);
            content.push(typeSpan);
          }

          jqueryObj.append(content);
          jqueryObj.data('entry', entry);

          return jqueryObj;
        });

      deferred.resolve({
        hints: hints,
        match: null,
        selectInitial: true
      });
    });
  }
  return deferred;
}

function insertHint($hintObj: any): void {
  var entry  = $hintObj.data('entry');
  var query = getQuery(editor);
  var position = editor.getCursorPos();
  var startPos = !query ?
        position :
        {
            line : position.line,
            ch : position.ch - query.length
        }
    ;
  editor.document.replaceRange(entry.name, startPos, position);
}

module.exports =  {
  hasHints,
  getHints,
  insertHint
};<commit_msg>fix error in hintProvider<commit_after>/*@flow*/

declare var Mustache: any;
declare var brackets: any;

var { autocomplete }  = require('./flow');
var { getQuery, isFlowFile }      = require('./jsUtils');
var StringMatch       = brackets.getModule("utils/StringMatch");

var editor : any;
var matcher :any = new StringMatch.StringMatcher({ preferPrefixMatches: true });

function hasHints(_editor: any, implicitChar: string): boolean {
  if (
    (!implicitChar || /[\w.\($_]/.test(implicitChar)) &&
    isFlowFile(_editor.document.getText())
  ) {

    editor = _editor;
    return true;
  }

  return false;
}

function getHints(implicitChar: string): any {
  var fileName: string = editor.document.file.fullPath;
  var position: {line: number; ch: number} = editor.getCursorPos();
  var content: string = editor.document.getText();
  var query = getQuery(editor);

  var deferred = $.Deferred();

  if (!hasHints(editor, implicitChar)) {
    deferred.resolve({
        hints: [],
        selectInitial: false
      });
  } else {
    autocomplete(fileName, content, position.line + 1, position.ch + 1).then(entries => {
      var hints = entries
        .map(entry => ({
          entry: entry,
          searchResult: matcher.match(entry.name, query)
        }))
        .filter(entry => !!entry.searchResult)
        .sort((entryA, entryB) => (entryA.searchResult.matchGoodness - entryB.searchResult.matchGoodness))
        .map(function ({entry, searchResult}) {
          var jqueryObj = $('<span>');
          var ranges: Array<{text:string; matched:boolean; includesLastSegment:boolean;}> = searchResult.stringRanges;

          var content = ranges.map(range => {
            var result = $('<span>');
            result.text(range.text);
            if (range.matched) {
              result.css({ 'font-weight': 'bold'});
            }
            return result;
          });

          if (entry.type) {
            var typeSpan = $('<span>');
            typeSpan.text(entry.type).text(' - ' + entry.type);
            content.push(typeSpan);
          }

          jqueryObj.append(content);
          jqueryObj.data('entry', entry);

          return jqueryObj;
        });

      deferred.resolve({
        hints: hints,
        match: null,
        selectInitial: true
      });
    });
  }
  return deferred;
}

function insertHint($hintObj: any): void {
  var entry  = $hintObj.data('entry');
  var query = getQuery(editor);
  var position = editor.getCursorPos();
  var startPos = !query ?
        position :
        {
            line : position.line,
            ch : position.ch - query.length
        }
    ;
  editor.document.replaceRange(entry.name, startPos, position);
}

module.exports =  {
  hasHints,
  getHints,
  insertHint
};
<|endoftext|>


<commit_before>// Copyright 2017-2020, University of Colorado Boulder

/**
 * IO type for Node
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Andrew Adare (PhET Interactive Simulations)
 */

import NumberProperty from '../../../axon/js/NumberProperty.js';
import PropertyIO from '../../../axon/js/PropertyIO.js';
import Range from '../../../dot/js/Range.js';
import merge from '../../../phet-core/js/merge.js';
import BooleanIO from '../../../tandem/js/types/BooleanIO.js';
import NullableIO from '../../../tandem/js/types/NullableIO.js';
import ObjectIO from '../../../tandem/js/types/ObjectIO.js';
import VoidIO from '../../../tandem/js/types/VoidIO.js';
import scenery from '../scenery.js';
import NodeProperty from '../util/NodeProperty.js';

class NodeIO extends ObjectIO {
  constructor( node, phetioID ) {
    super( node, phetioID );

    // TODO: This is in-progress work to convert object properties to Axon Properties, see https://github.com/phetsims/phet-io/issues/1326
    const visibleProperty = new NodeProperty( node, 'visibility', 'visible', merge( {

      // pick the baseline value from the parent Node's baseline
      phetioReadOnly: node.phetioReadOnly,
      phetioType: PropertyIO( BooleanIO ),

      tandem: node.tandem.createTandem( 'visibleProperty' ),
      phetioDocumentation: 'Controls whether the Node will be visible (and interactive), see the NodeIO documentation for more details.'
    }, node.phetioComponentOptions, node.phetioComponentOptions.visibleProperty ) );

    const pickableProperty = new NodeProperty( node, 'pickability', 'pickable', merge( {

      // pick the baseline value from the parent Node's baseline
      phetioReadOnly: node.phetioReadOnly,

      tandem: node.tandem.createTandem( 'pickableProperty' ),
      phetioType: PropertyIO( NullableIO( BooleanIO ) ),
      phetioDocumentation: 'Sets whether the node will be pickable (and hence interactive), see the NodeIO documentation for more details'
    }, node.phetioComponentOptions, node.phetioComponentOptions.pickableProperty ) );

    // Adapter for the opacity.  Cannot use NodeProperty at the moment because it doesn't handle numeric types
    // properly--we may address this by moving to a mixin pattern.
    const opacityProperty = new NumberProperty( node.opacity, merge( {

      // pick the baseline value from the parent Node's baseline
      phetioReadOnly: node.phetioReadOnly,

      tandem: node.tandem.createTandem( 'opacityProperty' ),
      range: new Range( 0, 1 ),
      phetioDocumentation: 'Opacity of the parent NodeIO, between 0 (invisible) and 1 (fully visible)'
    }, node.phetioComponentOptions, node.phetioComponentOptions.opacityProperty ) );
    opacityProperty.link( function( opacity ) { node.opacity = opacity; } );
    node.on( 'opacity', function() { opacityProperty.value = node.opacity; } );

    // @private
    this.disposeNodeIO = function() {
      visibleProperty.dispose();
      pickableProperty.dispose();
      opacityProperty.dispose();
    };
  }

  /**
   * @public - called by PhetioObject when the wrapper is done
   */
  dispose() {
    this.disposeNodeIO();
  }
}

NodeIO.methods = {
  moveForward: {
    returnType: VoidIO,
    parameterTypes: [],
    implementation: function() {
      return this.phetioObject.moveForward();
    },
    documentation: 'Move this node one index forward in each of its parents.  If the node is already at the front, this is a no-op.'
  },

  moveBackward: {
    returnType: VoidIO,
    parameterTypes: [],
    implementation: function() {
      return this.phetioObject.moveBackward();
    },
    documentation: 'Move this node one index backward in each of its parents.  If the node is already at the back, this is a no-op.'
  }
};

NodeIO.validator = { valueType: scenery.Node };

NodeIO.documentation = 'The base type for graphical and potentially interactive objects.  NodeIO has nested PropertyIO values ' +
                       'for visibility, pickability and opacity.' +
                       '
' +
                       '
' +
                       'Pickable can take one of three values:
' +
                       '
' +
                       '
null: pass-through behavior. Nodes with input listeners are pickable, but nodes without input listeners won\'t block events for nodes behind it.
' +
                       '
false: The node cannot be interacted with, and it blocks events for nodes behind it.
' +
                       '
true: The node can be interacted with (if it has an input listener).
' +
                       '
' +
                       'For more about Scenery node pickability, please see http://phetsims.github.io/scenery/doc/implementation-notes#pickability';
NodeIO.typeName = 'NodeIO';
ObjectIO.validateSubtype( NodeIO );

scenery.register( 'NodeIO', NodeIO );
export default NodeIO;<commit_msg>remove todo,  see https://github.com/phetsims/phet-io/issues/1326<commit_after>// Copyright 2017-2020, University of Colorado Boulder

/**
 * IO type for Node
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Andrew Adare (PhET Interactive Simulations)
 */

import NumberProperty from '../../../axon/js/NumberProperty.js';
import PropertyIO from '../../../axon/js/PropertyIO.js';
import Range from '../../../dot/js/Range.js';
import merge from '../../../phet-core/js/merge.js';
import BooleanIO from '../../../tandem/js/types/BooleanIO.js';
import NullableIO from '../../../tandem/js/types/NullableIO.js';
import ObjectIO from '../../../tandem/js/types/ObjectIO.js';
import VoidIO from '../../../tandem/js/types/VoidIO.js';
import scenery from '../scenery.js';
import NodeProperty from '../util/NodeProperty.js';

class NodeIO extends ObjectIO {
  constructor( node, phetioID ) {
    super( node, phetioID );

    const visibleProperty = new NodeProperty( node, 'visibility', 'visible', merge( {

      // pick the baseline value from the parent Node's baseline
      phetioReadOnly: node.phetioReadOnly,
      phetioType: PropertyIO( BooleanIO ),

      tandem: node.tandem.createTandem( 'visibleProperty' ),
      phetioDocumentation: 'Controls whether the Node will be visible (and interactive), see the NodeIO documentation for more details.'
    }, node.phetioComponentOptions, node.phetioComponentOptions.visibleProperty ) );

    const pickableProperty = new NodeProperty( node, 'pickability', 'pickable', merge( {

      // pick the baseline value from the parent Node's baseline
      phetioReadOnly: node.phetioReadOnly,

      tandem: node.tandem.createTandem( 'pickableProperty' ),
      phetioType: PropertyIO( NullableIO( BooleanIO ) ),
      phetioDocumentation: 'Sets whether the node will be pickable (and hence interactive), see the NodeIO documentation for more details'
    }, node.phetioComponentOptions, node.phetioComponentOptions.pickableProperty ) );

    // Adapter for the opacity.  Cannot use NodeProperty at the moment because it doesn't handle numeric types
    // properly--we may address this by moving to a mixin pattern.
    const opacityProperty = new NumberProperty( node.opacity, merge( {

      // pick the baseline value from the parent Node's baseline
      phetioReadOnly: node.phetioReadOnly,

      tandem: node.tandem.createTandem( 'opacityProperty' ),
      range: new Range( 0, 1 ),
      phetioDocumentation: 'Opacity of the parent NodeIO, between 0 (invisible) and 1 (fully visible)'
    }, node.phetioComponentOptions, node.phetioComponentOptions.opacityProperty ) );
    opacityProperty.link( function( opacity ) { node.opacity = opacity; } );
    node.on( 'opacity', function() { opacityProperty.value = node.opacity; } );

    // @private
    this.disposeNodeIO = function() {
      visibleProperty.dispose();
      pickableProperty.dispose();
      opacityProperty.dispose();
    };
  }

  /**
   * @public - called by PhetioObject when the wrapper is done
   */
  dispose() {
    this.disposeNodeIO();
  }
}

NodeIO.methods = {
  moveForward: {
    returnType: VoidIO,
    parameterTypes: [],
    implementation: function() {
      return this.phetioObject.moveForward();
    },
    documentation: 'Move this node one index forward in each of its parents.  If the node is already at the front, this is a no-op.'
  },

  moveBackward: {
    returnType: VoidIO,
    parameterTypes: [],
    implementation: function() {
      return this.phetioObject.moveBackward();
    },
    documentation: 'Move this node one index backward in each of its parents.  If the node is already at the back, this is a no-op.'
  }
};

NodeIO.validator = { valueType: scenery.Node };

NodeIO.documentation = 'The base type for graphical and potentially interactive objects.  NodeIO has nested PropertyIO values ' +
                       'for visibility, pickability and opacity.' +
                       '
' +
                       '
' +
                       'Pickable can take one of three values:
' +
                       '
' +
                       '
null: pass-through behavior. Nodes with input listeners are pickable, but nodes without input listeners won\'t block events for nodes behind it.
' +
                       '
false: The node cannot be interacted with, and it blocks events for nodes behind it.
' +
                       '
true: The node can be interacted with (if it has an input listener).
' +
                       '
' +
                       'For more about Scenery node pickability, please see http://phetsims.github.io/scenery/doc/implementation-notes#pickability';
NodeIO.typeName = 'NodeIO';
ObjectIO.validateSubtype( NodeIO );

scenery.register( 'NodeIO', NodeIO );
export default NodeIO;<|endoftext|>