<commit_before>i18n = {
  t: function (str, options) {
    return TAPi18n.__(str, options);
  }
};

getIncomingComments = function (selector) {
  var userId = Meteor.userId();
  var controller = getCurrentController();

  if (!userId || !controller) return [];

  var runAt = controller._runAt;
  selector.createdAt = { $gt: runAt };
  selector.userId = userId;

  return Comments.find(selector, { sort: { 'createdAt': -1 } }).fetch();
};
getComments = function (selector) {
  var controller = getCurrentController();
  if (!controller) return [];
  if (_.has(selector, 'userId')) delete selector.userId;

  var runAt = controller._runAt;
  selector.createdAt = { $lt: runAt };
  return Comments.find(selector, { sort: { 'initScore': -1 } }).fetch();
};

getSiteUrl = function () {
  return Meteor.absoluteUrl();
};
getCurrentController = function () {
  return Router && Router.current();
};
getCurrentRoute = function () {
  var controller = getCurrentController();
  return controller.url;
};
getCurrentParams = function () {
  var controller = getCurrentController();
  return controller && controller.getParams();
};
getCurrentQuery = function () {
  var params = getCurrentParams();
  return params && params.query;
};
getCurrentHash = function () {
  var params = getCurrentParams();
  return params && params.hash;
};
getSettingsUrl = function () {
  return Router.routes['settings'].url();
};
getTopicRoute = function (topicId, commentId) {
  return Router.routes['topic'].path({ '_id': topicId });
};
getTopicUrl = function (topicId, commentId) {
  return Router.routes['topic'].url({ '_id': topicId });
};
getCommentRoute = function (topicId, commentId) {
  return Router.routes['comment'].path({
    '_id': topicId,
    'commentId': commentId
  });
};
getCommentUrl = function (topicId, commentId) {
  return Router.routes['comment'].path({
    '_id': topicId,
    'commentId': commentId
  });
};
getProfileRoute = function (userId, tab) {
  if (typeof tab !== 'undefined') {
    var query = { 'query': { 'tab': tab } };
  }
  return Router.routes['profile'].path({ '_id': userId }, query);
};
getProfileUrl = function (userId, tab) {
  if (typeof tab !== 'undefined') {
    var query = { 'query': { 'tab': tab } };
  }
  return Router.routes['profile'].url({ '_id': userId }, query);
};
getInviteUrl = function (inviterId, inviteCode) {
  return Router.routes['invite'].url({}, {
    'query': {
      'inviter_id': inviterId,
      'invite_code': inviteCode
    }
  });
};

getScore = function (options) {
  check(options, { votes: Number, createdAt: Date });

  var votes = options.votes;
  var order = Math.log(Math.max(votes, 1)) / Math.LN10;
  var age = options.createdAt / 1000 - 1134028003;

  return (order + age / 45000).toFixed(7);
};
getCommentScore = function (comment) {
  check(comment, Match.ObjectIncluding({ upvotes: Number, createdAt: Date }));
  return getScore({ votes: comment.upvotes, createdAt: comment.createdAt });
};
getTopicScore = function (topic) {
  check(topic, Match.ObjectIncluding({ pro: Number, con: Number, createdAt: Date }));
  return getScore({ votes: topic.pro + topic.con, createdAt: topic.createdAt });
};

/**
 * Takes a string in camel case format and returns
 * the string with spaces and capitalization
 */
camelToTitle = function (str) {
  return str && capitalize(str.replace(/([a-z])([A-Z])/g, '$1 $2'));
};

capitalize = function (string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
};

// fadeElement = function ($elem) {
//   if ($elem.css('opacity') > 0) {
//     $elem.velocity('fadeOut', { duration: 1000, complete: function () {
//       $(this).html('');
//     }});
//   }
// };

/**
 * Sets the property 'property' of object 'obj'
 * to value 'value'
 */
setProperty = function (obj, property, value) {
  obj = obj || {};
  obj[property] = value;
  return obj;
};

getProperty = function (obj, path) {
  var path = path.split('.');
  for (var i = 0, len = path.length; i < len; i++)
    obj = obj && obj[path[i]];
  return obj;
};

// http://stackoverflow.com/questions/7793811/convert-javascript-dot-notation-object-to-nested-object
getObject = function (o) {
  var oo = {}, t, parts, part;
  for (var k in o) {
    t = oo;
    parts = k.split('.');
    var key = parts.pop();
    while (parts.length) {
      part = parts.shift();
      t = t[part] = t[part] || {};
    }
    t[key] = o[k]
  }
  return oo;
};

scrollToId = function (id) {
  // ensure that dom is ready first
  Tracker.afterFlush(function () {
    var $comment = $('#' + id);
    if (!$comment || !$comment.length) return;

    $comment
      .velocity('scroll', { 'duration': 500, 'offset': -63 })
      .addClass('bg-fade');

    setTimeout(function() {
      $comment.removeClass('bg-fade');
    }, 2000);
  });
};

validName = function (s) {
  var s = s && stripHTML(s).trim();
  return !!s && /^([a-zA-Z]+[a-zA-Z0-9.'-\s]*){3,25}$/.test(s);
};

validInput = function (s, len) {
  var len = len || 8;
  var s = s && stripSpaces(stripHTML(s));
  return !!s && s.length >= len;
};

sanitize = function (s) {
  if (Meteor.isServer) {
    var s = sanitizeHtml(s, {
      allowedTags: [
        'p', 'a', 'b', 'i', 'strong',
        'em', 'strike', 'code', 'pre'
      ]
    });
  }
  return s;
};

stripHTML = function (s) {
  return s.replace(/<(?:.|\n)*?>/gm, '');
};

stripMarkdown = function (s) {
  var html_body = marked(s);
  return stripHTML(html_body);
};

// Strips any form of whitespace, including spaces and newlines
stripSpaces = function (s) {
  return s.replace(/\s| /gm, '');
};

/**
 * Takes a javascript Date object
 * If the date is over a week ago,
 * Returns the date in month/day/year format
 * Otherwise, returns 'x time ago'
 */
formatDate = function (date) {
  if (!date) return;

  var then = date.getTime();
  var now  = new Date().getTime();
  var weekInMilliseconds = 604800000;

  if (now - then > weekInMilliseconds) {
    return moment(date).format('D MMM YYYY');
  }
  return moment(date).fromNow();
};

formatError = function (error) {
  return error.reason;
};

<commit_msg>Add markdownToHTML helper to sanitize and parse markdown<commit_after>i18n = {
  t: function (str, options) {
    return TAPi18n.__(str, options);
  }
};

getIncomingComments = function (selector) {
  var userId = Meteor.userId();
  var controller = getCurrentController();

  if (!userId || !controller) return [];

  var runAt = controller._runAt;
  selector.createdAt = { $gt: runAt };
  selector.userId = userId;

  return Comments.find(selector, { sort: { 'createdAt': -1 } }).fetch();
};
getComments = function (selector) {
  var controller = getCurrentController();
  if (!controller) return [];
  if (_.has(selector, 'userId')) delete selector.userId;

  var runAt = controller._runAt;
  selector.createdAt = { $lt: runAt };
  return Comments.find(selector, { sort: { 'initScore': -1 } }).fetch();
};

getSiteUrl = function () {
  return Meteor.absoluteUrl();
};
getCurrentController = function () {
  return Router && Router.current();
};
getCurrentRoute = function () {
  var controller = getCurrentController();
  return controller.url;
};
getCurrentParams = function () {
  var controller = getCurrentController();
  return controller && controller.getParams();
};
getCurrentQuery = function () {
  var params = getCurrentParams();
  return params && params.query;
};
getCurrentHash = function () {
  var params = getCurrentParams();
  return params && params.hash;
};
getSettingsUrl = function () {
  return Router.routes['settings'].url();
};
getTopicRoute = function (topicId, commentId) {
  return Router.routes['topic'].path({ '_id': topicId });
};
getTopicUrl = function (topicId, commentId) {
  return Router.routes['topic'].url({ '_id': topicId });
};
getCommentRoute = function (topicId, commentId) {
  return Router.routes['comment'].path({
    '_id': topicId,
    'commentId': commentId
  });
};
getCommentUrl = function (topicId, commentId) {
  return Router.routes['comment'].path({
    '_id': topicId,
    'commentId': commentId
  });
};
getProfileRoute = function (userId, tab) {
  if (typeof tab !== 'undefined') {
    var query = { 'query': { 'tab': tab } };
  }
  return Router.routes['profile'].path({ '_id': userId }, query);
};
getProfileUrl = function (userId, tab) {
  if (typeof tab !== 'undefined') {
    var query = { 'query': { 'tab': tab } };
  }
  return Router.routes['profile'].url({ '_id': userId }, query);
};
getInviteUrl = function (inviterId, inviteCode) {
  return Router.routes['invite'].url({}, {
    'query': {
      'inviter_id': inviterId,
      'invite_code': inviteCode
    }
  });
};

getScore = function (options) {
  check(options, { votes: Number, createdAt: Date });

  var votes = options.votes;
  var order = Math.log(Math.max(votes, 1)) / Math.LN10;
  var age = options.createdAt / 1000 - 1134028003;

  return (order + age / 45000).toFixed(7);
};
getCommentScore = function (comment) {
  check(comment, Match.ObjectIncluding({ upvotes: Number, createdAt: Date }));
  return getScore({ votes: comment.upvotes, createdAt: comment.createdAt });
};
getTopicScore = function (topic) {
  check(topic, Match.ObjectIncluding({ pro: Number, con: Number, createdAt: Date }));
  return getScore({ votes: topic.pro + topic.con, createdAt: topic.createdAt });
};

/**
 * Takes a string in camel case format and returns
 * the string with spaces and capitalization
 */
camelToTitle = function (str) {
  return str && capitalize(str.replace(/([a-z])([A-Z])/g, '$1 $2'));
};

capitalize = function (string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
};

// fadeElement = function ($elem) {
//   if ($elem.css('opacity') > 0) {
//     $elem.velocity('fadeOut', { duration: 1000, complete: function () {
//       $(this).html('');
//     }});
//   }
// };

/**
 * Sets the property 'property' of object 'obj'
 * to value 'value'
 */
setProperty = function (obj, property, value) {
  obj = obj || {};
  obj[property] = value;
  return obj;
};

getProperty = function (obj, path) {
  var path = path.split('.');
  for (var i = 0, len = path.length; i < len; i++)
    obj = obj && obj[path[i]];
  return obj;
};

// http://stackoverflow.com/questions/7793811/convert-javascript-dot-notation-object-to-nested-object
getObject = function (o) {
  var oo = {}, t, parts, part;
  for (var k in o) {
    t = oo;
    parts = k.split('.');
    var key = parts.pop();
    while (parts.length) {
      part = parts.shift();
      t = t[part] = t[part] || {};
    }
    t[key] = o[k]
  }
  return oo;
};

scrollToId = function (id) {
  // ensure that dom is ready first
  Tracker.afterFlush(function () {
    var $comment = $('#' + id);
    if (!$comment || !$comment.length) return;

    $comment
      .velocity('scroll', { 'duration': 500, 'offset': -63 })
      .addClass('bg-fade');

    setTimeout(function() {
      $comment.removeClass('bg-fade');
    }, 2000);
  });
};

validName = function (s) {
  var s = s && stripHTML(s).trim();
  return !!s && /^([a-zA-Z]+[a-zA-Z0-9.'-\s]*){3,25}$/.test(s);
};

validInput = function (s, len) {
  var len = len || 8;
  var s = s && stripSpaces(stripHTML(s));
  return !!s && s.length >= len;
};

sanitize = function (s) {
  if (Meteor.isServer) {
    var s = sanitizeHtml(s, {
      allowedTags: [
        'p', 'a', 'b', 'i', 'strong',
        'em', 'strike', 'code', 'pre'
      ]
    });
  }
  return s;
};

stripHTML = function (s) {
  return s && s.replace(/<(?:.|\n)*?>/gm, '');
};

stripMarkdown = function (s) {
  var html_body = marked(s);
  return stripHTML(html_body);
};

markdownToHTML = function (s) {
  return typeof s === 'string' && sanitize(marked(s));
};

// Strips any form of whitespace, including spaces and newlines
stripSpaces = function (s) {
  return s && s.replace(/\s| /gm, '');
};

/**
 * Takes a javascript Date object
 * If the date is over a week ago,
 * Returns the date in month/day/year format
 * Otherwise, returns 'x time ago'
 */
formatDate = function (date) {
  if (!date) return;

  var then = date.getTime();
  var now  = new Date().getTime();
  var weekInMilliseconds = 604800000;

  if (now - then > weekInMilliseconds) {
    return moment(date).format('D MMM YYYY');
  }
  return moment(date).fromNow();
};

formatError = function (error) {
  return error.reason;
};

<|endoftext|>


<commit_before>'use strict';

var util = require('util');

var helpers = {};

helpers.log = function log (input) {
  console.log(util.inspect(input, false, null));
};

helpers.propertySearch = function (haystack, needle, property) {
  var length = haystack.length,
      i;

  for (i = 0; i < length; i++) {
    if (haystack[i][property] === needle) {
      return i;
    }
  }
  return -1;
};

helpers.isEqual = function (a, b) {
  var startLine = a.start.line === b.start.line ? true : false,
      endLine = a.end.line === b.end.line ? true : false,
      type = a.type === b.type ? true : false,
      length = a.content.length === b.content.length ? true : false;

  if (startLine && endLine && type && length) {
    return true;
  }
  else {
    return false;
  }
};

helpers.isUnique = function (results, item) {
  var search = this.propertySearch(results, item.line, 'line');

  if (search === -1) {
    return true;
  }
  else if (results[search].column === item.column && results[search].message === item.message) {
    return false;
  }
  else {
    return true;
  }
};

helpers.addUnique = function (results, item) {
  if (this.isUnique(results, item)) {
    results.push(item);
  }
  return results;
};

helpers.sortDetects = function (a, b) {
  if (a.line < b.line) {
    return -1;
  }
  if (a.line > b.line) {
    return 1;
  }
  if (a.line === b.line) {
    if (a.column < b.column) {
      return -1;
    }
    if (a.column > b.column) {
      return 1;
    }
    return 0;
  }
  return 0;
};

helpers.isNumber = function (val) {
  if (isNaN(parseInt(val, 10))) {
    return false;
  }
  return true;
};

helpers.isUpperCase = function (str) {
  var pieces = str.split(''),
      i,
      result = 0;

  for (i = 0; i < pieces.length; i++) {
    if (!helpers.isNumber(pieces[i])) {
      if (pieces[i] === pieces[i].toUpperCase() && pieces[i] !== pieces[i].toLowerCase()) {
        result++;
      }
      else {
        return false;
      }
    }
  }
  if (result) {
    return true;
  }
  return false;
};

helpers.isLowerCase = function (str) {
  var pieces = str.split(''),
      i,
      result = 0;

  for (i = 0; i < pieces.length; i++) {
    if (!helpers.isNumber(pieces[i])) {
      if (pieces[i] === pieces[i].toLowerCase() && pieces[i] !== pieces[i].toUpperCase()) {
        result++;
      }
      else {
        return false;
      }
    }
  }
  if (result) {
    return true;
  }
  return false;
};

helpers.isValidHex = function (str) {
  if (str.match(/^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)) {
    return true;
  }
  return false;
};

module.exports = helpers;
<commit_msg>:art: Add helper functions to manage files<commit_after>'use strict';

var util = require('util'),
    fs = require('fs'),
    path = require('path'),
    yaml = require('js-yaml');

var helpers = {};

helpers.log = function log (input) {
  console.log(util.inspect(input, false, null));
};

helpers.propertySearch = function (haystack, needle, property) {
  var length = haystack.length,
      i;

  for (i = 0; i < length; i++) {
    if (haystack[i][property] === needle) {
      return i;
    }
  }
  return -1;
};

helpers.isEqual = function (a, b) {
  var startLine = a.start.line === b.start.line ? true : false,
      endLine = a.end.line === b.end.line ? true : false,
      type = a.type === b.type ? true : false,
      length = a.content.length === b.content.length ? true : false;

  if (startLine && endLine && type && length) {
    return true;
  }
  else {
    return false;
  }
};

helpers.isUnique = function (results, item) {
  var search = this.propertySearch(results, item.line, 'line');

  if (search === -1) {
    return true;
  }
  else if (results[search].column === item.column && results[search].message === item.message) {
    return false;
  }
  else {
    return true;
  }
};

helpers.addUnique = function (results, item) {
  if (this.isUnique(results, item)) {
    results.push(item);
  }
  return results;
};

helpers.sortDetects = function (a, b) {
  if (a.line < b.line) {
    return -1;
  }
  if (a.line > b.line) {
    return 1;
  }
  if (a.line === b.line) {
    if (a.column < b.column) {
      return -1;
    }
    if (a.column > b.column) {
      return 1;
    }
    return 0;
  }
  return 0;
};

helpers.isNumber = function (val) {
  if (isNaN(parseInt(val, 10))) {
    return false;
  }
  return true;
};

helpers.isUpperCase = function (str) {
  var pieces = str.split(''),
      i,
      result = 0;

  for (i = 0; i < pieces.length; i++) {
    if (!helpers.isNumber(pieces[i])) {
      if (pieces[i] === pieces[i].toUpperCase() && pieces[i] !== pieces[i].toLowerCase()) {
        result++;
      }
      else {
        return false;
      }
    }
  }
  if (result) {
    return true;
  }
  return false;
};

helpers.isLowerCase = function (str) {
  var pieces = str.split(''),
      i,
      result = 0;

  for (i = 0; i < pieces.length; i++) {
    if (!helpers.isNumber(pieces[i])) {
      if (pieces[i] === pieces[i].toLowerCase() && pieces[i] !== pieces[i].toUpperCase()) {
        result++;
      }
      else {
        return false;
      }
    }
  }
  if (result) {
    return true;
  }
  return false;
};

helpers.isValidHex = function (str) {
  if (str.match(/^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)) {
    return true;
  }
  return false;
};

helpers.loadConfigFile = function (dir, filename) {
  var filePath = path.join(__dirname, dir, filename),
      fileExtension = helpers.getFileExtension(filename),
      file = fs.readFileSync(filePath, 'utf8');

  if (fileExtension === 'yml') {
    return yaml.safeLoad(file);
  }
  else {
    return file;
  }
};

helpers.getFilename = function (filePath) {
  return filePath.split('/').pop().split('\\').pop();
};

helpers.getFileExtension = function (filename) {
  var lastIndex = filename.lastIndexOf('.');

  if (lastIndex < 1) {
    return false;
  }

  return filename.substr(lastIndex + 1);
};

module.exports = helpers;
<|endoftext|>


<commit_before>'use strict';

const { STATUS_CODES } = require('http');

const logger = require('./logger');
const config = require('../config/lib/helpers/response');
const helpers = require('./helpers/index');

// register helpers
Object.keys(helpers).forEach((helperName) => {
  module.exports[helperName] = helpers[helperName];
});

// TODO: Move functions below into lib/helpers/response.js

/**
 * Sends response with err code and message.
 *
 * @param  {Response} res
 * @param  {Error} err
 * @param  {Boolean} retry by default, errors should be retried by Blink
 */
module.exports.sendErrorResponse = function (res, err, retry = true) {
  const error = helpers.util.parseStatusAndMessageFromError(err);

  if (!retry) {
    exports.addNoRetryHeaders(res);
  }
  return this.sendResponseWithStatusCode(res, error.status, error.message);
};

module.exports.sendErrorResponseWithNoRetry = function (res, err) {
  return exports.sendErrorResponse(res, err, false);
};

/**
 * Sends response with custom status code and message
 *
 * @param  {Response} res
 * @param  {Number} code = 200
 * @param  {String} message = 'OK'
 */
module.exports.sendResponseWithStatusCode = function (res, code = 200, message) {
  // @see https://nodejs.org/api/http.html#http_http_status_codes
  const responseMessage = message || STATUS_CODES[code];
  const response = {
    message: responseMessage,
  };

  // log
  const logLevel = code < 400 ? 'debug' : 'error';
  logger[logLevel]('sendResponseWithStatusCode', { code, response }, res);

  helpers.analytics.addCustomAttributes({ gambitApiResponseMessage: responseMessage });
  return res.status(code).send(response);
};

/**
 * Sends response with Message.
 * @param {Request} req
 * @param {Message} message
 */
module.exports.sendResponseWithMessage = function (res, message) {
  logger.debug('sendResponseWithMessage', { messageId: message.id }, res);
  const data = { messages: [message] };

  return res.send({ data });
};

/**
 * Adds headers to the response that signal our message broker no to retry this request
 *
 * @param  {Response} res The response object
 * @return {Response}     Response
 */
module.exports.addNoRetryHeaders = function addNoRetryHeaders(res) {
  logger.debug('Adding Blink suppress headers', {}, res);
  return res.setHeader(config.noRetryHeader, true);
};

/**
 * Adds error noticeable versions of the most used response helpers. These methods are decorated
 * so that they will notice the error to NewRelic.
 * They exist so we can have flexibility to respond with an error but not log it in New relic. Like
 * Mobile not found errors in the ?origin=signup route.
 */
module.exports.errorNoticeable = {
  sendErrorResponseWithNoRetry: helpers.analytics
    .getErrorNoticeableMethod(module.exports.sendErrorResponseWithNoRetry),
  sendErrorResponse: helpers.analytics
    .getErrorNoticeableMethod(module.exports.sendErrorResponse),
};
<commit_msg>Catches helpers.tag.render errors<commit_after>'use strict';

const { STATUS_CODES } = require('http');

const logger = require('./logger');
const config = require('../config/lib/helpers/response');
const helpers = require('./helpers/index');

// register helpers
Object.keys(helpers).forEach((helperName) => {
  module.exports[helperName] = helpers[helperName];
});

// TODO: Move functions below into lib/helpers/response.js

/**
 * Sends response with err code and message.
 *
 * @param  {Response} res
 * @param  {Error} err
 * @param  {Boolean} retry by default, errors should be retried by Blink
 */
module.exports.sendErrorResponse = function (res, err, retry = true) {
  const error = helpers.util.parseStatusAndMessageFromError(err);

  if (!retry) {
    exports.addNoRetryHeaders(res);
  }
  return exports.sendResponseWithStatusCode(res, error.status, error.message);
};

module.exports.sendErrorResponseWithNoRetry = function (res, err) {
  return exports.sendErrorResponse(res, err, false);
};

/**
 * Sends response with custom status code and message
 *
 * @param  {Response} res
 * @param  {Number} code = 200
 * @param  {String} message = 'OK'
 */
module.exports.sendResponseWithStatusCode = function (res, code = 200, message) {
  // @see https://nodejs.org/api/http.html#http_http_status_codes
  const responseMessage = message || STATUS_CODES[code];
  const response = {
    message: responseMessage,
  };

  // log
  const logLevel = code < 400 ? 'debug' : 'error';
  logger[logLevel]('sendResponseWithStatusCode', { code, response }, res);

  helpers.analytics.addCustomAttributes({ gambitApiResponseMessage: responseMessage });
  return res.status(code).send(response);
};

/**
 * Sends response with Message.
 * @param {Request} req
 * @param {Message} message
 */
module.exports.sendResponseWithMessage = function (res, message) {
  logger.debug('sendResponseWithMessage', { messageId: message.id }, res);
  const data = { messages: [message] };

  return res.send({ data });
};

/**
 * Adds headers to the response that signal our message broker no to retry this request
 *
 * @param  {Response} res The response object
 * @return {Response}     Response
 */
module.exports.addNoRetryHeaders = function addNoRetryHeaders(res) {
  logger.debug('Adding Blink suppress headers', {}, res);
  return res.setHeader(config.noRetryHeader, true);
};

/**
 * Adds error noticeable versions of the most used response helpers. These methods are decorated
 * so that they will notice the error to NewRelic.
 * They exist so we can have flexibility to respond with an error but not log it in New relic. Like
 * Mobile not found errors in the ?origin=signup route.
 */
module.exports.errorNoticeable = {
  sendErrorResponseWithNoRetry: helpers.analytics
    .getErrorNoticeableMethod(module.exports.sendErrorResponseWithNoRetry),
  sendErrorResponse: helpers.analytics
    .getErrorNoticeableMethod(module.exports.sendErrorResponse),
};
<|endoftext|>


<commit_before>/* @flow */

import { Range } from 'atom'
import { shell } from 'electron'
import type { Point, TextEditor } from 'atom'
import type Editors from './editors'
import type { LinterMessage } from './types'

let lastPaneItem = null
export const severityScore = {
  error: 3,
  warning: 2,
  info: 1,
}

export const severityNames = {
  error: 'Error',
  warning: 'Warning',
  info: 'Info',
}
export const WORKSPACE_URI = 'atom://linter-ui-default'

export function $range(message: LinterMessage): ?Object {
  return message.version === 1 ? message.range : message.location.position
}
export function $file(message: LinterMessage): ?string {
  return message.version === 1 ? message.filePath : message.location.file
}
export function copySelection() {
  const selection = getSelection()
  if (selection) {
    atom.clipboard.write(selection.toString())
  }
}
export function getPathOfMessage(message: LinterMessage): string {
  return atom.project.relativizePath($file(message) || '')[1]
}
export function getActiveTextEditor(): ?TextEditor {
  let paneItem = atom.workspace.getCenter().getActivePaneItem()
  const paneIsTextEditor = atom.workspace.isTextEditor(paneItem)
  if (!paneIsTextEditor && paneItem && lastPaneItem && paneItem.getURI() === WORKSPACE_URI && (!lastPaneItem.isAlive || lastPaneItem.isAlive())) {
    paneItem = lastPaneItem
  } else {
    lastPaneItem = paneItem
  }
  return atom.workspace.isTextEditor(paneItem) ? paneItem : null
}

export function getEditorsMap(editors: Editors): { editorsMap: Object, filePaths: Array<string> } {
  const editorsMap = {}
  const filePaths = []
  for (const entry of editors.editors) {
    const filePath = entry.textEditor.getPath()
    if (editorsMap[filePath]) {
      editorsMap[filePath].editors.push(entry)
    } else {
      editorsMap[filePath] = {
        added: [],
        removed: [],
        editors: [entry],
      }
      filePaths.push(filePath)
    }
  }
  return { editorsMap, filePaths }
}

export function filterMessages(messages: Array<LinterMessage>, filePath: ?string, severity: ?string = null): Array<LinterMessage> {
  const filtered = []
  messages.forEach(function(message) {
    if ((filePath === null || $file(message) === filePath) && (!severity || message.severity === severity)) {
      filtered.push(message)
    }
  })
  return filtered
}

export function filterMessagesByRangeOrPoint(messages: Set<LinterMessage> | Array<LinterMessage>, filePath: string, rangeOrPoint: Point | Range): Array<LinterMessage> {
  const filtered = []
  const expectedRange = rangeOrPoint.constructor.name === 'Point' ? new Range(rangeOrPoint, rangeOrPoint) : Range.fromObject(rangeOrPoint)
  messages.forEach(function(message) {
    const file = $file(message)
    const range = $range(message)
    if (file && range && file === filePath && range.intersectsWith(expectedRange)) {
      filtered.push(message)
    }
  })
  return filtered
}

export function openFile(file: string, position: ?Point) {
  const options = {}
  options.searchAllPanes = true
  if (position) {
    options.initialLine = position.row
    options.initialColumn = position.column
  }
  atom.workspace.open(file, options)
}

export function visitMessage(message: LinterMessage, reference: boolean = false) {
  let messageFile
  let messagePosition
  if (reference) {
    if (message.version !== 2) {
      console.warn('[Linter-UI-Default] Only messages v2 are allowed in jump to reference. Ignoring')
      return
    }
    if (!message.reference || !message.reference.file) {
      console.warn('[Linter-UI-Default] Message does not have a valid reference. Ignoring')
      return
    }
    messageFile = message.reference.file
    messagePosition = message.reference.position
  } else {
    const messageRange = $range(message)
    messageFile = $file(message)
    if (messageRange) {
      messagePosition = messageRange.start
    }
  }
  if (messageFile) {
    openFile(messageFile, messagePosition)
  }
}

export function openExternally(message: LinterMessage): void {
  if (message.version === 2 && message.url) {
    shell.openExternal(message.url)
  }
}

export function sortMessages(sortInfo: Array<{ column: string, type: 'asc' | 'desc' }>, rows: Array<LinterMessage>): Array<LinterMessage> {
  const sortColumns : {
    severity?: 'asc' | 'desc',
    linterName?: 'asc' | 'desc',
    file?: 'asc' | 'desc',
    line?: 'asc' | 'desc'
  } = {}

  sortInfo.forEach(function(entry) {
    sortColumns[entry.column] = entry.type
  })

  return rows.slice().sort(function(a, b) {
    if (sortColumns.severity) {
      const multiplyWith = sortColumns.severity === 'asc' ? 1 : -1
      const severityA = severityScore[a.severity]
      const severityB = severityScore[b.severity]
      if (severityA !== severityB) {
        return multiplyWith * (severityA > severityB ? 1 : -1)
      }
    }
    if (sortColumns.linterName) {
      const multiplyWith = sortColumns.linterName === 'asc' ? 1 : -1
      const sortValue = a.severity.localeCompare(b.severity)
      if (sortValue !== 0) {
        return multiplyWith * sortValue
      }
    }
    if (sortColumns.file) {
      const multiplyWith = sortColumns.file === 'asc' ? 1 : -1
      const fileA = getPathOfMessage(a)
      const fileALength = fileA.length
      const fileB = getPathOfMessage(b)
      const fileBLength = fileB.length
      if (fileALength !== fileBLength) {
        return multiplyWith * (fileALength > fileBLength ? 1 : -1)
      } else if (fileA !== fileB) {
        return multiplyWith * fileA.localeCompare(fileB)
      }
    }
    if (sortColumns.line) {
      const multiplyWith = sortColumns.line === 'asc' ? 1 : -1
      const rangeA = $range(a)
      const rangeB = $range(b)
      if (rangeA && !rangeB) {
        return 1
      } else if (rangeB && !rangeA) {
        return -1
      } else if (rangeA && rangeB) {
        if (rangeA.start.row !== rangeB.start.row) {
          return multiplyWith * (rangeA.start.row > rangeB.start.row ? 1 : -1)
        }
        if (rangeA.start.column !== rangeB.start.column) {
          return multiplyWith * (rangeA.start.column > rangeB.start.column ? 1 : -1)
        }
      }
    }

    return 0
  })
}

export function sortSolutions(solutions: Array<Object>): Array<Object> {
  return solutions.slice().sort(function(a, b) {
    return b.priority - a.priority
  })
}

export function applySolution(textEditor: TextEditor, version: 1 | 2, solution: Object): boolean {
  if (solution.apply) {
    solution.apply()
    return true
  }
  const range = version === 1 ? solution.range : solution.position
  const currentText = version === 1 ? solution.oldText : solution.currentText
  const replaceWith = version === 1 ? solution.newText : solution.replaceWith
  if (currentText) {
    const textInRange = textEditor.getTextInBufferRange(range)
    if (currentText !== textInRange) {
      console.warn('[linter-ui-default] Not applying fix because text did not match the expected one', 'expected', currentText, 'but got', textInRange)
      return false
    }
  }
  textEditor.setTextInBufferRange(range, replaceWith)
  return true
}
<commit_msg>:new: Add a safeguard for paneItem.getURI Fixes #408<commit_after>/* @flow */

import { Range } from 'atom'
import { shell } from 'electron'
import type { Point, TextEditor } from 'atom'
import type Editors from './editors'
import type { LinterMessage } from './types'

let lastPaneItem = null
export const severityScore = {
  error: 3,
  warning: 2,
  info: 1,
}

export const severityNames = {
  error: 'Error',
  warning: 'Warning',
  info: 'Info',
}
export const WORKSPACE_URI = 'atom://linter-ui-default'

export function $range(message: LinterMessage): ?Object {
  return message.version === 1 ? message.range : message.location.position
}
export function $file(message: LinterMessage): ?string {
  return message.version === 1 ? message.filePath : message.location.file
}
export function copySelection() {
  const selection = getSelection()
  if (selection) {
    atom.clipboard.write(selection.toString())
  }
}
export function getPathOfMessage(message: LinterMessage): string {
  return atom.project.relativizePath($file(message) || '')[1]
}
export function getActiveTextEditor(): ?TextEditor {
  let paneItem = atom.workspace.getCenter().getActivePaneItem()
  const paneIsTextEditor = atom.workspace.isTextEditor(paneItem)
  if (!paneIsTextEditor && paneItem && lastPaneItem && paneItem.getURI && paneItem.getURI() === WORKSPACE_URI && (!lastPaneItem.isAlive || lastPaneItem.isAlive())) {
    paneItem = lastPaneItem
  } else {
    lastPaneItem = paneItem
  }
  return atom.workspace.isTextEditor(paneItem) ? paneItem : null
}

export function getEditorsMap(editors: Editors): { editorsMap: Object, filePaths: Array<string> } {
  const editorsMap = {}
  const filePaths = []
  for (const entry of editors.editors) {
    const filePath = entry.textEditor.getPath()
    if (editorsMap[filePath]) {
      editorsMap[filePath].editors.push(entry)
    } else {
      editorsMap[filePath] = {
        added: [],
        removed: [],
        editors: [entry],
      }
      filePaths.push(filePath)
    }
  }
  return { editorsMap, filePaths }
}

export function filterMessages(messages: Array<LinterMessage>, filePath: ?string, severity: ?string = null): Array<LinterMessage> {
  const filtered = []
  messages.forEach(function(message) {
    if ((filePath === null || $file(message) === filePath) && (!severity || message.severity === severity)) {
      filtered.push(message)
    }
  })
  return filtered
}

export function filterMessagesByRangeOrPoint(messages: Set<LinterMessage> | Array<LinterMessage>, filePath: string, rangeOrPoint: Point | Range): Array<LinterMessage> {
  const filtered = []
  const expectedRange = rangeOrPoint.constructor.name === 'Point' ? new Range(rangeOrPoint, rangeOrPoint) : Range.fromObject(rangeOrPoint)
  messages.forEach(function(message) {
    const file = $file(message)
    const range = $range(message)
    if (file && range && file === filePath && range.intersectsWith(expectedRange)) {
      filtered.push(message)
    }
  })
  return filtered
}

export function openFile(file: string, position: ?Point) {
  const options = {}
  options.searchAllPanes = true
  if (position) {
    options.initialLine = position.row
    options.initialColumn = position.column
  }
  atom.workspace.open(file, options)
}

export function visitMessage(message: LinterMessage, reference: boolean = false) {
  let messageFile
  let messagePosition
  if (reference) {
    if (message.version !== 2) {
      console.warn('[Linter-UI-Default] Only messages v2 are allowed in jump to reference. Ignoring')
      return
    }
    if (!message.reference || !message.reference.file) {
      console.warn('[Linter-UI-Default] Message does not have a valid reference. Ignoring')
      return
    }
    messageFile = message.reference.file
    messagePosition = message.reference.position
  } else {
    const messageRange = $range(message)
    messageFile = $file(message)
    if (messageRange) {
      messagePosition = messageRange.start
    }
  }
  if (messageFile) {
    openFile(messageFile, messagePosition)
  }
}

export function openExternally(message: LinterMessage): void {
  if (message.version === 2 && message.url) {
    shell.openExternal(message.url)
  }
}

export function sortMessages(sortInfo: Array<{ column: string, type: 'asc' | 'desc' }>, rows: Array<LinterMessage>): Array<LinterMessage> {
  const sortColumns : {
    severity?: 'asc' | 'desc',
    linterName?: 'asc' | 'desc',
    file?: 'asc' | 'desc',
    line?: 'asc' | 'desc'
  } = {}

  sortInfo.forEach(function(entry) {
    sortColumns[entry.column] = entry.type
  })

  return rows.slice().sort(function(a, b) {
    if (sortColumns.severity) {
      const multiplyWith = sortColumns.severity === 'asc' ? 1 : -1
      const severityA = severityScore[a.severity]
      const severityB = severityScore[b.severity]
      if (severityA !== severityB) {
        return multiplyWith * (severityA > severityB ? 1 : -1)
      }
    }
    if (sortColumns.linterName) {
      const multiplyWith = sortColumns.linterName === 'asc' ? 1 : -1
      const sortValue = a.severity.localeCompare(b.severity)
      if (sortValue !== 0) {
        return multiplyWith * sortValue
      }
    }
    if (sortColumns.file) {
      const multiplyWith = sortColumns.file === 'asc' ? 1 : -1
      const fileA = getPathOfMessage(a)
      const fileALength = fileA.length
      const fileB = getPathOfMessage(b)
      const fileBLength = fileB.length
      if (fileALength !== fileBLength) {
        return multiplyWith * (fileALength > fileBLength ? 1 : -1)
      } else if (fileA !== fileB) {
        return multiplyWith * fileA.localeCompare(fileB)
      }
    }
    if (sortColumns.line) {
      const multiplyWith = sortColumns.line === 'asc' ? 1 : -1
      const rangeA = $range(a)
      const rangeB = $range(b)
      if (rangeA && !rangeB) {
        return 1
      } else if (rangeB && !rangeA) {
        return -1
      } else if (rangeA && rangeB) {
        if (rangeA.start.row !== rangeB.start.row) {
          return multiplyWith * (rangeA.start.row > rangeB.start.row ? 1 : -1)
        }
        if (rangeA.start.column !== rangeB.start.column) {
          return multiplyWith * (rangeA.start.column > rangeB.start.column ? 1 : -1)
        }
      }
    }

    return 0
  })
}

export function sortSolutions(solutions: Array<Object>): Array<Object> {
  return solutions.slice().sort(function(a, b) {
    return b.priority - a.priority
  })
}

export function applySolution(textEditor: TextEditor, version: 1 | 2, solution: Object): boolean {
  if (solution.apply) {
    solution.apply()
    return true
  }
  const range = version === 1 ? solution.range : solution.position
  const currentText = version === 1 ? solution.oldText : solution.currentText
  const replaceWith = version === 1 ? solution.newText : solution.replaceWith
  if (currentText) {
    const textInRange = textEditor.getTextInBufferRange(range)
    if (currentText !== textInRange) {
      console.warn('[linter-ui-default] Not applying fix because text did not match the expected one', 'expected', currentText, 'but got', textInRange)
      return false
    }
  }
  textEditor.setTextInBufferRange(range, replaceWith)
  return true
}
<|endoftext|>


<commit_before>// Runtime

/**
 * 迭代器，支持数组与对象
 * @param {array|Object} data
 * @param {function} callback
 */
var each = function each(data, callback) {
    if (Array.isArray(data)) {
        for (var i = 0, len = data.length; i < len; i++) {
            callback(data[i], i, data);
        }
    } else {
        for (var _i in data) {
            callback(data[_i], _i);
        }
    }
};

/**
 * 编码模板输出的内容
 * @param  {any}   content
 * @return {string}
 */
var escape = function escape(content) {

    var escapeReg = /&(?![\w#]+;)|[<>"']/g;
    var escapeMap = {
        "<": "<",
        ">": ">",
        '"': """,
        "'": "'",
        "&": "&"
    };

    var toString = function toString(value) {
        if (typeof value !== 'string') {
            if (typeof value === 'function') {
                value = toString(value.call(value));
            } else if (value === null) {
                value = '';
            } else {
                // number | array | object | undefined
                value = JSON.stringify(value) || '';
            }
        }

        return value;
    };

    return toString(content).replace(escapeReg, function (s) {
        return escapeMap[s];
    });
};

/**
 * 载入子模板
 * @param   {string}    filename
 * @param   {Object}    data
 * @param   {string}    base
 * @param   {string}    root
 * @return  {string}
 */
var include = function() {
    throw new Error('does not support the "include" feature');
};

var imports = {
    $each: each,
    $escape: escape,
    $include: include
};

module.exports = imports;<commit_msg>修改报错信息<commit_after>// Runtime

/**
 * 迭代器，支持数组与对象
 * @param {array|Object} data
 * @param {function} callback
 */
var each = function each(data, callback) {
    if (Array.isArray(data)) {
        for (var i = 0, len = data.length; i < len; i++) {
            callback(data[i], i, data);
        }
    } else {
        for (var _i in data) {
            callback(data[_i], _i);
        }
    }
};

/**
 * 编码模板输出的内容
 * @param  {any}   content
 * @return {string}
 */
var escape = function escape(content) {

    var escapeReg = /&(?![\w#]+;)|[<>"']/g;
    var escapeMap = {
        "<": "<",
        ">": ">",
        '"': """,
        "'": "'",
        "&": "&"
    };

    var toString = function toString(value) {
        if (typeof value !== 'string') {
            if (typeof value === 'function') {
                value = toString(value.call(value));
            } else if (value === null) {
                value = '';
            } else {
                // number | array | object | undefined
                value = JSON.stringify(value) || '';
            }
        }

        return value;
    };

    return toString(content).replace(escapeReg, function (s) {
        return escapeMap[s];
    });
};

/**
 * 载入子模板
 * @param   {string}    filename
 * @param   {Object}    data
 * @param   {string}    base
 * @param   {string}    root
 * @return  {string}
 */
var include = function() {
    throw new Error('please implement the "include" interface');
};

var imports = {
    $each: each,
    $escape: escape,
    $include: include
};

module.exports = imports;<|endoftext|>


<commit_before>/**
 * Created by nuintun on 2015/4/27.
 */

'use strict';

var is = require('is');
var fs = require('fs');
var path = require('path');
var join = path.join;
var relative = path.relative;
var Vinyl = require('vinyl');
var through = require('through2');
var util = require('./util');
var common = require('./common');
var colors = util.colors;
var transport = require('./transport');
var debug = util.debug;

// empty buffer
var NULL = new Buffer('');

function include(options){
  var initialized = false;
  var defaults = common.initOptions(options);

  // stream
  return through.obj({ objectMode: true }, function (vinyl, encoding, next){
    // return empty vinyl
    if (vinyl.isNull()) {
      return next(null, vinyl);
    }

    // throw error if stream vinyl
    if (vinyl.isStream()) {
      return next(util.throwError('streaming not supported.'));
    }

    if (!initialized) {
      var ignore = [];
      var base = join(vinyl.cwd, vinyl.base);

      // debug
      debug('cwd: %s', colors.magenta(util.normalize(util.cwd)));

      // base out of bound of wwwroot
      if (util.isOutBound(base, defaults.wwwroot)) {
        util.throwError(
          'base: %s is out of bound of wwwroot: %s.',
          util.normalize(base),
          util.normalize(defaults.wwwroot)
        );
      }

      // format ignore
      defaults.ignore.forEach(function (id){
        var path;
        var alias = defaults.alias;
        var paths = defaults.paths;
        var vars = defaults.vars;

        // parse id form alias, paths, vars
        id = util.parseAlias(id, alias);
        id = util.parsePaths(id, paths);
        id = util.parseAlias(id, alias);
        id = util.parseVars(id, vars);
        id = util.parseAlias(id, alias);

        // local id add ignore
        if (util.isLocal(id)) {
          if (util.isAbsolute(id)) {
            path = join(defaults.wwwroot, id.substring(1));
          } else if (!util.isRelative(id)) {
            path = join(vinyl.cwd, vinyl.base, id);
          }

          if (path) {
            ignore.push(util.addExt(path));
          }
        }
      });

      // rewrite ignore
      defaults.ignore = ignore;

      initialized = true;
    }

    // catch error
    try {
      // clone options
      options = util.extend({}, defaults);

      // lock wwwroot
      Object.defineProperty(options, 'wwwroot', {
        __proto__: null,
        writable: false,
        enumerable: true,
        configurable: false
      });

      // lock plugins
      Object.defineProperty(options, 'plugins', {
        __proto__: null,
        writable: false,
        enumerable: true,
        configurable: false
      });

      // transport
      vinyl = transport(vinyl, options);

      var included = [];
      var pkg = vinyl.package;
      var start = vinyl.clone();
      var end = vinyl.clone();

      start.startConcat = true;
      start.contents = NULL;
      end.endConcat = true;

      delete start.package;

      this.push(start);
      included.push(start.path);

      // compute include
      options.include = is.fn(options.include)
        ? options.include(pkg.id || null, vinyl.path, vinyl.base, options.wwwroot)
        : options.include;

      includeDeps.call(this, vinyl, options, included);
      this.push(end);
    } catch (e) {
      // show error message
      util.print(colors.red.bold(e.stack));
    }

    next();
  });
}

/**
 * include dependencies file
 * @param vinyl
 * @param options
 * @param included
 */

function includeDeps(vinyl, options, included){
  var stream = this;
  var pkg = vinyl.package;
  var include = options.include;

  // return if include only self
  if (include === 'self') return;

  // clone options
  options = util.extend({}, options);

  // traverse
  function traverse(path, base){
    included.push(path);

    var vinyl = vinylFile(path, base);

    if (vinyl !== null) {
      vinyl = transport(vinyl, options);

      // debug
      debug('include: %s', colors.magenta(util.pathFromCwd(vinyl.path)));
      includeDeps.call(stream, vinyl, options, included);
      stream.push(vinyl);
    }
  }

  if (pkg && Array.isArray(pkg.include)) {
    // dependencies
    pkg.include.forEach(function (meta){
      if (meta && meta.id && meta.path) {
        // ignore or included
        if (options.ignore.indexOf(meta.path) !== -1 || included.indexOf(meta.path) !== -1) {
          return false;
        }

        switch (include) {
          case 'all':
            traverse(meta.path, vinyl);
            break;
          case 'relative':
          default :
            // include all relative file
            if (util.isRelative(meta.id)) {
              traverse(meta.path, vinyl);
            }
            break;
        }
      }
    });
  }
}

/**
 * create a new vinyl
 * @param path
 * @param vinyl
 * @returns {*}
 */

function vinylFile(path, vinyl){
  if (!is.string(path) || !vinyl) return null;

  var origin = path;

  if (!fs.existsSync(path)) {
    path = util.hideExt(path);
  }

  if (fs.existsSync(path)) {
    return new Vinyl({
      path: path,
      cwd: vinyl.cwd,
      base: vinyl.base,
      stat: fs.statSync(path),
      contents: fs.readFileSync(path)
    });
  }

  // file not exists
  util.print('file: %s not exists', colors.yellow(util.pathFromCwd(origin)));

  return null;
}

/**
 * Exports module.
 */

module.exports = include;
<commit_msg>bug fixed<commit_after>/**
 * Created by nuintun on 2015/4/27.
 */

'use strict';

var is = require('is');
var fs = require('fs');
var path = require('path');
var join = path.join;
var relative = path.relative;
var Vinyl = require('vinyl');
var through = require('through2');
var util = require('./util');
var common = require('./common');
var colors = util.colors;
var transport = require('./transport');
var debug = util.debug;

// empty buffer
var NULL = new Buffer('');

function include(options){
  var initialized = false;
  var defaults = common.initOptions(options);

  // stream
  return through.obj({ objectMode: true }, function (vinyl, encoding, next){
    // return empty vinyl
    if (vinyl.isNull()) {
      return next(null, vinyl);
    }

    // throw error if stream vinyl
    if (vinyl.isStream()) {
      return next(util.throwError('streaming not supported.'));
    }

    if (!initialized) {
      var ignore = [];
      var base = join(vinyl.cwd, vinyl.base);

      // debug
      debug('cwd: %s', colors.magenta(util.normalize(util.cwd)));

      // base out of bound of wwwroot
      if (util.isOutBound(base, defaults.wwwroot)) {
        util.throwError(
          'base: %s is out of bound of wwwroot: %s.',
          util.normalize(base),
          util.normalize(defaults.wwwroot)
        );
      }

      // format ignore
      defaults.ignore.forEach(function (id){
        var path;
        var alias = defaults.alias;
        var paths = defaults.paths;
        var vars = defaults.vars;

        // parse id form alias, paths, vars
        id = util.parseAlias(id, alias);
        id = util.parsePaths(id, paths);
        id = util.parseAlias(id, alias);
        id = util.parseVars(id, vars);
        id = util.parseAlias(id, alias);

        // local id add ignore
        if (util.isLocal(id)) {
          if (util.isAbsolute(id)) {
            path = join(defaults.wwwroot, id.substring(1));
          } else if (!util.isRelative(id)) {
            path = join(vinyl.cwd, vinyl.base, id);
          }

          if (path) {
            ignore.push(util.addExt(path));
          }
        }
      });

      // rewrite ignore
      defaults.ignore = ignore;

      initialized = true;
    }

    // catch error
    try {
      // clone options
      options = util.extend({}, defaults);

      // lock wwwroot
      Object.defineProperty(options, 'wwwroot', {
        __proto__: null,
        writable: false,
        enumerable: true,
        configurable: false
      });

      // lock plugins
      Object.defineProperty(options, 'plugins', {
        __proto__: null,
        writable: false,
        enumerable: true,
        configurable: false
      });

      // transport
      vinyl = transport(vinyl, options);

      var included = [];
      var pkg = vinyl.package;
      var start = vinyl.clone();
      var end = vinyl.clone();

      start.startConcat = true;
      start.contents = NULL;
      end.endConcat = true;

      delete start.package;

      this.push(start);
      included.push(start.path);

      // compute include
      options.include = is.fn(options.include)
        ? options.include(pkg.id || null, vinyl.path)
        : options.include;

      includeDeps.call(this, vinyl, options, included);
      this.push(end);
    } catch (e) {
      // show error message
      util.print(colors.red.bold(e.stack));
    }

    next();
  });
}

/**
 * include dependencies file
 * @param vinyl
 * @param options
 * @param included
 */

function includeDeps(vinyl, options, included){
  var stream = this;
  var pkg = vinyl.package;
  var include = options.include;

  // return if include only self
  if (include === 'self') return;

  // clone options
  options = util.extend({}, options);

  // traverse
  function traverse(path, base){
    included.push(path);

    var vinyl = vinylFile(path, base);

    if (vinyl !== null) {
      vinyl = transport(vinyl, options);

      // debug
      debug('include: %s', colors.magenta(util.pathFromCwd(vinyl.path)));
      includeDeps.call(stream, vinyl, options, included);
      stream.push(vinyl);
    }
  }

  if (pkg && Array.isArray(pkg.include)) {
    // dependencies
    pkg.include.forEach(function (meta){
      if (meta && meta.id && meta.path) {
        // ignore or included
        if (options.ignore.indexOf(meta.path) !== -1 || included.indexOf(meta.path) !== -1) {
          return false;
        }

        switch (include) {
          case 'all':
            traverse(meta.path, vinyl);
            break;
          case 'relative':
          default :
            // include all relative file
            if (util.isRelative(meta.id)) {
              traverse(meta.path, vinyl);
            }
            break;
        }
      }
    });
  }
}

/**
 * create a new vinyl
 * @param path
 * @param vinyl
 * @returns {*}
 */

function vinylFile(path, vinyl){
  if (!is.string(path) || !vinyl) return null;

  var origin = path;

  if (!fs.existsSync(path)) {
    path = util.hideExt(path);
  }

  if (fs.existsSync(path)) {
    return new Vinyl({
      path: path,
      cwd: vinyl.cwd,
      base: vinyl.base,
      stat: fs.statSync(path),
      contents: fs.readFileSync(path)
    });
  }

  // file not exists
  util.print('file: %s not exists', colors.yellow(util.pathFromCwd(origin)));

  return null;
}

/**
 * Exports module.
 */

module.exports = include;
<|endoftext|>


<commit_before>'use strict';

var bin = require('./');
var BinBuild = require('bin-build');
var log = require('imagemin-log');
var path = require('path');

/**
 * Install binary and check whether it works
 * If the test fails, try to build it
 */

bin.run(['--version'], function (err) {
	if (err) {
		log.warn('jpegoptim pre-build test failed');
		log.info('compiling from source');

		var builder = new BinBuild()
			.src('https://github.com/tjko/jpegoptim/archive/RELEASE.' + bin.v + '.tar.gz')
			.cmd('./configure --prefix="' + bin.dest() + '" --bindir="' + bin.dest() + '"')
			.cmd('make install')
			.cmd('mv ' + path.join(bin.dest(), 'bin', bin.use()) + ' ' + bin.path());

		return builder.run(function (err) {
			if (err) {
				log.error(err.stack);
				return;
			}

			log.success('jpegoptim built successfully');
		});
	}

	log.success('jpegoptim pre-build test passed successfully');
});
<commit_msg>Show error message<commit_after>'use strict';

var bin = require('./');
var BinBuild = require('bin-build');
var log = require('imagemin-log');
var path = require('path');

/**
 * Install binary and check whether it works
 * If the test fails, try to build it
 */

bin.run(['--version'], function (err) {
	if (err) {
		log.warn(err.message);
		log.warn('jpegoptim pre-build test failed');
		log.info('compiling from source');

		var builder = new BinBuild()
			.src('https://github.com/tjko/jpegoptim/archive/RELEASE.' + bin.v + '.tar.gz')
			.cmd('./configure --prefix="' + bin.dest() + '" --bindir="' + bin.dest() + '"')
			.cmd('make install')
			.cmd('mv ' + path.join(bin.dest(), 'bin', bin.use()) + ' ' + bin.path());

		return builder.run(function (err) {
			if (err) {
				log.error(err.stack);
				return;
			}

			log.success('jpegoptim built successfully');
		});
	}

	log.success('jpegoptim pre-build test passed successfully');
});
<|endoftext|>


<commit_before>'use strict';
var J = jQuery.noConflict();

var Zotero = {
    ajax: {},
    callbacks: {},
    ui: {callbacks:{}},
    url: {},
    utils: {},
    offline: {},
    temp: {},
    localizations: {},

    config: {librarySettings: {},
             baseApiUrl: 'https://api.zotero.org',
             baseWebsiteUrl: 'https://zotero.org',
             baseFeedUrl: 'https://api.zotero.org',
             baseZoteroWebsiteUrl: 'https://www.zotero.org',
             baseDownloadUrl: 'https://www.zotero.org',
             proxyPath: '/proxyrequest',
             ignoreLoggedInStatus: false,
             storePrefsRemote: true,
             sessionAuth: false,
             proxy: true,
             apiKey: '',
             ajax: 1,
             futureApi: true,
             locale: 'en-US',
             cacheStoreType: 'localStorage',
             mobile:0,
             sortOrdering: {
                 'dateAdded': 'desc',
                 'dateModified': 'desc',
                 'date': 'desc',
                 'year': 'desc',
                 'accessDate': 'desc',
                 'title': 'asc',
                 'creator': 'asc'
             },
             defaultSortColumn: 'title',
             defaultSortOrder: 'asc',
             largeFields: {
                 'title': 1,
                 'abstractNote': 1,
                 'extra' : 1
             },
             richTextFields: {
                 'note': 1
             },
             maxFieldSummaryLength: {title:60},
             exportFormats: [
                "bibtex",
                "bookmarks",
                "mods",
                "refer",
                "rdf_bibliontology",
                "rdf_dc",
                "rdf_zotero",
                "ris",
                "wikipedia"
                ],
            defaultApiArgs: {
                'order': 'title',
                'sort': 'asc',
                'limit': 50,
                'start': 0,
                'content':'json',
                'format': 'atom'
            }
             },

    debug: function(debugstring, level){
        if(typeof console == 'undefined'){
            return;
        }
        if(typeof(level) !== "number"){
            level = 1;
        }
        if(Zotero.prefs.debug_log && (level <= Zotero.prefs.debug_level)){
            console.log(debugstring);
        }
    },

    warn: function(warnstring){
        if(typeof console == 'undefined' || typeof console.warn == 'undefined'){
            this.debug(warnstring);
        }
        else{
            console.warn(warnstring);
        }
    },

    error: function(errorstring){
        if(typeof console == 'undefined' || typeof console.error == 'undefined'){
            this.debug(errorstring);
        }
        else{
            console.error(errorstring);
        }
    },

    feeds: {},

    cacheFeeds: {},

    defaultPrefs: {
        debug_level: 1, //lower level is higher priority
        debug_log: true,
        debug_mock: false
    },

    prefs: {},

    state: {},

    libraries: {},

    validator: {
        patterns: {
            //'itemKey': /^([A-Z0-9]{8,},?)+$/,
            'itemKey': /^.+$/,
            'collectionKey': /^([A-Z0-9]{8,})|trash$/,
            //'tag': /^[^#]*$/,
            'libraryID': /^[0-9]+$/,
            'libraryType': /^(user|group|)$/,
            'target': /^(items?|collections?|tags|children|deleted)$/,
            'targetModifier': /^(top|file|file\/view)$/,

            //get params
            'sort': /^(asc|desc)$/,
            'start': /^[0-9]*$/,
            'limit': /^[0-9]*$/,
            'order': /^\S*$/,
            'content': /^(json|html|csljson|bib|none)$/,
            'q': /^.*$/,
            'fq': /^\S*$/,
            'itemType': /^\S*$/,
            'locale': /^\S*$/,
            'tag': /^.*$/,
            'tagType': /^(0|1)$/,
            'key': /^\S*/,
            'format': /^(atom|bib|keys|versions|bibtex|bookmarks|mods|refer|rdf_bibliontology|rdf_dc|rdf_zotero|ris|wikipedia)$/,
            'style': /^\S*$/,
            'linkwrap': /^(0|1)*$/
        },

        validate: function(arg, type){
            Z.debug("Zotero.validate", 4);
            if(arg === ''){
                return null;
            }
            else if(arg === null){
                return true;
            }
            Z.debug(arg + " " + type, 4);
            var patterns = this.patterns;

            if(patterns.hasOwnProperty(type)){
                return patterns[type].test(arg);
            }
            else{
                return null;
            }
        }
    },

    _logEnabled: 0,
    enableLogging: function(){
        Zotero._logEnabled++;
        if(Zotero._logEnabled > 0){
            Zotero.prefs.debug_log = true;
        }
    },

    disableLogging: function(){
        Zotero._logEnabled--;
        if(Zotero._logEnabled <= 0){
            Zotero._logEnabled = 0;
            Zotero.prefs.debug_log = false;
        }
    },

    init: function(){
        var store;
        if(Zotero.config.cacheStoreType == 'localStorage' && typeof localStorage != 'undefined'){
            store = localStorage;
        }
        else if(Zotero.config.cacheStoreType == 'sessionStorage' && typeof sessionStorage != 'undefined'){
            store = sessionStorage;
        }
        else{
            store = {};
        }
        Zotero.store = store;

        Zotero.cache = new Zotero.Cache(store);
        //populate prefs with defaults, then override with stored prefs
        Zotero.prefs = J.extend({}, Zotero.defaultPrefs, Zotero.prefs, Zotero.utils.getStoredPrefs());
        /*
        Zotero.prefs = new Zotero.Prefs(store);
        J.each(Zotero.defaultPrefs, function(key, val){
            if(Zotero.prefs.getPref(key) === null){
                Zotero.prefs.setPref(key);
            }
        });
        */
        //get localized item constants if not stored in localstorage
        var locale = 'en-US';
        if(Zotero.config.locale){
            locale = Zotero.config.locale;
        }
        locale = 'en-US';

        J.ajaxSettings.traditional = true;

    }
};

Zotero.Cache = function(store){
    this.store = store;
    var registry = this.store['_registry'];
    if(typeof registry == 'null' || typeof registry == 'undefined'){
        registry = {};
        this.store['_registry'] = JSON.stringify(registry);
    }
};

//build a consistent string from an object to use as a cache key
//put object key/value pairs into array, sort array, and concatenate
//array with '/'
Zotero.Cache.prototype.objectCacheString = function(params){
    var paramVarsArray = [];
    J.each(params, function(index, value){
        if(!value) { return; }
        else if(value instanceof Array){
            J.each(value, function(i, v){
                paramVarsArray.push(index + '/' + encodeURIComponent(v) );
            });
        }
        else{
            paramVarsArray.push(index + '/' + encodeURIComponent(value) );
        }
    });
    paramVarsArray.sort();
    Z.debug(paramVarsArray, 4);
    var objectCacheString = paramVarsArray.join('/');
    return objectCacheString;
};

//should use setItem and getItem if I extend that to the case where no Storage object is available in the browser
Zotero.Cache.prototype.save = function(params, object, cachetags){
    //cachetags for expiring entries
    if(!J.isArray(cachetags)){
        cachetags = [];
    }
    //get registry object from storage
    var registry = JSON.parse(this.store['_registry']);
    if(!registry){
        registry = {};
    }
    var objectCacheString = this.objectCacheString(params);
    //save object in storage
    this.store[objectCacheString] = JSON.stringify(object);
    //make registry entry for object
    var registryEntry = {'id':objectCacheString, saved:Date.now(), cachetags:cachetags};
    registry[objectCacheString] = registryEntry;
    //save registry back to storage
    this.store['_registry'] = JSON.stringify(registry);
};

Zotero.Cache.prototype.load = function(params){
    Z.debug("Zotero.Cache.load", 3);
    var objectCacheString = this.objectCacheString(params);
    Z.debug(objectCacheString, 4);
    try{
        var s = this.store[objectCacheString];
        if(!s){
            Z.debug("No value found in cache store - " + objectCacheString, 3);
            return null;
        }
        else{
            return JSON.parse(s);
        }
    }
    catch(e){
        Z.debug('Error parsing retrieved cache data', 1);
        Z.debug(objectCacheString, 2);
        Z.debug(this.store[objectCacheString], 2);
        return null;
    }
};

Zotero.Cache.prototype.expireCacheTag = function(tag){
    Z.debug("Zotero.Cache.expireCacheTag", 3);
    var registry = JSON.parse(this.store['_registry']);
    var store = this.store;
    J.each(registry, function(index, value){
        if(J.inArray(tag, value.cachetags) != (-1) ){
            Z.debug('tag ' + tag + ' found for item ' + value['id'] + ' : expiring', 4);
            delete store[value['id']];
            delete registry[value['id']];
        }
    });
};

Zotero.Cache.prototype.clear = function(){
    if(typeof(this.store.clear) == 'function'){
        this.store.clear();
    }
    else{
        this.store = {};
    }
};

Zotero.PrefManager = function(store){
    this.store = store;
};

Zotero.PrefManager.prototype.setPref = function(key, val){
    var prefs = this.store["userpreferences"];
    if(typeof prefs === "undefined"){
        prefs = {};
    }
    prefs[key] = val;
    this.store["userpreferences"] = prefs;
};

Zotero.PrefManager.prototype.setPrefs = function(prefs){
    if(typeof(prefs) != "object") {
        throw "Preferences must be an object";
    }
    this.store["userpreferences"] = prefs;
};

Zotero.PrefManager.prototype.getPrefs = function(){
    var prefs = this.store["userpreferences"];
    if(typeof prefs === "undefined") {
        return {};
    }
    return prefs;
};

Zotero.PrefManager.prototype.getPref = function(key){
    var prefs = this.store["userpreferences"];
    if(typeof prefs === "undefined"){
        return null;
    }
    return prefs["key"];
};

//make a request to the Zotero api and get back a deferred
Zotero.apiRequest = function(url, method, body, headers){
    Z.debug("Zotero.apiRequest", 3);
    if(typeof method == 'undefined'){
        method = 'GET';
    }
    if(typeof headers == 'undefined'){
        headers = {};
    }

    var settings = {type: method,
                    headers:headers,
                    cache:false,
                    error: Zotero.ajax.errorCallback
                    };
    if(typeof body != 'undefined') {
        settings['data'] = body;
    }

    var jqxhr = J.ajax(Zotero.ajax.proxyWrapper(url, method), settings);
    return jqxhr;
};

Zotero.error = function(e){
    Z.debug("====================Zotero Error", 1);
    Z.debug(e, 1);
};

Zotero.saveLibrary = function(library){
    var dump = {};
    dump.libraryType = library.libraryType;
    dump.libraryID = library.libraryID;
    dump.libraryUrlIdentifier = library.libraryUrlIdentifier;
    dump.itemKeys = library.itemKeys;

    dump.collections = library.collections.dump();
    dump.items = library.items.dump();
    dump.tags = library.tags.dump();
    Zotero.cache.save({libraryString:library.libraryString}, dump);
};

Zotero.loadLibrary = function(params){
    Z.debug("Zotero.loadLibrary");
    Z.debug(params);
    var dump = Zotero.cache.load(params);
    if(dump === null){
        Z.debug("no library found in cache");
        return false;
    }

    var library = new Zotero.Library(dump.libraryType, dump.libraryID, dump.libraryUrlIdentifier);
    library.itemKeys = dump.itemKeys;

    library.collections.loadDump(dump.collections);
    library.items.loadDump(dump.items);
    library.tags.loadDump(dump.tags);

    return library;
};

Zotero.ajaxRequest = function(url, type, options){
    var defaultOptions = {
        type: "GET",
        headers:{},
        cache:false,
        error: Zotero.ajax.errorCallback
    };
    var reqOptions = J.extend({}, defaultOptions, options);
    if(type){
        reqOptions.type = type;
    }

    if(Zotero.config.futureApi) {
        reqOptions.headers['The-Future-Is-Now'] = 1;
    }

    var urlstring;
    if(typeof url === "object"){
        urlstring = Zotero.ajax.apiRequestUrl(url) + Zotero.ajax.apiQueryString(url);
    }
    else if(typeof url === "string"){
        urlstring = url;
    }
    Z.debug("library.ajaxRequest urlstring " + urlstring);
    var reqUrl = Zotero.ajax.proxyWrapper(urlstring, type);
    return J.ajax(reqUrl, reqOptions);
};

var Z = Zotero;

<commit_msg>allow base downloadproxy url<commit_after>'use strict';
var J = jQuery.noConflict();

var Zotero = {
    ajax: {},
    callbacks: {},
    ui: {callbacks:{}},
    url: {},
    utils: {},
    offline: {},
    temp: {},
    localizations: {},

    config: {librarySettings: {},
             baseApiUrl: 'https://api.zotero.org',
             baseWebsiteUrl: 'https://zotero.org',
             baseFeedUrl: 'https://api.zotero.org',
             baseZoteroWebsiteUrl: 'https://www.zotero.org',
             baseDownloadUrl: 'https://www.zotero.org',
             directDownloads: true,
             proxyPath: '/proxyrequest',
             ignoreLoggedInStatus: false,
             storePrefsRemote: true,
             sessionAuth: false,
             proxy: true,
             apiKey: '',
             ajax: 1,
             futureApi: true,
             futureApiVersion: 2,
             locale: 'en-US',
             cacheStoreType: 'localStorage',
             mobile:0,
             sortOrdering: {
                 'dateAdded': 'desc',
                 'dateModified': 'desc',
                 'date': 'desc',
                 'year': 'desc',
                 'accessDate': 'desc',
                 'title': 'asc',
                 'creator': 'asc'
             },
             defaultSortColumn: 'title',
             defaultSortOrder: 'asc',
             largeFields: {
                 'title': 1,
                 'abstractNote': 1,
                 'extra' : 1
             },
             richTextFields: {
                 'note': 1
             },
             maxFieldSummaryLength: {title:60},
             exportFormats: [
                "bibtex",
                "bookmarks",
                "mods",
                "refer",
                "rdf_bibliontology",
                "rdf_dc",
                "rdf_zotero",
                "ris",
                "wikipedia"
                ],
            defaultApiArgs: {
                'order': 'title',
                'sort': 'asc',
                'limit': 50,
                'start': 0,
                'content':'json',
                'format': 'atom'
            }
             },

    debug: function(debugstring, level){
        if(typeof console == 'undefined'){
            return;
        }
        if(typeof(level) !== "number"){
            level = 1;
        }
        if(Zotero.prefs.debug_log && (level <= Zotero.prefs.debug_level)){
            console.log(debugstring);
        }
    },

    warn: function(warnstring){
        if(typeof console == 'undefined' || typeof console.warn == 'undefined'){
            this.debug(warnstring);
        }
        else{
            console.warn(warnstring);
        }
    },

    error: function(errorstring){
        if(typeof console == 'undefined' || typeof console.error == 'undefined'){
            this.debug(errorstring);
        }
        else{
            console.error(errorstring);
        }
    },

    feeds: {},

    cacheFeeds: {},

    defaultPrefs: {
        debug_level: 1, //lower level is higher priority
        debug_log: true,
        debug_mock: false
    },

    prefs: {},

    state: {},

    libraries: {},

    validator: {
        patterns: {
            //'itemKey': /^([A-Z0-9]{8,},?)+$/,
            'itemKey': /^.+$/,
            'collectionKey': /^([A-Z0-9]{8,})|trash$/,
            //'tag': /^[^#]*$/,
            'libraryID': /^[0-9]+$/,
            'libraryType': /^(user|group|)$/,
            'target': /^(items?|collections?|tags|children|deleted)$/,
            'targetModifier': /^(top|file|file\/view)$/,

            //get params
            'sort': /^(asc|desc)$/,
            'start': /^[0-9]*$/,
            'limit': /^[0-9]*$/,
            'order': /^\S*$/,
            'content': /^(json|html|csljson|bib|none)$/,
            'q': /^.*$/,
            'fq': /^\S*$/,
            'itemType': /^\S*$/,
            'locale': /^\S*$/,
            'tag': /^.*$/,
            'tagType': /^(0|1)$/,
            'key': /^\S*/,
            'format': /^(atom|bib|keys|versions|bibtex|bookmarks|mods|refer|rdf_bibliontology|rdf_dc|rdf_zotero|ris|wikipedia)$/,
            'style': /^\S*$/,
            'linkwrap': /^(0|1)*$/
        },

        validate: function(arg, type){
            Z.debug("Zotero.validate", 4);
            if(arg === ''){
                return null;
            }
            else if(arg === null){
                return true;
            }
            Z.debug(arg + " " + type, 4);
            var patterns = this.patterns;

            if(patterns.hasOwnProperty(type)){
                return patterns[type].test(arg);
            }
            else{
                return null;
            }
        }
    },

    _logEnabled: 0,
    enableLogging: function(){
        Zotero._logEnabled++;
        if(Zotero._logEnabled > 0){
            Zotero.prefs.debug_log = true;
        }
    },

    disableLogging: function(){
        Zotero._logEnabled--;
        if(Zotero._logEnabled <= 0){
            Zotero._logEnabled = 0;
            Zotero.prefs.debug_log = false;
        }
    },

    init: function(){
        var store;
        if(Zotero.config.cacheStoreType == 'localStorage' && typeof localStorage != 'undefined'){
            store = localStorage;
        }
        else if(Zotero.config.cacheStoreType == 'sessionStorage' && typeof sessionStorage != 'undefined'){
            store = sessionStorage;
        }
        else{
            store = {};
        }
        Zotero.store = store;

        Zotero.cache = new Zotero.Cache(store);
        //populate prefs with defaults, then override with stored prefs
        Zotero.prefs = J.extend({}, Zotero.defaultPrefs, Zotero.prefs, Zotero.utils.getStoredPrefs());
        /*
        Zotero.prefs = new Zotero.Prefs(store);
        J.each(Zotero.defaultPrefs, function(key, val){
            if(Zotero.prefs.getPref(key) === null){
                Zotero.prefs.setPref(key);
            }
        });
        */
        //get localized item constants if not stored in localstorage
        var locale = 'en-US';
        if(Zotero.config.locale){
            locale = Zotero.config.locale;
        }
        locale = 'en-US';

        J.ajaxSettings.traditional = true;

    }
};

Zotero.Cache = function(store){
    this.store = store;
    var registry = this.store['_registry'];
    if(typeof registry == 'null' || typeof registry == 'undefined'){
        registry = {};
        this.store['_registry'] = JSON.stringify(registry);
    }
};

//build a consistent string from an object to use as a cache key
//put object key/value pairs into array, sort array, and concatenate
//array with '/'
Zotero.Cache.prototype.objectCacheString = function(params){
    var paramVarsArray = [];
    J.each(params, function(index, value){
        if(!value) { return; }
        else if(value instanceof Array){
            J.each(value, function(i, v){
                paramVarsArray.push(index + '/' + encodeURIComponent(v) );
            });
        }
        else{
            paramVarsArray.push(index + '/' + encodeURIComponent(value) );
        }
    });
    paramVarsArray.sort();
    Z.debug(paramVarsArray, 4);
    var objectCacheString = paramVarsArray.join('/');
    return objectCacheString;
};

//should use setItem and getItem if I extend that to the case where no Storage object is available in the browser
Zotero.Cache.prototype.save = function(params, object, cachetags){
    //cachetags for expiring entries
    if(!J.isArray(cachetags)){
        cachetags = [];
    }
    //get registry object from storage
    var registry = JSON.parse(this.store['_registry']);
    if(!registry){
        registry = {};
    }
    var objectCacheString = this.objectCacheString(params);
    //save object in storage
    this.store[objectCacheString] = JSON.stringify(object);
    //make registry entry for object
    var registryEntry = {'id':objectCacheString, saved:Date.now(), cachetags:cachetags};
    registry[objectCacheString] = registryEntry;
    //save registry back to storage
    this.store['_registry'] = JSON.stringify(registry);
};

Zotero.Cache.prototype.load = function(params){
    Z.debug("Zotero.Cache.load", 3);
    var objectCacheString = this.objectCacheString(params);
    Z.debug(objectCacheString, 4);
    try{
        var s = this.store[objectCacheString];
        if(!s){
            Z.debug("No value found in cache store - " + objectCacheString, 3);
            return null;
        }
        else{
            return JSON.parse(s);
        }
    }
    catch(e){
        Z.debug('Error parsing retrieved cache data', 1);
        Z.debug(objectCacheString, 2);
        Z.debug(this.store[objectCacheString], 2);
        return null;
    }
};

Zotero.Cache.prototype.expireCacheTag = function(tag){
    Z.debug("Zotero.Cache.expireCacheTag", 3);
    var registry = JSON.parse(this.store['_registry']);
    var store = this.store;
    J.each(registry, function(index, value){
        if(J.inArray(tag, value.cachetags) != (-1) ){
            Z.debug('tag ' + tag + ' found for item ' + value['id'] + ' : expiring', 4);
            delete store[value['id']];
            delete registry[value['id']];
        }
    });
};

Zotero.Cache.prototype.clear = function(){
    if(typeof(this.store.clear) == 'function'){
        this.store.clear();
    }
    else{
        this.store = {};
    }
};

Zotero.PrefManager = function(store){
    this.store = store;
};

Zotero.PrefManager.prototype.setPref = function(key, val){
    var prefs = this.store["userpreferences"];
    if(typeof prefs === "undefined"){
        prefs = {};
    }
    prefs[key] = val;
    this.store["userpreferences"] = prefs;
};

Zotero.PrefManager.prototype.setPrefs = function(prefs){
    if(typeof(prefs) != "object") {
        throw "Preferences must be an object";
    }
    this.store["userpreferences"] = prefs;
};

Zotero.PrefManager.prototype.getPrefs = function(){
    var prefs = this.store["userpreferences"];
    if(typeof prefs === "undefined") {
        return {};
    }
    return prefs;
};

Zotero.PrefManager.prototype.getPref = function(key){
    var prefs = this.store["userpreferences"];
    if(typeof prefs === "undefined"){
        return null;
    }
    return prefs["key"];
};

//make a request to the Zotero api and get back a deferred
Zotero.apiRequest = function(url, method, body, headers){
    Z.debug("Zotero.apiRequest", 3);
    if(typeof method == 'undefined'){
        method = 'GET';
    }
    if(typeof headers == 'undefined'){
        headers = {};
    }

    var settings = {type: method,
                    headers:headers,
                    cache:false,
                    error: Zotero.ajax.errorCallback
                    };
    if(typeof body != 'undefined') {
        settings['data'] = body;
    }

    var jqxhr = J.ajax(Zotero.ajax.proxyWrapper(url, method), settings);
    return jqxhr;
};

Zotero.error = function(e){
    Z.debug("====================Zotero Error", 1);
    Z.debug(e, 1);
};

Zotero.saveLibrary = function(library){
    var dump = {};
    dump.libraryType = library.libraryType;
    dump.libraryID = library.libraryID;
    dump.libraryUrlIdentifier = library.libraryUrlIdentifier;
    dump.itemKeys = library.itemKeys;

    dump.collections = library.collections.dump();
    dump.items = library.items.dump();
    dump.tags = library.tags.dump();
    Zotero.cache.save({libraryString:library.libraryString}, dump);
};

Zotero.loadLibrary = function(params){
    Z.debug("Zotero.loadLibrary");
    Z.debug(params);
    var dump = Zotero.cache.load(params);
    if(dump === null){
        Z.debug("no library found in cache");
        return false;
    }

    var library = new Zotero.Library(dump.libraryType, dump.libraryID, dump.libraryUrlIdentifier);
    library.itemKeys = dump.itemKeys;

    library.collections.loadDump(dump.collections);
    library.items.loadDump(dump.items);
    library.tags.loadDump(dump.tags);

    return library;
};

Zotero.ajaxRequest = function(url, type, options){
    var defaultOptions = {
        type: "GET",
        headers:{},
        cache:false,
        error: Zotero.ajax.errorCallback
    };
    var reqOptions = J.extend({}, defaultOptions, options);
    if(type){
        reqOptions.type = type;
    }

    if(Zotero.config.futureApi) {
        reqOptions.headers['Zotero-API-Version'] = Zotero.config.futureApiVersion;
    }

    var urlstring;
    if(typeof url === "object"){
        urlstring = Zotero.ajax.apiRequestUrl(url) + Zotero.ajax.apiQueryString(url);
    }
    else if(typeof url === "string"){
        urlstring = url;
    }
    Z.debug("library.ajaxRequest urlstring " + urlstring);
    var reqUrl = Zotero.ajax.proxyWrapper(urlstring, type);
    return J.ajax(reqUrl, reqOptions);
};

var Z = Zotero;

<|endoftext|>


<commit_before>/*!
 * Kaiseki
 * Copyright(c) 2012 BJ Basañes / Shiki (shikishiji@gmail.com)
 * MIT Licensed
 */

var request = require('request');
var _ = require('underscore');

var Kaiseki = function(applicationId, restAPIKey) {
  this.applicationId = applicationId;
  this.restAPIKey = restAPIKey;
};

Kaiseki.prototype = {
  API_BASE_URL: 'https://api.parse.com',

  applicationId: null,
  restAPIKey: null,

  createObject: function(className, data, callback) {
    var url = '/1/classes/' + className;
    var wrap = function(err, res, body) {
      if (!err)
        body = _.extend({}, data, body);
      callback(err, res, body);
    };
    this.request('POST', url, data, wrap);
  },

  getObject: function(className, objectId, params, callback) {
    if (_.isFunction(params)) {
      callback = params;
      params = null;
    }
    var wrap = function(err, res, body) {
      if (!err)
        body = JSON.parse(body);
      callback(err, res, body);
    };
    var url = '/1/classes/' + className + '/' + objectId;
    this.request('GET', url, params, wrap);
  },

  updateObject: function(className, objectId, data, callback) {
    var url = '/1/classes/' + className + '/' + objectId;
    this.request('PUT', url, data, callback);
  },

  deleteObject: function(className, objectId, callback) {
    var url = '/1/classes/' + className + '/' + objectId;
    this.request('DELETE', url, null, callback);
  },

  getObjects: function(className, params, callback) {
    if (_.isFunction(params)) {
      callback = params;
      params = null;
    } else {
      params = this.stringifyParamValues(params);
    }
    var wrap = function(err, res, body) {
      if (!err && res.statusCode === 200)
        body = JSON.parse(body).results;
      callback(err, res, body);
    };
    var url = '/1/classes/' + className;
    this.request('GET', url, params, wrap);
  },

  getUsers: function(objectId, params, callback) {
    if (_.isFunction(params)) {
      callback = params;
      params = null;
    }
    var url = '/1/users/' + objectId;
    this.request('GET', url, params, callback);
  },

  stringifyParamValues: function(params) {
    if (!params || _.isEmpty(params))
      return null;
    var values = _(params).map(function(value, key) {
      if (_.isObject(value) || _.isArray(value))
        return JSON.stringify(value);
      else
        return value;
    });
    var keys = _(params).keys();
    var ret = {};
    for (var i = 0; i < keys.length; i++)
      ret[keys[i]] = values[i];
    return ret;
  },

  request: function(method, url, params, callback) {
    url = this.API_BASE_URL + url;
    var options = {
      method: method,
      headers: {
        'X-Parse-Application-Id': this.applicationId,
        'X-Parse-REST-API-Key': this.restAPIKey
      }
    };
    if (params) {
      var key = 'qs';
      if (method === 'POST' || method === 'PUT')
        key = 'json';
      options[key] = params;
    }

    request(url, options, callback);
  }
};

module.exports = Kaiseki;<commit_msg>A little refactoring. Fixed a failing delete object test.<commit_after>/*!
 * Kaiseki
 * Copyright(c) 2012 BJ Basañes / Shiki (shikishiji@gmail.com)
 * MIT Licensed
 */

var request = require('request');
var _ = require('underscore');

var Kaiseki = function(applicationId, restAPIKey) {
  this.applicationId = applicationId;
  this.restAPIKey = restAPIKey;
};

Kaiseki.prototype = {
  API_BASE_URL: 'https://api.parse.com',

  applicationId: null,
  restAPIKey: null,

  createObject: function(className, data, callback) {
    var url = '/1/classes/' + className;
    var wrap = function(err, res, body) {
      if (!err)
        body = _.extend({}, data, body);
      callback(err, res, body);
    };
    this.request('POST', url, data, wrap);
  },

  getObject: function(className, objectId, params, callback) {
    var url = '/1/classes/' + className + '/' + objectId;
    this._jsonRequest('GET', url, params, false, callback);
  },

  updateObject: function(className, objectId, data, callback) {
    var url = '/1/classes/' + className + '/' + objectId;
    this.request('PUT', url, data, callback);
  },

  deleteObject: function(className, objectId, callback) {
    var url = '/1/classes/' + className + '/' + objectId;
    this._jsonRequest('DELETE', url, null, false, callback);
  },

  getObjects: function(className, params, callback) {
    var url = '/1/classes/' + className;
    this._jsonRequest('GET', url, params, true, callback);
  },

  getUsers: function(objectId, params, callback) {
    if (_.isFunction(params)) {
      callback = params;
      params = null;
    }
    var url = '/1/users/' + objectId;
    this.request('GET', url, params, callback);
  },

  stringifyParamValues: function(params) {
    if (!params || _.isEmpty(params))
      return null;
    var values = _(params).map(function(value, key) {
      if (_.isObject(value) || _.isArray(value))
        return JSON.stringify(value);
      else
        return value;
    });
    var keys = _(params).keys();
    var ret = {};
    for (var i = 0; i < keys.length; i++)
      ret[keys[i]] = values[i];
    return ret;
  },

  request: function(method, url, params, callback) {
    url = this.API_BASE_URL + url;
    var options = {
      method: method,
      headers: {
        'X-Parse-Application-Id': this.applicationId,
        'X-Parse-REST-API-Key': this.restAPIKey
      }
    };
    if (params) {
      var key = 'qs';
      if (method === 'POST' || method === 'PUT')
        key = 'json';
      options[key] = params;
    }

    request(url, options, callback);
  },

  _jsonRequest: function(method, url, params, expectArray, callback) {
    if (_.isFunction(params)) {
      callback = params;
      params = null;
    } else {
      params = this.stringifyParamValues(params);
    }
    var wrap = function(err, res, body) {
      if (!err)
        body = expectArray ? JSON.parse(body).results : JSON.parse(body);
      callback(err, res, body);
    };
    this.request(method, url, params, wrap);
  }
};

module.exports = Kaiseki;<|endoftext|>