<commit_before>'use strict'

var Stream = require('readable-stream')
var inherit = require('util').inherits
var http = require('http')
var https = require('https')
var spdy = require('spdy')
var parseUrl = require('url').parse
var normalizeUrl = require('normalize-url')
var Cookies = require('cookie-manager')

/**
 * Trace
 * @constructor
 * @return {Trace}
 */
function Trace (url, options) {
  if (!(this instanceof Trace)) {
    return new Trace(url, options)
  }

  options = options != null ? options : {}
  options.objectMode = true

  Stream.Readable.call(this, options)

  this.hops = 0
  this.start = 0
  this.time = 0
  this.url = url
  this.currentUrl = url
  this.prevUrl = null
  this.statusCode = 0
  this.cookies = new Cookies()
  this.userAgent = options.userAgent || Trace.userAgent
}

/**
 * User-Agent string to be used in requests
 * @type {String}
 */
Trace.userAgent = 'Mozilla/5.0 AppleWebKit/537.36 Chrome/50.0.2653.0 Safari/537.36'

/**
 * Set `response.protocol` to the appropriate value
 * @param {http.IncomingMessage} res
 */
Trace.setProtocol = function (res) {
  res.protocol = 'HTTP'
  if (res.socket._spdyState) {
    var spdyState = res.socket._spdyState.parent
    var protocol = spdyState.alpnProtocol || spdyState.npnProtocol
    var parts = protocol.match(/^([^/\d]+)\/?(\d+)(?:\.(\d+))?/i)
    if (parts) {
      res.protocol = parts[1] === 'h' ? 'HTTP' : parts[1].toUpperCase()
      res.httpVersionMajor = parts[2]
      res.httpVersionMinor = parts[3] || 0
      res.httpVersion = res.httpVersionMajor + '.' + res.httpVersionMinor
    }
  }
}

inherit(Trace, Stream.Readable)

Object.assign(Trace.prototype, {

  _setCookie: function (url, headers) {
    if (!headers['set-cookie']) return 0
    var cookieCount = headers['set-cookie'].length
    for (var i = 0; i < cookieCount; i++) {
      this.cookies.store(url, headers['set-cookie'][0])
    }
    return cookieCount
  },

  _follow: function (url, ms) {
    var self = this

    this.currentUrl = normalizeUrl(url, { stripWWW: false })

    if (this.currentUrl === this.prevUrl) {
      this.emit('error', new Error('Self-referencing redirect: ' + this.currentUrl))
      return
    }

    this.prevUrl = this.currentUrl

    var opts = parseUrl(this.currentUrl)

    opts.method = 'HEAD'
    opts.headers = {
      'Cookie': this.cookies.prepare(this.currentUrl),
      'User-Agent': this.userAgent
    }

    var protocol = opts.protocol === 'https:' ? https : http

    if (opts.protocol === 'https:') {
      opts.agent = spdy.createAgent({
        host: opts.hostname || opts.host,
        port: opts.port || 443
      })

      // There's a case where spdy deadlocks, as it attempts to fall back to http/1.x;
      // see https://github.com/indutny/node-spdy/blob/v3.4.4/lib/spdy/agent.js#L121-L127,
      // https://github.com/indutny/node-spdy/blob/v3.4.4/lib/spdy/agent.js#L157-L160 and
      // https://github.com/indutny/node-spdy/blob/v3.4.4/lib/spdy/agent.js#L66
      // Fix: overwrite `.createSocket()` with node core's,
      // as spdy's `Agent.prototype._getCreateSocket()` is bugged
      opts.agent.createSocket = https.Agent.prototype.createSocket

      // If a custom agent is used, by default all connection-level
      // errors will result in an uncaught exception
      // (See https://github.com/indutny/node-spdy#usage)
      opts.agent.on('error', function (error) {
        this.emit('error', error)
      })
    }

    var req = protocol.request(opts, function (res) {
      var diff = Date.now() - ms
      var newCookies = self._setCookie(self.currentUrl, res.headers)

      Trace.setProtocol(res)

      self.statusCode = res.statusCode

      self.push({
        protocol: res.protocol,
        protocolVersionMajor: res.httpVersionMajor,
        protocolVersionMinor: res.httpVersionMinor,
        method: opts.method || 'GET',
        url: self.currentUrl,
        statusCode: res.statusCode,
        statusMessage: res.statusMessage,
        cookies: self.cookies.length,
        newCookies: newCookies,
        time: diff,
        headers: res.headers,
        hop: self.hops
      })

      switch (res.statusCode) {
        case 301:
        case 302:
        case 303:
        case 307:
          self.hops++
          self._follow(res.headers.location, Date.now())
          break
        default:
          diff = Date.now() - self.start
          self.time = diff
          self.push(null)
          break
      }

      // For SPDY/H2 connections the agent needs to be closed,
      // to close all remaining TCP connections
      if (opts.agent) {
        res.once('end', function () {
          opts.agent.close()
        })
      }

      res.resume()
    })

    req.on('error', function (error) {
      self.emit('error', error)
    })

    req.end()
  },

  _read: function (size) {
    if (this.start === 0) {
      this.start = Date.now()
      this._follow(this.url, this.start)
    }
  }

})

module.exports = Trace
<commit_msg>Fix error emitter<commit_after>'use strict'

var Stream = require('readable-stream')
var inherit = require('util').inherits
var http = require('http')
var https = require('https')
var spdy = require('spdy')
var parseUrl = require('url').parse
var normalizeUrl = require('normalize-url')
var Cookies = require('cookie-manager')

/**
 * Trace
 * @constructor
 * @return {Trace}
 */
function Trace (url, options) {
  if (!(this instanceof Trace)) {
    return new Trace(url, options)
  }

  options = options != null ? options : {}
  options.objectMode = true

  Stream.Readable.call(this, options)

  this.hops = 0
  this.start = 0
  this.time = 0
  this.url = url
  this.currentUrl = url
  this.prevUrl = null
  this.statusCode = 0
  this.cookies = new Cookies()
  this.userAgent = options.userAgent || Trace.userAgent
}

/**
 * User-Agent string to be used in requests
 * @type {String}
 */
Trace.userAgent = 'Mozilla/5.0 AppleWebKit/537.36 Chrome/50.0.2653.0 Safari/537.36'

/**
 * Set `response.protocol` to the appropriate value
 * @param {http.IncomingMessage} res
 */
Trace.setProtocol = function (res) {
  res.protocol = 'HTTP'
  if (res.socket._spdyState) {
    var spdyState = res.socket._spdyState.parent
    var protocol = spdyState.alpnProtocol || spdyState.npnProtocol
    var parts = protocol.match(/^([^/\d]+)\/?(\d+)(?:\.(\d+))?/i)
    if (parts) {
      res.protocol = parts[1] === 'h' ? 'HTTP' : parts[1].toUpperCase()
      res.httpVersionMajor = parts[2]
      res.httpVersionMinor = parts[3] || 0
      res.httpVersion = res.httpVersionMajor + '.' + res.httpVersionMinor
    }
  }
}

inherit(Trace, Stream.Readable)

Object.assign(Trace.prototype, {

  _setCookie: function (url, headers) {
    if (!headers['set-cookie']) return 0
    var cookieCount = headers['set-cookie'].length
    for (var i = 0; i < cookieCount; i++) {
      this.cookies.store(url, headers['set-cookie'][0])
    }
    return cookieCount
  },

  _follow: function (url, ms) {
    var self = this

    this.currentUrl = normalizeUrl(url, { stripWWW: false })

    if (this.currentUrl === this.prevUrl) {
      this.emit('error', new Error('Self-referencing redirect: ' + this.currentUrl))
      return
    }

    this.prevUrl = this.currentUrl

    var opts = parseUrl(this.currentUrl)

    opts.method = 'HEAD'
    opts.headers = {
      'Cookie': this.cookies.prepare(this.currentUrl),
      'User-Agent': this.userAgent
    }

    var protocol = opts.protocol === 'https:' ? https : http

    if (opts.protocol === 'https:') {
      opts.agent = spdy.createAgent({
        host: opts.hostname || opts.host,
        port: opts.port || 443
      })

      // There's a case where spdy deadlocks, as it attempts to fall back to http/1.x;
      // see https://github.com/indutny/node-spdy/blob/v3.4.4/lib/spdy/agent.js#L121-L127,
      // https://github.com/indutny/node-spdy/blob/v3.4.4/lib/spdy/agent.js#L157-L160 and
      // https://github.com/indutny/node-spdy/blob/v3.4.4/lib/spdy/agent.js#L66
      // Fix: overwrite `.createSocket()` with node core's,
      // as spdy's `Agent.prototype._getCreateSocket()` is bugged
      opts.agent.createSocket = https.Agent.prototype.createSocket

      // If a custom agent is used, by default all connection-level
      // errors will result in an uncaught exception
      // (See https://github.com/indutny/node-spdy#usage)
      opts.agent.on('error', function (error) {
        self.emit('error', error)
      })
    }

    var req = protocol.request(opts, function (res) {
      var diff = Date.now() - ms
      var newCookies = self._setCookie(self.currentUrl, res.headers)

      Trace.setProtocol(res)

      self.statusCode = res.statusCode

      self.push({
        protocol: res.protocol,
        protocolVersionMajor: res.httpVersionMajor,
        protocolVersionMinor: res.httpVersionMinor,
        method: opts.method || 'GET',
        url: self.currentUrl,
        statusCode: res.statusCode,
        statusMessage: res.statusMessage,
        cookies: self.cookies.length,
        newCookies: newCookies,
        time: diff,
        headers: res.headers,
        hop: self.hops
      })

      switch (res.statusCode) {
        case 301:
        case 302:
        case 303:
        case 307:
          self.hops++
          self._follow(res.headers.location, Date.now())
          break
        default:
          diff = Date.now() - self.start
          self.time = diff
          self.push(null)
          break
      }

      // For SPDY/H2 connections the agent needs to be closed,
      // to close all remaining TCP connections
      if (opts.agent) {
        res.once('end', function () {
          opts.agent.close()
        })
      }

      res.resume()
    })

    req.on('error', function (error) {
      self.emit('error', error)
    })

    req.end()
  },

  _read: function (size) {
    if (this.start === 0) {
      this.start = Date.now()
      this._follow(this.url, this.start)
    }
  }

})

module.exports = Trace
<|endoftext|>


<commit_before>/* @flow */

import type {TextEditor, Point, Range, TextEditorMarker} from 'atom'

export type Intentions$Suggestion$List = {
  priority: number,
  title: string,
  icon: string,
  class: ?string,
  selected: (() => void)
}

export type Intentions$Suggestion$Highlight = {
  range: Range,
  class: ?string,
  created: ((parameters: {
    textEditor: TextEditor,
    element: HTMLElement,
    marker: TextEditorMarker,
    matchedText: string
  }) => any)
}

export type Intentions$Provider$List = {
  grammarScopes: Array<string>,
  getIntentions: ((parameters: {
    textEditor: TextEditor,
    bufferPosition: Point
  }) => Array<Intentions$Suggestion$List> | Promise<Array<Intentions$Suggestion$List>>)
}

export type Intentions$Provider$Highlight = {
  grammarScopes: Array<string>,
  getIntentions: ((parameters: {
    textEditor: TextEditor,
    visibleRange: Range
  }) => Array<Intentions$Suggestion$Highlight> | Promise<Array<Intentions$Suggestion$Highlight>>)
}
<commit_msg>:fire: Cleanup types<commit_after>/* @flow */

import type { Point, Range, TextEditor, TextEditorMarker } from 'atom'

export type ListItem = {
  icon: string,
  class?: string,
  title: string,
  priority: ?number,
  selected(): void;
}

export type HighlightItem = {
  range: Range,
  class: ?string,
  created: ((parameters: {
    marker: TextEditorMarker,
    element: HTMLElement,
    textEditor: TextEditor,
    matchedText: string
  }) => any)
}

export type ListProvider = {
  grammarScopes: Array<string>,
  getIntentions(parameters: {
    textEditor: TextEditor,
    bufferPosition: Point
  }): Array<ListItem> | Promise<Array<ListItem>>
}

export type HighlightProvider = {
  grammarScopes: Array<string>,
  getIntentions(parameters: {
    textEditor: TextEditor,
    visibleRange: Range
  }): Array<HighlightItem> | Promise<Array<HighlightItem>>
}
<|endoftext|>


<commit_before>/**
 * untar.js
 *
 * Copyright(c) 2011 Google Inc.
 * Copyright(c) 2015 antimatter15
 *
 * Reference Documentation:
 *
 * TAR format: http://www.gnu.org/software/automake/manual/tar/Standard.html
 */

var ByteStream = require('./bytestream')

// Removes all characters from the first zero-byte in the string onwards.
var readCleanString = function(bstr, numBytes) {
    var str = bstr.readString(numBytes);
    var zIndex = str.indexOf(String.fromCharCode(0));
    return zIndex != -1 ? str.substr(0, zIndex) : str;
};

// takes a ByteStream and parses out the local file information
function TarLocalFile(bstream) {
    this.isValid = false;

    // Read in the header block
    this.name = readCleanString(bstream, 100);
    this.mode = readCleanString(bstream, 8);
    this.uid = readCleanString(bstream, 8);
    this.gid = readCleanString(bstream, 8);

    this.size = parseInt(readCleanString(bstream, 12), 8);
    this.mtime = readCleanString(bstream, 12);
    this.chksum = readCleanString(bstream, 8);
    this.typeflag = readCleanString(bstream, 1);
    this.linkname = readCleanString(bstream, 100);
    this.maybeMagic = readCleanString(bstream, 6);

    if (this.maybeMagic == "ustar") {
        this.version = readCleanString(bstream, 2);
        this.uname = readCleanString(bstream, 32);
        this.gname = readCleanString(bstream, 32);
        this.devmajor = readCleanString(bstream, 8);
        this.devminor = readCleanString(bstream, 8);
        this.prefix = readCleanString(bstream, 155);

        if (this.prefix.length) {
            this.name = this.prefix + this.name;
        }
        bstream.readBytes(12); // 512 - 500
    } else {
        bstream.readBytes(255); // 512 - 257
    }

    // Done header, now rest of blocks are the file contents.
    this.filename = this.name;
    this.fileData = null;

    // console.info("Untarring file '" + this.filename + "'");
    // console.info("  size = " + this.size);
    // console.info("  typeflag = " + this.typeflag);

    if (this.typeflag == 0) {
        // console.info("  This is a regular file.");
        var sizeInBytes = parseInt(this.size);
        this.fileData = new Uint8Array(bstream.bytes.buffer, bstream.ptr, this.size);
        if (this.name.length > 0 && this.size > 0 && this.fileData && this.fileData.buffer) {
            this.isValid = true;
        }
    } else if (this.typeflag == 5) {
        // console.info("  This is a directory.")
    }

    bstream.ptr += this.size;
    // Round up to 512-byte blocks.
    var remaining = 512 - bstream.ptr % 512;
    // console.log('remaining')
    if (remaining > 0 && remaining < 512) {
        bstream.readBytes(remaining)
    }
};

exports.untar = function(arrayBuffer){
    var bstream = new ByteStream(arrayBuffer);
    var localFiles = [];
    // While we don't encounter an empty block, keep making TarLocalFiles.
    while (bstream.peekNumber(4) != 0) {
        var oneLocalFile = new TarLocalFile(bstream);
        if (oneLocalFile && oneLocalFile.isValid) {
            localFiles.push(oneLocalFile);
            // totalUncompressedBytesInArchive += oneLocalFile.size;
        }
    }
    return localFiles;
}<commit_msg>Bugfix parsing tar files.<commit_after>/**
 * untar.js
 *
 * Copyright(c) 2011 Google Inc.
 * Copyright(c) 2015 antimatter15
 *
 * Reference Documentation:
 *
 * TAR format: http://www.gnu.org/software/automake/manual/tar/Standard.html
 */

var ByteStream = require('./bytestream')

// Removes all characters from the first zero-byte in the string onwards.
var readCleanString = function(bstr, numBytes) {
    var str = bstr.readString(numBytes);
    var zIndex = str.indexOf(String.fromCharCode(0));
    return zIndex != -1 ? str.substr(0, zIndex) : str;
};

// takes a ByteStream and parses out the local file information
function TarLocalFile(bstream) {
    this.isValid = false;

    // Read in the header block
    this.name = readCleanString(bstream, 100);
    this.mode = readCleanString(bstream, 8);
    this.uid = readCleanString(bstream, 8);
    this.gid = readCleanString(bstream, 8);

    this.size = parseInt(readCleanString(bstream, 12), 8);
    this.mtime = readCleanString(bstream, 12);
    this.chksum = readCleanString(bstream, 8);
    this.typeflag = readCleanString(bstream, 1);
    this.linkname = readCleanString(bstream, 100);
    this.maybeMagic = readCleanString(bstream, 6);

    // 100+8+8+8+12+12+8+1+100+6 = 263 Bytes

    if (this.maybeMagic == "ustar") {
        this.version = readCleanString(bstream, 2);
        this.uname = readCleanString(bstream, 32);
        this.gname = readCleanString(bstream, 32);
        this.devmajor = readCleanString(bstream, 8);
        this.devminor = readCleanString(bstream, 8);
        this.prefix = readCleanString(bstream, 155);

        // 2+32+32+8+8+155 = 237 Bytes

        if (this.prefix.length) {
            this.name = this.prefix + this.name;
        }
        bstream.readBytes(12); // 512 - 263 - 237
    } else {
        bstream.readBytes(249); // 512 - 263
    }

    // Done header, now rest of blocks are the file contents.
    this.filename = this.name;
    this.fileData = null;

    // console.info("Untarring file '" + this.filename + "'");
    // console.info("  size = " + this.size);
    // console.info("  typeflag = " + this.typeflag);

    if (this.typeflag == 0) {
        // console.info("  This is a regular file.");
        var sizeInBytes = parseInt(this.size);
        this.fileData = new Uint8Array(bstream.bytes.buffer, bstream.ptr, this.size);
        if (this.name.length > 0 && this.size > 0 && this.fileData && this.fileData.buffer) {
            this.isValid = true;
        }
    } else if (this.typeflag == 5) {
        // console.info("  This is a directory.")
    }

    bstream.ptr += this.size;
    // Round up to 512-byte blocks.
    var remaining = 512 - bstream.ptr % 512;
    // console.log('remaining')
    if (remaining > 0 && remaining < 512) {
        bstream.readBytes(remaining)
    }
};

exports.untar = function(arrayBuffer){
    var bstream = new ByteStream(arrayBuffer);
    var localFiles = [];
    // While we don't encounter an empty block, keep making TarLocalFiles.
    while (bstream.peekNumber(4) != 0) {
        var oneLocalFile = new TarLocalFile(bstream);
        if (oneLocalFile && oneLocalFile.isValid) {
            localFiles.push(oneLocalFile);
            // totalUncompressedBytesInArchive += oneLocalFile.size;
        }
    }
    return localFiles;
}<|endoftext|>


<commit_before>/*
 * barcode generator - UPC-A
 */

var gm = require('gm');

const START  = [1,1,1];
const MIDDLE = [1,1,1,1,1];
const END    = [1,1,1];
const BARMAP = [
  [3,2,1,1], [2,2,2,1], [2,1,2,2], [1,4,1,1], [1,1,3,2],
  [1,2,3,1], [1,1,1,4], [1,3,1,2], [1,2,1,3], [3,1,1,2]
];

/*
 This is because UPC always has the same formula:
 Start - 3 wide
 Data (x6) - 7 wide
 Middle - 5 wide)
 Data (x5) - 7 wide
 Check - 7 wide
 End - 3 wide
*/
const MODULE_WIDTH = 93;
const FULL_DATA_LEN = 12
const REG_DATA_LEN = 11;

/*
 * get the check digit of a string
 *
 * @param String data - Numeric string of numbers
 * @return int - Check digit
 */
function getCheckDigit(data) {
  var checksum = 0,
    nData;
  for (var i = 0; i < data.length; i++) {
    nData = parseInt(data[i]);
    // If i is odd (pos is even), add the digit
    // If i is even (pos is odd), add the digit x 3
    checksum += (i & 1) ? nData : 3 * nData;
  }

  return (10 - checksum % 10) % 10;
}

module.exports.createCode = function (options, callback) {
  if (!options.data) {
    return callback(new Error('No data given'), {});
  }

  var userCheckDigit = false;
  options.data = ('' + options.data).replace(/[^0-9]/g, ''); // force to string

  if (options.data.length === FULL_DATA_LEN) {
    userCheckDigit = parseInt(options.data.substr(-1));
    options.data = options.data.substr(0, REG_DATA_LEN)
  }
  else if (options.data.length !== REG_DATA_LEN) {
    return callback(new Error('Data must be 11 digits (0-9) long for UPC-A'), {});
  }

  if (!options.w || !options.h) {
    return callback(new Error('Width and Height must be non-zero'), {});
  }

  var barWidth = options.w / MODULE_WIDTH >> 0;

  if (!barWidth) {
    return callback(new Error('Width will result in a degenerate barcode'), {});
  }

  var digit, encoding = [START];
  for (var i = 0; i < options.data.length; i++) {
    // Between position 6 and 7
    if (i == 6) {
      encoding.push(MIDDLE);
    }

    digit = parseInt(options.data[i]);
    encoding.push( BARMAP[ digit ] );
  }

  var checkDigit = getCheckDigit(options.data);

  // we're doing them a service by verifying it for them, the UPC wont work
  // otherwise, and they might have bad data.
  if (userCheckDigit !== false && checkDigit !== userCheckDigit) {
    return callback(new Error('Supplied check digit (digit 12: ' +
      userCheckDigit + ') is incorrect. Correct: ' + checkDigit), {} );
  }

  encoding.push(BARMAP[checkDigit]);
  encoding.push(END);

  var img = gm(options.w, options.h, options.bgcolor),
    count = 0,
    draw = true,
    h = options.h,
    pos = (options.w - MODULE_WIDTH * barWidth) / 2 >> 0,
    w;

  img.stroke(options.barcolor, 1);

  // This for loop below looks at each symbol.
  for (var i = 0; i < encoding.length; i++) {

    // This for loop below looks each bar
    for (var j = 0; j < encoding[i].length; j++) {
      w = encoding[i][j] * barWidth;

      // @todo - add option to print numbers under the barcode, with varying
      // height to allow for number placement below the code and between bars
      if (draw) {
        // This for loop looks each module the bar is composed of
        // work around for graphicsmagick, who cant set gravity on drawn lines.
        for (var k = 0; k < w; k++) {
          img.drawLine(pos + k, 0, pos + k, h);
        }
      }

      pos += w;
      draw ^= true;
    }
  }

  img.stream(options.type, function (err, stdout, stderr) {
    callback(err, stdout);
  });
}

module.exports.getCheckDigit = getCheckDigit;
<commit_msg>fixed a few issues<commit_after>/*
 * barcode generator - UPC-A
 */

var gm = require('gm');

const START  = [1,1,1];
const MIDDLE = [1,1,1,1,1];
const END    = [1,1,1];
const BARMAP = [
  [3,2,1,1], [2,2,2,1], [2,1,2,2], [1,4,1,1], [1,1,3,2],
  [1,2,3,1], [1,1,1,4], [1,3,1,2], [1,2,1,3], [3,1,1,2]
];

/*
 This is because UPC always has the same formula:
 Start - 3 wide
 Data (x6) - 7 wide
 Middle - 5 wide)
 Data (x5) - 7 wide
 Check - 7 wide
 End - 3 wide
*/
const MODULE_WIDTH = 95;
const FULL_DATA_LEN = 12
const REG_DATA_LEN = 11;

/*
 * get the check digit of a string
 *
 * @param String data - Numeric string of numbers
 * @return int - Check digit. -1 if failure
 */
function getCheckDigit(data) {
  var checksum = 0,
    nData;
  // we will never have a UPC-A code with anything different than 11 digits not
  // including the check digit (which is what we happen to be calculating)
  for (var i = 0; i < REG_DATA_LEN; i++) {

    if ( typeof data[i] !== 'string' ) {
      return -1;
    }

    nData = parseInt(data[i]);
    // If i is odd (pos is even), add the digit
    // If i is even (pos is odd), add the digit x 3
    checksum += (i & 1) ? nData : 3 * nData;
  }

  return (10 - checksum % 10) % 10;
}

module.exports.createCode = function (options, callback) {
  if (!options.data) {
    return callback(new Error('No data given'), {});
  }

  var userCheckDigit = false;
  options.data = ('' + options.data).replace(/[^0-9]/g, ''); // force to string

  if (options.data.length === FULL_DATA_LEN) {
    userCheckDigit = parseInt(options.data.substr(-1));
    options.data = options.data.substr(0, REG_DATA_LEN)
  }
  else if (options.data.length !== REG_DATA_LEN) {
    return callback(new Error('Data must be 11 digits (0-9) long for UPC-A'), {});
  }

  if (!options.w || !options.h) {
    return callback(new Error('Width and Height must be non-zero'), {});
  }

  var barWidth = options.w / MODULE_WIDTH >> 0;

  if (!barWidth) {
    return callback(new Error('Width will result in a degenerate barcode'), {});
  }

  var digit, encoding = [START];
  for (var i = 0; i < options.data.length; i++) {
    // Between position 6 and 7
    if (i == 6) {
      encoding.push(MIDDLE);
    }

    digit = parseInt(options.data[i]);
    encoding.push( BARMAP[ digit ] );
  }

  var checkDigit = getCheckDigit(options.data);

  // we're doing them a service by verifying it for them, the UPC wont work
  // otherwise, and they might have bad data.
  if (userCheckDigit !== false && checkDigit !== userCheckDigit) {
    return callback(new Error('Supplied check digit (digit 12: ' +
      userCheckDigit + ') is incorrect. Correct: ' + checkDigit), {} );
  }

  encoding.push(BARMAP[checkDigit]);
  encoding.push(END);

  var img = gm(options.w, options.h, options.bgcolor),
    count = 0,
    draw = true,
    h = options.h,
    pos = (options.w - MODULE_WIDTH * barWidth) / 2 >> 0,
    w;

  img.stroke(options.barcolor, 1);

  // This for loop below looks at each symbol.
  for (var i = 0; i < encoding.length; i++) {

    // This for loop below looks each bar
    for (var j = 0; j < encoding[i].length; j++) {
      w = encoding[i][j] * barWidth;

      // @todo - add option to print numbers under the barcode, with varying
      // height to allow for number placement below the code and between bars
      if (draw) {
        // This for loop looks each module the bar is composed of
        // work around for graphicsmagick, who cant set gravity on drawn lines.
        for (var k = 0; k < w; k++) {
          img.drawLine(pos + k, 0, pos + k, h);
        }
      }

      pos += w;
      draw ^= true;
    }
  }

  img.stream(options.type, function (err, stdout, stderr) {
    callback(err, stdout);
  });
}

module.exports.getCheckDigit = getCheckDigit;
<|endoftext|>


<commit_before>var http = require('http'),
    util = require('util'),
    EventEmitter = require('events').EventEmitter,
    randomWord;

function urban() {
  var word = new Dictionary(null); // instantiate first
  return word.constructor.apply(word, arguments); // then re-instantiate it with the arguments of `urban`
}

function random() {
  randomWord = true;
  return urban();
}

urban.version = "0.3.1";

function Dictionary(words) {
  if (randomWord == true && !arguments.length){
    this.getData();
    randomWord = false;
    return this;
  }

  if (!arguments.length) {
    throw new Error('missing argument(s)');
  }
  else if (arguments.length > 1) {
    for (var i = 1; i < arguments.length; i++) words += ' ' +arguments[i];
  }
  else {
    if (Array.isArray(words)) {
      words = words.join(' ');
    }
  }

  this._ended = false;
  this.json = '';

  if (words !== null) {
    this.words = encodeURI(words.trim());
    this.getData();
  }
  else {
    return false;
  }

  return this;
}

util.inherits(Dictionary, EventEmitter);
Dictionary.fn = Dictionary.prototype;
Dictionary.fn._noop = function() {};
Dictionary.fn._end = function(fn) {
  if (this._ended) {
    fn(this.json);
  }
  else {
    this.once('end', function(json) {
      fn(json);
    });
  }
  return this;
};

Dictionary.fn.getData = function(page) {
  var self = this;
  var _path = (!randomWord) ? '/v0/define?page=' + self.page + '&term=' + self.words : '/v0/random';
  this.page = page || 1;
  if (this._req && this._ended === 0) this._req.abort(); // abort if there's already one request happening
  this._ended = false;
  this._req = http.get({
    port: 80,
    host: 'api.urbandictionary.com',
    path: _path
  }, function(res) {
    self._res = res; // reference
    self.json = '';
    res.on('data', function(data) {
      if (self._ended !== 0) self._ended = 0; // in progress
      self.json += data;
    }).on('end', function() {
      self.json = JSON.parse(self.json.trim());
      self.emit('end', self.json);
      self._ended = true;
    });
  });
  return this;
};

Dictionary.fn.images = function(fn) {
  return this._end(function(json) {
    if (fn) fn(json.images);
  });
};

Dictionary.fn.total = function(fn) {
  return this._end(function(json) {
    if (fn) fn(json.total);
  });
};

Dictionary.fn.pages = function(fn) {
  return this._end(function(json) {
    if (fn) fn(json.pages);
  });
};

Dictionary.fn.more = Dictionary.fn.next = function() {
  return this.getData(++this.page);
};

Dictionary.fn.prev = function() {
  return this.getData(this.page < 2 ? 1 : --this.page);
}

Dictionary.fn.res = Dictionary.fn.results = function(fn) {
  return this._end(function(json) {
    if (fn) fn(json.list);
  });
};

Dictionary.fn.first = function(fn) {
  return this._end(function(json) {
    if (fn && json.list) fn(json.list[0]);
  });
};

module.exports = urban;
module.exports.random = random;
<commit_msg>Fixed missing semi-colon and true comparison<commit_after>var http = require('http'),
    util = require('util'),
    EventEmitter = require('events').EventEmitter,
    randomWord;

function urban() {
  var word = new Dictionary(null); // instantiate first
  return word.constructor.apply(word, arguments); // then re-instantiate it with the arguments of `urban`
}

function random() {
  randomWord = true;
  return urban();
}

urban.version = "0.3.1";

function Dictionary(words) {
  if (randomWord === true && !arguments.length){
    this.getData();
    randomWord = false;
    return this;
  }

  if (!arguments.length) {
    throw new Error('missing argument(s)');
  }
  else if (arguments.length > 1) {
    for (var i = 1; i < arguments.length; i++) words += ' ' +arguments[i];
  }
  else {
    if (Array.isArray(words)) {
      words = words.join(' ');
    }
  }

  this._ended = false;
  this.json = '';

  if (words !== null) {
    this.words = encodeURI(words.trim());
    this.getData();
  }
  else {
    return false;
  }

  return this;
}

util.inherits(Dictionary, EventEmitter);
Dictionary.fn = Dictionary.prototype;
Dictionary.fn._noop = function() {};
Dictionary.fn._end = function(fn) {
  if (this._ended) {
    fn(this.json);
  }
  else {
    this.once('end', function(json) {
      fn(json);
    });
  }
  return this;
};

Dictionary.fn.getData = function(page) {
  var self = this;
  var _path = (!randomWord) ? '/v0/define?page=' + self.page + '&term=' + self.words : '/v0/random';
  this.page = page || 1;
  if (this._req && this._ended === 0) this._req.abort(); // abort if there's already one request happening
  this._ended = false;
  this._req = http.get({
    port: 80,
    host: 'api.urbandictionary.com',
    path: _path
  }, function(res) {
    self._res = res; // reference
    self.json = '';
    res.on('data', function(data) {
      if (self._ended !== 0) self._ended = 0; // in progress
      self.json += data;
    }).on('end', function() {
      self.json = JSON.parse(self.json.trim());
      self.emit('end', self.json);
      self._ended = true;
    });
  });
  return this;
};

Dictionary.fn.images = function(fn) {
  return this._end(function(json) {
    if (fn) fn(json.images);
  });
};

Dictionary.fn.total = function(fn) {
  return this._end(function(json) {
    if (fn) fn(json.total);
  });
};

Dictionary.fn.pages = function(fn) {
  return this._end(function(json) {
    if (fn) fn(json.pages);
  });
};

Dictionary.fn.more = Dictionary.fn.next = function() {
  return this.getData(++this.page);
};

Dictionary.fn.prev = function() {
  return this.getData(this.page < 2 ? 1 : --this.page);
};

Dictionary.fn.res = Dictionary.fn.results = function(fn) {
  return this._end(function(json) {
    if (fn) fn(json.list);
  });
};

Dictionary.fn.first = function(fn) {
  return this._end(function(json) {
    if (fn && json.list) fn(json.list[0]);
  });
};

module.exports = urban;
module.exports.random = random;
<|endoftext|>


<commit_before>gpf.require.define({
    Tile: "tile.js",
    dom: "../dom.js",
    config: "../../tmp/config.json",
    charts: "charts.js"

}, function (require) {
    "use strict";

    var dom = require.dom,
        metrics = require.config.metrics;

    return gpf.define({
        $class: "Plato",
        $extend: require.Tile,

        constructor: function () {
            this.$super("plato", "Plato report");
            this._setGruntCommand("plato", "Execute plato");
        },

        getDynamicContent: function () {
            return gpf.http.get("/tmp/plato/report.json")
                .then(function (response) {
                    if (404 === response.status) {
                        return [];
                    }
                    return JSON.parse(response.responseText);
                })
                .then(function (reportData) {
                    var maintainability = reportData.summary.average.maintainability,
                        statusClassName;
                    if (maintainability < metrics.maintainability) {
                        statusClassName = "ko";
                    } else {
                        statusClassName = "ok";
                    }
                    return [
                        dom.div({
                            className: "percentage " + statusClassName,
                            link: "tmp/plato/index.html"
                        }, maintainability)
                    ];
                });
        },

        drawCharts: function () {
            require.charts.series({
                maintainability: "metrics.maintainability"
            });
            return true;
        }

    });

});
<commit_msg>!yoda style (#280)<commit_after>gpf.require.define({
    Tile: "tile.js",
    dom: "../dom.js",
    config: "../../tmp/config.json",
    charts: "charts.js"

}, function (require) {
    "use strict";

    var dom = require.dom,
        metrics = require.config.metrics;

    return gpf.define({
        $class: "Plato",
        $extend: require.Tile,

        constructor: function () {
            this.$super("plato", "Plato report");
            this._setGruntCommand("plato", "Execute plato");
        },

        getDynamicContent: function () {
            return gpf.http.get("/tmp/plato/report.json")
                .then(function (response) {
                    if (response.status === 404) {
                        return [];
                    }
                    return JSON.parse(response.responseText);
                })
                .then(function (reportData) {
                    var maintainability = reportData.summary.average.maintainability,
                        statusClassName;
                    if (maintainability < metrics.maintainability) {
                        statusClassName = "ko";
                    } else {
                        statusClassName = "ok";
                    }
                    return [
                        dom.div({
                            className: "percentage " + statusClassName,
                            link: "tmp/plato/index.html"
                        }, maintainability)
                    ];
                });
        },

        drawCharts: function () {
            require.charts.series({
                maintainability: "metrics.maintainability"
            });
            return true;
        }

    });

});
<|endoftext|>


<commit_before>'use strict';

var request = require('request');

/* API check from current <-> legacy */
exports.getUser = function(req) {
  if (req.session.passport.user._json && req.session.passport.user._json.data) {
    return req.session.passport.user._json.data;
  } else {
    return req.session.passport.user;
  }
};

exports.getUserById = function(req) {
  if (req.session.passport.user._json && req.session.passport.user._json.data) {
    return req.session.passport.user._json.data.id;
  } else {
    return req.session.passport.user.id;
  }
};

/* Generate the feed content
 * Requires: web request, recentMessages, redis client, pagination boolean, callback
 * Returns: the messages as JSON
 */
exports.generateFeed = function(req, recentMessages, client, paginated, callback) {
  var webremix = require('./web-remix');
  var userDb = require('./user');
  var newMessages = [];
  var messageCount = 0;
  var userSession = this.getUser(req);
  var userId = userSession.id;
  var username = userSession.username;
  var metadata = false;
  var messageData = {};

  var createClientMessage = function(options, callback) {
    /* maxId is used for starred posts, since they can't be paginated
     * by their post_id - reason is that posts can be starred in any
     * order and therefore have their own id system on app.net for sorting.
     */
    var minId = null;
    var isSelf = false;
    var isStarred = false;
    var isThread = false;

    if (options.metadata && options.metadata.min_id) {
      minId = options.metadata.min_id;
    }

    if (options.user.id === userId) {
      isSelf = true;
    }

    if (options.recent.reply_to) {
      isThread = true;
    }

    // We want to preserve the line breaks if there are any
    var message = options.tokenized.join('').replace(/\n/, '
');

    // Annotations
    message += options.moods + options.photos;

    userDb.isStarred(userId, options.recent.id, client, function(err, starred) {
      var userReferences = ['@' + options.user.username];
      var reply_to = null;

      options.userMentions.forEach(function(user) {
        if (userReferences.indexOf('@' + user.name) === -1) {
          userReferences.push('@' + user.name);
        }
      });

      userReferences.splice(userReferences.indexOf('@' + options.user.username), 1);
      userReferences.splice(userReferences.indexOf('@' + username), 1);

      if (options.recent.you_starred || starred) {
        userDb.star(userId, options.recent.id, client);
        isStarred = true;
      } else {
        userDb.unstar(userId, options.recent.id, client);
      }

      userDb.isReposted(userId, options.recent.id, client, function(err, reposted) {
        var isRepost = false;

        if (options.recent.you_reposted || reposted) {
          userDb.repost(userId, options.recent.id, client);
          isRepost = true;
        } else {
          userDb.unrepost(userId, options.recent.id, client);
        }

        if (options.recent.repost_of) {
          reply_to = options.recent.repost_of.id;
        }

        messageData = {
          id: options.recent.id,
          created_at: options.recent.created_at,
          message: message,
          text: options.recent.text,
          user: options.user.avatar_image.url,
          name: options.user.name,
          user_id: options.user.id,
          username: options.user.username,
          isSelf: isSelf,
          isThread: isThread,
          isStarred: isStarred,
          isRepost: isRepost,
          isFollowing: options.user.you_follow,
          isMuted: options.user.you_muted,
          numStars: options.recent.num_stars,
          numReposts: options.recent.num_reposts,
          numReplies: options.recent.num_replies,
          appSource: options.recent.source.name,
          mentions: userReferences.join(' '),
          min_id: minId,
          reply_to: reply_to
        };

        newMessages.push(messageData);

        if (newMessages.length === recentMessages.length) {
          if (!options.paginated) {
            newMessages = newMessages.sort(function(a, b) {
              return parseInt(a.id, 10) - parseInt(b.id, 10);
            });
          }
          callback(newMessages);
        }
      });
    });
  };

  if (recentMessages.meta) {
    metadata = recentMessages.meta;
  }

  if (recentMessages.data) {
    recentMessages = recentMessages.data;
  }

  if (recentMessages.length > 0) {
    recentMessages.forEach(function(recent) {
      if (recent.data) {
        recent = recent.data;
      }

      if (recent.text) {
        messageCount ++;

        var user = recent.user;
        var moods = '';
        var photos = '';

        // Annotations
        var moodArray = ['happy', 'sad', 'tired', 'angry', 'calm', 'omg'];

        recent.annotations.forEach(function(annotation) {
          if (annotation.type === 'net.xtendr.mood' && moodArray.indexOf(annotation.value.mood) > -1) {
            var mood = '';

            moods += mood;

          } else if (annotation.type === 'net.app.core.oembed') {
            if (annotation.value.type === 'photo' && recent.text.indexOf(annotation.value.url) === -1) {
              var linkUrl = annotation.value.embeddable_url || annotation.value.url;
              var photo = '

' +
                '' +
                linkUrl + '';

              photos += photo;
            }
          }
        });

        var entities = [];

        // Mentions
        var userMentions = recent.entities.mentions;
        recent.entities.mentions.forEach(function(mention) {
          var name = recent.text.substr(mention.pos, mention.len);
          entities.push({
            pos: mention.pos,
            len: mention.len,
            html: '' + name + ''
          });
        });

        // Hashtags
        recent.entities.hashtags.forEach(function(hashtag) {
          var name = recent.text.substr(hashtag.pos, hashtag.len);
          entities.push({
            pos: hashtag.pos,
            len: hashtag.len,
            html: '' + name + ''
          });
        });

        var continueRendering = function() {
          entities.sort(function(entity1, entity2) {
            return entity1.pos - entity2.pos;
          });

          var htmlMessages = [];
          var textIdx = 0;
          entities.forEach(function(entity) {
            // Before entity
            htmlMessages.push(recent.text.substring(textIdx, entity.pos));

            htmlMessages.push(entity.html);
            textIdx = entity.pos + entity.len;
          });
          // After last entity
          htmlMessages.push(recent.text.substring(textIdx));

          var options = {
            recent: recent,
            tokenized: htmlMessages,
            user: user,
            userMentions: userMentions,
            messageCount: messageCount,
            metadata: metadata,
            moods: moods,
            photos: photos,
            paginated: paginated
          };

          createClientMessage(options, callback);
        };

        var processLink = function(idx) {
          var link = recent.entities.links[idx];
          webremix.generate(link, client, function(errMsg, message) {
            if (!errMsg) {
              entities.push({
                pos: link.pos,
                len: link.len,
                html: message
              });
            }

            if (idx === recent.entities.links.length - 1) {
              continueRendering();
            } else {
              processLink(idx + 1);
            }
          });
        };

        if (recent.entities.links.length > 0) {
          processLink(0);
        }
        else {
          continueRendering();
        }
      }
    });
  } else {
    callback(newMessages);
  }
};
<commit_msg>ugh regression; horrid<commit_after>'use strict';

var request = require('request');

/* API check from current <-> legacy */
exports.getUser = function(req) {
  if (req.session.passport.user._json && req.session.passport.user._json.data) {
    return req.session.passport.user._json.data;
  } else {
    return req.session.passport.user;
  }
};

exports.getUserById = function(req) {
  if (req.session.passport.user._json && req.session.passport.user._json.data) {
    return req.session.passport.user._json.data.id;
  } else {
    return req.session.passport.user.id;
  }
};

/* Generate the feed content
 * Requires: web request, recentMessages, redis client, pagination boolean, callback
 * Returns: the messages as JSON
 */
exports.generateFeed = function(req, recentMessages, client, paginated, callback) {
  var webremix = require('./web-remix');
  var userDb = require('./user');
  var newMessages = [];
  var messageCount = 0;
  var userSession = this.getUser(req);
  var userId = userSession.id;
  var username = userSession.username;
  var metadata = false;
  var messageData = {};

  var createClientMessage = function(options, callback) {
    /* maxId is used for starred posts, since they can't be paginated
     * by their post_id - reason is that posts can be starred in any
     * order and therefore have their own id system on app.net for sorting.
     */
    var minId = null;
    var isSelf = false;
    var isStarred = false;
    var isThread = false;

    if (options.metadata && options.metadata.min_id) {
      minId = options.metadata.min_id;
    }

    if (options.user.id === userId) {
      isSelf = true;
    }

    if (options.recent.reply_to) {
      isThread = true;
    }

    // We want to preserve the line breaks if there are any
    var message = options.tokenized.join('').replace(/\n/, '
');

    // Annotations
    message += options.moods + options.photos;

    userDb.isStarred(userId, options.recent.id, client, function(err, starred) {
      var userReferences = ['@' + options.user.username];
      var reply_to = null;

      options.userMentions.forEach(function(user) {
        if (userReferences.indexOf('@' + user.name) === -1) {
          userReferences.push('@' + user.name);
        }
      });

      userReferences.splice(userReferences.indexOf('@' + options.user.username), 1);
      userReferences.splice(userReferences.indexOf('@' + username), 1);

      if (options.recent.you_starred || starred) {
        userDb.star(userId, options.recent.id, client);
        isStarred = true;
      } else {
        userDb.unstar(userId, options.recent.id, client);
      }

      userDb.isReposted(userId, options.recent.id, client, function(err, reposted) {
        var isRepost = false;

        if (options.recent.you_reposted || reposted) {
          userDb.repost(userId, options.recent.id, client);
          isRepost = true;
        } else {
          userDb.unrepost(userId, options.recent.id, client);
        }

        if (options.recent.repost_of) {
          reply_to = options.recent.repost_of.id;
        }

        messageData = {
          id: options.recent.id,
          created_at: options.recent.created_at,
          message: message,
          text: options.recent.text,
          user: options.user.avatar_image.url,
          name: options.user.name,
          user_id: options.user.id,
          username: options.user.username,
          isSelf: isSelf,
          isThread: isThread,
          isStarred: isStarred,
          isRepost: isRepost,
          isFollowing: options.user.you_follow,
          isMuted: options.user.you_muted,
          numStars: options.recent.num_stars,
          numReposts: options.recent.num_reposts,
          numReplies: options.recent.num_replies,
          appSource: options.recent.source.name,
          mentions: userReferences.join(' '),
          min_id: minId,
          reply_to: reply_to
        };

        newMessages.push(messageData);

        if (newMessages.length === recentMessages.length) {
          if (!options.paginated) {
            newMessages = newMessages.sort(function(a, b) {
              return parseInt(a.id, 10) - parseInt(b.id, 10);
            });
          }
          callback(newMessages);
        }
      });
    });
  };

  if (recentMessages.meta) {
    metadata = recentMessages.meta;
  }

  if (recentMessages.data) {
    recentMessages = recentMessages.data;
  }

  if (recentMessages.length > 0) {
    recentMessages.forEach(function(recent) {
      if (recent.data) {
        recent = recent.data;
      }

      if (recent.text) {
        messageCount ++;

        var user = recent.user;
        var moods = '';
        var photos = '';

        // Annotations
        var moodArray = ['happy', 'sad', 'tired', 'angry', 'calm', 'omg'];

        recent.annotations.forEach(function(annotation) {
          if (annotation.type === 'net.xtendr.mood' && moodArray.indexOf(annotation.value.mood) > -1) {
            var mood = '';

            moods += mood;

          } else if (annotation.type === 'net.app.core.oembed') {
            if (annotation.value.type === 'photo' && recent.text.indexOf(annotation.value.url) === -1) {
              var linkUrl = annotation.value.embeddable_url || annotation.value.url;
              var photo = '

' +
                '' +
                linkUrl + '';

              photos += photo;
            }
          }
        });

        var entities = [];

        // Mentions
        var userMentions = recent.entities.mentions;
        recent.entities.mentions.forEach(function(mention) {
          var name = recent.text.substr(mention.pos, mention.len);
          entities.push({
            pos: mention.pos,
            len: mention.len,
            html: '' + name + ''
          });
        });

        // Hashtags
        recent.entities.hashtags.forEach(function(hashtag) {
          var name = recent.text.substr(hashtag.pos, hashtag.len);
          entities.push({
            pos: hashtag.pos,
            len: hashtag.len,
            html: '' + name + ''
          });
        });

        recent.text = recent.text.replace(/</gm, '<');
        recent.text = recent.text.replace(/>/gm, '>');
        recent.text = recent.text.replace(/\"/gm, '"');
        recent.text = recent.text.replace(/;base64/gm, '');

        var continueRendering = function() {
          entities.sort(function(entity1, entity2) {
            return entity1.pos - entity2.pos;
          });

          var htmlMessages = [];
          var textIdx = 0;
          entities.forEach(function(entity) {
            // Before entity
            htmlMessages.push(recent.text.substring(textIdx, entity.pos));

            htmlMessages.push(entity.html);
            textIdx = entity.pos + entity.len;
          });
          // After last entity
          htmlMessages.push(recent.text.substring(textIdx));

          var options = {
            recent: recent,
            tokenized: htmlMessages,
            user: user,
            userMentions: userMentions,
            messageCount: messageCount,
            metadata: metadata,
            moods: moods,
            photos: photos,
            paginated: paginated
          };

          createClientMessage(options, callback);
        };

        var processLink = function(idx) {
          var link = recent.entities.links[idx];
          webremix.generate(link, client, function(errMsg, message) {
            if (!errMsg) {
              entities.push({
                pos: link.pos,
                len: link.len,
                html: message
              });
            }

            if (idx === recent.entities.links.length - 1) {
              continueRendering();
            } else {
              processLink(idx + 1);
            }
          });
        };

        if (recent.entities.links.length > 0) {
          processLink(0);
        }
        else {
          continueRendering();
        }
      }
    });
  } else {
    callback(newMessages);
  }
};
<|endoftext|>


<commit_before>var fs = require("fs"),
    path = require('path');

// Check if basic auth is available - all other modules checked as part of package.json
checkNodeModule('basic-auth');
var basicAuth = require('basic-auth');

/**
 * Simple basic auth middleware for use with Express 4.x.
 *
 * Based on template found at: http://www.danielstjules.com/2014/08/03/basic-auth-with-express-4/
 *
 * @example
 * app.use('/api-requiring-auth', utils.basicAuth('username', 'password'));
 *
 * @param   {string}   username Expected username
 * @param   {string}   password Expected password
 * @returns {function} Express 4 middleware requiring the given credentials
 */
function basicAuthUsernamePassword (username, password) {
  return function(req, res, next) {

    if (!username || !password) {
      console.log('Username or password is not set.');
      return res.send('
Error:

Username or password not set. See guidance for setting these.
');
    }

    var user = basicAuth(req);

    if (!user || user.name !== username || user.pass !== password) {
      res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
      return res.sendStatus(401);
    }

    next();
  };
}

// Checks all modules in package.json are available, quit if not available
function checkNodeModules(){
  var env = process.env.NODE_ENV || 'development',
      nodeModules = require(__dirname + '/../package.json');
  env      = env.toLowerCase();

  for (var nodeModule in nodeModules.dependencies) {
    checkNodeModule(nodeModule);
  }

  if (env === 'development'){
    for (var nodeModule in nodeModules.devDependencies) {
      checkNodeModule(nodeModule);
    }
  }
};

// Check a single node module, quit app if not available
function checkNodeModule(moduleName){
  if(isModuleAvailableSync(moduleName) !== true ){
    console.error('\nERROR: ' + moduleName + ' module missing. Try running `npm install`\n');
    process.exit(0);
  }
};

// checks if a given node module is available to load
function isModuleAvailableSync (moduleName){
  // return value, boolean
  var ret = false;

  // scan each module.paths. If there exists
  // node_modules/moduleName then
  // return true. Otherwise return false.
  module.paths.forEach(function(nodeModulesPath) {
    var modulePath = path.join(nodeModulesPath, moduleName);
    if(fs.existsSync(modulePath) === true) {
      ret = true;
      // break forEach
      return false;
    }
  });
  return ret;
};

module.exports = {
  basicAuth: basicAuthUsernamePassword,
  checkNodeModules: checkNodeModules,
};
<commit_msg>Make code more readable<commit_after>var fs = require("fs"),
    path = require('path');

// Check if basic auth is available - all other modules checked as part of package.json
checkNodeModule('basic-auth');
var basicAuth = require('basic-auth');

/**
 * Simple basic auth middleware for use with Express 4.x.
 *
 * Based on template found at: http://www.danielstjules.com/2014/08/03/basic-auth-with-express-4/
 *
 * @example
 * app.use('/api-requiring-auth', utils.basicAuth('username', 'password'));
 *
 * @param   {string}   username Expected username
 * @param   {string}   password Expected password
 * @returns {function} Express 4 middleware requiring the given credentials
 */
function basicAuthUsernamePassword (username, password) {
  return function(req, res, next) {

    if (!username || !password) {
      console.log('Username or password is not set.');
      return res.send('
Error:

Username or password not set. See guidance for setting these.
');
    }

    var user = basicAuth(req);

    if (!user || user.name !== username || user.pass !== password) {
      res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
      return res.sendStatus(401);
    }

    next();
  };
}

// Checks all modules in package.json are available, quit if not available
function checkNodeModules(){
  var env = process.env.NODE_ENV || 'development',
      packagePath = path.join(__dirname, '..', 'package.json'),
      nodeModules = require(packagePath);

  for (var nodeModule in nodeModules.dependencies) {
    checkNodeModule(nodeModule);
  }

  if (env.toLowerCase() === 'development'){
    for (var nodeModule in nodeModules.devDependencies) {
      checkNodeModule(nodeModule);
    }
  }
};

// Check a single node module, quit app if not available
function checkNodeModule(moduleName){
  if(isModuleAvailableSync(moduleName) !== true ){
    console.error('\nERROR: ' + moduleName + ' module missing. Try running `npm install`\n');
    process.exit(0);
  }
};

// checks if a given node module is available to load
function isModuleAvailableSync (moduleName){
  // return value, boolean
  var ret = false;

  // scan each module.paths. If there exists
  // node_modules/moduleName then
  // return true. Otherwise return false.
  module.paths.forEach(function(nodeModulesPath) {
    var modulePath = path.join(nodeModulesPath, moduleName);
    if(fs.existsSync(modulePath) === true) {
      ret = true;
      // break forEach
      return false;
    }
  });
  return ret;
};

module.exports = {
  basicAuth: basicAuthUsernamePassword,
  checkNodeModules: checkNodeModules,
};
<|endoftext|>


<commit_before>const os = require('os')
const { spawn } = require('child_process')
const frida = require('frida')
const plist = require('plist')

const { DeviceNotFoundError, CommandError, AppAttachError } = require('./error')

async function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

async function retry(operation, options) {
  if (typeof operation !== 'function')
    throw new Error('operation should be a function')

  const opt = options || {}
  let times = opt.retry || 10
  const interval = opt.interval || 200
  while (--times > 0) {
    try {
      return operation()
    } catch (ignored) {
      console.log(ignored)
    }
    await sleep(interval)
  }

  throw new Error('max retry exceed')
}

class FridaUtil {
  static async getDevice(id) {
    const list = await frida.enumerateDevices()
    const dev = list.find(d => d.id === id && d.type === 'tether')

    if (dev)
      return dev

    throw new DeviceNotFoundError(id)
  }

  static async screenshot(id) {
    const tmp = os.tmpdir() + new Date().getTime()
    return FridaUtil.getDevice(id).then(() => new Promise((resolve, reject) => {
      spawn('idevicescreenshot', ['-u', id, tmp])
        .on('close', (code) => {
          if (code === 0)
            resolve(tmp)
          else
            reject(new CommandError('Unable to capture screenshot'))
        })
        .on('error', err => reject(new CommandError(err)))
    }))
  }

  // spawn and wait until it's ready
  static async spawn(dev, app) {
    const pid = await dev.spawn([app.identifier])
    const session = await dev.attach(pid)
    await dev.resume(pid)

    const probeScript = await session.createScript('rpc.exports.ok = function() { return true }')

    await probeScript.load()
    const probe = await probeScript.getExports()
    try {
      const ok = await retry(probe.ok.bind(probe))
      if (!ok)
        throw new AppAttachError(app.identifier)
    } catch (ex) {
      console.error(ex)
      await session.detach()
      throw new AppAttachError(app.identifier)
    }
    return session
  }

  static info(id) {
    return new Promise((resolve, reject) => {
      const child = spawn('ideviceinfo', ['-u', id, '-x'])
      const stdout = []
      child.stdout.on('data', data => stdout.push(data))
      child.on('close', (code) => {
        let message = stdout.join('')
        if (code !== 0) {
          if (message.match(/Could not connect to lockdownd, error code/)) {
            message = `Unable to connect to lockdownd, it may be a known issue.
              Try: sudo chmod -R 777 /var/db/lockdown/`
            console.error(message)
          }
          reject(new CommandError(message))
          return
        }
        resolve(plist.parse(message))
      }).on('error', err => reject(new CommandError(err)))
    })
  }
}

function serializeIcon(icon) {
  if (!icon)
    return icon
  const { pixels, height, width, rowstride } = icon
  return { width, height, rowstride, pixels: pixels.toJSON() }
}

function serializeDevice(dev) {
  const { name, id, icon } = dev
  return { name, id, icon: serializeIcon(icon) }
}

function serializeApp(app) {
  const { name, id, smallIcon, largeIcon, identifier } = app
  return {
    name,
    id,
    identifier,
    smallIcon: serializeIcon(smallIcon),
    largeIcon: serializeIcon(largeIcon),
  }
}

module.exports = {
  FridaUtil,
  serializeDevice,
  serializeApp,
  sleep,
  retry,
}
<commit_msg>handle plist format error<commit_after>const os = require('os')
const { spawn } = require('child_process')
const frida = require('frida')
const plist = require('plist')

const { DeviceNotFoundError, CommandError, AppAttachError } = require('./error')

async function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

async function retry(operation, options) {
  if (typeof operation !== 'function')
    throw new Error('operation should be a function')

  const opt = options || {}
  let times = opt.retry || 10
  const interval = opt.interval || 200
  while (--times > 0) {
    try {
      return operation()
    } catch (ignored) {
      console.log(ignored)
    }
    await sleep(interval)
  }

  throw new Error('max retry exceed')
}

class FridaUtil {
  static async getDevice(id) {
    const list = await frida.enumerateDevices()
    const dev = list.find(d => d.id === id && d.type === 'tether')

    if (dev)
      return dev

    throw new DeviceNotFoundError(id)
  }

  static async screenshot(id) {
    const tmp = os.tmpdir() + new Date().getTime()
    return FridaUtil.getDevice(id).then(() => new Promise((resolve, reject) => {
      spawn('idevicescreenshot', ['-u', id, tmp])
        .on('close', (code) => {
          if (code === 0)
            resolve(tmp)
          else
            reject(new CommandError('Unable to capture screenshot'))
        })
        .on('error', err => reject(new CommandError(err)))
    }))
  }

  // spawn and wait until it's ready
  static async spawn(dev, app) {
    const pid = await dev.spawn([app.identifier])
    const session = await dev.attach(pid)
    await dev.resume(pid)

    const probeScript = await session.createScript('rpc.exports.ok = function() { return true }')

    await probeScript.load()
    const probe = await probeScript.getExports()
    try {
      const ok = await retry(probe.ok.bind(probe))
      if (!ok)
        throw new AppAttachError(app.identifier)
    } catch (ex) {
      console.error(ex)
      await session.detach()
      throw new AppAttachError(app.identifier)
    }
    return session
  }

  static info(id) {
    return new Promise((resolve, reject) => {
      const child = spawn('ideviceinfo', ['-u', id, '-x'])
      const stdout = []
      child.stdout.on('data', data => stdout.push(data))
      child.on('close', (code) => {
        let message = stdout.join('')
        if (code !== 0) {
          if (message.match(/Could not connect to lockdownd, error code/)) {
            message = `Unable to connect to lockdownd, it may be a known issue.
              Try: sudo chmod -R 777 /var/db/lockdown/`
            console.error(message)
          }
          reject(new CommandError(message))
          return
        }
        try {
          resolve(plist.parse(message))
        } catch(e) {
          reject(`${id} is not a valid iOS device`)
        }
      }).on('error', err => reject(new CommandError(err)))
    })
  }
}

function serializeIcon(icon) {
  if (!icon)
    return icon
  const { pixels, height, width, rowstride } = icon
  return { width, height, rowstride, pixels: pixels.toJSON() }
}

function serializeDevice(dev) {
  const { name, id, icon } = dev
  return { name, id, icon: serializeIcon(icon) }
}

function serializeApp(app) {
  const { name, id, smallIcon, largeIcon, identifier } = app
  return {
    name,
    id,
    identifier,
    smallIcon: serializeIcon(smallIcon),
    largeIcon: serializeIcon(largeIcon),
  }
}

module.exports = {
  FridaUtil,
  serializeDevice,
  serializeApp,
  sleep,
  retry,
}
<|endoftext|>


<commit_before>'use strict';

const https = require('https');

exports.downloadGithubPackage = function(repo, token, done) {
  const parts = repo.split(/[\/#]/);

  if (parts.length < 2) {
    return done(new Error(`Invalid github repository: "${repo}"`));
  }

  if (parts.length === 2) {
    parts.push('master');
  }

  const path    = parts.join('/');
  const request = {
    hostname : 'raw.githubusercontent.com',
    path     : `/${path}/package.json`,
    headers  : {}
  };

  if (token) {
    request.headers.Authorization = `token ${token}`;
  }

  https.get(request, res => {
    if (res.statusCode !== 200) {
      return done(new Error(`Github returned status ${res.statusCode} for repo "${repo}"`));
    }

    let content = '';

    res.on('data', chunk => {
      content += chunk.toString();
    });

    res.on('end', () => {
      let json;
      try {
        json = JSON.parse(content);
      } catch (err) {
        return done(err);
      }
      return done(null, json);
    });

  }).on('error', done);
};
<commit_msg>Add `utils.createReportTable` and `utils.formatReportTable`<commit_after>'use strict';

const https = require('https');

exports.createReportTable = function(deps) {
  let table = '';

  for (const { name, found, needs, type } of deps) {
    let needs2 = needs;
    if (type === 'github') { needs2 += ' (on github)'; }

    table += `${name}|needs ${needs2}|found ${found}\n`;
  }

  return exports.formatReportTable(table.trim());
};

exports.formatReportTable = function(text) {
  const lines       = text.split('\n');
  let maxLenghtCol1 = 0;
  let maxLenghtCol2 = 0;

  for (const line of lines) {
    const idxSeparator1 = line.indexOf('|');
    if (idxSeparator1 === -1) { continue; }
    maxLenghtCol1 = Math.max(maxLenghtCol1, idxSeparator1);

    const idxSeparator2 = line.indexOf('|', idxSeparator1 + 1);
    if (idxSeparator2 === -1) { continue; }
    maxLenghtCol2 = Math.max(maxLenghtCol2, idxSeparator2 - idxSeparator1 - 1);
  }

  for (let i = 0; i < lines.length; ++i) {
    const parts = lines[i].split('|');
    if (parts.length !== 3) { continue; }

    const filler1 = new Array(maxLenghtCol1 - parts[0].length + 1).join(' ');
    const filler2 = new Array(maxLenghtCol2 - parts[1].length + 1).join(' ');

    lines[i] = parts[0] + filler1 + ' | ' + parts[1] + filler2 + ' | ' + parts[2];
  }

  return lines.join('\n');
};

exports.downloadGithubPackage = function(repo, token, done) {
  const parts = repo.split(/[\/#]/);

  if (parts.length < 2) {
    return done(new Error(`Invalid github repository: "${repo}"`));
  }

  if (parts.length === 2) {
    parts.push('master');
  }

  const path    = parts.join('/');
  const request = {
    hostname : 'raw.githubusercontent.com',
    path     : `/${path}/package.json`,
    headers  : {}
  };

  if (token) {
    request.headers.Authorization = `token ${token}`;
  }

  https.get(request, res => {
    if (res.statusCode !== 200) {
      return done(new Error(`Github returned status ${res.statusCode} for repo "${repo}"`));
    }

    let content = '';

    res.on('data', chunk => {
      content += chunk.toString();
    });

    res.on('end', () => {
      let json;
      try {
        json = JSON.parse(content);
      } catch (err) {
        return done(err);
      }
      return done(null, json);
    });

  }).on('error', done);
};
<|endoftext|>


<commit_before>const path = require("path")
const { Point } = require("atom")
const _ = require("underscore-plus")

function getAdjacentPane(basePane, which) {
  const parent = basePane.getParent()
  let children = null
  if (parent && parent.getChildren) {
    children = parent.getChildren()
  }
  if (!children) return

  let index = children.indexOf(basePane)
  if (which === "next") {
    index += 1
  } else if (which === "previous") {
    index -= 1
  }
  const pane = children[index]
  // console.log(pane);
  if (pane && pane.constructor && pane.constructor.name === "Pane") {
    return pane
  }
}

function getNextAdjacentPaneForPane(basePane) {
  return getAdjacentPane(basePane, "next")
}

function getPreviousAdjacentPaneForPane(basePane) {
  return getAdjacentPane(basePane, "previous")
}

function splitPane(basePane, { split }) {
  const wasActive = basePane.isActive()
  let pane = null
  if (split === "right") {
    pane = basePane.splitRight()
  } else if (split === "down") {
    pane = basePane.splitDown()
  }
  // Can not 'split' without activating new pane
  // re-activte basePane if it was active.
  if (wasActive && !basePane.isActive()) basePane.activate()
  return pane
}

function saveEditorState(editor) {
  const editorElement = editor.element
  const scrollTop = editorElement.getScrollTop()
  const cursorPosition = editor.getCursorBufferPosition()
  const foldStartRows = editor.displayLayer.foldsMarkerLayer
    .findMarkers({})
    .map(m => m.getStartPosition().row)

  return restoreEditorState

  function restoreEditorState() {
    let pane = paneForItem(editor)
    if (!pane) return
    pane.activate()
    pane.activateItem(editor)
    if (editorElement.component.getScrollTop() == null) {
      let disposable = editorElement.onDidChangeScrollTop(() => {
        disposable.dispose()
        restoreCursorAndScrollTop()
      })
    } else {
      restoreCursorAndScrollTop()
    }
  }

  function restoreCursorAndScrollTop() {
    if (!editor.getCursorBufferPosition().isEqual(cursorPosition)) {
      editor.setCursorBufferPosition(cursorPosition)
    }
    foldStartRows.reverse().forEach(row => {
      if (!editor.isFoldedAtBufferRow(row)) editor.foldBufferRow(row)
    })
    editorElement.setScrollTop(scrollTop)
  }
}

function requireFrom(pack, path) {
  const packPath = atom.packages.resolvePackagePath(pack)
  return require(`${packPath}/lib/${path}`)
}

function limitNumber(number, { max, min } = {}) {
  if (max != null) number = Math.min(number, max)
  if (min != null) number = Math.max(number, min)
  return number
}

function getCurrentWord(editor) {
  const selection = editor.getLastSelection()
  if (selection.isEmpty()) {
    const point = selection.cursor.getBufferPosition()
    selection.selectWord()
    const text = selection.getText()
    selection.cursor.setBufferPosition(point)
    return text
  } else {
    return selection.getText()
  }
}

function isActiveEditor(editor) {
  return editor === atom.workspace.getActiveTextEditor()
}

function getValidIndexForList(list, index) {
  const length = list.length
  if (length === 0) return -1

  index = index % length
  return index >= 0 ? index : length + index
}

// Respect goalColumn when moving cursor.
function setBufferRow(cursor, row) {
  if (cursor.goalColumn == null) {
    cursor.goalColumn = cursor.getBufferColumn()
  }
  cursor.setBufferPosition([row, cursor.goalColumn])
}

function isTextEditor(item) {
  return atom.workspace.isTextEditor(item)
}

function paneForItem(item) {
  return atom.workspace.paneForItem(item)
}

function isNarrowEditor(editor) {
  return (
    isTextEditor(editor) && editor.element.classList.contains("narrow-editor")
  )
}

function getVisibleEditors() {
  return atom.workspace
    .getPanes()
    .map(pane => pane.getActiveEditor())
    .filter(editor => editor)
}

function getFirstCharacterPositionForBufferRow(editor, row) {
  let point = null
  const scanRange = editor.scanInBufferRange(
    /\S/,
    editor.bufferRangeForBufferRow(row),
    ({ range }) => (point = range.start)
  )
  return point ? point : new Point(row, 0)
}

function itemForGitDiff(diff, { editor, filePath }) {
  const row = limitNumber(diff.newStart - 1, { min: 0 })
  return {
    point: getFirstCharacterPositionForBufferRow(editor, row),
    text: editor.lineTextForBufferRow(row),
    filePath: filePath,
  }
}

function isDefinedAndEqual(a, b) {
  return a != null && b != null && a === b
}

function cloneRegExp(regExp) {
  return new RegExp(regExp.source, regExp.flags)
}

function addToolTips({ element, commandName, keyBindingTarget }) {
  return atom.tooltips.add(element, {
    title: _.humanizeEventName(commandName.split(":")[1]),
    keyBindingCommand: commandName,
    keyBindingTarget: keyBindingTarget,
  })
}

// Utils used in Ui
// =========================
// direct-edit related
// -------------------------
function getModifiedFilePathsInChanges(changes) {
  const toFilePath = change => change.item.filePath
  const isModified = atom.project.isPathModified(filePath)

  return changes.map(toFilePath).filter(isModified)
}

// detect conflicting change
function ensureNoConflictForChanges(changes) {
  const message = []
  const conflictChanges = detectConflictForChanges(changes)
  const success = _.isEmpty(conflictChanges)
  if (!success) {
    message.push("Cancelled `update-real-file`.")
    message.push("Detected **conflicting change to same line**.")
    for (const filePath in conflictChanges) {
      const changesInFile = conflictChanges[filePath]
      message.push(`- ${filePath}`)
      for (let { newText, item } of changesInFile) {
        message.push(
          `  - ${item.point.translate([1, 1]).toString()}, ${newText}`
        )
      }
    }
  }

  return { success, message: message.join("\n") }
}

function detectConflictForChanges(changes) {
  const conflictChanges = {}
  const changesByFilePath = _.groupBy(changes, ({ item }) => item.filePath)
  for (let filePath in changesByFilePath) {
    const changesInFile = changesByFilePath[filePath]
    const changesByRow = _.groupBy(changesInFile, ({ item }) => item.point.row)
    for (let row in changesByRow) {
      const changesInRow = changesByRow[row]
      const newTexts = _.pluck(changesInRow, "newText")
      if (_.uniq(newTexts).length > 1) {
        if (conflictChanges[filePath] == null) {
          conflictChanges[filePath] = []
        }
        conflictChanges[filePath].push(...Array.from(changesInRow || []))
      }
    }
  }
  return conflictChanges
}

//
// item utils
// -------------------------
function isNormalItem(item) {
  return item != null && !item.skip
}

function compareByPoint(a, b) {
  return a.point.compare(b.point)
}

function findEqualLocationItem(items, itemToFind) {
  const normalItems = items.filter(isNormalItem)
  const isEqualLocation = ({ point, filePath }) =>
    point.isEqual(itemToFind.point) && filePath === itemToFind.filePath

  return _.detect(normalItems, isEqualLocation)
}

function toMB(num) {
  return Math.floor(num / (1024 * 1024))
}

const ignoreSubject = ["refresh"]
function startMeasureMemory(subject, simple = false) {
  if (ignoreSubject.includes(subject)) {
    return () => {}
  }
  console.time(subject)

  const v8 = require("v8")
  const before = v8.getHeapStatistics()
  console.time(subject)
  return function() {
    const after = v8.getHeapStatistics()
    const diff = {}
    for (let key of Object.keys(before)) {
      diff[key] = after[key] - before[key]
    }

    console.info(`= ${subject}`)
    if (simple) {
      console.time(subject)
      console.log("diff.used_heap_size", toMB(diff.used_heap_size))
    } else {
      const table = [before, after, diff]
      for (let result of table) {
        for (key in result) {
          const value = result[key]
          result[key] = toMB(value)
        }
      }
      console.timeEnd(subject)
      console.table(table)
    }
  }
}

function getProjectPaths(editor) {
  if (editor == null) return atom.project.getPaths()

  let paths = null
  if ((filePath = editor.getPath())) {
    for (const dir in atom.project.getDirectories()) {
      if (dir.contains(filePath)) {
        paths = [dir.getPath()]
        break
      }
    }
  }
  if (!paths) {
    const message = "This file is not belonging to any project"
    atom.notifications.addInfo(message, { dismissable: true })
  }
  return paths
}

function suppressEvent(event) {
  if (event != null) {
    event.preventDefault()
    event.stopPropagation()
  }
}

function relativizeFilePath(filePath) {
  const [projectPath, relativeFilePath] = atom.project.relativizePath(filePath)
  return path.join(path.basename(projectPath), relativeFilePath)
}

function getMemoizedRelativizeFilePath() {
  const cache = {}
  return filePath =>
    cache[filePath] != null
      ? cache[filePath]
      : (cache[filePath] = relativizeFilePath(filePath))
}

function arrayForRange(start, end) {
  return [...Array(1 + end - start).keys()].map(v => start + v)
}

module.exports = {
  getAdjacentPane,
  getNextAdjacentPaneForPane,
  getPreviousAdjacentPaneForPane,
  splitPane,
  saveEditorState,
  requireFrom,
  limitNumber,
  getCurrentWord,
  isActiveEditor,
  getValidIndexForList,
  setBufferRow,

  isTextEditor,
  isNarrowEditor,
  paneForItem,
  getVisibleEditors,
  getFirstCharacterPositionForBufferRow,
  itemForGitDiff,
  isDefinedAndEqual,
  cloneRegExp,
  addToolTips,

  ensureNoConflictForChanges,
  isNormalItem,
  compareByPoint,
  findEqualLocationItem,
  getProjectPaths,
  suppressEvent,
  startMeasureMemory,
  relativizeFilePath,
  getMemoizedRelativizeFilePath,
  arrayForRange
}
<commit_msg>improve arrayForRange<commit_after>const path = require("path")
const {Point} = require("atom")
const _ = require("underscore-plus")

function getAdjacentPane(basePane, which) {
  const parent = basePane.getParent()
  let children = null
  if (parent && parent.getChildren) {
    children = parent.getChildren()
  }
  if (!children) return

  let index = children.indexOf(basePane)
  if (which === "next") {
    index += 1
  } else if (which === "previous") {
    index -= 1
  }
  const pane = children[index]
  // console.log(pane);
  if (pane && pane.constructor && pane.constructor.name === "Pane") {
    return pane
  }
}

function getNextAdjacentPaneForPane(basePane) {
  return getAdjacentPane(basePane, "next")
}

function getPreviousAdjacentPaneForPane(basePane) {
  return getAdjacentPane(basePane, "previous")
}

function splitPane(basePane, {split}) {
  const wasActive = basePane.isActive()
  let pane = null
  if (split === "right") {
    pane = basePane.splitRight()
  } else if (split === "down") {
    pane = basePane.splitDown()
  }
  // Can not 'split' without activating new pane
  // re-activte basePane if it was active.
  if (wasActive && !basePane.isActive()) basePane.activate()
  return pane
}

function saveEditorState(editor) {
  const editorElement = editor.element
  const scrollTop = editorElement.getScrollTop()
  const cursorPosition = editor.getCursorBufferPosition()
  const foldStartRows = editor.displayLayer.foldsMarkerLayer
    .findMarkers({})
    .map(m => m.getStartPosition().row)

  return restoreEditorState

  function restoreEditorState() {
    let pane = paneForItem(editor)
    if (!pane) return
    pane.activate()
    pane.activateItem(editor)
    if (editorElement.component.getScrollTop() == null) {
      let disposable = editorElement.onDidChangeScrollTop(() => {
        disposable.dispose()
        restoreCursorAndScrollTop()
      })
    } else {
      restoreCursorAndScrollTop()
    }
  }

  function restoreCursorAndScrollTop() {
    if (!editor.getCursorBufferPosition().isEqual(cursorPosition)) {
      editor.setCursorBufferPosition(cursorPosition)
    }
    foldStartRows.reverse().forEach(row => {
      if (!editor.isFoldedAtBufferRow(row)) editor.foldBufferRow(row)
    })
    editorElement.setScrollTop(scrollTop)
  }
}

function requireFrom(pack, path) {
  const packPath = atom.packages.resolvePackagePath(pack)
  return require(`${packPath}/lib/${path}`)
}

function limitNumber(number, {max, min} = {}) {
  if (max != null) number = Math.min(number, max)
  if (min != null) number = Math.max(number, min)
  return number
}

function getCurrentWord(editor) {
  const selection = editor.getLastSelection()
  if (selection.isEmpty()) {
    const point = selection.cursor.getBufferPosition()
    selection.selectWord()
    const text = selection.getText()
    selection.cursor.setBufferPosition(point)
    return text
  } else {
    return selection.getText()
  }
}

function isActiveEditor(editor) {
  return editor === atom.workspace.getActiveTextEditor()
}

function getValidIndexForList(list, index) {
  const length = list.length
  if (length === 0) return -1

  index = index % length
  return index >= 0 ? index : length + index
}

// Respect goalColumn when moving cursor.
function setBufferRow(cursor, row) {
  if (cursor.goalColumn == null) {
    cursor.goalColumn = cursor.getBufferColumn()
  }
  cursor.setBufferPosition([row, cursor.goalColumn])
}

function isTextEditor(item) {
  return atom.workspace.isTextEditor(item)
}

function paneForItem(item) {
  return atom.workspace.paneForItem(item)
}

function isNarrowEditor(editor) {
  return (
    isTextEditor(editor) && editor.element.classList.contains("narrow-editor")
  )
}

function getVisibleEditors() {
  return atom.workspace
    .getPanes()
    .map(pane => pane.getActiveEditor())
    .filter(editor => editor)
}

function getFirstCharacterPositionForBufferRow(editor, row) {
  let point = null
  const scanRange = editor.scanInBufferRange(
    /\S/,
    editor.bufferRangeForBufferRow(row),
    ({range}) => (point = range.start)
  )
  return point ? point : new Point(row, 0)
}

function itemForGitDiff(diff, {editor, filePath}) {
  const row = limitNumber(diff.newStart - 1, {min: 0})
  return {
    point: getFirstCharacterPositionForBufferRow(editor, row),
    text: editor.lineTextForBufferRow(row),
    filePath: filePath,
  }
}

function isDefinedAndEqual(a, b) {
  return a != null && b != null && a === b
}

function cloneRegExp(regExp) {
  return new RegExp(regExp.source, regExp.flags)
}

function addToolTips({element, commandName, keyBindingTarget}) {
  return atom.tooltips.add(element, {
    title: _.humanizeEventName(commandName.split(":")[1]),
    keyBindingCommand: commandName,
    keyBindingTarget: keyBindingTarget,
  })
}

// Utils used in Ui
// =========================
// direct-edit related
// -------------------------
function getModifiedFilePathsInChanges(changes) {
  const toFilePath = change => change.item.filePath
  const isModified = atom.project.isPathModified(filePath)

  return changes.map(toFilePath).filter(isModified)
}

// detect conflicting change
function ensureNoConflictForChanges(changes) {
  const message = []
  const conflictChanges = detectConflictForChanges(changes)
  const success = _.isEmpty(conflictChanges)
  if (!success) {
    message.push("Cancelled `update-real-file`.")
    message.push("Detected **conflicting change to same line**.")
    for (const filePath in conflictChanges) {
      const changesInFile = conflictChanges[filePath]
      message.push(`- ${filePath}`)
      for (let {newText, item} of changesInFile) {
        message.push(
          `  - ${item.point.translate([1, 1]).toString()}, ${newText}`
        )
      }
    }
  }

  return {success, message: message.join("\n")}
}

function detectConflictForChanges(changes) {
  const conflictChanges = {}
  const changesByFilePath = _.groupBy(changes, ({item}) => item.filePath)
  for (let filePath in changesByFilePath) {
    const changesInFile = changesByFilePath[filePath]
    const changesByRow = _.groupBy(changesInFile, ({item}) => item.point.row)
    for (let row in changesByRow) {
      const changesInRow = changesByRow[row]
      const newTexts = _.pluck(changesInRow, "newText")
      if (_.uniq(newTexts).length > 1) {
        if (conflictChanges[filePath] == null) {
          conflictChanges[filePath] = []
        }
        conflictChanges[filePath].push(...Array.from(changesInRow || []))
      }
    }
  }
  return conflictChanges
}

//
// item utils
// -------------------------
function isNormalItem(item) {
  return item != null && !item.skip
}

function compareByPoint(a, b) {
  return a.point.compare(b.point)
}

function findEqualLocationItem(items, itemToFind) {
  const normalItems = items.filter(isNormalItem)
  const isEqualLocation = ({point, filePath}) =>
    point.isEqual(itemToFind.point) && filePath === itemToFind.filePath

  return _.detect(normalItems, isEqualLocation)
}

function toMB(num) {
  return Math.floor(num / (1024 * 1024))
}

const ignoreSubject = ["refresh"]
function startMeasureMemory(subject, simple = false) {
  if (ignoreSubject.includes(subject)) {
    return () => {}
  }
  console.time(subject)

  const v8 = require("v8")
  const before = v8.getHeapStatistics()
  console.time(subject)
  return function() {
    const after = v8.getHeapStatistics()
    const diff = {}
    for (let key of Object.keys(before)) {
      diff[key] = after[key] - before[key]
    }

    console.info(`= ${subject}`)
    if (simple) {
      console.time(subject)
      console.log("diff.used_heap_size", toMB(diff.used_heap_size))
    } else {
      const table = [before, after, diff]
      for (let result of table) {
        for (key in result) {
          const value = result[key]
          result[key] = toMB(value)
        }
      }
      console.timeEnd(subject)
      console.table(table)
    }
  }
}

function getProjectPaths(editor) {
  if (editor == null) return atom.project.getPaths()

  let paths = null
  if ((filePath = editor.getPath())) {
    for (const dir in atom.project.getDirectories()) {
      if (dir.contains(filePath)) {
        paths = [dir.getPath()]
        break
      }
    }
  }
  if (!paths) {
    const message = "This file is not belonging to any project"
    atom.notifications.addInfo(message, {dismissable: true})
  }
  return paths
}

function suppressEvent(event) {
  if (event != null) {
    event.preventDefault()
    event.stopPropagation()
  }
}

function relativizeFilePath(filePath) {
  const [projectPath, relativeFilePath] = atom.project.relativizePath(filePath)
  return path.join(path.basename(projectPath), relativeFilePath)
}

function getMemoizedRelativizeFilePath() {
  const cache = {}
  return filePath =>
    cache[filePath] != null
      ? cache[filePath]
      : (cache[filePath] = relativizeFilePath(filePath))
}

function arrayForRange(start, end) {
  if (end == null) [start, end] = [0, start]
  const range = []
  while (start <= end) range.push(start++)
  return range
}

module.exports = {
  getAdjacentPane,
  getNextAdjacentPaneForPane,
  getPreviousAdjacentPaneForPane,
  splitPane,
  saveEditorState,
  requireFrom,
  limitNumber,
  getCurrentWord,
  isActiveEditor,
  getValidIndexForList,
  setBufferRow,

  isTextEditor,
  isNarrowEditor,
  paneForItem,
  getVisibleEditors,
  getFirstCharacterPositionForBufferRow,
  itemForGitDiff,
  isDefinedAndEqual,
  cloneRegExp,
  addToolTips,

  ensureNoConflictForChanges,
  isNormalItem,
  compareByPoint,
  findEqualLocationItem,
  getProjectPaths,
  suppressEvent,
  startMeasureMemory,
  relativizeFilePath,
  getMemoizedRelativizeFilePath,
  arrayForRange,
}
<|endoftext|>


<commit_before>'use strict';
var chalk = require('chalk');
var repeating = require('repeating');

var humanizeTitleMap = {
  numberResources: 'Resources',
  numberHosts: 'Hosts',
  totalRequestBytes: 'Total size',
  numberStaticResources: 'Static resources',
  htmlResponseBytes: 'HTML size',
  cssResponseBytes: 'CSS size',
  imageResponseBytes: 'Image size',
  javascriptResponseBytes: 'JavaScript size',
  otherResponseBytes: 'Other size',
  numberJsResources: 'JS resouces',
  numberCssResources: 'CSS resources',
  AvoidLandingPageRedirects: 'Avoid landing page redirects',
  AvoidPlugins: 'Avoid plugins',
  ConfigureViewport: 'Configure viewport',
  EnableGzipCompression: 'Enable GZIP compression',
  LeverageBrowserCaching: 'Leverage browser caching',
  MainResourceServerResponseTime: 'Main resource server response time',
  MinifyCss: 'Minify CSS',
  MinifyHTML: 'Minify HTML',
  MinifyJavaScript: 'Minify JavaScript',
  MinimizeRenderBlockingResources: 'Minimize render blocking resources',
  OptimizeImages: 'Optimize images',
  PrioritizeVisibleContent: 'Prioritize visible content',
  SizeContentToViewport: 'Size content to viewport',
  SizeTapTargetsAppropriately: 'Size tap targets appropriately',
  UseLegibleFontSizes: 'Use legible font sizes'
};

exports.divider = '\n' + chalk.grey(repeating('-', 56)) + '\n';

exports.buffer = function (msg, length) {
  var ret = '';

  if (length === undefined) {
      length = 44;
  }

  length = length - msg.length - 1;

  if (length > 0) {
    ret = repeating(' ', length);
  }

  return ret;
};

exports.scoreColor = function(score) {
  var color = chalk.yellow;
  color = score < 21 ? chalk.red : color;
  color = score > 79 ? chalk.green : color;
  return color;
};

exports.labelize = function(str) {
  var label = humanizeTitleMap[str] || str;
  return label + exports.buffer(label) + chalk.grey('| ');
};
<commit_msg>Typo correction<commit_after>'use strict';
var chalk = require('chalk');
var repeating = require('repeating');

var humanizeTitleMap = {
  numberResources: 'Resources',
  numberHosts: 'Hosts',
  totalRequestBytes: 'Total size',
  numberStaticResources: 'Static resources',
  htmlResponseBytes: 'HTML size',
  cssResponseBytes: 'CSS size',
  imageResponseBytes: 'Image size',
  javascriptResponseBytes: 'JavaScript size',
  otherResponseBytes: 'Other size',
  numberJsResources: 'JS resources',
  numberCssResources: 'CSS resources',
  AvoidLandingPageRedirects: 'Avoid landing page redirects',
  AvoidPlugins: 'Avoid plugins',
  ConfigureViewport: 'Configure viewport',
  EnableGzipCompression: 'Enable GZIP compression',
  LeverageBrowserCaching: 'Leverage browser caching',
  MainResourceServerResponseTime: 'Main resource server response time',
  MinifyCss: 'Minify CSS',
  MinifyHTML: 'Minify HTML',
  MinifyJavaScript: 'Minify JavaScript',
  MinimizeRenderBlockingResources: 'Minimize render blocking resources',
  OptimizeImages: 'Optimize images',
  PrioritizeVisibleContent: 'Prioritize visible content',
  SizeContentToViewport: 'Size content to viewport',
  SizeTapTargetsAppropriately: 'Size tap targets appropriately',
  UseLegibleFontSizes: 'Use legible font sizes'
};

exports.divider = '\n' + chalk.grey(repeating('-', 56)) + '\n';

exports.buffer = function (msg, length) {
  var ret = '';

  if (length === undefined) {
      length = 44;
  }

  length = length - msg.length - 1;

  if (length > 0) {
    ret = repeating(' ', length);
  }

  return ret;
};

exports.scoreColor = function(score) {
  var color = chalk.yellow;
  color = score < 21 ? chalk.red : color;
  color = score > 79 ? chalk.green : color;
  return color;
};

exports.labelize = function(str) {
  var label = humanizeTitleMap[str] || str;
  return label + exports.buffer(label) + chalk.grey('| ');
};
<|endoftext|>


<commit_before>'use strict';
var _ = require('underscore');
var grunt = require('grunt');
var dot = require('dot');
var md = require('marked');
var err = require('./error_handlers.js');

module.exports = {
  compile_dot: compile_dot,
  find_closest_match: find_closest_match,
  meta_data: meta_data,
  prepare_it_obj: prepare_it_obj,
  to_markdown: to_markdown
};

//=========================================================
// Use dot to compile the contents of a given input file,
// discarding any meta data that may be present
//=========================================================

function compile_dot (template_settings, meta_data_sep, disable_strip, input_file, it) {

  var src = grunt.file.read(input_file);
  template_settings.strip = disable_strip ? false : template_settings.strip;
  _.extend(dot.templateSettings, template_settings);

  return err.try(function () {
    return dot.template(content(src, meta_data_sep))(it);
  }, err.msgs.cannot_process(input_file));

}

function content (src, meta_data_sep) {
  return contains_meta_data(src) ? extract_content(src, meta_data_sep) : src;
}

function contains_meta_data (src) {
  return src[0] === '{';
}

function extract_content (src, meta_data_sep) {
  var chunks = src.split(meta_data_sep);
  return chunks.slice(1).join(meta_data_sep);
}

//=========================================================
// Return a filepath given a folder to look in,
// and a relative path which may or may not contain an extension
//=========================================================

function find_closest_match (folder, rel_path) {

  // Warn user if the base folder doesn't exist
  err.warn(!grunt.file.isDir(folder), err.msgs.nonexisting(folder));

  var pattern = build_pattern(folder, rel_path);
  var file = grunt.file.expand(pattern);

  // Warn again if the resulting file doesn't exist
  err.warn(!file.length, err.msgs.nonexisting(pattern));

  return file;
}

function build_pattern (folder, rel_path) {
  var separator = folder.length ? '/' : '';
  var extension = has_extension(rel_path) ? '' : '.*';
  return folder + separator + rel_path + extension;
}

function has_extension (path) {
  return path.match(/\.[0-9a-z]+$/i);
}

//=========================================================
// Given an input file, return an object containing the
// meta data that may or may not have been defined in the
// beginning of the file, or in the beginning of any file
// 'include'd in the input file
//=========================================================
function meta_data (input_file, meta_data_sep) {
  var src = grunt.file.read(input_file);
  var chunks = src.split(meta_data_sep);

  // For the input file, and each file that is referenced within,
  // check for meta data and append to meta_data obj

  return err.try(function () {
    return contains_meta_data(src) ? fold_fns(chunks,
                                              extract_meta_data,
                                              parse_meta_data)
                                   : {};
  }, err.msgs.cannot_parse(input_file));
}

function fold_fns () {
  return Array.prototype.reduce.call(arguments, function (arg, fn) {
    return fn(arg);
  });
}

function extract_meta_data (chunks) {
  return chunks[0];
}

function parse_meta_data (meta_data_str) {
  return JSON.parse(meta_data_str);
}

//=========================================================
// Build an appropriate it object to pass to a dot template
// Values in the 'file_lists' key need to be expanded to actual paths
//=========================================================

function prepare_it_obj (given_it, partials_compiler) {

  // Convert given patterns to actual file paths
  given_it.file_lists = expand_file_lists(given_it.file_lists);

  // Assign a function to include
  // to give it_obj access to contents of a given file
  given_it.include = partials_compiler;

  return given_it;
}

function expand_file_lists (file_lists) {
  var expanded_lists = {};

  // Underscore's .each can iterate over objects
  _.each(file_lists, function(value, key) {
    expanded_lists[key] = grunt.file.expand(value[0], value[1]);
  });

  return expanded_lists;
}

//=========================================================
// Compile a file's contents to markdown.
// If a source is given, compile it instead.
//=========================================================
function to_markdown(input_file, src) {
  var contents_to_compile = src || grunt.file.read(input_file);
  if (is_markdown(input_file)) {
    contents_to_compile = md(contents_to_compile);
  }
  return contents_to_compile;
}

function is_markdown(input_file) {
  return /\.md$/.test(input_file);
}<commit_msg>Meta data recursion will not be needed, remove placeholder<commit_after>'use strict';
var _ = require('underscore');
var grunt = require('grunt');
var dot = require('dot');
var md = require('marked');
var err = require('./error_handlers.js');

module.exports = {
  compile_dot: compile_dot,
  find_closest_match: find_closest_match,
  meta_data: meta_data,
  prepare_it_obj: prepare_it_obj,
  to_markdown: to_markdown
};

//=========================================================
// Use dot to compile the contents of a given input file,
// discarding any meta data that may be present
//=========================================================

function compile_dot (template_settings, meta_data_sep, disable_strip, input_file, it) {

  var src = grunt.file.read(input_file);
  template_settings.strip = disable_strip ? false : template_settings.strip;
  _.extend(dot.templateSettings, template_settings);

  return err.try(function () {
    return dot.template(content(src, meta_data_sep))(it);
  }, err.msgs.cannot_process(input_file));

}

function content (src, meta_data_sep) {
  return contains_meta_data(src) ? extract_content(src, meta_data_sep) : src;
}

function contains_meta_data (src) {
  return src[0] === '{';
}

function extract_content (src, meta_data_sep) {
  var chunks = src.split(meta_data_sep);
  return chunks.slice(1).join(meta_data_sep);
}

//=========================================================
// Return a filepath given a folder to look in,
// and a relative path which may or may not contain an extension
//=========================================================

function find_closest_match (folder, rel_path) {

  // Warn user if the base folder doesn't exist
  err.warn(!grunt.file.isDir(folder), err.msgs.nonexisting(folder));

  var pattern = build_pattern(folder, rel_path);
  var file = grunt.file.expand(pattern);

  // Warn again if the resulting file doesn't exist
  err.warn(!file.length, err.msgs.nonexisting(pattern));

  return file;
}

function build_pattern (folder, rel_path) {
  var separator = folder.length ? '/' : '';
  var extension = has_extension(rel_path) ? '' : '.*';
  return folder + separator + rel_path + extension;
}

function has_extension (path) {
  return path.match(/\.[0-9a-z]+$/i);
}

//=========================================================
// Given an input file, return an object containing the
// meta data that may or may not have been defined in the
// beginning of the file, or in the beginning of any file
// 'include'd in the input file
//=========================================================
function meta_data (input_file, meta_data_sep) {
  var src = grunt.file.read(input_file);
  var chunks = src.split(meta_data_sep);

  return err.try(function () {
    return contains_meta_data(src) ? fold_fns(chunks,
                                              extract_meta_data,
                                              parse_meta_data)
                                   : {};
  }, err.msgs.cannot_parse(input_file));
}

function fold_fns () {
  return Array.prototype.reduce.call(arguments, function (arg, fn) {
    return fn(arg);
  });
}

function extract_meta_data (chunks) {
  return chunks[0];
}

function parse_meta_data (meta_data_str) {
  return JSON.parse(meta_data_str);
}

//=========================================================
// Build an appropriate it object to pass to a dot template
// Values in the 'file_lists' key need to be expanded to actual paths
//=========================================================

function prepare_it_obj (given_it, partials_compiler) {

  // Convert given patterns to actual file paths
  given_it.file_lists = expand_file_lists(given_it.file_lists);

  // Assign a function to include
  // to give it_obj access to contents of a given file
  given_it.include = partials_compiler;

  return given_it;
}

function expand_file_lists (file_lists) {
  var expanded_lists = {};

  // Underscore's .each can iterate over objects
  _.each(file_lists, function(value, key) {
    expanded_lists[key] = grunt.file.expand(value[0], value[1]);
  });

  return expanded_lists;
}

//=========================================================
// Compile a file's contents to markdown.
// If a source is given, compile it instead.
//=========================================================
function to_markdown(input_file, src) {
  var contents_to_compile = src || grunt.file.read(input_file);
  if (is_markdown(input_file)) {
    contents_to_compile = md(contents_to_compile);
  }
  return contents_to_compile;
}

function is_markdown(input_file) {
  return /\.md$/.test(input_file);
}<|endoftext|>