<commit_before>var _ = require('lodash')
  , raf = require('raf/polyfill')
  , Ribcage
  , extendView;

Ribcage = {
  initialize: function (opts){

    opts = opts || {};

    // if we need to load data before rendering, do it
    if (typeof this.loadData == 'function') {
      this._dataLoaded = false
    }
    // otherwise, assume we have the data already
    else {
      this._dataLoaded = true
    }

    this._nukeOnRender = opts._nukeOnRender
    delete opts._nukeOnRender

    // backbone 1.1+ doesn't auto-set this.options
    this.options = opts

    if(this.beforeInit) {
      this.beforeInit(opts);
    }

    this.template = this.template || opts.template;

    if (!this.template) {
      this.template = function () { return ''; };
    }

    if (this.afterInit) {
      this.afterInit(opts);
    }

    this.render();
  }

, context: function () {
    return _.extend({}, this.options, this.model);
  }

, render: function () {
    var self = this
      , model = this.model;

    if(typeof this.bindEvents === 'function') {
      this.bindEvents()
    }

    if (!this._dataLoaded && typeof this.loadData == 'function') {
      return this.loadData(function () {
        self._dataLoaded = true
        self.render()
      })
    }

    if (this.beforeRender) {
      this.beforeRender();
    }

    // Maintainers of legacy code might want to use this
    // but certainly not YOU, young grasshopper!
    if (this._nukeOnRender) {
      this.closeSubviews();
      this.$el.empty();
    }

    if (this.beforeTemplating) {
      model = this.beforeTemplating();
    }

    if (this.context) {
      model = this.context();
    }

    this.$el.html(this.template(model));

    // As soon as the view is bound to DOM, we need to delegate events and re-render all
    // subviews to keep events intact. -cstumph
    this.delegateEvents()
    this.eachSubview( function eachSubviewInRender (view){
      view.render()
    })

    // I'm not happy deferring here, but backbone's
    // event system is based on the DOM, so my hands
    // are tied. - Daniel
    _.defer(function () {
      self.trigger('afterRender')
    });

    if (this.afterRender) {
      this.afterRender();
    }

    return this;
  }

, proxy: function (name, view){
    this.listenTo(view, name, function proxiedEventCallback(){
      var args = Array.prototype.slice.call(arguments, 0);
      args.splice(0, 0, name);
      this.trigger.apply(this, args);
    })
  }

, eachSubview: function (iterator){
    _.each(this.subviews, iterator);
  }

, _attachSubView: function (view){
    this.subviews = this.subviews || {};
    this.subviewByModelId = this.subviewByModelId || {};

    this.subviews[view.cid] = view;
    if (view.model) {
      if (!this.subviewByModelId[view.model.id]) this.subviewByModelId[view.model.id] = [];
      this.subviewByModelId[view.model.id].push(view);
    }

    return view;
  }

, appendSubview: function (view, el){
    el || (el = this.$el);

    this._attachSubView(view);

    if (view.options.render) view.render()
    el.append(view.el);

    _.defer(function (){
      view.trigger('afterAppend', view);
    });

    if (view.afterAppend) {
      view.afterAppend();
    }
  }

, prependSubview: function (view, el){
    el || (el = this.$el);

    this._attachSubView(view);

    if (view.options.renderOnAppend) view.render()
    el.prepend(view.el);

    _.defer(function () {
      view.trigger('afterPrepend', view);
    });

    if (view.afterPrepend) {
      view.afterPrepend();
    }
  }

, appendSubviews: function (views, el, callback){
    el || (el = this.$el);

    var fragment = document.createDocumentFragment();

    _.each(views, function(view){
      this._attachSubView(view);

      if (view.options.renderOnAppend) view.render()
      fragment.appendChild(view.el);

      _.defer(function () {
        view.trigger('afterAppend', view);
      });

      if (view.afterAppend) {
        view.afterAppend();
      }
    }, this);

    raf.call(window, function(){
      el[0].appendChild(fragment);
      if (_.isFunction(callback)) callback(views);
    });
  }

, batchAppendSubviews: function (views, el, batchCount, batchCallback, callback){
    var self = this
      , batches = _(views)
                  .groupBy( function (view, index){
                    return Math.floor(index / batchCount);
                  })
                  .toArray()
                  .valueOf();

    function appendNextBatch () {
      if(!batches.length && typeof callback == 'function') {
        return callback();
      }

      var viewBatch = batches.shift();

      self.appendSubviews(viewBatch, el, function (){
        if (typeof batchCallback == 'function') {
          batchCallback(viewBatch);
        }

        appendNextBatch();
      });
    }

    appendNextBatch();
  }

, close: function(options, callback) {
    options || (options = {})

    if (this.beforeClose) {
      this.beforeClose();
    }

    this.closeSubviews(_.defaults({}, options, {keepDom: true}));
    this.undelegateEvents();
    this.stopListening();

    if (!options.keepDom) {
      raf.call(window, function closeRequestAnimationFrame(){
        this.remove();
        if (_.isFunction(callback)) callback()
      }.bind(this))
    }
    else {
      if (_.isFunction(callback)) callback()
    }
  }

, closeSubviews: function (options, callback){
    var done = _.isFunction(callback)
      ? _.after(_.size(this.subviews), callback)
      : _.noop

    // by default, we won't destroy the DOM elements of subviews
    // b/c we can assume that removing the parent will remove the subview DOM
    _.defaults(options, {
      keepDom: false
    })

    this.eachSubview( function (subview){
      subview.close(options, done);
    });

    this.subviews = {};
  }

, detachSubview: function (view){
    var msg

    if (this.subviews) {

      if (view && !this.subviews[view.cid]) {
        msg = 'View not found in ' + this.className + '\'s subviews: ' + view.className

        if(view.model)
          msg += '\n\n'+ view.model.toJSON()

        throw new Error(msg)
      }

      delete this.subviews[view.cid];
    }

    view.$el.detach();
  }

, _removeSubviewByModel: function _removeSubviewByModel(model, method){
    var id = model.id
    if (this.subviewByModelId){
      if (!id || !this.subviewByModelId[id]){
        throw new Error('No views with ' + id + ' model id found in ' + this.className + ' subviews');
      }

      _.each(this.subviewByModelId[id], function(view){
        method(view);
      }, this);

      delete this.subviewByModelId[id];
    }

  }

, closeSubviewsByModel: function closeSubviewsByModel(model){
    this._removeSubviewByModel(model, this.close)
  }

, detachSubviewByModel: function detachSubviewByModel(model){
    this._removeSubviewByModel(model, this.detachSubview)
  }

};//end Ribcage{}

extendView = function (view){
  return view.extend(Ribcage);
};

module.exports = extendView;
<commit_msg>Linter fixes. Add ‘use strict’<commit_after>'use strict';

var _ = require('lodash')
  , raf = require('raf/polyfill')
  , Ribcage
  , extendView;

Ribcage = {
  initialize: function (opts){

    opts = opts || {};

    // if we need to load data before rendering, do it
    if (typeof this.loadData === 'function') {
      this._dataLoaded = false
    }
    // otherwise, assume we have the data already
    else {
      this._dataLoaded = true
    }

    this._nukeOnRender = opts._nukeOnRender
    delete opts._nukeOnRender

    // backbone 1.1+ doesn't auto-set this.options
    this.options = opts

    if(this.beforeInit) {
      this.beforeInit(opts);
    }

    this.template = this.template || opts.template;

    if (!this.template) {
      this.template = function () { return ''; };
    }

    if (this.afterInit) {
      this.afterInit(opts);
    }

    this.render();
  }

, context: function () {
    return _.extend({}, this.options, this.model);
  }

, render: function () {
    var self = this
      , model = this.model;

    if(typeof this.bindEvents === 'function') {
      this.bindEvents()
    }

    if (!this._dataLoaded && typeof this.loadData === 'function') {
      return this.loadData(function () {
        self._dataLoaded = true
        self.render()
      })
    }

    if (this.beforeRender) {
      this.beforeRender();
    }

    // Maintainers of legacy code might want to use this
    // but certainly not YOU, young grasshopper!
    if (this._nukeOnRender) {
      this.closeSubviews();
      this.$el.empty();
    }

    if (this.beforeTemplating) {
      model = this.beforeTemplating();
    }

    if (this.context) {
      model = this.context();
    }

    this.$el.html(this.template(model));

    // As soon as the view is bound to DOM, we need to delegate events and re-render all
    // subviews to keep events intact. -cstumph
    this.delegateEvents()
    this.eachSubview( function eachSubviewInRender (view){
      view.render()
    })

    // I'm not happy deferring here, but backbone's
    // event system is based on the DOM, so my hands
    // are tied. - Daniel
    _.defer(function () {
      self.trigger('afterRender')
    });

    if (this.afterRender) {
      this.afterRender();
    }

    return this;
  }

, proxy: function (name, view){
    this.listenTo(view, name, function proxiedEventCallback(){
      var args = Array.prototype.slice.call(arguments, 0);
      args.splice(0, 0, name);
      this.trigger.apply(this, args);
    })
  }

, eachSubview: function (iterator){
    _.each(this.subviews, iterator);
  }

, _attachSubView: function (view){
    this.subviews = this.subviews || {};
    this.subviewByModelId = this.subviewByModelId || {};

    this.subviews[view.cid] = view;
    if (view.model) {
      if (!this.subviewByModelId[view.model.id]) this.subviewByModelId[view.model.id] = [];
      this.subviewByModelId[view.model.id].push(view);
    }

    return view;
  }

, appendSubview: function (view, el){
    el || (el = this.$el);

    this._attachSubView(view);

    if (view.options.render) view.render()
    el.append(view.el);

    _.defer(function (){
      view.trigger('afterAppend', view);
    });

    if (view.afterAppend) {
      view.afterAppend();
    }
  }

, prependSubview: function (view, el){
    el || (el = this.$el);

    this._attachSubView(view);

    if (view.options.renderOnAppend) view.render()
    el.prepend(view.el);

    _.defer(function () {
      view.trigger('afterPrepend', view);
    });

    if (view.afterPrepend) {
      view.afterPrepend();
    }
  }

, appendSubviews: function (views, el, callback){
    el || (el = this.$el);

    var fragment = document.createDocumentFragment();

    _.each(views, function(view){
      this._attachSubView(view);

      if (view.options.renderOnAppend) view.render()
      fragment.appendChild(view.el);

      _.defer(function () {
        view.trigger('afterAppend', view);
      });

      if (view.afterAppend) {
        view.afterAppend();
      }
    }, this);

    raf.call(window, function(){
      el[0].appendChild(fragment);
      if (_.isFunction(callback)) callback(views);
    });
  }

, batchAppendSubviews: function (views, el, batchCount, batchCallback, callback){
    var self = this
      , batches = _(views)
                  .groupBy( function (view, index){
                    return Math.floor(index / batchCount);
                  })
                  .toArray()
                  .valueOf();

    function appendNextBatch () {
      if(!batches.length && typeof callback === 'function') {
        return callback();
      }

      var viewBatch = batches.shift();

      self.appendSubviews(viewBatch, el, function (){
        if (typeof batchCallback === 'function') {
          batchCallback(viewBatch);
        }

        appendNextBatch();
      });
    }

    appendNextBatch();
  }

, close: function(options, callback) {
    options || (options = {})

    if (this.beforeClose) {
      this.beforeClose();
    }

    this.closeSubviews(_.defaults({}, options, {keepDom: true}));
    this.undelegateEvents();
    this.stopListening();

    if (!options.keepDom) {
      raf.call(window, function closeRequestAnimationFrame(){
        this.remove();
        if (_.isFunction(callback)) callback()
      }.bind(this))
    }
    else {
      if (_.isFunction(callback)) callback()
    }
  }

, closeSubviews: function (options, callback){
    var done = _.isFunction(callback)
      ? _.after(_.size(this.subviews), callback)
      : _.noop

    // by default, we won't destroy the DOM elements of subviews
    // b/c we can assume that removing the parent will remove the subview DOM
    _.defaults(options, {
      keepDom: false
    })

    this.eachSubview( function (subview){
      subview.close(options, done);
    });

    this.subviews = {};
  }

, detachSubview: function (view){
    var msg

    if (this.subviews) {

      if (view && !this.subviews[view.cid]) {
        msg = 'View not found in ' + this.className + '\'s subviews: ' + view.className

        if(view.model)
          msg += '\n\n'+ view.model.toJSON()

        throw new Error(msg)
      }

      delete this.subviews[view.cid];
    }

    view.$el.detach();
  }

, _removeSubviewByModel: function _removeSubviewByModel(model, method){
    var id = model.id
    if (this.subviewByModelId){
      if (!id || !this.subviewByModelId[id]){
        throw new Error('No views with ' + id + ' model id found in ' + this.className + ' subviews');
      }

      _.each(this.subviewByModelId[id], function(view){
        method(view);
      }, this);

      delete this.subviewByModelId[id];
    }

  }

, closeSubviewsByModel: function closeSubviewsByModel(model){
    this._removeSubviewByModel(model, this.close)
  }

, detachSubviewByModel: function detachSubviewByModel(model){
    this._removeSubviewByModel(model, this.detachSubview)
  }

};//end Ribcage{}

extendView = function (view){
  return view.extend(Ribcage);
};

module.exports = extendView;
<|endoftext|>


<commit_before>
var worddiff = require('worddiff');
var levenshtein = require('levenshtein-component');

var domHelpers = require('../helpers-dom.js');
var mathHelpers = require('../helpers-math.js');

function TextAlgoritme() {
  // Contains text string there have something to do with the wanted title
  // and the amount of times it has appeared
  this._metaAppear = [];
  this._metaText = [];

  // Contains all body elements, when they all are collected it will be sorted
  // by its text/tag density
  this._elements = [];

  // Each feature is adjusted by its [min, max] relative to the meta text
  this._adjustLevenshtein = [];
  this._adjustWorddiff = [];

  // The header level feature is adjused to the highest and lowest level in the
  // document
  this._adjustLevel = [Infinity, -Infinity];
}
module.exports = TextAlgoritme;

var metaDescription = domHelpers.buildAttributeMatcher({
  property: ['rnews:description', 'og:description', 'twitter:description'],
  name: ['description', 'lp', 'twitter:description'],
  itemprop: ['description']
});

console.log(metaDescription.toString());

TextAlgoritme.prototype.element = function (node) {
  if (node.tagname === 'meta' && metaDescription(node.attr)) console.log(node);
  // Grap the <meta> tags, there may contain some valuable information.
  if (node.tagname === 'meta' && metaDescription(node.attr)) {
    this._handleMeta(domHelpers.normalizeString(node.attr.content));
  }
  // Grap actual text containing elements
  else if (node.tagname !== 'script' &&
          node.tagname !== 'pre' &&
          node.tagname !== 'style' &&
          node.density !== 0) {
    this._handleText(node);
 }
};

TextAlgoritme.prototype._handleMeta = function (text) {
  // trim the text
  text = text.trim();

  // Check if this is a new string, in case of dublication there is no need
  // for calculating the distances again, just incease a counter
  var index = this._metaText.indexOf(text);

  // Not found add a new string
  if (index === -1) {
    // Add text to the meta collection
    this._metaText.push(text);
    this._metaAppear.push(1);

    // prepear adjusted feature arrays to be maintaned when the <h_> tags
    // are handled
    this._adjustLevenshtein.push([Infinity, -Infinity]);
    this._adjustWorddiff.push([Infinity, -Infinity]);
  } else {
    // The text already exists, just incease the appear counter
    this._metaAppear[index] += 1;
  }
};

TextAlgoritme.prototype._handleText = function (node) {
  this._elements.push(node);
};

// The end of the document is reached
TextAlgoritme.prototype.end = function () {
  this._elements = this._elements.sort(function (a, b) {
    return b.density - a.density;
  });
};

// It is time to return the best result
TextAlgoritme.prototype.result = function () {
  console.log(this._metaText);
  return domHelpers.getRawText(this._elements[0]);
};
<commit_msg>[cleanup] remove console.log<commit_after>
var worddiff = require('worddiff');
var levenshtein = require('levenshtein-component');

var domHelpers = require('../helpers-dom.js');
var mathHelpers = require('../helpers-math.js');

function TextAlgoritme() {
  // Contains text string there have something to do with the wanted title
  // and the amount of times it has appeared
  this._metaAppear = [];
  this._metaText = [];

  // Contains all body elements, when they all are collected it will be sorted
  // by its text/tag density
  this._elements = [];

  // Each feature is adjusted by its [min, max] relative to the meta text
  this._adjustLevenshtein = [];
  this._adjustWorddiff = [];

  // The header level feature is adjused to the highest and lowest level in the
  // document
  this._adjustLevel = [Infinity, -Infinity];
}
module.exports = TextAlgoritme;

var metaDescription = domHelpers.buildAttributeMatcher({
  property: ['rnews:description', 'og:description', 'twitter:description'],
  name: ['description', 'lp', 'twitter:description'],
  itemprop: ['description']
});

TextAlgoritme.prototype.element = function (node) {
  // Grap the <meta> tags, there may contain some valuable information.
  if (node.tagname === 'meta' && metaDescription(node.attr)) {
    this._handleMeta(domHelpers.normalizeString(node.attr.content));
  }
  // Grap actual text containing elements
  else if (node.tagname !== 'script' &&
          node.tagname !== 'pre' &&
          node.tagname !== 'style' &&
          node.density !== 0) {
    this._handleText(node);
 }
};

TextAlgoritme.prototype._handleMeta = function (text) {
  // trim the text
  text = text.trim();

  // Check if this is a new string, in case of dublication there is no need
  // for calculating the distances again, just incease a counter
  var index = this._metaText.indexOf(text);

  // Not found add a new string
  if (index === -1) {
    // Add text to the meta collection
    this._metaText.push(text);
    this._metaAppear.push(1);

    // prepear adjusted feature arrays to be maintaned when the <h_> tags
    // are handled
    this._adjustLevenshtein.push([Infinity, -Infinity]);
    this._adjustWorddiff.push([Infinity, -Infinity]);
  } else {
    // The text already exists, just incease the appear counter
    this._metaAppear[index] += 1;
  }
};

TextAlgoritme.prototype._handleText = function (node) {
  this._elements.push(node);
};

// The end of the document is reached
TextAlgoritme.prototype.end = function () {
  this._elements = this._elements.sort(function (a, b) {
    return b.density - a.density;
  });
};

// It is time to return the best result
TextAlgoritme.prototype.result = function () {
  return domHelpers.getRawText(this._elements[0]);
};
<|endoftext|>


<commit_before>"use babel"
/*
 * decaffeinate suggestions:
 * DS102: Remove unnecessary code created because of implicit returns
 * DS206: Consider reworking classes to avoid initClass
 * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
 */

import path from "path"
import fs from "fs-plus"
import { File, CompositeDisposable } from "atom"
import {NewMemoryFace} from "freetype2"

// Editor model for a font file
export default class FontViewer {
  static initClass() {
    atom.deserializers.add(this)
  }

  static deserialize({ filePath }) {
    if (fs.isFileSync(filePath)) {
      return new FontViewer(filePath)
    } else {
      console.warn(`Could not deserialize font viewer for path '${filePath}' because that file no longer exists`)
    }
  }

  constructor(filePath) {
    this.file = new File(filePath)
    this.subscriptions = new CompositeDisposable()
  }

  serialize() {
    return { filePath: this.getPath(), deserializer: this.constructor.name }
  }

  getViewClass() {
    return require("./font-viewer-view")
  }

  destroy() {
    this.subscriptions.dispose()
  }

  // Retrieves the filename of the open file.
  //
  // This is `'untitled'` if the file is new and not saved to the disk.
  //
  // Returns a {String}.
  getTitle() {
    let filePath
    if ((filePath = this.getPath())) {
      return path.basename(filePath)
    } else {
      return "untitled"
    }
  }

  // Retrieves the URI of the font file.
  //
  // Returns a {String}.
  getUri() {
    return this.getPath()
  }

  // Retrieves the absolute path to the font file.
  //
  // Returns a {String} path.
  getPath() {
    return this.file.getPath()
  }

  getAvailableCharacters(callback) {
    return fs.readFile(this.getPath(), function (err, buffer) {
      const chars = []
      const face = NewMemoryFace(buffer, 0);

      let char = face.getFirstChar()
      while (char && char.glyphIndex !== 0) {
        chars.push(char.charCode)
        char = face.getNextChar(char.charCode)
      }

      return callback(chars)
    })
  }

  // Compares two {FontViewer}s to determine equality.
  //
  // Equality is based on the condition that the two URIs are the same.
  //
  // Returns a {Boolean}.
  isEqual(other) {
    return other instanceof FontViewer && this.getUri() === other.getUri()
  }
}

FontViewer.initClass()
<commit_msg>chore: getTitle no assignment in if<commit_after>"use babel"
/*
 * decaffeinate suggestions:
 * DS102: Remove unnecessary code created because of implicit returns
 * DS206: Consider reworking classes to avoid initClass
 * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
 */

import path from "path"
import fs from "fs-plus"
import { File, CompositeDisposable } from "atom"
import {NewMemoryFace} from "freetype2"

// Editor model for a font file
export default class FontViewer {
  static initClass() {
    atom.deserializers.add(this)
  }

  static deserialize({ filePath }) {
    if (fs.isFileSync(filePath)) {
      return new FontViewer(filePath)
    } else {
      console.warn(`Could not deserialize font viewer for path '${filePath}' because that file no longer exists`)
    }
  }

  constructor(filePath) {
    this.file = new File(filePath)
    this.subscriptions = new CompositeDisposable()
  }

  serialize() {
    return { filePath: this.getPath(), deserializer: this.constructor.name }
  }

  getViewClass() {
    return require("./font-viewer-view")
  }

  destroy() {
    this.subscriptions.dispose()
  }

  // Retrieves the filename of the open file.
  //
  // This is `'untitled'` if the file is new and not saved to the disk.
  //
  // Returns a {String}.
  getTitle() {
    const filePath = this.getPath()
    if (filePath) {
      return path.basename(filePath)
    } else {
      return "untitled"
    }
  }

  // Retrieves the URI of the font file.
  //
  // Returns a {String}.
  getUri() {
    return this.getPath()
  }

  // Retrieves the absolute path to the font file.
  //
  // Returns a {String} path.
  getPath() {
    return this.file.getPath()
  }

  getAvailableCharacters(callback) {
    return fs.readFile(this.getPath(), function (err, buffer) {
      const chars = []
      const face = NewMemoryFace(buffer, 0);

      let char = face.getFirstChar()
      while (char && char.glyphIndex !== 0) {
        chars.push(char.charCode)
        char = face.getNextChar(char.charCode)
      }

      return callback(chars)
    })
  }

  // Compares two {FontViewer}s to determine equality.
  //
  // Equality is based on the condition that the two URIs are the same.
  //
  // Returns a {Boolean}.
  isEqual(other) {
    return other instanceof FontViewer && this.getUri() === other.getUri()
  }
}

FontViewer.initClass()
<|endoftext|>


<commit_before>var equal      = require('deep-equal'),
    _          = require('lodash'),
    gengisKhan = exports;

/*
 * Dispatch to the handlers
 */
var dispatchTable = {
  '$ne' : $ne,
  '$all': $all,
  '$in' : $in,
  '$nin': $nin
};

/*
 * Same as MongoDB, check reference
 */

function $ne(objectField, subQuery) {
  return !equal(objectField, subQuery);
}

/*
 * Same as MongoDB, check reference
 */

function $all(objectField, subQuery) {
  return _.every(subQuery, function(subQueryValue) {
    if(subQueryValue instanceof RegExp) {
      return _.any(objectField, function(element) {
        return subQueryValue.test(element);
      });
    }

    return ~objectField.indexOf(subQueryValue);
  });
}

/*
 * Same as MongoDB, check reference
 */

function $in(objectField, subQuery) {
  return _.any(subQuery, function(subQueryValue) {
    if(subQueryValue instanceof RegExp) {
      return _.any(objectField, function(element) {
        return subQueryValue.test(element);
      });
    }

    return ~objectField.indexOf(subQueryValue);
  });
}

/*
 * Same as MongoDB, check reference
 */

function $nin(objectField, subQuery) {
  return _.every(subQuery, function(subQueryValue) {
    if(subQueryValue instanceof RegExp) {
      return _.every(objectField, function(element) {
        return !subQueryValue.test(element);
      });
    }

    return !~objectField.indexOf(subQueryValue);
  });
}

/*
 * Dispatches the special symbol (with `$`) to the appropriate
 * function using the `dispatchTable`, otherwise throw an Error
 *
 * @param {Object} Field of the object we want to match
 * @param {Object} Sub-query containing the `$` key
 * @api private
 */

function parseSpecial(objectField, subQuery) {
  return _.every(subQuery, function(subQueryValue, subQueryKey) {
    if(dispatchTable[subQueryKey])
      return dispatchTable[subQueryKey](objectField, subQuery[subQueryKey]);

    throw new Error('Unknown symbol ' + subQueryKey);
  });
}

/*
 * Returns a closure which filters the object according
 * to the query.
 *
 * @param {Object} Query to run
 * @api private
 */

function filterWithQuery(query) {
  return function(object) {
    /* Make sure everything matches */
    return _.every(query, function(queryValue, queryKey) {

      /*
        If it's an Array, skip. If any of the keys of the query
        contain `$`, it's a reserved key, so dispatch to `parseSpecial`.
      */
      if(
        typeof 'queryValue' === 'object' &&
        !Array.isArray(queryValue) &&
        _.any(queryValue, function(_, queryValueKey) {
          return ~queryValueKey.indexOf('$');
        })
      ) {
        return parseSpecial(object[queryKey], queryValue);
      }

      /* RegExp is evaluated by itself, otherwise use deep equal */
      if(queryValue instanceof RegExp)
        return queryValue.test(object[queryKey]);

      return equal(queryValue, object[queryKey]);
    });
  };
}

/*
 * Matches the list of objects with the provided query,
 * returns the list of objects matching said query.
 *
 * @param {Array, Object} List of objects to match
 * @param {Object, String} Query to run
 * @api public
 */

gengisKhan.match = function(objects, query) {
  if(!Array.isArray(objects)) { objects = [objects]; }
  if(typeof query === 'string') {
    /*
     * XXX: Yes, it's dumb. No, no way around it.
     *      Keep hatin' ◕ ◡ ◔
     */
    eval('query = ' + query);
  }

  /* Filter the objects */
  var res = objects.filter(filterWithQuery(query));
  return res.length === 0 ?
    null :
    res  ;
};

<commit_msg>fix: ops<commit_after>var equal      = require('deep-equal'),
    _          = require('lodash'),
    gengisKhan = exports;

/*
 * Dispatch to the handlers
 */
var dispatchTable = {
  '$ne' : $ne,
  '$all': $all,
  '$in' : $in,
  '$nin': $nin
};

/*
 * Same as MongoDB, check reference
 */

function $ne(objectField, subQuery) {
  return !equal(objectField, subQuery);
}

/*
 * Same as MongoDB, check reference
 */

function $all(objectField, subQuery) {
  return _.every(subQuery, function(subQueryValue) {
    if(subQueryValue instanceof RegExp) {
      return _.any(objectField, function(element) {
        return subQueryValue.test(element);
      });
    }

    return ~objectField.indexOf(subQueryValue);
  });
}

/*
 * Same as MongoDB, check reference
 */

function $in(objectField, subQuery) {
  return _.any(subQuery, function(subQueryValue) {
    if(subQueryValue instanceof RegExp) {
      return _.any(objectField, function(element) {
        return subQueryValue.test(element);
      });
    }

    return ~objectField.indexOf(subQueryValue);
  });
}

/*
 * Same as MongoDB, check reference
 */

function $nin(objectField, subQuery) {
  return _.every(subQuery, function(subQueryValue) {
    if(subQueryValue instanceof RegExp) {
      return _.every(objectField, function(element) {
        return !subQueryValue.test(element);
      });
    }

    return !~objectField.indexOf(subQueryValue);
  });
}

/*
 * Dispatches the special symbol (with `$`) to the appropriate
 * function using the `dispatchTable`, otherwise throw an Error
 *
 * @param {Object} Field of the object we want to match
 * @param {Object} Sub-query containing the `$` key
 * @api private
 */

function parseSpecial(objectField, subQuery) {
  return _.every(subQuery, function(subQueryValue, subQueryKey) {
    if(dispatchTable[subQueryKey])
      return dispatchTable[subQueryKey](objectField, subQuery[subQueryKey]);

    throw new Error('Unknown symbol ' + subQueryKey);
  });
}

/*
 * Returns a closure which filters the object according
 * to the query.
 *
 * @param {Object} Query to run
 * @api private
 */

function filterWithQuery(query) {
  return function(object) {
    /* Make sure everything matches */
    return _.every(query, function(queryValue, queryKey) {

      /*
        If it's an Array, skip. If any of the keys of the query
        contain `$`, it's a reserved key, so dispatch to `parseSpecial`.
      */
      if(
        !Array.isArray(queryValue) &&
        _.any(queryValue, function(_, queryValueKey) {
          return ~queryValueKey.indexOf('$');
        })
      ) {
        return parseSpecial(object[queryKey], queryValue);
      }

      /* RegExp is evaluated by itself, otherwise use deep equal */
      if(queryValue instanceof RegExp)
        return queryValue.test(object[queryKey]);

      return equal(queryValue, object[queryKey]);
    });
  };
}

/*
 * Matches the list of objects with the provided query,
 * returns the list of objects matching said query.
 *
 * @param {Array, Object} List of objects to match
 * @param {Object, String} Query to run
 * @api public
 */

gengisKhan.match = function(objects, query) {
  if(!Array.isArray(objects)) { objects = [objects]; }
  if(typeof query === 'string') {
    /*
     * XXX: Yes, it's dumb. No, no way around it.
     *      Keep hatin' ◕ ◡ ◔
     */
    eval('query = ' + query);
  }

  /* Filter the objects */
  var res = objects.filter(filterWithQuery(query));
  return res.length === 0 ?
    null :
    res  ;
};

<|endoftext|>


<commit_before>var request = require('request'),
    querystring = require('querystring'),
    jsdom = require('jsdom'),
    errors = require('./errors')

exports.GooglePlus = function(apiKey) {
    return {
        userPosts: function(userId, callback) {
            var url = 'https://www.googleapis.com/plus/v1/people/' + userId + '/activities/public?' + querystring.stringify({key: apiKey})
            request(url, function(error, response, body) {
                if (error) return callback(error)
                try {
                    var json = JSON.parse(body)
                } catch (error) {
                    return callback(error)
                }
                if (json.error) {
                    var errorType = function() {
                        if (json.error.code == 404) return errors.NotFoundError
                        if (json.error.code >= 400) return errors.UserError
                        return errors.ServerError
                    }()
                    return callback(new errorType("[Google+ error] " + json.error.message))
                }
                var posts = []
                if (json.items) {
                    json.items.each(function(item) {
                        posts.push({
                            url: item.url,
                            title: postTitle(item),
                            body: formatBody(item),
                            updated: new Date(item.updated),
                            author: item.actor.displayName
                        })
                    })
                }
                callback(null, posts)
            })
        }
    }
}

var formatBody = function(item) {

    if (item.object.attachments) {
        var type = (function() {
            if (item.object.attachments[0].objectType === 'article') {
                return formatLink(item.object.attachments[0]);
            }
            if (item.object.attachments[0].objectType === 'photo') {
                return formatPhoto(item.object.attachments[0]);
            }
            if (item.object.attachments[0].objectType === 'video') {
                return formatVideo(item.object.attachments[0]);
            }
        })()
        if (type) var type = '
' + type + '
';
    }

    var body = (function() {
        if (item.annotation) return '
' + item.annotation + '
';
        else if (item.title) return '
' + item.title + '
';
        else if (item.object.title) return '
' + item.object.title + '
';
        return " ";
        })()

    if (type) {
        body = body + type;
    }
    return body;
}

var firstSentence = function(string) {
    if (! string) return string;
    // split sentences, from http://stackoverflow.com/a/11127276/74919
    var re = /[^\r\n.!?]+(:?(:?\r\n|[\r\n]|[.!?])+|$)/gi;
    var first = string.match(re)[0];
    if (first) {
        return first;
    } else {
        return string;
    }

}

var formatLink = function(attachment) {
    var a = attachment;
    var head = (function() {
        if (attachment.displayName) {
            if (attachment.url) return ''+ attachment.displayName + '';
            return '
' + attachment.displayName + '
';
        }
        return "Attached Article";
    })()
    var content = (function() {
        if (attachment.content) return attachment.content;
        return " ";
    })()
    var image = (function() {
        if (attachment.fullImage) return '';
        else if (attachment.image) return '';
        return " ";
    })()

    var link = head + '
'+ content + '
' + image

    return link
}
var formatPhoto = function(attachment) {
    var alt = (function() {
        if (attachment.content) return attachment.content;
        return "attached image";
    })()
    var image = (function() {
        if (attachment.image) return '';
        else if (attachment.fullImage) return '';
        return " ";
    })()
    return image;
}
var formatVideo = function(attachment) {
    var a = attachment;
    var head = (function() {
        if (attachment.displayName) {
            if (attachment.url) return ''+ attachment.displayName + '';
            return '
' + attachment.displayName + '
';
        }
        return "Attached Video";
    })()
    var content = (function() {
        if (attachment.content) return attachment.content;
        return " ";
    })()
    var video = (function() {
        // Embedding is not working, need to figure this out.
        if (false) return '<object src="' + attachment.embed.url + '" type="' + attachment.embed.type + '"></object>';
        else if (attachment.image) {
            return '';
        }
        return " ";
    })()

    var link = head + '
'+ cut(content, 150) + '
' + video;

    return link
}

var cut = function(string, length) {
    if (string.length > length) {
        string = string.slice(0, length - 2) + '…'
    }
    return string
}

var htmlToPlain = function(html) {
    var document = jsdom.jsdom('' + html + '')

    // Add line breaks for block elements
    ;['br', 'div', 'p'].forEach(function(tag) {
        var elements = document.getElementsByTagName(tag)
        for (var i = 0; i < elements.length; i++) {
            var newline = document.createTextNode('\n')
            elements[i].parentNode.insertBefore(newline, elements[i])
        }
    })

    return document.documentElement.textContent
}

var postTitle = function(item) {

    var belongsToPhotoAlbum = function() {
        return item.object.attachments &&
            item.object.attachments.any(function(a) {
                return a.objectType === 'photo-album'
            })
    }

    var userAnnotation = function() {
        if (item.verb === 'share' && item.annotation) {
            return htmlToPlain(item.annotation)
        }
    }

    var titleFromAttachments = function() {
        if (item.object.attachments) {
            if (item.title) return item.title;
            else {
                for (var i = 0; i < item.object.attachments.length; i++) {
                    title = item.object.attachments[i].displayName
                    if (title) return title
                }
            }
        }
    }

    var content = function() {
        return htmlToPlain(item.object.content)
    }

    var title = firstSentence(userAnnotation())

    if (! title) titleFromAttachments();

    // When item is an album photo G+ uses the album title as the content, but
    // we'll prefer photo's own annotation
    if (! title && ! belongsToPhotoAlbum()) title = content()

    if (! title && belongsToPhotoAlbum()) title = content()

    if (! title) title = '' // Avoid undefineds

    return firstSentence(title);
}
<commit_msg>Add tags to end of title if not included in title<commit_after>var request = require('request'),
    querystring = require('querystring'),
    jsdom = require('jsdom'),
    errors = require('./errors')

exports.GooglePlus = function(apiKey) {
    return {
        userPosts: function(userId, callback) {
            var url = 'https://www.googleapis.com/plus/v1/people/' + userId + '/activities/public?' + querystring.stringify({key: apiKey})
            request(url, function(error, response, body) {
                if (error) return callback(error)
                try {
                    var json = JSON.parse(body)
                } catch (error) {
                    return callback(error)
                }
                if (json.error) {
                    var errorType = function() {
                        if (json.error.code == 404) return errors.NotFoundError
                        if (json.error.code >= 400) return errors.UserError
                        return errors.ServerError
                    }()
                    return callback(new errorType("[Google+ error] " + json.error.message))
                }
                var posts = []
                if (json.items) {
                    json.items.each(function(item) {
                        posts.push({
                            url: item.url,
                            title: postTitle(item),
                            body: formatBody(item),
                            updated: new Date(item.updated),
                            author: item.actor.displayName
                        })
                    })
                }
                callback(null, posts)
            })
        }
    }
}

var formatBody = function(item) {

    if (item.object.attachments) {
        var type = (function() {
            if (item.object.attachments[0].objectType === 'article') {
                return formatLink(item.object.attachments[0]);
            }
            if (item.object.attachments[0].objectType === 'photo') {
                return formatPhoto(item.object.attachments[0]);
            }
            if (item.object.attachments[0].objectType === 'video') {
                return formatVideo(item.object.attachments[0]);
            }
        })()
        if (type) var type = '
' + type + '
';
    }

    var body = (function() {
        if (item.annotation) return '
' + item.annotation + '
';
        else if (item.title) return '
' + item.title + '
';
        else if (item.object.title) return '
' + item.object.title + '
';
        return " ";
        })()

    if (type) {
        body = body + type;
    }
    return body;
}

var firstSentence = function(string) {
    if (! string) return string;
    // split sentences, from http://stackoverflow.com/a/11127276/74919
    var re = /[^\r\n.!?]+(:?(:?\r\n|[\r\n]|[.!?])+|$)/gi;
    var first = string.match(re)[0];
    var sentence = (function() {
        if (first) {
                return first;
            } else {
                return string;
            }
    })()
    var re = /(^|\s)#([^ ]*)/gi;
    var matches = string.match(re);
    var addons = (function() {
        if (matches) {
            var tags = [];
            matches.each(function(item) {
                if (! sentence.match(item)) tags.push(item.trim());
            })
            return tags.join(' ');
        } else return " ";
    })()
    return [sentence,addons].join(' ');

}

var formatLink = function(attachment) {
    var a = attachment;
    var head = (function() {
        if (attachment.displayName) {
            if (attachment.url) return ''+ attachment.displayName + '';
            return '
' + attachment.displayName + '
';
        }
        return "Attached Article";
    })()
    var content = (function() {
        if (attachment.content) return attachment.content;
        return " ";
    })()
    var image = (function() {
        if (attachment.fullImage) return '';
        else if (attachment.image) return '';
        return " ";
    })()

    var link = head + '
'+ content + '
' + image

    return link
}
var formatPhoto = function(attachment) {
    var alt = (function() {
        if (attachment.content) return attachment.content;
        return "attached image";
    })()
    var image = (function() {
        if (attachment.image) return '';
        else if (attachment.fullImage) return '';
        return " ";
    })()
    return image;
}
var formatVideo = function(attachment) {
    var a = attachment;
    var head = (function() {
        if (attachment.displayName) {
            if (attachment.url) return ''+ attachment.displayName + '';
            return '
' + attachment.displayName + '
';
        }
        return "Attached Video";
    })()
    var content = (function() {
        if (attachment.content) return attachment.content;
        return " ";
    })()
    var video = (function() {
        // Embedding is not working, need to figure this out.
        if (false) return '<object src="' + attachment.embed.url + '" type="' + attachment.embed.type + '"></object>';
        else if (attachment.image) {
            return '';
        }
        return " ";
    })()

    var link = head + '
'+ cut(content, 150) + '
' + video;

    return link
}

var cut = function(string, length) {
    if (string.length > length) {
        string = string.slice(0, length - 2) + '…'
    }
    return string
}

var htmlToPlain = function(html) {
    var document = jsdom.jsdom('' + html + '')

    // Add line breaks for block elements
    ;['br', 'div', 'p'].forEach(function(tag) {
        var elements = document.getElementsByTagName(tag)
        for (var i = 0; i < elements.length; i++) {
            var newline = document.createTextNode('\n')
            elements[i].parentNode.insertBefore(newline, elements[i])
        }
    })

    return document.documentElement.textContent
}

var postTitle = function(item) {

    var belongsToPhotoAlbum = function() {
        return item.object.attachments &&
            item.object.attachments.any(function(a) {
                return a.objectType === 'photo-album'
            })
    }

    var userAnnotation = function() {
        if (item.verb === 'share' && item.annotation) {
            return htmlToPlain(item.annotation)
        }
    }

    var titleFromAttachments = function() {
        if (item.object.attachments) {
            if (item.title) return item.title;
            else {
                for (var i = 0; i < item.object.attachments.length; i++) {
                    title = item.object.attachments[i].displayName
                    if (title) return title
                }
            }
        }
    }

    var content = function() {
        return htmlToPlain(item.object.content)
    }

    var title = firstSentence(userAnnotation())

    if (! title) titleFromAttachments();

    // When item is an album photo G+ uses the album title as the content, but
    // we'll prefer photo's own annotation
    if (! title && ! belongsToPhotoAlbum()) title = content()

    if (! title && belongsToPhotoAlbum()) title = content()

    if (! title) title = '' // Avoid undefineds

    return firstSentence(title);
}
<|endoftext|>


<commit_before>var fs = require('fs'),
    ejs = require('ejs'),
    request = require('request'),
    querystring = require('querystring')

exports.Client = function(apiKey) {
    var userPosts = function(userId, callback) {
        var url = 'https://www.googleapis.com/plus/v1/people/' + userId + '/activities/public?' + querystring.stringify({key: apiKey})
        request(url, function(error, response, body) {
            if (error) return callback(error)
            try {
                var json = JSON.parse(body)
            } catch (error) {
                return callback(error)
            }
            if (json.error) return callback(new Error(json.error.message))
            var posts = []
            if (json.items) {
                json.items.each(function(item) {
                    posts.push({
                        url: item.url,
                        title: postTitle(item),
                        updated: new Date(item.updated)
                    })
                })
            }
            callback(null, posts)
        })
    }

    return {
        userFeed: function(userId, callback) {
            userPosts(userId, function(error, posts) {
                if (error) return callback(error)

                fs.readFile(__dirname + '/../views/feed.ejs', 'utf8', function(error, template) {
                    if (error) return callback(error)

                    var feed = ejs.render(template, {
                        locals: {
                            profileUrl: 'https://plus.google.com/' + userId,
                            posts: posts
                        }
                    })

                    callback(null, feed)
                })
            })
        }
    }
}

var cut = function(string, length) {
    if (string.length > length) {
        string = string.slice(0, length - 2) + '…'
    }
    return string
}

var postTitle = function(item) {
    var maxLength = 100

    var title = item.title // Already cutted to 100 chars

    // Prefer user comment to "Reshared post from" when it is a shared post
    if (item.verb == 'share') title = cut(item.annotation, maxLength)

    // If there is no title try to get it from attachments
    if (! title && item.object.attachments) {
        for (var i = 0; i < item.object.attachments.length; i++) {
            var title = item.object.attachments[i].displayName
            if (title) break
        }
    }

    // Attachment type
    var attachment = ''
    if (item.object.attachments) {
        var type = (function() {
            if (item.object.attachments.some(function(a) { return a.objectType === 'article' })) return 'link'
            if (item.object.attachments.any(function(a) { return a.objectType === 'photo' })) return 'photo'
            if (item.object.attachments.any(function(a) { return a.objectType === 'video' })) return 'video'
        })()
        if (type) attachment = '[' + type + ']'
    }

    var finalTitle = []
    if (title) finalTitle.push(title)
    if (attachment) finalTitle.push(attachment)
    return finalTitle.join(' ')
}
<commit_msg>Better handling distinct cases when getting title<commit_after>var fs = require('fs'),
    ejs = require('ejs'),
    request = require('request'),
    querystring = require('querystring'),
    jsdom = require('jsdom')

exports.Client = function(apiKey) {
    var userPosts = function(userId, callback) {
        var url = 'https://www.googleapis.com/plus/v1/people/' + userId + '/activities/public?' + querystring.stringify({key: apiKey})
        request(url, function(error, response, body) {
            if (error) return callback(error)
            try {
                var json = JSON.parse(body)
            } catch (error) {
                return callback(error)
            }
            if (json.error) return callback(new Error(json.error.message))
            var posts = []
            if (json.items) {
                json.items.each(function(item) {
                    posts.push({
                        url: item.url,
                        title: postTitle(item),
                        updated: new Date(item.updated)
                    })
                })
            }
            callback(null, posts)
        })
    }

    return {
        userFeed: function(userId, callback) {
            userPosts(userId, function(error, posts) {
                if (error) return callback(error)

                fs.readFile(__dirname + '/../views/feed.ejs', 'utf8', function(error, template) {
                    if (error) return callback(error)

                    var feed = ejs.render(template, {
                        locals: {
                            profileUrl: 'https://plus.google.com/' + userId,
                            posts: posts
                        }
                    })

                    callback(null, feed)
                })
            })
        }
    }
}

var cut = function(string, length) {
    if (string.length > length) {
        string = string.slice(0, length - 2) + '…'
    }
    return string
}

var htmlToPlain = function(html) {
    var document = jsdom.jsdom('<html>' + html + '</html>')

    // Add line breaks for block elements
    ;['br', 'div', 'p'].forEach(function(tag) {
        var elements = document.getElementsByTagName(tag)
        for (var i = 0; i < elements.length; i++) {
            var newline = document.createTextNode('\n')
            elements[i].parentNode.insertBefore(newline, elements[i])
        }
    })

    return document.documentElement.textContent
}

var postTitle = function(item) {
    var title = (item.verb == 'share' && item.annotation) ?
        item.annotation : // Prefer user annotation on shared items
        htmlToPlain(item.object.content)

    // If there is no title try to get it from attachments
    if (! title && item.object.attachments) {
        for (var i = 0; i < item.object.attachments.length; i++) {
            var title = item.object.attachments[i].displayName
            if (title) break
        }
    }

    if (! title) title = '' // Avoid undefineds

    title = cut(title, 100)

    // Include attachment type
    if (item.object.attachments) {
        var type = (function() {
            if (item.object.attachments.some(function(a) { return a.objectType === 'article' })) return 'link'
            if (item.object.attachments.any(function(a) { return a.objectType === 'photo' })) return 'photo'
            if (item.object.attachments.any(function(a) { return a.objectType === 'video' })) return 'video'
        })()
        if (type) title += ' [' + type + ']'
    }

    return title
}
<|endoftext|>


<commit_before>module.exports = (function(){
    'use strict';

    /* NOTE: before requiring in an entity that uses the db a call to .configure needs to be done first */
    var grasshopper = {},
        config = require('./config'),
        q = require('q');

    /**
     * Expose the available roles in the system.
     */
    grasshopper.roles = require('./security/roles');

    /**
     * Expose a function that you can use to authenticate and get a token to use for authenticated calls.
     */
    grasshopper.auth = require('./security/auth');

    /**
     * Configure the module with your specific database settings.
     * @param method
     */
    grasshopper.configure = function(method){
        method.apply(this);
        config.init(this.config);
        require('./db');
    };

    /**
     * The grasshopper request function will return back an object that can execute calls to the system.
     * If you are making an authenticated call then you should send in your token. If you are making a
     * public call then don't pass in an argument.
     * @param token
     * @returns {{users: *, tokens: *, content: *, contentTypes: *, nodes: *}}
     */
    grasshopper.request = function(token){
        var kontx = {};

        kontx.deferred = q.defer();
        kontx.token = token;
        kontx.payload = {};
        kontx.args = {};

        return {
            users: require('./runners/users')(kontx),
            tokens: require('./runners/tokens')(kontx),
            content: require('./runners/content')(kontx),
            contentTypes: require('./runners/contentTypes')(kontx),
            nodes: require('./runners/nodes')(kontx)
        };
    };

    return grasshopper;
})();
<commit_msg>Added reference to asset module in the main lib.<commit_after>module.exports = (function(){
    'use strict';

    /* NOTE: before requiring in an entity that uses the db a call to .configure needs to be done first */
    var grasshopper = {},
        config = require('./config'),
        q = require('q');

    /**
     * Expose the available roles in the system.
     */
    grasshopper.roles = require('./security/roles');

    /**
     * Expose a function that you can use to authenticate and get a token to use for authenticated calls.
     */
    grasshopper.auth = require('./security/auth');

    /**
     * Configure the module with your specific database settings.
     * @param method
     */
    grasshopper.configure = function(method){
        method.apply(this);
        config.init(this.config);
        require('./db');
    };

    /**
     * The grasshopper request function will return back an object that can execute calls to the system.
     * If you are making an authenticated call then you should send in your token. If you are making a
     * public call then don't pass in an argument.
     * @param token
     * @returns {{users: *, tokens: *, content: *, contentTypes: *, nodes: *}}
     */
    grasshopper.request = function(token){
        var kontx = {};

        kontx.deferred = q.defer();
        kontx.token = token;
        kontx.payload = {};
        kontx.args = {};

        return {
            users: require('./runners/users')(kontx),
            tokens: require('./runners/tokens')(kontx),
            content: require('./runners/content')(kontx),
            contentTypes: require('./runners/contentTypes')(kontx),
            nodes: require('./runners/nodes')(kontx),
            assets: require('./runners/assets')(kontx)
        };
    };

    return grasshopper;
})();
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var grunt = require('grunt');
var semver = require('semver');
var shell = require('shelljs');

// Get the list of angular files (angular.js, angular-mocks.js, etc)
var cachedAngularFiles = grunt.file.readJSON('lib/test/angular/files.json');

var util = module.exports = {

  testDependencies: {
    unit: ['bower_components/jquery/jquery.min.js', 'lib/test/jquery.simulate.js','lib/test/classList.polyFill.js', 'dist/release/ui-grid.css', 'bower_components/lodash/dist/lodash.min.js', 'bower_components/csv-js/csv.js']
  },

  testFiles: {
    unit: ['src/js/core/bootstrap.js', 'src/js/**/*.js', 'test/unit/**/*.spec.js', 'src/features/*/js/**/*.js', 'src/features/*/test/**/*.spec.js', '.tmp/template.js'],
    core_unit: ['src/js/core/bootstrap.js', 'src/js/**/*.js', 'test/unit/**/*.spec.js', 'src/features/*/js/**/*.js', '.tmp/template.js'],
  },
  testFilesFeature: function(featureName){
    var featurePattern = 'src/features/' + featureName +'/test/**/*.spec.js';

    return {
      unit: ['src/js/core/bootstrap.js', 'src/js/**/*.js', 'test/unit/**/*.spec.js', 'src/features/*/js/**/*.js', featurePattern, '.tmp/template.js'],
      core_unit: util.testDependencies.unit.core_unit
    };
  },

  // Return a list of angular files for a specific version
  angularFiles: function (version) {
    if (version === 'latest') {
      version = util.latestAngular();
    }

    // Start with our test files
    var retFiles = []; //grunt.template.process('<%= karma.options.files %>').split(",");

    cachedAngularFiles.forEach(function(f) {
      var filePath = path.join('lib', 'test', 'angular', version, f);

      if (! fs.existsSync(filePath)) {
        grunt.fatal("Angular file " + filePath + " doesn't exist");
      }

      retFiles.push(filePath);
    });

    return retFiles;
  },

  startKarma: function(config, singleRun, done){
    var browsers = grunt.option('browsers');
    var reporters = grunt.option('reporters');
    var noColor = grunt.option('no-colors');
    var port = grunt.option('port');
    var p = spawn('node', ['node_modules/karma/bin/karma', 'start', config,
      singleRun ? '--single-run=true' : '',
      reporters ? '--reporters=' + reporters : '',
      browsers ? '--browsers=' + browsers : '',
      noColor ? '--no-colors' : '',
      port ? '--port=' + port : ''
    ]);
    p.stdout.pipe(process.stdout);
    p.stderr.pipe(process.stderr);
    p.on('exit', function(code){
      if(code !== 0) grunt.fail.warn("Karma test(s) failed. Exit code: " + code);
      done();
    });
  },

  customLaunchers: function() {
    return {
      'SL_Chrome': {
        base: 'SauceLabs',
        browserName: 'chrome'
      },
      'SL_Firefox': {
        base: 'SauceLabs',
        browserName: 'firefox'
      },
      'SL_Safari_5': {
        base: 'SauceLabs',
        browserName: 'safari',
        version: '5'
      },
      'SL_Safari_6': {
        base: 'SauceLabs',
        browserName: 'safari',
        platform: 'Mac 10.8',
        version: '6'
      },
      'SL_Safari_7': {
        base: 'SauceLabs',
        browserName: 'safari',
        platform: 'Mac 10.9',
        version: '7'
      },
      // 'SL_IE_8_XP': {
      //   base: 'SauceLabs',
      //   browserName: 'internet explorer',
      //   platform: 'Windows XP',
      //   version: '8'
      // },
      // 'SL_IE_8': {
      //   base: 'SauceLabs',
      //   browserName: 'internet explorer',
      //   platform: 'Windows 7',
      //   version: '8'
      // },
      'SL_IE_9': {
        base: 'SauceLabs',
        browserName: 'internet explorer',
        platform: 'Windows 7',
        version: '9',
        'X-UA-Compatible': 'IE=edge,chrome=1'
      },
      'SL_IE_10': {
        base: 'SauceLabs',
        browserName: 'internet explorer',
        platform: 'Windows 7',
        version: '10'
      },
      'SL_IE_11': {
        base: 'SauceLabs',
        browserName: 'internet explorer',
        platform: 'Windows 8.1',
        version: '11'
      },
      'SL_Android_4.4': {
        base: 'SauceLabs',
        browserName: 'android',
        platform: 'Linux',
        version: '4.4'
      },
      'SL_Android_5.0': {
        base: 'SauceLabs',
        browserName: 'android',
        platform: 'Linux',
        version: '5.0'
      },
      'SL_Linux_Opera': {
        base: 'SauceLabs',
        browserName: 'opera',
        platform: 'Linux',
        version: '12'
      },

      // NOTE (c0bra): Currently both iOS 6 and 7 will run (w/ a 45 second activity timeout) and the tests pass, but after that the session just hangs indefinitely -- 20140320
      // 'SL_iOS_6': {
      //   base: 'SauceLabs',
      //   browserName: 'iphone',
      //   platform: 'OS X 10.8',
      //   version: '6.0'
      // },
      // 'SL_iOS_7': {
      //   base: 'SauceLabs',
      //   browserName: 'iphone',
      //   platform: 'OS X 10.9',
      //   version: '7.0'
      // }
    };
  },

  //
  browsers: function() {

  },

  angulars: function() {
    var angularLib = path.join('lib', 'test', 'angular');

    // Loop over all the files in the angular testlib directory
    var files = fs.readdirSync(angularLib);

    // For each file found, make sure it's a directory...
    var versions = [];
    files.forEach(function(file) {
      var dir = path.join(angularLib, file);
      if (! fs.lstatSync(dir).isDirectory()) return;

      if (! semver.valid(file)) return;

      versions.push(file);
    });

    return versions;
  },

  latestAngular: function() {
    function sortFn(a,b) {
      return semver.gt(b, a);
    };

    // For each file found, make sure it's a directory...
    var versions = util.angulars();

    return versions.sort(sortFn)[0];
  },

  /* Read in whatever angular versions are in lib/test/angular and register karma configs for them all! */
  createKarmangularConfig: function() {
    if (grunt.option('fast')){
      var versions = [util.latestAngular()];
    } else {
      // For each file found, make sure it's a directory...
      var versions = grunt.option('angular') ? grunt.option('angular').split(/,/) : null || util.angulars();
    }

    if (grunt.option('angular')) {
      if (grunt.option('angular') === 'latest') {
        versions = [util.latestAngular()];
      }

      grunt.log.writeln("Using angular " + grunt.util.pluralize(versions, "version/versions") + ": " + versions.join(', '));
    }

    versions.forEach(function (version) {
      // .. then create a karma config for it!
      var karmaConfigName = 'angular-' + grunt.config.escape(version);

      if (grunt.option('core') || grunt.option('fast')){
        grunt.config('karma.' + karmaConfigName, {
          options: {
            files: util.testDependencies.unit
              .concat(util.angularFiles(version)
              .concat(util.testFiles.core_unit))
          }
        });
      } else if ( grunt.option('feature') ){
        grunt.config('karma.' + karmaConfigName, {
          options: {
            files: util.testDependencies.unit
              .concat(util.angularFiles(version)
              .concat(util.testFilesFeature(grunt.option('feature')).unit))
          }
        });
      } else {
        grunt.config('karma.' + karmaConfigName, {
          options: {
            files: util.testDependencies.unit
              .concat(util.angularFiles(version)
                .concat(util.testFiles.unit))
          }
        });
      }
    });
  },

  // Take the SauceLabs browsers from the karma config file and split them into groups of 3
  createSauceConfig: function() {
    var launchers = util.customLaunchers();

    var chunkNames = Object.keys(launchers);
    var chunks = [].concat.apply([], chunkNames.map(function (c, i) {
      return i % 3 ? [] : [ chunkNames.slice(i, i + 3) ];
    }));

    // console.log(chunks);
    chunks.forEach(function (c, i) {
      grunt.config('karma.sauce-' + i, {
        background: false,
        singleRun: true,
        // reporters: ['saucelabs', 'coverage'],
        reporters: ['saucelabs'],
        browsers: c
        // preprocessors: {
        //   'src/**/!(*.spec)+(.js)': ['coverage']
        // },
        // coverageReporter: {
        //   type: 'lcov',
        //   dir:  'coverage',
        //   subdir: '.'
        // }
      });
    });

    // console.log('tasks', chunks.map(function(c, i) { return 'karma:sauce-' + i }));

    grunt.config('serialsauce', chunks.map(function(c, i) { return 'karma:sauce-' + i }));
  },

  updateConfig: function() {
    grunt.config('customLaunchers', util.customLaunchers());
    util.createKarmangularConfig()
    util.createSauceConfig();

    if (process.env.TRAVIS) {
      // Update the config for the gh-pages task for it pushes changes as the user: Grud
      grunt.config('gh-pages.ui-grid-site.options.user', {
        name: 'grud',
        email: 'nggridteam@gmail.com'
      });

      grunt.config('gh-pages.ui-grid-site.options.repo', 'https://' + process.env.GITHUB_NAME + ':' + process.env.GITHUB_PASS + '@github.com/angular-ui/ui-grid.info.git');

      grunt.config('gh-pages.bower.options.user', {
        name: 'grud',
        email: 'nggridteam@gmail.com'
      });

      grunt.config('gh-pages.bower.options.repo', 'https://' + process.env.GITHUB_NAME + ':' + process.env.GITHUB_PASS + '@github.com/angular-ui/bower-ui-grid.git');
    }
  },

  // Return the tag for the current commit at HEAD if there is one, null if there isn't
  getCurrentTag: function() {
    var out = shell.exec('git tag -l --points-at HEAD', {silent:true});

    return out.output.trim();
  },

  // Get the current release version
  getVersion: function() {
    // Try to get a tag for the current version
    var out = shell.exec('git tag -l --points-at HEAD', {silent:true});

    var version, tag;

    // If there's a tag on this commit, use it as the version
    if (out.code === 0 && out.output.trim() !== '' && out.output.trim() !== null) {
      version = out.output.trim();
      tag = version;
    }
    // ...otherwise, get the most recent stable tag
    else {
      var hash;

      // If there isn't one then just get the most recent tag, whatever it is
      version = shell.exec('git rev-list --tags --max-count=1 | xargs git describe', {silent:true}).output.trim();

      // Get the short commit hash from the current commit to append to the most recent tag
      hash = shell.exec('git rev-parse --short HEAD', {silent:true}).output.trim();

      version = version + '-' + hash;

      tag = version;
    }

    tag = semver.clean(tag);

    return tag;
  },

  getStableVersion: function() {
    var cmd = 'git log --date-order --graph --tags --simplify-by-decoration --pretty=format:\"%ai %h %d\"';
    // grunt.log.writeln(cmd);
    var out = shell.exec(cmd, {silent:true}).output;

    // grunt.log.writeln(lines);

    var lines = out.split('\n');
    for (var i in lines) {
      var l = lines[i];

      var match = l.match(/\(.*?tag: (.+?)(\)|,)/);
      if (! match || match.length < 2 || !match[1]) { continue; }
      var tag = match[1];

      var v = semver.clean(tag);

      if (!v.match(/-.+?$/)) {
        return v;
      }
    }
  },

  travisFoldStart: function (msg) {
    if (!msg) { return; }
    grunt.log.writeln('travis_fold:start:' + msg);
  },

  travisFoldEnd: function (msg) {
    if (!msg) { return; }
    grunt.log.writeln('travis_fold:end:' + msg);
  }
};
<commit_msg>chore(sauce labs): Disabling android builds to fix the main build. (#6036)<commit_after>var fs = require('fs');
var path = require('path');
var grunt = require('grunt');
var semver = require('semver');
var shell = require('shelljs');

// Get the list of angular files (angular.js, angular-mocks.js, etc)
var cachedAngularFiles = grunt.file.readJSON('lib/test/angular/files.json');

var util = module.exports = {

  testDependencies: {
    unit: ['bower_components/jquery/jquery.min.js', 'lib/test/jquery.simulate.js','lib/test/classList.polyFill.js', 'dist/release/ui-grid.css', 'bower_components/lodash/dist/lodash.min.js', 'bower_components/csv-js/csv.js']
  },

  testFiles: {
    unit: ['src/js/core/bootstrap.js', 'src/js/**/*.js', 'test/unit/**/*.spec.js', 'src/features/*/js/**/*.js', 'src/features/*/test/**/*.spec.js', '.tmp/template.js'],
    core_unit: ['src/js/core/bootstrap.js', 'src/js/**/*.js', 'test/unit/**/*.spec.js', 'src/features/*/js/**/*.js', '.tmp/template.js'],
  },
  testFilesFeature: function(featureName){
    var featurePattern = 'src/features/' + featureName +'/test/**/*.spec.js';

    return {
      unit: ['src/js/core/bootstrap.js', 'src/js/**/*.js', 'test/unit/**/*.spec.js', 'src/features/*/js/**/*.js', featurePattern, '.tmp/template.js'],
      core_unit: util.testDependencies.unit.core_unit
    };
  },

  // Return a list of angular files for a specific version
  angularFiles: function (version) {
    if (version === 'latest') {
      version = util.latestAngular();
    }

    // Start with our test files
    var retFiles = []; //grunt.template.process('<%= karma.options.files %>').split(",");

    cachedAngularFiles.forEach(function(f) {
      var filePath = path.join('lib', 'test', 'angular', version, f);

      if (! fs.existsSync(filePath)) {
        grunt.fatal("Angular file " + filePath + " doesn't exist");
      }

      retFiles.push(filePath);
    });

    return retFiles;
  },

  startKarma: function(config, singleRun, done){
    var browsers = grunt.option('browsers');
    var reporters = grunt.option('reporters');
    var noColor = grunt.option('no-colors');
    var port = grunt.option('port');
    var p = spawn('node', ['node_modules/karma/bin/karma', 'start', config,
      singleRun ? '--single-run=true' : '',
      reporters ? '--reporters=' + reporters : '',
      browsers ? '--browsers=' + browsers : '',
      noColor ? '--no-colors' : '',
      port ? '--port=' + port : ''
    ]);
    p.stdout.pipe(process.stdout);
    p.stderr.pipe(process.stderr);
    p.on('exit', function(code){
      if(code !== 0) grunt.fail.warn("Karma test(s) failed. Exit code: " + code);
      done();
    });
  },

  customLaunchers: function() {
    return {
      'SL_Chrome': {
        base: 'SauceLabs',
        browserName: 'chrome'
      },
      'SL_Firefox': {
        base: 'SauceLabs',
        browserName: 'firefox'
      },
      'SL_Safari_5': {
        base: 'SauceLabs',
        browserName: 'safari',
        version: '5'
      },
      'SL_Safari_6': {
        base: 'SauceLabs',
        browserName: 'safari',
        platform: 'Mac 10.8',
        version: '6'
      },
      'SL_Safari_7': {
        base: 'SauceLabs',
        browserName: 'safari',
        platform: 'Mac 10.9',
        version: '7'
      },
      // 'SL_IE_8_XP': {
      //   base: 'SauceLabs',
      //   browserName: 'internet explorer',
      //   platform: 'Windows XP',
      //   version: '8'
      // },
      // 'SL_IE_8': {
      //   base: 'SauceLabs',
      //   browserName: 'internet explorer',
      //   platform: 'Windows 7',
      //   version: '8'
      // },
      'SL_IE_9': {
        base: 'SauceLabs',
        browserName: 'internet explorer',
        platform: 'Windows 7',
        version: '9',
        'X-UA-Compatible': 'IE=edge,chrome=1'
      },
      'SL_IE_10': {
        base: 'SauceLabs',
        browserName: 'internet explorer',
        platform: 'Windows 7',
        version: '10'
      },
      'SL_IE_11': {
        base: 'SauceLabs',
        browserName: 'internet explorer',
        platform: 'Windows 8.1',
        version: '11'
      },

      // NOTE (mportuga): Currently android keeps failing. It might be a change to Sauce Labs to use Appium instead of selenium
      // 'SL_Android_4.4': {
      //   base: 'SauceLabs',
      //   browserName: 'android',
      //   platform: 'Linux',
      //   version: '4.4'
      // },
      // 'SL_Android_5.0': {
      //   base: 'SauceLabs',
      //   browserName: 'android',
      //   platform: 'Linux',
      //   version: '5.0'
      // },
      'SL_Linux_Opera': {
        base: 'SauceLabs',
        browserName: 'opera',
        platform: 'Linux',
        version: '12'
      },

      // NOTE (c0bra): Currently both iOS 6 and 7 will run (w/ a 45 second activity timeout) and the tests pass, but after that the session just hangs indefinitely -- 20140320
      // 'SL_iOS_6': {
      //   base: 'SauceLabs',
      //   browserName: 'iphone',
      //   platform: 'OS X 10.8',
      //   version: '6.0'
      // },
      // 'SL_iOS_7': {
      //   base: 'SauceLabs',
      //   browserName: 'iphone',
      //   platform: 'OS X 10.9',
      //   version: '7.0'
      // }
    };
  },

  //
  browsers: function() {

  },

  angulars: function() {
    var angularLib = path.join('lib', 'test', 'angular');

    // Loop over all the files in the angular testlib directory
    var files = fs.readdirSync(angularLib);

    // For each file found, make sure it's a directory...
    var versions = [];
    files.forEach(function(file) {
      var dir = path.join(angularLib, file);
      if (! fs.lstatSync(dir).isDirectory()) return;

      if (! semver.valid(file)) return;

      versions.push(file);
    });

    return versions;
  },

  latestAngular: function() {
    function sortFn(a,b) {
      return semver.gt(b, a);
    };

    // For each file found, make sure it's a directory...
    var versions = util.angulars();

    return versions.sort(sortFn)[0];
  },

  /* Read in whatever angular versions are in lib/test/angular and register karma configs for them all! */
  createKarmangularConfig: function() {
    if (grunt.option('fast')){
      var versions = [util.latestAngular()];
    } else {
      // For each file found, make sure it's a directory...
      var versions = grunt.option('angular') ? grunt.option('angular').split(/,/) : null || util.angulars();
    }

    if (grunt.option('angular')) {
      if (grunt.option('angular') === 'latest') {
        versions = [util.latestAngular()];
      }

      grunt.log.writeln("Using angular " + grunt.util.pluralize(versions, "version/versions") + ": " + versions.join(', '));
    }

    versions.forEach(function (version) {
      // .. then create a karma config for it!
      var karmaConfigName = 'angular-' + grunt.config.escape(version);

      if (grunt.option('core') || grunt.option('fast')){
        grunt.config('karma.' + karmaConfigName, {
          options: {
            files: util.testDependencies.unit
              .concat(util.angularFiles(version)
              .concat(util.testFiles.core_unit))
          }
        });
      } else if ( grunt.option('feature') ){
        grunt.config('karma.' + karmaConfigName, {
          options: {
            files: util.testDependencies.unit
              .concat(util.angularFiles(version)
              .concat(util.testFilesFeature(grunt.option('feature')).unit))
          }
        });
      } else {
        grunt.config('karma.' + karmaConfigName, {
          options: {
            files: util.testDependencies.unit
              .concat(util.angularFiles(version)
                .concat(util.testFiles.unit))
          }
        });
      }
    });
  },

  // Take the SauceLabs browsers from the karma config file and split them into groups of 3
  createSauceConfig: function() {
    var launchers = util.customLaunchers();

    var chunkNames = Object.keys(launchers);
    var chunks = [].concat.apply([], chunkNames.map(function (c, i) {
      return i % 3 ? [] : [ chunkNames.slice(i, i + 3) ];
    }));

    // console.log(chunks);
    chunks.forEach(function (c, i) {
      grunt.config('karma.sauce-' + i, {
        background: false,
        singleRun: true,
        // reporters: ['saucelabs', 'coverage'],
        reporters: ['saucelabs'],
        browsers: c
        // preprocessors: {
        //   'src/**/!(*.spec)+(.js)': ['coverage']
        // },
        // coverageReporter: {
        //   type: 'lcov',
        //   dir:  'coverage',
        //   subdir: '.'
        // }
      });
    });

    // console.log('tasks', chunks.map(function(c, i) { return 'karma:sauce-' + i }));

    grunt.config('serialsauce', chunks.map(function(c, i) { return 'karma:sauce-' + i }));
  },

  updateConfig: function() {
    grunt.config('customLaunchers', util.customLaunchers());
    util.createKarmangularConfig()
    util.createSauceConfig();

    if (process.env.TRAVIS) {
      // Update the config for the gh-pages task for it pushes changes as the user: Grud
      grunt.config('gh-pages.ui-grid-site.options.user', {
        name: 'grud',
        email: 'nggridteam@gmail.com'
      });

      grunt.config('gh-pages.ui-grid-site.options.repo', 'https://' + process.env.GITHUB_NAME + ':' + process.env.GITHUB_PASS + '@github.com/angular-ui/ui-grid.info.git');

      grunt.config('gh-pages.bower.options.user', {
        name: 'grud',
        email: 'nggridteam@gmail.com'
      });

      grunt.config('gh-pages.bower.options.repo', 'https://' + process.env.GITHUB_NAME + ':' + process.env.GITHUB_PASS + '@github.com/angular-ui/bower-ui-grid.git');
    }
  },

  // Return the tag for the current commit at HEAD if there is one, null if there isn't
  getCurrentTag: function() {
    var out = shell.exec('git tag -l --points-at HEAD', {silent:true});

    return out.output.trim();
  },

  // Get the current release version
  getVersion: function() {
    // Try to get a tag for the current version
    var out = shell.exec('git tag -l --points-at HEAD', {silent:true});

    var version, tag;

    // If there's a tag on this commit, use it as the version
    if (out.code === 0 && out.output.trim() !== '' && out.output.trim() !== null) {
      version = out.output.trim();
      tag = version;
    }
    // ...otherwise, get the most recent stable tag
    else {
      var hash;

      // If there isn't one then just get the most recent tag, whatever it is
      version = shell.exec('git rev-list --tags --max-count=1 | xargs git describe', {silent:true}).output.trim();

      // Get the short commit hash from the current commit to append to the most recent tag
      hash = shell.exec('git rev-parse --short HEAD', {silent:true}).output.trim();

      version = version + '-' + hash;

      tag = version;
    }

    tag = semver.clean(tag);

    return tag;
  },

  getStableVersion: function() {
    var cmd = 'git log --date-order --graph --tags --simplify-by-decoration --pretty=format:\"%ai %h %d\"';
    // grunt.log.writeln(cmd);
    var out = shell.exec(cmd, {silent:true}).output;

    // grunt.log.writeln(lines);

    var lines = out.split('\n');
    for (var i in lines) {
      var l = lines[i];

      var match = l.match(/\(.*?tag: (.+?)(\)|,)/);
      if (! match || match.length < 2 || !match[1]) { continue; }
      var tag = match[1];

      var v = semver.clean(tag);

      if (!v.match(/-.+?$/)) {
        return v;
      }
    }
  },

  travisFoldStart: function (msg) {
    if (!msg) { return; }
    grunt.log.writeln('travis_fold:start:' + msg);
  },

  travisFoldEnd: function (msg) {
    if (!msg) { return; }
    grunt.log.writeln('travis_fold:end:' + msg);
  }
};
<|endoftext|>


<commit_before>"use strict";

// Disable pending items / Fix focus for docked tree-view
atom.workspace.onDidAddPaneItem(event => {
	const {pane} = event;
	if(!atom.config.get("user.enable-pending-items"))
		pane.setPendingItem(null);
	pane.focus();
});

// Match brackets inside regular expressions and CSON strings
const BracketMatcher = loadFromCore("bracket-matcher/lib/bracket-matcher-view");
const {isScopeCommentedOrString} = BracketMatcher.prototype;
BracketMatcher.prototype.isScopeCommentedOrString = function(...args){
	if(args[0].some(scopeList => /^string\.quoted.*?\.coffee$/.test(scopeList))
	|| args[0].some(scopeList => /^string\b.*?\.regexp(?:$|\.)/.test(scopeList)
	&& args[0].some(scopeList => scopeList.split(".").includes("string"))))
		return false;
	return isScopeCommentedOrString.call(this, ...args);
};

// Increase token limit
loadGrammar("source.js").then(js => js.maxTokensPerLine = 500);

// Define custom filetypes without upsetting File Icons
const customTypes = {
	"source.js":   ["cjs", "jsx"],
	"source.json": ["css.map", "js.map", "mjs.map", "terserrc", "nycrc", "c8rc", "hintrc"],
};
for(const scope in customTypes)
	loadGrammar(scope).then(grammar => customTypes[scope].map(ext => {
		grammar.fileTypes.push(ext);
		for(const ed of atom.textEditors.editors)
			(ed.getFileName() || "").endsWith("." + ext) && ed.setGrammar(grammar);
	}));

// Fix idiotic and/or conflicting filetype associations
const fixGrammars = {
	"source.shell": ["install"],
	"source.erlang.config": ["app", "config"],
	"text.generic-config": [".config/git/ignore", ".git/info/exclude", "gitattributes", "gitignore", "hgignore", "stylelintignore"],
	"text.html.php": ["install", "profile", "module", "inc"],
	"text.xml": ["svg"],
};
for(const scope in fixGrammars)
	loadGrammar(scope).then(grammar => {
		grammar.fileTypes = grammar.fileTypes.filter(type => {
			return !fixGrammars[scope].includes(type);
		});
	});

// Wipe junk <template/> elements added to <body> after a notification
atom.notifications.onDidAddNotification(note => {
	for(const el of document.querySelectorAll("body > template"))
		document.body.removeChild(el);
});

// Remind grammar-selector I don't give a fuck about tree-shitter
const {getGrammars} = atom.grammars;
atom.grammars.getGrammars = function(params){
	return getGrammars.call(this, {...params, includeTreeSitter: false});
};

// Exclude subdirectories in ~/.atom/packages which *aren't* packages…
const PackageList = loadFromCore("settings-view/lib/list.js");
const {setItems} = PackageList.prototype;
PackageList.prototype.setItems = function(items){
	items = items.filter(item => "patches" !== item.name);
	return setItems.call(this, items);
};

// Force Java to be listed after JavaScript in the grammar-selector
loadGrammar("source.java").then(java => java.name = `\x7F${java.name}`);

// Force `.npmrc` files to use proper grammar instead of INI
atom.workspace.observeTextEditors(ed => {
	if(/^\.?npmrc$/i.test(ed.getFileName()))
		ed.setGrammar(atom.grammars.grammarForId("source.ini.npmrc"));
});

// Purge context-menus of commands I rarely/never use
for(const {items, selector} of atom.contextMenu.itemSets)
	for(let i = items.length - 1; i >= 0; --i){
		const {command} = items[i];
		if(/.tree-view/.test(selector) && "split-diff:enable" === command
		|| /^tree-view:(duplicate|open-selected-entry-\w+)$/.test(command)
		|| /^pane:split-\w+-and-copy-active-item$/.test(command))
			items.splice(i, 1);
	}

// Tidy config to reduce diff-noise
const stringLists = [
	"core.disabledPackages",
	"markdown-preview.grammars",
	"spell-check.grammars",
];
for(const key of stringLists){
	const currentValue = atom.config.get(key);
	const sortedValue = [...new Set(currentValue)].sort();
	if(currentValue.join("\n") !== sortedValue.join("\n"))
		atom.config.set(key, sortedValue);
}

// Delete settings which aren't meant to linger around
const ephemeralKeys = ["user:enable-pending-items"];
for(const keyPath of ephemeralKeys){
	if(undefined !== atom.config.getRawValue(keyPath))
		atom.config.unset(keyPath);
}

// Fix TypeError thrown when reloading window
for(const key of atom.blobStore.inMemoryBlobs.keys())
	if(atom.blobStore.usedKeys.has(key) && !atom.blobStore.getFromMemory(key))
		atom.blobStore.delete(key);
<commit_msg>Check for `fileTypes` array before attacking it<commit_after>"use strict";

// Disable pending items / Fix focus for docked tree-view
atom.workspace.onDidAddPaneItem(event => {
	const {pane} = event;
	if(!atom.config.get("user.enable-pending-items"))
		pane.setPendingItem(null);
	pane.focus();
});

// Match brackets inside regular expressions and CSON strings
const BracketMatcher = loadFromCore("bracket-matcher/lib/bracket-matcher-view");
const {isScopeCommentedOrString} = BracketMatcher.prototype;
BracketMatcher.prototype.isScopeCommentedOrString = function(...args){
	if(args[0].some(scopeList => /^string\.quoted.*?\.coffee$/.test(scopeList))
	|| args[0].some(scopeList => /^string\b.*?\.regexp(?:$|\.)/.test(scopeList)
	&& args[0].some(scopeList => scopeList.split(".").includes("string"))))
		return false;
	return isScopeCommentedOrString.call(this, ...args);
};

// Increase token limit
loadGrammar("source.js").then(js => js.maxTokensPerLine = 500);

// Define custom filetypes without upsetting File Icons
const customTypes = {
	"source.js":   ["cjs", "jsx"],
	"source.json": ["css.map", "js.map", "mjs.map", "terserrc", "nycrc", "c8rc", "hintrc"],
};
for(const scope in customTypes)
	loadGrammar(scope).then(grammar => customTypes[scope].map(ext => {
		if(!grammar || !grammar.fileTypes) return;
		grammar.fileTypes.push(ext);
		for(const ed of atom.textEditors.editors)
			(ed.getFileName() || "").endsWith("." + ext) && ed.setGrammar(grammar);
	}));

// Fix idiotic and/or conflicting filetype associations
const fixGrammars = {
	"source.shell": ["install"],
	"source.erlang.config": ["app", "config"],
	"text.generic-config": [".config/git/ignore", ".git/info/exclude", "gitattributes", "gitignore", "hgignore", "stylelintignore"],
	"text.html.php": ["install", "profile", "module", "inc"],
	"text.xml": ["svg"],
};
for(const scope in fixGrammars)
	loadGrammar(scope).then(grammar => {
		grammar.fileTypes = grammar.fileTypes.filter(type => {
			return !fixGrammars[scope].includes(type);
		});
	});

// Wipe junk <template/> elements added to <body> after a notification
atom.notifications.onDidAddNotification(note => {
	for(const el of document.querySelectorAll("body > template"))
		document.body.removeChild(el);
});

// Remind grammar-selector I don't give a fuck about tree-shitter
const {getGrammars} = atom.grammars;
atom.grammars.getGrammars = function(params){
	return getGrammars.call(this, {...params, includeTreeSitter: false});
};

// Exclude subdirectories in ~/.atom/packages which *aren't* packages…
const PackageList = loadFromCore("settings-view/lib/list.js");
const {setItems} = PackageList.prototype;
PackageList.prototype.setItems = function(items){
	items = items.filter(item => "patches" !== item.name);
	return setItems.call(this, items);
};

// Force Java to be listed after JavaScript in the grammar-selector
loadGrammar("source.java").then(java => java.name = `\x7F${java.name}`);

// Force `.npmrc` files to use proper grammar instead of INI
atom.workspace.observeTextEditors(ed => {
	if(/^\.?npmrc$/i.test(ed.getFileName()))
		ed.setGrammar(atom.grammars.grammarForId("source.ini.npmrc"));
});

// Purge context-menus of commands I rarely/never use
for(const {items, selector} of atom.contextMenu.itemSets)
	for(let i = items.length - 1; i >= 0; --i){
		const {command} = items[i];
		if(/.tree-view/.test(selector) && "split-diff:enable" === command
		|| /^tree-view:(duplicate|open-selected-entry-\w+)$/.test(command)
		|| /^pane:split-\w+-and-copy-active-item$/.test(command))
			items.splice(i, 1);
	}

// Tidy config to reduce diff-noise
const stringLists = [
	"core.disabledPackages",
	"markdown-preview.grammars",
	"spell-check.grammars",
];
for(const key of stringLists){
	const currentValue = atom.config.get(key);
	const sortedValue = [...new Set(currentValue)].sort();
	if(currentValue.join("\n") !== sortedValue.join("\n"))
		atom.config.set(key, sortedValue);
}

// Delete settings which aren't meant to linger around
const ephemeralKeys = ["user:enable-pending-items"];
for(const keyPath of ephemeralKeys){
	if(undefined !== atom.config.getRawValue(keyPath))
		atom.config.unset(keyPath);
}

// Fix TypeError thrown when reloading window
for(const key of atom.blobStore.inMemoryBlobs.keys())
	if(atom.blobStore.usedKeys.has(key) && !atom.blobStore.getFromMemory(key))
		atom.blobStore.delete(key);
<|endoftext|>


<commit_before>var utils = require('../lib/utils')

var getChildren = utils.getChildren
var inTile = utils.inTile
var toObject = utils.toObject

var depth = 4
var maxtiles = Math.pow(4, depth)

module.exports = function (data, tile, writeData, done) {
  var features = data.mexico.osm.features
  var haveHighway = {}

  for (var i = 0, j = features.length; i < j; i++) {
    var feature = features[i]
    if (feature.properties.highway) {
      // Break loop if we already found features in all tiles
      var found = Object.keys(haveHighway)
      if (found.length === maxtiles) break

      // Get tiles containing a feature, skipping known tiles
      var tiles = getChildren(tile, depth)
        .map(JSON.stringify)
        .filter(tile => !haveHighway[tile])
        .filter(tile => inTile(feature, JSON.parse(tile)))

      // Update results map
      if (tiles.length) Object.assign(haveHighway, toObject(tiles))
    }
  }

  done(null, Object.keys(haveHighway))
}
<commit_msg>Remove unused var<commit_after>var utils = require('../lib/utils')

var getChildren = utils.getChildren
var inTile = utils.inTile
var toObject = utils.toObject

var depth = 4
var maxtiles = Math.pow(4, depth)

module.exports = function (data, tile, writeData, done) {
  var features = data.mexico.osm.features
  var haveHighway = {}

  for (var i = 0, j = features.length; i < j; i++) {
    var feature = features[i]
    if (feature.properties.highway) {
      // Break loop if we already found features in all tiles
      if (Object.keys(haveHighway).length === maxtiles) break

      // Get tiles containing a feature, skipping known tiles
      var tiles = getChildren(tile, depth)
        .map(JSON.stringify)
        .filter(tile => !haveHighway[tile])
        .filter(tile => inTile(feature, JSON.parse(tile)))

      // Update results map
      if (tiles.length) Object.assign(haveHighway, toObject(tiles))
    }
  }

  done(null, Object.keys(haveHighway))
}
<|endoftext|>


<commit_before>/*
 * heap-server
 * https://github.com/anthonyringoet/heap-server
 *
 * Copyright (c) 2014 Anthony Ringoet
 * Licensed under the MIT license.
 */

'use strict';

var xtend = require('xtend');
var request = require('request')

module.exports = Heap;

function Heap(id, debug) {
  if (!(this instanceof Heap)) return new Heap(id);
  if (!id) throw new TypeError('An api token is required');
  this.remote = 'https://heapanalytics.com/api/';
  this.config = {
    'app_id': id
  };
  this.debug = debug;
}

Heap.prototype.push = function(data, callback) {
  var result = xtend(this.config, data);

  if(result.event){
    this.remote = this.remote + 'track';
  }
  else{
    this.remote = this.remote + 'identify';
  }

  var options = {
    url: this.remote,
    json: true,
    method: 'POST',
    body: result
  }

  request(options, function(error, response, body){
    if(error || response.statusCode != 200){
      if(this.debug){
        console.log(error);
      }
      if(callback){
        callback(true);
      }
    }
    else{
      if(callback){
        callback(false, body);
      }
    }
  });
};<commit_msg>bug fix for repeat invocations appending identify/track<commit_after>/*
 * heap-server
 * https://github.com/anthonyringoet/heap-server
 *
 * Copyright (c) 2014 Anthony Ringoet
 * Licensed under the MIT license.
 */

'use strict';

var xtend = require('xtend');
var request = require('request')
var HEAP_URL = 'https://heapanalytics.com/api/';

module.exports = Heap;

function Heap(id, debug) {
  if (!(this instanceof Heap)) return new Heap(id);
  if (!id) throw new TypeError('An api token is required');
  this.config = {
    'app_id': id
  };
  this.debug = debug;
}

Heap.prototype.push = function(data, callback) {
  var result = xtend(this.config, data);

  if(result.event){
    this.remote = HEAP_URL + 'track';
  }
  else{
    this.remote = HEAP_URL + 'identify';
  }

  var options = {
    url: this.remote,
    json: true,
    method: 'POST',
    body: result
  }

  request(options, function(error, response, body){
    if(error || response.statusCode != 200){
      if(this.debug){
        console.log(error);
      }
      if(callback){
        callback(true);
      }
    }
    else{
      if(callback){
        callback(false, body);
      }
    }
  });
};
<|endoftext|>