<commit_before>
/**
 * Module dependencies.
 */

var deprecate = require('util-deprecate');
var DOMParser = require('xmldom').DOMParser;

/**
 * Module exports.
 */

exports.parse = parse;
exports.parseString = deprecate(parseString, '`parseString()` is deprecated. ' +
  'It\'s not actually async. Use `parse()` instead.');
exports.parseStringSync = deprecate(parseStringSync, '`parseStringSync()` is ' +
  'deprecated. Use `parse()` instead.');

/**
 * We ignore raw text (usually whitespace), <!-- xml comments -->,
 * and raw CDATA nodes.
 *
 * @param {Element} node
 * @returns {Boolean}
 * @api private
 */

function shouldIgnoreNode (node) {
  return node.nodeType === 3 // text
    || node.nodeType === 8   // comment
    || node.nodeType === 4;  // cdata
}

/**
 * Parses a Plist XML string. Returns an Object.
 *
 * @param {String} xml - the XML String to decode
 * @returns {Mixed} the decoded value from the Plist XML
 * @api public
 */

function parse (xml) {
  var doc = new DOMParser().parseFromString(xml);
  if (doc.documentElement.nodeName !== 'plist') {
    throw new Error('malformed document. First element should be <plist>');
  }
  var plist = parsePlistXML(doc.documentElement);

  // the root <plist> node gets interpreted as an Array,
  // so pull out the inner data first
  if (plist.length == 1) plist = plist[0];

  return plist;
}

/**
 * Parses a Plist XML string. Returns an Object. Takes a `callback` function.
 *
 * @param {String} xml - the XML String to decode
 * @param {Function} callback - callback function
 * @returns {Mixed} the decoded value from the Plist XML
 * @api public
 * @deprecated not actually async. use parse() instead
 */

function parseString (xml, callback) {
  var doc, error, plist;
  try {
    doc = new DOMParser().parseFromString(xml);
    plist = parsePlistXML(doc.documentElement);
  } catch(e) {
    error = e;
  }
  callback(error, plist);
}

/**
 * Parses a Plist XML string. Returns an Object.
 *
 * @param {String} xml - the XML String to decode
 * @param {Function} callback - callback function
 * @returns {Mixed} the decoded value from the Plist XML
 * @api public
 * @deprecated use parse() instead
 */

function parseStringSync (xml) {
  var doc = new DOMParser().parseFromString(xml);
  var plist;
  if (doc.documentElement.nodeName !== 'plist') {
    throw new Error('malformed document. First element should be <plist>');
  }
  plist = parsePlistXML(doc.documentElement);

  // if the plist is an array with 1 element, pull it out of the array
  if (plist.length == 1) {
    plist = plist[0];
  }
  return plist;
}

/**
 * Convert an XML based plist document into a JSON representation.
 *
 * @param {Object} xml_node - current XML node in the plist
 * @returns {Mixed} built up JSON object
 * @api private
 */

function parsePlistXML (node) {
  var i, new_obj, key, val, new_arr, res, d;

  if (!node)
    return null;

  if (node.nodeName === 'plist') {
    new_arr = [];
    for (i=0; i < node.childNodes.length; i++) {
      // ignore comment nodes (text)
      if (!shouldIgnoreNode(node.childNodes[i])) {
        new_arr.push( parsePlistXML(node.childNodes[i]));
      }
    }
    return new_arr;

  } else if (node.nodeName === 'dict') {
    new_obj = {};
    key = null;
    for (i=0; i < node.childNodes.length; i++) {
      // ignore comment nodes (text)
      if (!shouldIgnoreNode(node.childNodes[i])) {
        if (key === null) {
          key = parsePlistXML(node.childNodes[i]);
        } else {
          new_obj[key] = parsePlistXML(node.childNodes[i]);
          key = null;
        }
      }
    }
    return new_obj;

  } else if (node.nodeName === 'array') {
    new_arr = [];
    for (i=0; i < node.childNodes.length; i++) {
      // ignore comment nodes (text)
      if (!shouldIgnoreNode(node.childNodes[i])) {
        res = parsePlistXML(node.childNodes[i]);
        if (null != res) new_arr.push(res);
      }
    }
    return new_arr;

  } else if (node.nodeName === '#text') {
    // TODO: what should we do with text types? (CDATA sections)

  } else if (node.nodeName === 'key') {
    return node.childNodes[0].nodeValue;

  } else if (node.nodeName === 'string') {
    res = '';
    for (d=0; d < node.childNodes.length; d++) {
      res += node.childNodes[d].nodeValue;
    }
    return res;

  } else if (node.nodeName === 'integer') {
    // parse as base 10 integer
    return parseInt(node.childNodes[0].nodeValue, 10);

  } else if (node.nodeName === 'real') {
    res = '';
    for (d=0; d < node.childNodes.length; d++) {
      if (node.childNodes[d].nodeType === 3) {
        res += node.childNodes[d].nodeValue;
      }
    }
    return parseFloat(res);

  } else if (node.nodeName === 'data') {
    res = '';
    for (d=0; d < node.childNodes.length; d++) {
      if (node.childNodes[d].nodeType === 3) {
        res += node.childNodes[d].nodeValue.replace(/\s+/g, '');
      }
    }

    // decode base64 data to a Buffer instance
    return new Buffer(res, 'base64');

  } else if (node.nodeName === 'date') {
    return new Date(node.childNodes[0].nodeValue);

  } else if (node.nodeName === 'true') {
    return true;

  } else if (node.nodeName === 'false') {
    return false;
  }
}
<commit_msg>Fix Cannot read property 'nodeValue' of undefined exception that is thrown when a <key></key> construct appears in plist<commit_after>
/**
 * Module dependencies.
 */

var deprecate = require('util-deprecate');
var DOMParser = require('xmldom').DOMParser;

/**
 * Module exports.
 */

exports.parse = parse;
exports.parseString = deprecate(parseString, '`parseString()` is deprecated. ' +
  'It\'s not actually async. Use `parse()` instead.');
exports.parseStringSync = deprecate(parseStringSync, '`parseStringSync()` is ' +
  'deprecated. Use `parse()` instead.');

/**
 * We ignore raw text (usually whitespace), <!-- xml comments -->,
 * and raw CDATA nodes.
 *
 * @param {Element} node
 * @returns {Boolean}
 * @api private
 */

function shouldIgnoreNode (node) {
  return node.nodeType === 3 // text
    || node.nodeType === 8   // comment
    || node.nodeType === 4;  // cdata
}

/**
 * Parses a Plist XML string. Returns an Object.
 *
 * @param {String} xml - the XML String to decode
 * @returns {Mixed} the decoded value from the Plist XML
 * @api public
 */

function parse (xml) {
  var doc = new DOMParser().parseFromString(xml);
  if (doc.documentElement.nodeName !== 'plist') {
    throw new Error('malformed document. First element should be <plist>');
  }
  var plist = parsePlistXML(doc.documentElement);

  // the root <plist> node gets interpreted as an Array,
  // so pull out the inner data first
  if (plist.length == 1) plist = plist[0];

  return plist;
}

/**
 * Parses a Plist XML string. Returns an Object. Takes a `callback` function.
 *
 * @param {String} xml - the XML String to decode
 * @param {Function} callback - callback function
 * @returns {Mixed} the decoded value from the Plist XML
 * @api public
 * @deprecated not actually async. use parse() instead
 */

function parseString (xml, callback) {
  var doc, error, plist;
  try {
    doc = new DOMParser().parseFromString(xml);
    plist = parsePlistXML(doc.documentElement);
  } catch(e) {
    error = e;
  }
  callback(error, plist);
}

/**
 * Parses a Plist XML string. Returns an Object.
 *
 * @param {String} xml - the XML String to decode
 * @param {Function} callback - callback function
 * @returns {Mixed} the decoded value from the Plist XML
 * @api public
 * @deprecated use parse() instead
 */

function parseStringSync (xml) {
  var doc = new DOMParser().parseFromString(xml);
  var plist;
  if (doc.documentElement.nodeName !== 'plist') {
    throw new Error('malformed document. First element should be <plist>');
  }
  plist = parsePlistXML(doc.documentElement);

  // if the plist is an array with 1 element, pull it out of the array
  if (plist.length == 1) {
    plist = plist[0];
  }
  return plist;
}

/**
 * Convert an XML based plist document into a JSON representation.
 *
 * @param {Object} xml_node - current XML node in the plist
 * @returns {Mixed} built up JSON object
 * @api private
 */

function parsePlistXML (node) {
  var i, new_obj, key, val, new_arr, res, d;

  if (!node)
    return null;

  if (node.nodeName === 'plist') {
    new_arr = [];
    for (i=0; i < node.childNodes.length; i++) {
      // ignore comment nodes (text)
      if (!shouldIgnoreNode(node.childNodes[i])) {
        new_arr.push( parsePlistXML(node.childNodes[i]));
      }
    }
    return new_arr;

  } else if (node.nodeName === 'dict') {
    new_obj = {};
    key = null;
    for (i=0; i < node.childNodes.length; i++) {
      // ignore comment nodes (text)
      if (!shouldIgnoreNode(node.childNodes[i])) {
        if (key === null) {
          key = parsePlistXML(node.childNodes[i]);
        } else {
          new_obj[key] = parsePlistXML(node.childNodes[i]);
          key = null;
        }
      }
    }
    return new_obj;

  } else if (node.nodeName === 'array') {
    new_arr = [];
    for (i=0; i < node.childNodes.length; i++) {
      // ignore comment nodes (text)
      if (!shouldIgnoreNode(node.childNodes[i])) {
        res = parsePlistXML(node.childNodes[i]);
        if (null != res) new_arr.push(res);
      }
    }
    return new_arr;

  } else if (node.nodeName === '#text') {
    // TODO: what should we do with text types? (CDATA sections)

  } else if (node.nodeName === 'key') {
    res = '';
    if(node.childNodes[0]) {
      res = node.childNodes[0].nodeValue;
    }
    return res;

  } else if (node.nodeName === 'string') {
    res = '';
    for (d=0; d < node.childNodes.length; d++) {
      res += node.childNodes[d].nodeValue;
    }
    return res;

  } else if (node.nodeName === 'integer') {
    // parse as base 10 integer
    return parseInt(node.childNodes[0].nodeValue, 10);

  } else if (node.nodeName === 'real') {
    res = '';
    for (d=0; d < node.childNodes.length; d++) {
      if (node.childNodes[d].nodeType === 3) {
        res += node.childNodes[d].nodeValue;
      }
    }
    return parseFloat(res);

  } else if (node.nodeName === 'data') {
    res = '';
    for (d=0; d < node.childNodes.length; d++) {
      if (node.childNodes[d].nodeType === 3) {
        res += node.childNodes[d].nodeValue.replace(/\s+/g, '');
      }
    }

    // decode base64 data to a Buffer instance
    return new Buffer(res, 'base64');

  } else if (node.nodeName === 'date') {
    return new Date(node.childNodes[0].nodeValue);

  } else if (node.nodeName === 'true') {
    return true;

  } else if (node.nodeName === 'false') {
    return false;
  }
}
<|endoftext|>


<commit_before>'use strict';
Java.perform(function(argument) {
  var Context = Java.use("android.content.Context");
  var BluetoothGatt = Dalvik.use("android.bluetooth.BluetoothGatt");
  var BluetoothGattCharacteristic = Dalvik.use("android.bluetooth.BluetoothGattCharacteristic");

  BluetoothGatt.readCharacteristic.overload("android.bluetooth.BluetoothGattCharacteristic").implementation = function(characteristic) {
    //console.log("characteristic: ", characteristic.getUuid(), " readCharacteristic: ", characteristic.getValue());
    /*   --- Payload Header --- */
    var send_data = {};
    send_data.time = new Date();
    send_data.txnType = 'Bluetooth';
    send_data.lib = 'android.bluetooth.BluetoothGatt';
    send_data.method = 'readCharacteristic';
    send_data.artifact = [];
    /*   --- Payload Body --- */
    var data = {};
    data.name = characteristic.getUuid().toString();
    data.value = characteristic.getValue().toString();
    data.argSeq = 0;
    send_data.artifact.push(data);
    send(JSON.stringify(send_data));
    return this.readCharacteristic.overload("android.bluetooth.BluetoothGattCharacteristic").apply(this, arguments);
  };

  BluetoothGattCharacteristic.setValue.overload("[B").implementation = function(value) {
    //console.log("characteristic: ", this.getUuid(), " setValue [B: ", value);
    /*   --- Payload Header --- */
    var send_data = {};
    send_data.time = new Date();
    send_data.txnType = 'Bluetooth';
    send_data.lib = 'android.bluetooth.BluetoothGattCharacteristic';
    send_data.method = 'setValue';
    send_data.artifact = [];
    /*   --- Payload Body --- */
    var data = {};
    data.name = this.getUuid().toString();
    data.value = value.toString();
    data.argSeq = 0;
    send_data.artifact.push(data);
    send(JSON.stringify(send_data));
    return this.setValue.overload("[B").apply(this, arguments);
  };

});<commit_msg>PR refactor<commit_after>'use strict';
Java.perform(function(argument) {
  var Context = Java.use("android.content.Context");
  var BluetoothGatt = Java.use("android.bluetooth.BluetoothGatt");
  var BluetoothGattCharacteristic = Java.use("android.bluetooth.BluetoothGattCharacteristic");

  BluetoothGatt.readCharacteristic.overload("android.bluetooth.BluetoothGattCharacteristic").implementation = function(characteristic) {
    //console.log("characteristic: ", characteristic.getUuid(), " readCharacteristic: ", characteristic.getValue());
    /*   --- Payload Header --- */
    var send_data = {};
    send_data.time = new Date();
    send_data.txnType = 'Bluetooth';
    send_data.lib = 'android.bluetooth.BluetoothGatt';
    send_data.method = 'readCharacteristic';
    send_data.artifact = [];
    /*   --- Payload Body --- */
    var data = {};
    data.name = characteristic.getUuid().toString();
    data.value = characteristic.getValue().toString();
    data.argSeq = 0;
    send_data.artifact.push(data);
    send(JSON.stringify(send_data));
    return this.readCharacteristic.overload("android.bluetooth.BluetoothGattCharacteristic").apply(this, arguments);
  };

  BluetoothGattCharacteristic.setValue.overload("[B").implementation = function(value) {
    //console.log("characteristic: ", this.getUuid(), " setValue [B: ", value);
    /*   --- Payload Header --- */
    var send_data = {};
    send_data.time = new Date();
    send_data.txnType = 'Bluetooth';
    send_data.lib = 'android.bluetooth.BluetoothGattCharacteristic';
    send_data.method = 'setValue';
    send_data.artifact = [];
    /*   --- Payload Body --- */
    var data = {};
    data.name = this.getUuid().toString();
    data.value = value.toString();
    data.argSeq = 0;
    send_data.artifact.push(data);
    send(JSON.stringify(send_data));
    return this.setValue.overload("[B").apply(this, arguments);
  };

});<|endoftext|>


<commit_before>
/*!
 * Connect
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var http = require('http')
  , res = http.ServerResponse.prototype
  , setHeader = res.setHeader
  , _renderHeaders = res._renderHeaders
  , writeHead = res.writeHead;

// apply only once

if (!res._hasConnectPatch) {

  /**
   * Provide a public "header sent" flag
   * until node does.
   *
   * @return {Boolean}
   * @api public
   */

  res.__defineGetter__('headerSent', function(){
    return this._header;
  });

  /**
   * Set header `field` to `val`, special-casing
   * the `Set-Cookie` field for multiple support.
   *
   * @param {String} field
   * @param {String} val
   * @api public
   */

  res.setHeader = function(field, val){
    var key = field.toLowerCase()
      , prev;

    // special-case Set-Cookie
    if (this._headers && 'set-cookie' == key) {
      if (prev = this.getHeader(field)) {
        val = Array.isArray(prev)
          ? prev.concat(val)
          : [prev, val];
      }
    // charset
    } else if ('content-type' == key && this.charset) {
      val += '; charset=' + this.charset;
    }

    return setHeader.call(this, field, val);
  };

  /**
   * Proxy to emit "header" event.
   */

  res._renderHeaders = function(){
    if (!this._emittedHeader) this.emit('header');
    this._emittedHeader = true;
    return _renderHeaders.call(this);
  };

  res.writeHead = function(){
    if (!this._emittedHeader) this.emit('header');
    this._emittedHeader = true;
    return writeHead.apply(this, arguments);
  };

  res._hasConnectPatch = true;
}
<commit_msg>Set-Cookie Header have mupltile cookies as its value while prxiing from Node to Rails<commit_after>
/*!
 * Connect
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var http = require('http')
  , res = http.ServerResponse.prototype
  , setHeader = res.setHeader
  , _renderHeaders = res._renderHeaders
  , writeHead = res.writeHead;

// apply only once

if (!res._hasConnectPatch) {

  /**
   * Provide a public "header sent" flag
   * until node does.
   *
   * @return {Boolean}
   * @api public
   */

  res.__defineGetter__('headerSent', function(){
    return this._header;
  });

  /**
   * Set header `field` to `val`, special-casing
   * the `Set-Cookie` field for multiple support.
   *
   * @param {String} field
   * @param {String} val
   * @api public
   */

  res.setHeader = function(field, val){
    var key = field.toLowerCase()
      , prev;

    // special-case Set-Cookie
    if (this._headers && 'set-cookie' == key) {
      if (prev = this.getHeader(field)) {
          if (Array.isArray(prev)) {
              val = prev.concat(val);
          } else if (Array.isArray(val)) {
              val = val.concat(prev);
          } else {
              val = [prev, val];
          }
      }
    // charset
    } else if ('content-type' == key && this.charset) {
      val += '; charset=' + this.charset;
    }

    return setHeader.call(this, field, val);
  };

  /**
   * Proxy to emit "header" event.
   */

  res._renderHeaders = function(){
    if (!this._emittedHeader) this.emit('header');
    this._emittedHeader = true;
    return _renderHeaders.call(this);
  };

  res.writeHead = function(){
    if (!this._emittedHeader) this.emit('header');
    this._emittedHeader = true;
    return writeHead.apply(this, arguments);
  };

  res._hasConnectPatch = true;
}
<|endoftext|>


<commit_before>// Copyright 2014 Orchestrate, Inc.

// Module Dependencies.
var assert = require('assert');
var Builder = require('./builder');

/**
 * @constructor
 */
function PatchBuilder (collection, key) {
  assert(collection && key, 'Collection and key are required.');
  this._collection = collection;
  this._key = key;
  this._ops = [];
}

require('util').inherits(PatchBuilder, Builder);

/**
 * Add a value at the given path in the JSON document
 * @param {string} path - JSON document path; delimited by periods or slashes
 * @param {Object} value - Value to store at the given path
 */
PatchBuilder.prototype.add = function (path, value) {
  assert(path, 'Add requires a path parameter.');
  this._ops.push({"op": "add", "path": path, "value": value});
  return this;
};

/**
 * Remove a value from the given path in the JSON document
 * @param {string} path - JSON document path; delimited by periods or slashes
 */
PatchBuilder.prototype.remove = function (path) {
  assert(path, 'Remove requires a path parameter.');
  this._ops.push({"op": "remove", "path": path});
  return this;
};

/**
 * Replace a value at the given path in the JSON document
 * @param {string} path - JSON document path; delimited by periods or slashes
 * @param {Object} value - Value to replace at the given {path}
 */
PatchBuilder.prototype.replace = function (path, value) {
  assert(path, 'Replace requires a path parameter.');
  this._ops.push({"op": "replace", "path": path, "value": value});
  return this;
};

/**
 * Move a value at from one path in the JSON document to another path
 * @param {string} from - Source from which to move the value
 * @param {string} path - Destination document path for the value
 */
PatchBuilder.prototype.move = function (from, path) {
  assert(from && path, 'Move requires from and path parameters.');
  this._ops.push({"op": "move", "from": from, "path": path});
  return this;
};

/**
 * Copy a value at from one path in the JSON document to another path
 * @param {string} from - Source path from which to copy the value
 * @param {string} path - Destination path for the value
 */
PatchBuilder.prototype.copy = function (from, path) {
  assert(from && path, 'Copy requires from and path parameters.');
  this._ops.push({"op": "copy", "from": from, "path": path});
  return this;
};

/**
 * Test equality of a value at the specified JSON document path
 * @param {string} path - JSON document path; delimtied by periods or slashes
 * @param {Object} value - Value to compare against
 */
PatchBuilder.prototype.test = function (path, value) {
  assert(path, 'Test requires a path parameter.');
  this._ops.push({"op": "test", "path": path, "value": value});
  return this;
};

/**
 * Increase the value at the specified JSON document path by the given number
 * @param {string} path - JSON document path; delimtied by periods or slashes
 * @param {Object} value - Number by which to increase the value
 */
PatchBuilder.prototype.inc = function (path, value) {
  assert(path, 'Inc requires a path parameter.');
  assert(value, 'Inc requires a path parameter.');
  this._ops.push({"op": "inc", "path": path, "value": value});
  return this;
};

/**
 * return {Promise}
 */
PatchBuilder.prototype.apply = function (match) {
  assert(this._ops.length > 0, 'At least one operation is required in a patch operation.');
  assert(this.getDelegate(), 'No client delegate assigned');
  var pathArgs = [this._collection, this._key];
  var url = this.getDelegate().generateApiUrl(pathArgs);
  var header = {'Content-Type': 'application/json-patch+json'};
  if (typeof match === 'string') header['If-Match'] = this.getDelegate()._quote(match);
  return this.getDelegate()._patch(url, this._ops, header);
};

// Module Exports.
module.exports = PatchBuilder;
<commit_msg>address @housejester comments<commit_after>// Copyright 2014 Orchestrate, Inc.

// Module Dependencies.
var assert = require('assert');
var Builder = require('./builder');

/**
 * @constructor
 */
function PatchBuilder (collection, key) {
  assert(collection && key, 'Collection and key are required.');
  this._collection = collection;
  this._key = key;
  this._ops = [];
}

require('util').inherits(PatchBuilder, Builder);

/**
 * Add a value at the given path in the JSON document
 * @param {string} path - JSON document path; delimited by periods or slashes
 * @param {Object} value - Value to store at the given path
 */
PatchBuilder.prototype.add = function (path, value) {
  assert(path, 'Add requires a path parameter.');
  this._ops.push({"op": "add", "path": path, "value": value});
  return this;
};

/**
 * Remove a value from the given path in the JSON document
 * @param {string} path - JSON document path; delimited by periods or slashes
 */
PatchBuilder.prototype.remove = function (path) {
  assert(path, 'Remove requires a path parameter.');
  this._ops.push({"op": "remove", "path": path});
  return this;
};

/**
 * Replace a value at the given path in the JSON document
 * @param {string} path - JSON document path; delimited by periods or slashes
 * @param {Object} value - Value to replace at the given {path}
 */
PatchBuilder.prototype.replace = function (path, value) {
  assert(path, 'Replace requires a path parameter.');
  this._ops.push({"op": "replace", "path": path, "value": value});
  return this;
};

/**
 * Move a value at from one path in the JSON document to another path
 * @param {string} from - Source from which to move the value
 * @param {string} path - Destination document path for the value
 */
PatchBuilder.prototype.move = function (from, path) {
  assert(from && path, 'Move requires from and path parameters.');
  this._ops.push({"op": "move", "from": from, "path": path});
  return this;
};

/**
 * Copy a value at from one path in the JSON document to another path
 * @param {string} from - Source path from which to copy the value
 * @param {string} path - Destination path for the value
 */
PatchBuilder.prototype.copy = function (from, path) {
  assert(from && path, 'Copy requires from and path parameters.');
  this._ops.push({"op": "copy", "from": from, "path": path});
  return this;
};

/**
 * Test equality of a value at the specified JSON document path
 * @param {string} path - JSON document path; delimtied by periods or slashes
 * @param {Object} value - Value to compare against
 */
PatchBuilder.prototype.test = function (path, value) {
  assert(path, 'Test requires a path parameter.');
  this._ops.push({"op": "test", "path": path, "value": value});
  return this;
};

/**
 * Increase the value at the specified JSON document path by the given number
 * @param {string} path - JSON document path; delimtied by periods or slashes
 * @param {Object} value - Number by which to increase the value
 */
PatchBuilder.prototype.inc = function (path, value) {
  assert(path, 'Inc requires a path parameter.');
  var op = {
    op: "inc",
    path: path,
  };
  if (value) op.value = value;
  this._ops.push(op);
  return this;
};

/**
 * return {Promise}
 */
PatchBuilder.prototype.apply = function (match) {
  assert(this._ops.length > 0, 'At least one operation is required in a patch operation.');
  assert(this.getDelegate(), 'No client delegate assigned');
  var pathArgs = [this._collection, this._key];
  var url = this.getDelegate().generateApiUrl(pathArgs);
  var header = {'Content-Type': 'application/json-patch+json'};
  if (typeof match === 'string') header['If-Match'] = this.getDelegate()._quote(match);
  return this.getDelegate()._patch(url, this._ops, header);
};

// Module Exports.
module.exports = PatchBuilder;
<|endoftext|>


<commit_before>JanusFireboxParser = function() {
}

JanusFireboxParser.prototype.parse = function(source, baseurl, datapath) {
  var xml = this.parseXML(source, false, true);
  var rooms = this.getAsArray(this.arrayget(xml, 'fireboxroom._children.room', {}));
  var room = {_children: {}};
  for (var i = 0; i < rooms.length; i++) {
    var attrs = Object.keys(rooms[i]).filter(function(k) { return (k[0] != '_'); });
    attrs.forEach(function(k) {
      room[k] = rooms[i][k];
    });
    if (rooms[i]._children) {
      Object.keys(rooms[i]._children).forEach(function(k) {
        room._children[k] = rooms[i]._children[k];
      });
    }
  }
  var roomdata = this.getRoomData(xml, room, baseurl, datapath);
  roomdata.source = source;
  return roomdata;
}
JanusFireboxParser.prototype.getRoomData = function(xml, room, baseurl, datapath) {
  var assets = this.parseAssets(xml, baseurl, datapath);

  var parseNode = this.parseNode.bind(this);

  var roomdata = {
    assets: assets,
    room: this.parseNode(room)
  };
  for (var k in room._children) {
    var objects = this.getAsArray(room._children[k]);
    roomdata[k] = objects.map(parseNode);
  }

  // TODO - some rooms have orphan objects, outside of the <Room> tag.
  // We should parse these too, but I don't have any examples to test with
/*
  var orphantypes = ['link', 'image', 'image3d', 'video', 'sound', 'text', 'paragraph', 'light', 'particle', 'ghost'];
  for (var i = 0; i < orphantypes.length; i++) {
    var type = orphantypes[i],
        orphans = this.getAsArray(this.arrayget(xml, 'fireboxroom._children.' + type));
    if (orphans && orphans.length > 0) {
      if (!roomdata[type]) roomdata[type] = [];
      roomdata[type].push.apply(roomdata[type], orphans);
    }
  };
*/
  return roomdata;
}
JanusFireboxParser.prototype.getAsArray = function(arr) {
  return (arr instanceof Array ? arr : [arr]);
}
JanusFireboxParser.prototype.parseAssets = function(xml, baseurl, datapath) {
  var assetxml = this.arrayget(xml, 'fireboxroom._children.assets.0', {});
  var objectassets = this.getAsArray(this.arrayget(assetxml, "_children.assetobject", []));
  var soundassets = this.getAsArray(this.arrayget(assetxml, "_children.assetsound", []));
  var imageassets = this.getAsArray(this.arrayget(assetxml, "_children.assetimage", []));
  var videoassets = this.getAsArray(this.arrayget(assetxml, "_children.assetvideo", []));
  var scriptassets = this.getAsArray(this.arrayget(assetxml, "_children.assetscript", []));
  var ghostassets = this.getAsArray(this.arrayget(assetxml, "_children.assetghost", []));
  var websurfaceassets = this.getAsArray(this.arrayget(assetxml, "_children.assetwebsurface", []));
  var shaderassets = this.getAsArray(this.arrayget(assetxml, "_children.assetshader", []));
  var assetlist = [];
  if (!datapath) {
    datapath = 'http://web.janusvr.com/media';
  }
  var fixURLEncoding = this.fixURLEncoding.bind(this);
  imageassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype: 'image',
      name: n.id,
      src: src,
      baseurl: baseurl,
      hasalpha: n.hasalpha,
      proxy: n.proxy,
      sbs3d: n.sbs3d,
      ou3d: n.ou3d,
      flipy: n.flipy,
      reverse3d: n.reverse3d,
    });
  });
  videoassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'video',
      name:n.id,
      src: src,
      loop: n.loop,
      sbs3d: n.sbs3d == 'true',
      ou3d: n.ou3d == 'true',
      hasalpha: n.hasalpha == 'true',
      flipy: n.flipy,
      reverse3d: n.reverse3d,
      auto_play: n.auto_play == 'true',
      baseurl: baseurl,
      proxy: n.proxy && n.proxy != 'false'
    });
  });
  soundassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'sound',
      name:n.id,
      src: src,
      baseurl: baseurl
    });
  });
  var websurfaces = {};
  websurfaceassets.forEach(function(n) { websurfaces[n.id] = n; });
  scriptassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'script',
      name: src,
      src: src,
      baseurl: baseurl
    });
  });
  shaderassets.forEach(function(n) {
    n.uniforms = (n._children && n._children.uniform ? n._children.uniform : false);
    assetlist.push({
      assettype: 'shader',
      name: n.id,
      fragment_src: n.src,
      vertex_src: n.vertex_src,
      uniforms: n.uniforms,
      baseurl: baseurl,
    });
  });

  var objlist = [];
  objectassets.forEach(function(n) {
    if (n.src) {
      var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
      var mtlsrc = (n.mtl && n.mtl.match(/^file:/) ? n.mtl.replace(/^file:/, datapath) : n.mtl);
      if (mtlsrc && !mtlsrc.match(/^(https?:)?\/\//)) mtlsrc = baseurl + mtlsrc;
      var srcparts = src.split(' ');
      src = srcparts[0];
      assetlist.push({assettype: 'model', name: n.id, src: src, mtl: mtlsrc, tex_linear: n.tex_linear, tex0: n.tex || n.tex0 || srcparts[1], tex1: n.tex1 || srcparts[2], tex2: n.tex2 || srcparts[3], tex3: n.tex3 || srcparts[4]});
    }
  });
  var assets = {
    object: objectassets,
    image: imageassets,
    sound: soundassets,
    video: videoassets,
    websurfaces: websurfaces,
    scripts: scriptassets,
    ghosts: ghostassets,
    shaders: shaderassets,
    assetlist: assetlist
  };
  return assets;
}

JanusFireboxParser.prototype.getVectorValue = function(vector, defaultvalue) {
  if (typeof defaultvalue == 'undefined') {
    defaultvalue = null;//[0,0,0];
  }
  if (typeof vector == 'string') {
    return vector.trim().split(' ').map(parseFloat);
  } else if (vector instanceof THREE.Vector3) {
    return vector.toArray();
  } else if (typeof vector == 'undefined') {
    return defaultvalue;
  }
  return vector;
}
JanusFireboxParser.prototype.parseNode = function(n) {
  var nodeinfo = {};
  var attrs = Object.keys(n);
  attrs.forEach(function(k) {
    nodeinfo[k] = (n[k] == 'false' ? false : n[k]);
  });

  nodeinfo.pos = this.getVectorValue(n.pos);
  nodeinfo.scale = this.getVectorValue(n.scale, [1,1,1]);
  nodeinfo.orientation = this.getOrientation(n.xdir, n.ydir || n.up, n.zdir || n.fwd);
  nodeinfo.col = (n.col ? (n.col[0] == '#' ? [parseInt(n.col.substr(1,2), 16)/255, parseInt(n.col.substr(3, 2), 16)/255, parseInt(n.col.substr(5, 2), 16)/255] : n.col) : null);

  var minscale = 1e-20;
/*
  nodeinfo.scale[0] = Math.max(minscale, nodeinfo.scale[0]);
  nodeinfo.scale[1] = Math.max(minscale, nodeinfo.scale[1]);
  nodeinfo.scale[2] = Math.max(minscale, nodeinfo.scale[2]);
*/
  if (nodeinfo.scale[0] < minscale && nodeinfo.scale[0] > -minscale) nodeinfo.scale[0] = minscale;
  if (nodeinfo.scale[1] < minscale && nodeinfo.scale[1] > -minscale) nodeinfo.scale[1] = minscale;
  if (nodeinfo.scale[2] < minscale && nodeinfo.scale[2] > -minscale) nodeinfo.scale[2] = minscale;

  return nodeinfo;
}

JanusFireboxParser.prototype.getOrientation = function(xdir, ydir, zdir) {
  if (xdir) {
    xdir = (xdir instanceof THREE.Vector3 ? xdir : new THREE.Vector3().fromArray(xdir.split(' '))).normalize();
  } else {
    xdir = new THREE.Vector3(1,0,0);
  }
  if (ydir) {
    ydir = (ydir instanceof THREE.Vector3 ? ydir : new THREE.Vector3().fromArray(ydir.split(' '))).normalize();
  } else {
    ydir = new THREE.Vector3(0,1,0);
  }
  if (zdir) {
    zdir = (zdir instanceof THREE.Vector3 ? zdir : new THREE.Vector3().fromArray(zdir.split(' '))).normalize();
  } else {
    zdir = new THREE.Vector3(0,0,1);
  }

  var newydir = ydir.clone().sub(zdir).multiplyScalar(ydir.dot(zdir)).normalize();
  xdir.crossVectors(ydir, zdir).normalize();

  var mat4 = new THREE.Matrix4().makeBasis(xdir, ydir, zdir);
  var quat = new THREE.Quaternion();
  var pos = new THREE.Vector3();
  var scale = new THREE.Vector3();
  //quat.setFromRotationMatrix(mat4);
  mat4.decompose(pos, quat, scale);
  quat.normalize();
  //quat.multiply(new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI, 0)));
  return quat;
}
JanusFireboxParser.prototype.parseXML = function(imgxml, leaf, forceLower) {
  var node, root, parent, xmldoc;
  if (imgxml.nodeName) {
    xmldoc = node = imgxml;
  } else {
    try {
      if (window.DOMParser) {
        var parser = new DOMParser();
        xmldoc = parser.parseFromString(imgxml,"application/xml");
        node = xmldoc.children[0];
      } else {
        node = new ActiveXObject("Microsoft.XMLDOM");
        node.async = "false";
        node.loadXML(imgxml).firstChild;
      }

      // Chrome doesn't throw an exception for malformed XML, so we look for a <parsererror> xml tag
      // Firefox now appears to follow the same behavior, but puts the <parsererror> as the top-level element instead of as a child of the last DOM element which parsed successfully
      var parsererrors = (node.tagName == 'parsererror' ? [node] : node.getElementsByTagName("parsererror"));
      if (parsererrors.length > 0) {
        // Extract the message from the first div child of the <parsererror> element
        var errorel = parsererrors[0].getElementsByTagName('div')[0] || parsererrors[0];
        throw new JanusFireboxParserException(errorel.innerHTML);
      }
    } catch (e) {
      throw new JanusFireboxParserException(e.message);
    }
  }
  root = {};
  if (!leaf) {
    var rootname = node.tagName;
    if (forceLower) rootname = rootname.toLowerCase();
    if (!root[rootname]) root[rootname] = {};
    parent = root[rootname];
    //node = parent[node.tagName];
  } else {
    parent = root;
  }
  if (node.attributes) {
    for (var i = 0; i < node.attributes.length; i++) {
      var name = node.attributes[i].nodeName;
      if (forceLower) name = name.toLowerCase();
      var value = node.attributes[i].nodeValue;
      parent[name] = value;
    }
  }
  if (node.childNodes) {
    for (var j = 0; j < node.childNodes.length; j++) {
      var child = node.childNodes[j];
      var nodename = child.nodeName;
      if (forceLower) nodename = nodename.toLowerCase();
      if (!parent._children) parent._children = {};
      if (!parent._children[nodename]) {
        parent._children[nodename] = [];
      } else if (parent._children[nodename].constructor !== Array) {
        parent._children[nodename] = [parent._children[nodename]];
      }
      if (node.getElementsByTagName(child.tagName).length > 0) {
        parent._children[nodename].push(this.parseXML(child, true, forceLower));
      } else if (child.nodeName) {
        if (child.nodeName == "#text" || child.nodeName == "#cdata-section") {
          // this gets confused if you have multiple text/cdata nodes...
          if (!child.nodeValue.match(/^[\s\n]*$/m)) {
            parent._content = child.nodeValue;
          }
        } else {
          parent._children[nodename] = parent._children[nodename].concat(this.parseXML(child, true, forceLower));
        }
      }
    }
  }
  return root;
};

/**
 * Retrieves specified dot-separated value from a multilevel object element
 *
 * @function JanusFireboxParser.arrayget
 * @param {object} obj
 * @param {string} name
 * @param {object|number|string} [defval] default value if none found
*/
JanusFireboxParser.prototype.arrayget = function(obj, name, defval) {
  var ptr = obj;
  var x = name.split(".");
  for (var i = 0; i < x.length; i++) {
    if (ptr==null || (!(ptr[x[i]] instanceof Array) && !(ptr[x[i]] instanceof Object) && i != x.length-1)) {
      ptr = null;
      break;
    }
    ptr = ptr[x[i]];
  }
  if (typeof ptr == "undefined" || ptr === null) {
    return (typeof defval == "undefined" ? null : defval);
  }
  return ptr;
};

/**
 * Fixes encoding of URL strings if they weren't properly encoded
 *
 * @function JanusFireboxParser.fixURLEncoding
 * @param {string} url
 * @returns {string} encoded URL
*/
JanusFireboxParser.prototype.fixURLEncoding = function(url) {
  var fixed = url;
  if (url.indexOf(' ') != -1) {
    fixed = encodeURI(url);
  }
  return fixed;
};

/**
 * Exception class for XML parse errors
 */
function JanusFireboxParserException(msg) {
  this.message = msg;
}
<commit_msg>Added <assetfont> support<commit_after>JanusFireboxParser = function() {
}

JanusFireboxParser.prototype.parse = function(source, baseurl, datapath) {
  var xml = this.parseXML(source, false, true);
  var rooms = this.getAsArray(this.arrayget(xml, 'fireboxroom._children.room', {}));
  var room = {_children: {}};
  for (var i = 0; i < rooms.length; i++) {
    var attrs = Object.keys(rooms[i]).filter(function(k) { return (k[0] != '_'); });
    attrs.forEach(function(k) {
      room[k] = rooms[i][k];
    });
    if (rooms[i]._children) {
      Object.keys(rooms[i]._children).forEach(function(k) {
        room._children[k] = rooms[i]._children[k];
      });
    }
  }
  var roomdata = this.getRoomData(xml, room, baseurl, datapath);
  roomdata.source = source;
  return roomdata;
}
JanusFireboxParser.prototype.getRoomData = function(xml, room, baseurl, datapath) {
  var assets = this.parseAssets(xml, baseurl, datapath);

  var parseNode = this.parseNode.bind(this);

  var roomdata = {
    assets: assets,
    room: this.parseNode(room)
  };
  for (var k in room._children) {
    var objects = this.getAsArray(room._children[k]);
    roomdata[k] = objects.map(parseNode);
  }

  // TODO - some rooms have orphan objects, outside of the <Room> tag.
  // We should parse these too, but I don't have any examples to test with
/*
  var orphantypes = ['link', 'image', 'image3d', 'video', 'sound', 'text', 'paragraph', 'light', 'particle', 'ghost'];
  for (var i = 0; i < orphantypes.length; i++) {
    var type = orphantypes[i],
        orphans = this.getAsArray(this.arrayget(xml, 'fireboxroom._children.' + type));
    if (orphans && orphans.length > 0) {
      if (!roomdata[type]) roomdata[type] = [];
      roomdata[type].push.apply(roomdata[type], orphans);
    }
  };
*/
  return roomdata;
}
JanusFireboxParser.prototype.getAsArray = function(arr) {
  return (arr instanceof Array ? arr : [arr]);
}
JanusFireboxParser.prototype.parseAssets = function(xml, baseurl, datapath) {
  var assetxml = this.arrayget(xml, 'fireboxroom._children.assets.0', {});
  var objectassets = this.getAsArray(this.arrayget(assetxml, "_children.assetobject", []));
  var soundassets = this.getAsArray(this.arrayget(assetxml, "_children.assetsound", []));
  var imageassets = this.getAsArray(this.arrayget(assetxml, "_children.assetimage", []));
  var videoassets = this.getAsArray(this.arrayget(assetxml, "_children.assetvideo", []));
  var scriptassets = this.getAsArray(this.arrayget(assetxml, "_children.assetscript", []));
  var ghostassets = this.getAsArray(this.arrayget(assetxml, "_children.assetghost", []));
  var websurfaceassets = this.getAsArray(this.arrayget(assetxml, "_children.assetwebsurface", []));
  var shaderassets = this.getAsArray(this.arrayget(assetxml, "_children.assetshader", []));
  var fontassets = this.getAsArray(this.arrayget(assetxml, "_children.assetfont", []));
  var assetlist = [];
  if (!datapath) {
    datapath = 'http://web.janusvr.com/media';
  }
  var fixURLEncoding = this.fixURLEncoding.bind(this);
  imageassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype: 'image',
      name: n.id,
      src: src,
      baseurl: baseurl,
      hasalpha: n.hasalpha,
      proxy: n.proxy,
      sbs3d: n.sbs3d,
      ou3d: n.ou3d,
      flipy: n.flipy,
      reverse3d: n.reverse3d,
    });
  });
  videoassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'video',
      name:n.id,
      src: src,
      loop: n.loop,
      sbs3d: n.sbs3d == 'true',
      ou3d: n.ou3d == 'true',
      hasalpha: n.hasalpha == 'true',
      flipy: n.flipy,
      reverse3d: n.reverse3d,
      auto_play: n.auto_play == 'true',
      baseurl: baseurl,
      proxy: n.proxy && n.proxy != 'false'
    });
  });
  soundassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'sound',
      name:n.id,
      src: src,
      baseurl: baseurl
    });
  });
  var websurfaces = {};
  websurfaceassets.forEach(function(n) { websurfaces[n.id] = n; });
  scriptassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'script',
      name: src,
      src: src,
      baseurl: baseurl
    });
  });
  shaderassets.forEach(function(n) {
    n.uniforms = (n._children && n._children.uniform ? n._children.uniform : false);
    assetlist.push({
      assettype: 'shader',
      name: n.id,
      fragment_src: n.src,
      vertex_src: n.vertex_src,
      uniforms: n.uniforms,
      baseurl: baseurl,
    });
  });
  fontassets.forEach(function(n) {
    assetlist.push({
      assettype: 'font',
      name: n.id,
      src: n.src,
      baseurl: baseurl,
    });
  });

  var objlist = [];
  objectassets.forEach(function(n) {
    if (n.src) {
      var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
      var mtlsrc = (n.mtl && n.mtl.match(/^file:/) ? n.mtl.replace(/^file:/, datapath) : n.mtl);
      if (mtlsrc && !mtlsrc.match(/^(https?:)?\/\//)) mtlsrc = baseurl + mtlsrc;
      var srcparts = src.split(' ');
      src = srcparts[0];
      assetlist.push({assettype: 'model', name: n.id, src: src, mtl: mtlsrc, tex_linear: n.tex_linear, tex0: n.tex || n.tex0 || srcparts[1], tex1: n.tex1 || srcparts[2], tex2: n.tex2 || srcparts[3], tex3: n.tex3 || srcparts[4]});
    }
  });
  var assets = {
    object: objectassets,
    image: imageassets,
    sound: soundassets,
    video: videoassets,
    websurfaces: websurfaces,
    scripts: scriptassets,
    ghosts: ghostassets,
    shaders: shaderassets,
    assetlist: assetlist
  };
  return assets;
}

JanusFireboxParser.prototype.getVectorValue = function(vector, defaultvalue) {
  if (typeof defaultvalue == 'undefined') {
    defaultvalue = null;//[0,0,0];
  }
  if (typeof vector == 'string') {
    return vector.trim().split(' ').map(parseFloat);
  } else if (vector instanceof THREE.Vector3) {
    return vector.toArray();
  } else if (typeof vector == 'undefined') {
    return defaultvalue;
  }
  return vector;
}
JanusFireboxParser.prototype.parseNode = function(n) {
  var nodeinfo = {};
  var attrs = Object.keys(n);
  attrs.forEach(function(k) {
    nodeinfo[k] = (n[k] == 'false' ? false : n[k]);
  });

  nodeinfo.pos = this.getVectorValue(n.pos);
  nodeinfo.scale = this.getVectorValue(n.scale, [1,1,1]);
  nodeinfo.orientation = this.getOrientation(n.xdir, n.ydir || n.up, n.zdir || n.fwd);
  nodeinfo.col = (n.col ? (n.col[0] == '#' ? [parseInt(n.col.substr(1,2), 16)/255, parseInt(n.col.substr(3, 2), 16)/255, parseInt(n.col.substr(5, 2), 16)/255] : n.col) : null);

  var minscale = 1e-20;
/*
  nodeinfo.scale[0] = Math.max(minscale, nodeinfo.scale[0]);
  nodeinfo.scale[1] = Math.max(minscale, nodeinfo.scale[1]);
  nodeinfo.scale[2] = Math.max(minscale, nodeinfo.scale[2]);
*/
  if (nodeinfo.scale[0] < minscale && nodeinfo.scale[0] > -minscale) nodeinfo.scale[0] = minscale;
  if (nodeinfo.scale[1] < minscale && nodeinfo.scale[1] > -minscale) nodeinfo.scale[1] = minscale;
  if (nodeinfo.scale[2] < minscale && nodeinfo.scale[2] > -minscale) nodeinfo.scale[2] = minscale;

  return nodeinfo;
}

JanusFireboxParser.prototype.getOrientation = function(xdir, ydir, zdir) {
  if (xdir) {
    xdir = (xdir instanceof THREE.Vector3 ? xdir : new THREE.Vector3().fromArray(xdir.split(' '))).normalize();
  } else {
    xdir = new THREE.Vector3(1,0,0);
  }
  if (ydir) {
    ydir = (ydir instanceof THREE.Vector3 ? ydir : new THREE.Vector3().fromArray(ydir.split(' '))).normalize();
  } else {
    ydir = new THREE.Vector3(0,1,0);
  }
  if (zdir) {
    zdir = (zdir instanceof THREE.Vector3 ? zdir : new THREE.Vector3().fromArray(zdir.split(' '))).normalize();
  } else {
    zdir = new THREE.Vector3(0,0,1);
  }

  var newydir = ydir.clone().sub(zdir).multiplyScalar(ydir.dot(zdir)).normalize();
  xdir.crossVectors(ydir, zdir).normalize();

  var mat4 = new THREE.Matrix4().makeBasis(xdir, ydir, zdir);
  var quat = new THREE.Quaternion();
  var pos = new THREE.Vector3();
  var scale = new THREE.Vector3();
  //quat.setFromRotationMatrix(mat4);
  mat4.decompose(pos, quat, scale);
  quat.normalize();
  //quat.multiply(new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI, 0)));
  return quat;
}
JanusFireboxParser.prototype.parseXML = function(imgxml, leaf, forceLower) {
  var node, root, parent, xmldoc;
  if (imgxml.nodeName) {
    xmldoc = node = imgxml;
  } else {
    try {
      if (window.DOMParser) {
        var parser = new DOMParser();
        xmldoc = parser.parseFromString(imgxml,"application/xml");
        node = xmldoc.children[0];
      } else {
        node = new ActiveXObject("Microsoft.XMLDOM");
        node.async = "false";
        node.loadXML(imgxml).firstChild;
      }

      // Chrome doesn't throw an exception for malformed XML, so we look for a <parsererror> xml tag
      // Firefox now appears to follow the same behavior, but puts the <parsererror> as the top-level element instead of as a child of the last DOM element which parsed successfully
      var parsererrors = (node.tagName == 'parsererror' ? [node] : node.getElementsByTagName("parsererror"));
      if (parsererrors.length > 0) {
        // Extract the message from the first div child of the <parsererror> element
        var errorel = parsererrors[0].getElementsByTagName('div')[0] || parsererrors[0];
        throw new JanusFireboxParserException(errorel.innerHTML);
      }
    } catch (e) {
      throw new JanusFireboxParserException(e.message);
    }
  }
  root = {};
  if (!leaf) {
    var rootname = node.tagName;
    if (forceLower) rootname = rootname.toLowerCase();
    if (!root[rootname]) root[rootname] = {};
    parent = root[rootname];
    //node = parent[node.tagName];
  } else {
    parent = root;
  }
  if (node.attributes) {
    for (var i = 0; i < node.attributes.length; i++) {
      var name = node.attributes[i].nodeName;
      if (forceLower) name = name.toLowerCase();
      var value = node.attributes[i].nodeValue;
      parent[name] = value;
    }
  }
  if (node.childNodes) {
    for (var j = 0; j < node.childNodes.length; j++) {
      var child = node.childNodes[j];
      var nodename = child.nodeName;
      if (forceLower) nodename = nodename.toLowerCase();
      if (!parent._children) parent._children = {};
      if (!parent._children[nodename]) {
        parent._children[nodename] = [];
      } else if (parent._children[nodename].constructor !== Array) {
        parent._children[nodename] = [parent._children[nodename]];
      }
      if (node.getElementsByTagName(child.tagName).length > 0) {
        parent._children[nodename].push(this.parseXML(child, true, forceLower));
      } else if (child.nodeName) {
        if (child.nodeName == "#text" || child.nodeName == "#cdata-section") {
          // this gets confused if you have multiple text/cdata nodes...
          if (!child.nodeValue.match(/^[\s\n]*$/m)) {
            parent._content = child.nodeValue;
          }
        } else {
          parent._children[nodename] = parent._children[nodename].concat(this.parseXML(child, true, forceLower));
        }
      }
    }
  }
  return root;
};

/**
 * Retrieves specified dot-separated value from a multilevel object element
 *
 * @function JanusFireboxParser.arrayget
 * @param {object} obj
 * @param {string} name
 * @param {object|number|string} [defval] default value if none found
*/
JanusFireboxParser.prototype.arrayget = function(obj, name, defval) {
  var ptr = obj;
  var x = name.split(".");
  for (var i = 0; i < x.length; i++) {
    if (ptr==null || (!(ptr[x[i]] instanceof Array) && !(ptr[x[i]] instanceof Object) && i != x.length-1)) {
      ptr = null;
      break;
    }
    ptr = ptr[x[i]];
  }
  if (typeof ptr == "undefined" || ptr === null) {
    return (typeof defval == "undefined" ? null : defval);
  }
  return ptr;
};

/**
 * Fixes encoding of URL strings if they weren't properly encoded
 *
 * @function JanusFireboxParser.fixURLEncoding
 * @param {string} url
 * @returns {string} encoded URL
*/
JanusFireboxParser.prototype.fixURLEncoding = function(url) {
  var fixed = url;
  if (url.indexOf(' ') != -1) {
    fixed = encodeURI(url);
  }
  return fixed;
};

/**
 * Exception class for XML parse errors
 */
function JanusFireboxParserException(msg) {
  this.message = msg;
}
<|endoftext|>


<commit_before>(function($){

  $.declare('pickr', {
    defaults: {
      // Used to detect if user clicked on modal
      // instead of another input.
      hideDelay: 100,

      displayMonths: 1,
      template: '##template##',
      currentMonth: new Date(),
      dayLabels: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
      dateFormat: '%Y-%m-%d'
    },

    init: function() {
      this.el.addClass('pickr');
      this.pickrContainer = $('

').addClass('pickr-container');
      this.el.after(this.pickrContainer);
      this.focus = false;

      if(this.el.data('pickr-format')) {
        this.dateFormat = this.el.data('pickr-format');
      }

      this.bindEvents();
    },

    bindEvents: function() {
      this.el.on('focus', this.proxy(this.showModal));
      this.el.on('blur', this.proxy(this.hideModal));
      this.pickrContainer.on('click', this.proxy(this.containerClicked));
      this.pickrContainer.on('click', '*', this.proxy(this.containerClicked));
    },

    update: function() {
      var months = [], i, month;

      for(i = 0; i < this.displayMonths; i++) {
        month = new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth() + i, 1);

        months.push({
          date: month,
          days: this.daysInMonth(month),
          start: this.monthStartIndex(month)
        });
      }

      var data = {
        timef: TimeFormat,
        months: months,
        dayLabels: this.dayLabels
      };

      this.render(data, this.pickrContainer);
    },

    showModal: function() {
      if(!this.focus) {
        this.focus = true;
        var offset = this.el.offset();
        console.log(offset);
        this.pickrContainer.css({
          left: offset.left,
          top: offset.top + this.el.outerHeight()
        });
        this.update();
      }
    },

    hideModal: function() {
      this.hideTimer = setTimeout(this.proxy(function(){
        //this.pickrContainer.empty();
        //this.focus = false;
      }), this.hideDelay);
    },

    containerClicked: function(event) {
      event.stopPropagation();

      clearTimeout(this.hideTimer);

      this.focus = true;
      this.el.focus();

      var target = $(event.target);

      if(target.is('.pickr-day')) {
        var daySelected = target.text();
        var selectedDate = new Date(target.parents('.pickr-month').data('pickr-date'));
        selectedDate.setDate(daySelected);
        this.selectDate(selectedDate);
      }

      if(target.is('.pickr-prev-month')) {
        this.prevMonth();
      }

      if(target.is('.pickr-next-month')) {
        this.nextMonth();
      }

      if(target.is('.pickr-month-title')) {
        this.today();
      }
    },

    selectDate: function(date) {
      this.el.val(TimeFormat(this.dateFormat, date));
      this.el.blur();
    },

    daysInMonth: function(date) {
      var month = new Date(date.getFullYear(), date.getMonth()+1, 0);
      return month.getDate();
    },

    monthStartIndex: function(date) {
      var month = new Date(date.getFullYear(), date.getMonth(), 1);
      return month.getDay();
    },

    prevMonth: function() {
      this.currentMonth.setMonth(this.currentMonth.getMonth() - this.displayMonths);
      this.update();
    },

    nextMonth: function() {
      this.currentMonth.setMonth(this.currentMonth.getMonth() + this.displayMonths);
      this.update();
    },

    today: function() {
      this.currentMonth = new Date();
      this.update();
    }
  });
}(jQuery));<commit_msg>Removed console log and uncommented hide code.<commit_after>(function($){

  $.declare('pickr', {
    defaults: {
      // Used to detect if user clicked on modal
      // instead of another input.
      hideDelay: 100,

      displayMonths: 1,
      template: '##template##',
      currentMonth: new Date(),
      dayLabels: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
      dateFormat: '%Y-%m-%d'
    },

    init: function() {
      this.el.addClass('pickr');
      this.pickrContainer = $('

').addClass('pickr-container');
      this.el.after(this.pickrContainer);
      this.focus = false;

      if(this.el.data('pickr-format')) {
        this.dateFormat = this.el.data('pickr-format');
      }

      this.bindEvents();
    },

    bindEvents: function() {
      this.el.on('focus', this.proxy(this.showModal));
      this.el.on('blur', this.proxy(this.hideModal));
      this.pickrContainer.on('click', this.proxy(this.containerClicked));
      this.pickrContainer.on('click', '*', this.proxy(this.containerClicked));
    },

    update: function() {
      var months = [], i, month;

      for(i = 0; i < this.displayMonths; i++) {
        month = new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth() + i, 1);

        months.push({
          date: month,
          days: this.daysInMonth(month),
          start: this.monthStartIndex(month),
          today: new Date()
        });
      }

      var data = {
        timef: TimeFormat,
        months: months,
        dayLabels: this.dayLabels
      };

      this.render(data, this.pickrContainer);
    },

    showModal: function() {
      if(!this.focus) {
        this.focus = true;
        var offset = this.el.offset();
        this.pickrContainer.css({
          left: offset.left,
          top: offset.top + this.el.outerHeight()
        });
        this.update();
      }
    },

    hideModal: function() {
      this.hideTimer = setTimeout(this.proxy(function(){
        this.pickrContainer.empty();
        this.focus = false;
      }), this.hideDelay);
    },

    containerClicked: function(event) {
      event.stopPropagation();

      clearTimeout(this.hideTimer);

      this.focus = true;
      this.el.focus();

      var target = $(event.target);

      if(target.is('.pickr-day')) {
        var daySelected = target.text();
        var selectedDate = new Date(target.parents('.pickr-month').data('pickr-date'));
        selectedDate.setDate(daySelected);
        this.selectDate(selectedDate);
      }

      if(target.is('.pickr-prev-month')) {
        this.prevMonth();
      }

      if(target.is('.pickr-next-month')) {
        this.nextMonth();
      }

      if(target.is('.pickr-month-title')) {
        this.today();
      }
    },

    selectDate: function(date) {
      this.el.val(TimeFormat(this.dateFormat, date));
      this.el.blur();
    },

    daysInMonth: function(date) {
      var month = new Date(date.getFullYear(), date.getMonth()+1, 0);
      return month.getDate();
    },

    monthStartIndex: function(date) {
      var month = new Date(date.getFullYear(), date.getMonth(), 1);
      return month.getDay();
    },

    prevMonth: function() {
      this.currentMonth.setMonth(this.currentMonth.getMonth() - this.displayMonths);
      this.update();
    },

    nextMonth: function() {
      this.currentMonth.setMonth(this.currentMonth.getMonth() + this.displayMonths);
      this.update();
    },

    today: function() {
      this.currentMonth = new Date();
      this.update();
    }
  });
}(jQuery));<|endoftext|>


<commit_before>var async         = require('async')
  , fs            = require('fs')
  , mongoose      = require('mongoose')
  , Schema        = mongoose.Schema
  , mongoenabled  = true
  , CommentSchema = new Schema({
      post_id   : {type: String, require: true},
      username  : {type: String, require: true},
      comment   : {type: String, require: true},
      insertdate: {type: Date, require: true}
  })
  , Comment       = mongoose.model('Comment', CommentSchema);

// The file containing posts data
var jsonfile      = 'notes.json';

// So that jade views are loaded from:
// __dirname + /relativeviews + /notes
var viewdir       = 'notes';
var relativeviews = '../../../views';

// Mongodb connection parameters
var mongoconf      = 'mongodb://127.0.0.1/Comments';

/*
 * @brief Connects to mongo
 * @args env Connection string i.e. mongoconf
 *
 */
exports.mongod = function(env, start) {
  if (start == 'no') {
    mongoenabled = false;
    return;
  }

  mongoose.connect(env);
  mongoose.connection.on('open', function() {
    console.log('Mongodb connected');
  });
}

/*
 * @brief Renders notes index
 * @params res - http response
 *
 */
exports.blogIndex = function(res) {
  async.waterfall([
    function readData(callback) {
      var list = Array();
      fs.readFile(jsonfile, 'utf8', function(err, data) {
        if (err) { console.log("Error"); throw err; }
        obj = Array(JSON.parse(data));
        obj.forEach(function(entry) {
          entry.forEach(function(inner) {
            for (var key in inner) {
              if (key != 'current') {
                var jsonart = inner[key];
                list[list.length] = jsonart;
              }
            }
          });
        });
        callback(err, list);
      });
    },
    function renderIndex(list, callback) {
      res.render(viewdir, { title: 'Notes', articles: list});
    }
  ]);
}

/*
 * @brief Renders a specific post
 * @params res - http response
 *         mytitle - post unique title
 *
 */
exports.blogPost = function(res, mytitle) {
  var found = false;
  fs.readFile(jsonfile, 'utf8', function(err, data) {
    if (err) { console.log("Error"); throw err; }
    obj = Array(JSON.parse(data));
    obj.forEach(function(entry) {
      entry.forEach(function(inner) {
        for (var key in inner) {
          if (key == mytitle) {
            var jsonart = inner[key];
            if (jsonart['jade'] != undefined)
            {
              found = true;
              var art = jsonart['jade'] + '.jade';
              var view = [__dirname, relativeviews, viewdir, art].join('/');
              var id = jsonart['jade'];
              // Pack comments
              if (mongoenabled)
              {
                mongoose.model('Comment', Comment);
                async.waterfall([
                  function readComments(callback) {
                    var comments = Array();
                    Comment.find({post_id : id}).sort({insertdate: 'desc'}).
                      execFind(function(err,docs) {
                      if (err)
                        comments = [];
                      else
                        comments = docs;
                    callback(err, comments);
                    });
                  },
                function renderPost(comments, callback) {
                  res.render(view, {
                    title: jsonart['title'],
                    _title: jsonart['title'],
                    _subtitle: jsonart['subtitle'],
                    _date: jsonart['date'],
                    _id: id,
                    _url: jsonart['url'],
                    _comments: comments
                  });
                }
                ]);
              }
              else {
                res.render(view, {
                  title: jsonart['title'],
                  _title: jsonart['title'],
                  _subtitle: jsonart['subtitle'],
                  _date: jsonart['date'],
                  _id: id,
                  _url: jsonart['url'],
                  _comments: null
                });
              }
            }
          }
        }
      });
    });
    if (! found)
    {
      var err404 = [__dirname, relativeviews, '404.jade'].join('/');
      res.render(err404, { title: "404" });
    }
  });
}

/*
 * Adds a comment via POST
 *
 */
exports.blogAddComment = function(req, res) {
  var comment = {
    username    : req.body.cname,
    comment     : req.body.ccomment,
    post_id     : req.body.post_id,
    insertdate  : new Date()
  };

  _url = req.body.post_url;

  mongoose.model('Comment', Comment);
  var commentObj = new Comment(comment);

  commentObj.save(function(err, data) {
    if (err)
      console.log('Error save' + req.body.ccomment);
    else
      // TODO thanks flash
      res.redirect([viewdir, _url].join('/'));
  });
}
<commit_msg>Conditional inclusion / workaround of Openshift bug<commit_after>var async         = require('async')
  , fs            = require('fs')
  , mongoose      = ''
  , Schema        = ''
  , mongoenabled  = ''
  , CommentSchema = ''
  , Comment       = '';

// The file containing posts data
var jsonfile      = 'notes.json';

// So that jade views are loaded from:
// __dirname + /relativeviews + /notes
var viewdir       = 'notes';
var relativeviews = '../../../views';

// Mongodb connection parameters
var mongoconf      = 'mongodb://127.0.0.1/Comments';

/*
 * @brief Connects to mongo
 * @args env Connection string i.e. mongoconf
 *
 */
exports.mongod = function(env, start) {
  if (start == 'no') {
    mongoenabled = false;
    return;
  }

  var mongoose      = require('mongoose')
    , Schema        = mongoose.Schema
    , mongoenabled  = true
    , CommentSchema = new Schema({
        post_id   : {type: String, require: true},
        username  : {type: String, require: true},
        comment   : {type: String, require: true},
        insertdate: {type: Date, require: true}
    })
    , Comment       = mongoose.model('Comment', CommentSchema);

  mongoose.connect(env);
  mongoose.connection.on('open', function() {
    console.log('Mongodb connected');
  });
}

/*
 * @brief Renders notes index
 * @params res - http response
 *
 */
exports.blogIndex = function(res) {
  async.waterfall([
    function readData(callback) {
      var list = Array();
      fs.readFile(jsonfile, 'utf8', function(err, data) {
        if (err) { console.log("Error"); throw err; }
        obj = Array(JSON.parse(data));
        obj.forEach(function(entry) {
          entry.forEach(function(inner) {
            for (var key in inner) {
              if (key != 'current') {
                var jsonart = inner[key];
                list[list.length] = jsonart;
              }
            }
          });
        });
        callback(err, list);
      });
    },
    function renderIndex(list, callback) {
      res.render(viewdir, { title: 'Notes', articles: list});
    }
  ]);
}

/*
 * @brief Renders a specific post
 * @params res - http response
 *         mytitle - post unique title
 *
 */
exports.blogPost = function(res, mytitle) {
  var found = false;
  fs.readFile(jsonfile, 'utf8', function(err, data) {
    if (err) { console.log("Error"); throw err; }
    obj = Array(JSON.parse(data));
    obj.forEach(function(entry) {
      entry.forEach(function(inner) {
        for (var key in inner) {
          if (key == mytitle) {
            var jsonart = inner[key];
            if (jsonart['jade'] != undefined)
            {
              found = true;
              var art = jsonart['jade'] + '.jade';
              var view = [__dirname, relativeviews, viewdir, art].join('/');
              var id = jsonart['jade'];
              // Pack comments
              if (mongoenabled)
              {
                mongoose.model('Comment', Comment);
                async.waterfall([
                  function readComments(callback) {
                    var comments = Array();
                    Comment.find({post_id : id}).sort({insertdate: 'desc'}).
                      execFind(function(err,docs) {
                      if (err)
                        comments = [];
                      else
                        comments = docs;
                    callback(err, comments);
                    });
                  },
                function renderPost(comments, callback) {
                  res.render(view, {
                    title: jsonart['title'],
                    _title: jsonart['title'],
                    _subtitle: jsonart['subtitle'],
                    _date: jsonart['date'],
                    _id: id,
                    _url: jsonart['url'],
                    _comments: comments
                  });
                }
                ]);
              }
              else {
                res.render(view, {
                  title: jsonart['title'],
                  _title: jsonart['title'],
                  _subtitle: jsonart['subtitle'],
                  _date: jsonart['date'],
                  _id: id,
                  _url: jsonart['url'],
                  _comments: null
                });
              }
            }
          }
        }
      });
    });
    if (! found)
    {
      var err404 = [__dirname, relativeviews, '404.jade'].join('/');
      res.render(err404, { title: "404" });
    }
  });
}

/*
 * Adds a comment via POST
 *
 */
exports.blogAddComment = function(req, res) {
  var comment = {
    username    : req.body.cname,
    comment     : req.body.ccomment,
    post_id     : req.body.post_id,
    insertdate  : new Date()
  };

  _url = req.body.post_url;

  mongoose.model('Comment', Comment);
  var commentObj = new Comment(comment);

  commentObj.save(function(err, data) {
    if (err)
      console.log('Error save' + req.body.ccomment);
    else
      // TODO thanks flash
      res.redirect([viewdir, _url].join('/'));
  });
}
<|endoftext|>


<commit_before>/*
 * plato
 * https://github.com/es-analysis/plato
 *
 * Copyright (c) 2012 Jarrod Overson
 * Licensed under the MIT license.
 */

'use strict';

// node api
var path = require('path');

// node api with sugar
var fs = require('fs-extra');

// vendor
var _ = require('lodash');
var glob = require('glob');

// local lib
var util = require('./util'),
    OverviewHistory = require('./models/OverviewHistory'),
    FileHistory = require('./models/FileHistory'),
    Logger = require('./logger'),
    reporters = {
      complexity : require('./reporters/complexity'),
      jshint : require('./reporters/jshint')
    };

var overviewTemplate = __dirname + '/templates/overview.html',
    displayTemplate = __dirname + '/templates/display.html',
    fileTemplate = __dirname + '/templates/file.html',
    assets = __dirname + '/assets/',
    fileDir = 'files';

var log = new Logger(Logger.WARNING);

function unary(fn) { return function(a){ return fn(a);}; }

exports.inspect = function(files, outputDir, options, done) {

	if (!files) {
	  // at least give me a file man...
	  return;
	}

  files = files instanceof Array ? files : [files];
  files = _.flatten(files.map(unary(glob.sync)));

  var flags = {
    complexity : {
      logicalor : true,
      switchcase : true,
      forin : false,
      trycatch : false,
      newmi : true
    },
    jshint : { } // use jshint defaults
  };

  Object.keys(flags).forEach(function(flag){
    if (flag in options) flags[flag] = _.clone(options[flag]);
  });

  if (options.q) log.level = Logger.ERROR;

  if (options.date) {
    // if we think we were given seconds
    if (options.date < 10000000000 ) options.date = options.date * 1000;
    options.date = new Date(options.date);
  }

  var reports = [];

  var fileOutputDir = outputDir ? path.join(outputDir, fileDir) : false;

  var commonBasePath = util.findCommonBase(files);

  var runReports = function(files, done) {
    files.forEach(function(file) {
      if (options.exclude && options.exclude.test(file)) return;

      if (options.recurse && fs.statSync(file).isDirectory()) {
        files = fs.readdirSync(file).map(function(innerFile) {
          return path.join(file,innerFile);
        });
        runReports(files);
      } else if (file.match(/\.js$/)) {
        log.info('Reading "%s"', file);

        var fileShort = file.replace(commonBasePath, '');
        var fileSafe = fileShort.replace(/[^a-zA-Z0-9]/g,'_');
        var source = fs.readFileSync(file).toString().trim();
        if (!source) {
          log.info('Not parsing empty file "%s"', file);
          return;
        }

        // if skip empty line option
        if(options.noempty) {
          source = source.replace(/^\s*[\r\n]/gm ,"");
        }

        // if begins with shebang
        if (source[0] === '#' && source[1] === '!') {
          source = '//' + source;
        }
        var report = {
          info : {
            file : file,
            fileShort : fileShort,
            fileSafe : fileSafe,
            link : fileDir + '/' + fileSafe + '/index.html'
          }
        };

        var error = false;
        _.each(reporters,function(reporter, name) {
          if (!flags[name]) return;
          try {
            report[name] = reporter.process(source, flags[name], report.info);
          } catch (e) {
            error = true;
            log.error('Error reading file %s: ', file, e.toString());
            log.error(e.stack);
          }
        });

        if (error) return;
        reports.push(report);
        if (fileOutputDir) {
          var outdir = path.join(fileOutputDir, report.info.fileSafe);
          if (!fs.existsSync(outdir)) fs.mkdirSync(outdir);
          writeFileReport(outdir, report, source, options);
        }
      }
    });
    if (done) done();
  };

  if (!fileOutputDir) {
    runReports(files,function() {
      done(reports);
    });
  } else {
    fs.mkdirp(fileOutputDir,function() {
      runReports(files,function() {
        var reportFilePrefix = path.join(outputDir, 'report');
        var overview = path.join(outputDir, 'index.html');
        var wallDisplay = path.join(outputDir, 'display.html');

        fs.copy(assets, path.join(outputDir, 'assets'), function() {
          var overviewReport = exports.getOverviewReport(reports);
          updateHistoricalOverview(reportFilePrefix, overviewReport, options);
          writeReport(reportFilePrefix, overviewReport);
          writeOverview(overview, overviewReport, {
            title : options.title,
            flags : flags
          }, overviewTemplate);
          writeOverview(wallDisplay, overviewReport, {
            title : options.title,
            flags : flags
          }, displayTemplate);
          done(reports);
        });
      });
    });
  }
};

// Filters out information unused in the overview for space/performance
exports.getOverviewReport = function (reports) {
  var culledReports = [];
  var summary = {
    total : {
      jshint: 0,
      sloc : 0,
      maintainability : 0,
    },
    average : {
      sloc : 0,
      maintainability : 0,
    }
  };

  reports.forEach(function(report) {
    // clone objects so we don't have to worry about side effects
    summary.total.sloc += report.complexity.aggregate.complexity.sloc.physical;
    summary.total.maintainability += report.complexity.maintainability;

    var aggregate = _.cloneDeep(report.complexity.aggregate);
    var reportItem = {};
    reportItem.info = report.info;
    if (report.jshint) {
      summary.total.jshint += report.jshint.messages.length;
      reportItem.jshint = {
        messages : report.jshint.messages.length
      };
    }
    if (report.complexity) {
      reportItem.complexity = {
        aggregate : aggregate,
        module : report.complexity.module,
        module_safe : report.complexity.module_safe,
        maintainability : _.cloneDeep(report.complexity.maintainability)
      };
    }
    culledReports.push(reportItem);
  });

  summary.average.sloc = ~~(summary.total.sloc / reports.length);
  summary.average.jshint = (summary.total.jshint / reports.length).toFixed(2);
  summary.average.maintainability = (summary.total.maintainability / reports.length).toFixed(2);

  return {
    summary : summary,
    reports : culledReports
  };
};

function updateHistoricalOverview(outfilePrefix, overview, options) {
  var existingData = util.readJSON(outfilePrefix + '.history.json', options) || {};
  var history = new OverviewHistory(existingData);
  history.addReport(overview, options.date);
  writeReport(outfilePrefix + '.history', history.toJSON(), '__history');
}

function updateHistoricalReport(outfilePrefix, overview, options) {
  var existingData = util.readJSON(outfilePrefix + '.history.json', options) || {};
  var history = new FileHistory(existingData);
  overview.date = options.date;
  history.addReport(overview, options.date);
  writeReport(outfilePrefix + '.history', history.toJSON(), '__history');
}

function writeFile(file, source) {
  log.info('Writing file "%s".', file);
  fs.writeFileSync(file, source, 'utf8');
}

function writeReport(outfilePrefix, report, exportName) {
  var formatted = util.formatJSON(report);

  writeFile(outfilePrefix + '.json', formatted);

  exportName = exportName || '__report';

  var module = exportName + ' = ' + formatted;

  writeFile(outfilePrefix + '.js', module);
}

function writeOverview(outfile, report, options, templatePath) {
  var overviewSource = fs.readFileSync(templatePath).toString();
  var template = _.template(overviewSource);
  var parsed = template({
    report : report,
    options : options
  });
  writeFile(outfile, parsed);
}

function writeFileReport(outdir, report, source, options) {
  var overviewSource = fs.readFileSync(fileTemplate).toString();
  var parsed = _.template(overviewSource)({
    source : util.escapeHTML(source),
    report : report
  });
  var indexPath = path.join(outdir,'index.html');
  var outfilePrefix = path.join(outdir,'report');

  writeFile(indexPath, parsed);
  updateHistoricalReport(outfilePrefix, report, options);
  writeReport(outfilePrefix, report);
}
<commit_msg>Remove individual file reporting<commit_after>'use strict';

var path = require('path');
var fs = require('fs-extra'); // node api with sugar
var _ = require('lodash');
var glob = require('glob');

// local lib
var util = require('./util'),
    OverviewHistory = require('./models/OverviewHistory'),
    Logger = require('./logger'),
    reporters = {
      complexity : require('./reporters/complexity'),
      jshint : require('./reporters/jshint')
    };

var overviewTemplate = __dirname + '/templates/overview.html',
    displayTemplate = __dirname + '/templates/display.html',
    assets = __dirname + '/assets/',
    fileDir = 'files';

var log = new Logger(Logger.WARNING);

function unary(fn) { return function(a){ return fn(a);}; }

exports.inspect = function(files, outputDir, options, done) {

	if (!files) {
	  // at least give me a file man...
	  return;
	}

  files = files instanceof Array ? files : [files];
  files = _.flatten(files.map(unary(glob.sync)));

  var flags = {
    complexity : {
      logicalor : true,
      switchcase : true,
      forin : false,
      trycatch : false,
      newmi : true
    },
    jshint : { } // use jshint defaults
  };

  Object.keys(flags).forEach(function(flag){
    if (flag in options) flags[flag] = _.clone(options[flag]);
  });

  if (options.q) log.level = Logger.ERROR;

  if (options.date) {
    // if we think we were given seconds
    if (options.date < 10000000000 ) options.date = options.date * 1000;
    options.date = new Date(options.date);
  }

  var reports = [];

  var fileOutputDir = outputDir ? path.join(outputDir, fileDir) : false;

  var commonBasePath = util.findCommonBase(files);

  var runReports = function(files, done) {
    files.forEach(function(file) {
      if (options.exclude && options.exclude.test(file)) return;

      if (options.recurse && fs.statSync(file).isDirectory()) {
        files = fs.readdirSync(file).map(function(innerFile) {
          return path.join(file,innerFile);
        });
        runReports(files);
      } else if (file.match(/\.js$/)) {
        log.info('Reading "%s"', file);

        var fileShort = file.replace(commonBasePath, '');
        var fileSafe = fileShort.replace(/[^a-zA-Z0-9]/g,'_');
        var source = fs.readFileSync(file).toString().trim();
        if (!source) {
          log.info('Not parsing empty file "%s"', file);
          return;
        }

        // if skip empty line option
        if(options.noempty) {
          source = source.replace(/^\s*[\r\n]/gm ,"");
        }

        // if begins with shebang
        if (source[0] === '#' && source[1] === '!') {
          source = '//' + source;
        }
        var report = {
          info : {
            file : file,
            fileShort : fileShort,
            fileSafe : fileSafe,
            link : fileDir + '/' + fileSafe + '/index.html'
          }
        };

        var error = false;
        _.each(reporters,function(reporter, name) {
          if (!flags[name]) return;
          try {
            report[name] = reporter.process(source, flags[name], report.info);
          } catch (e) {
            error = true;
            log.error('Error reading file %s: ', file, e.toString());
            log.error(e.stack);
          }
        });

        if (error) return;
        reports.push(report);
      }
    });
    if (done) done();
  };

  if (!fileOutputDir) {
    runReports(files,function() {
      done(reports);
    });
  } else {
    fs.mkdirp(fileOutputDir,function() {
      runReports(files,function() {
        var reportFilePrefix = path.join(outputDir, 'report');
        var overview = path.join(outputDir, 'index.html');
        var wallDisplay = path.join(outputDir, 'display.html');

        fs.copy(assets, path.join(outputDir, 'assets'), function() {
          var overviewReport = exports.getOverviewReport(reports);
          updateHistoricalOverview(reportFilePrefix, overviewReport, options);
          writeReport(reportFilePrefix, overviewReport);
          writeOverview(overview, overviewReport, {
            title : options.title,
            flags : flags
          }, overviewTemplate);
          writeOverview(wallDisplay, overviewReport, {
            title : options.title,
            flags : flags
          }, displayTemplate);
          done(reports);
        });
      });
    });
  }
};

// Filters out information unused in the overview for space/performance
exports.getOverviewReport = function (reports) {
  var culledReports = [];
  var summary = {
    total : {
      jshint: 0,
      sloc : 0,
      maintainability : 0,
    },
    average : {
      sloc : 0,
      maintainability : 0,
    }
  };

  reports.forEach(function(report) {
    // clone objects so we don't have to worry about side effects
    summary.total.sloc += report.complexity.aggregate.complexity.sloc.physical;
    summary.total.maintainability += report.complexity.maintainability;

    var aggregate = _.cloneDeep(report.complexity.aggregate);
    var reportItem = {};
    reportItem.info = report.info;
    if (report.jshint) {
      summary.total.jshint += report.jshint.messages.length;
      reportItem.jshint = {
        messages : report.jshint.messages.length
      };
    }
    if (report.complexity) {
      reportItem.complexity = {
        aggregate : aggregate,
        module : report.complexity.module,
        module_safe : report.complexity.module_safe,
        maintainability : _.cloneDeep(report.complexity.maintainability)
      };
    }
    culledReports.push(reportItem);
  });

  summary.average.sloc = ~~(summary.total.sloc / reports.length);
  summary.average.jshint = (summary.total.jshint / reports.length).toFixed(2);
  summary.average.maintainability = (summary.total.maintainability / reports.length).toFixed(2);

  return {
    summary : summary,
    reports : culledReports
  };
};

function updateHistoricalOverview(outfilePrefix, overview, options) {
  var existingData = util.readJSON(outfilePrefix + '.history.json', options) || {};
  var history = new OverviewHistory(existingData);
  history.addReport(overview, options.date);
  writeReport(outfilePrefix + '.history', history.toJSON(), '__history');
}

function writeFile(file, source) {
  log.info('Writing file "%s".', file);
  fs.writeFileSync(file, source, 'utf8');
}

function writeReport(outfilePrefix, report, exportName) {
  var formatted = util.formatJSON(report);

  writeFile(outfilePrefix + '.json', formatted);

  exportName = exportName || '__report';

  var module = exportName + ' = ' + formatted;

  writeFile(outfilePrefix + '.js', module);
}

function writeOverview(outfile, report, options, templatePath) {
  var overviewSource = fs.readFileSync(templatePath).toString();
  var template = _.template(overviewSource);
  var parsed = template({
    report : report,
    options : options
  });
  writeFile(outfile, parsed);
}
<|endoftext|>


<commit_before>// ゲーム用コマンド

commands={};
function addCommand(name,definition){
 if(commands[name]){
  throw new Error('commands['+name+'] is already exist.');
 }
 definition.cmdName=name;
 commands[name]=enchant.Class.create(Command,definition);
 return commands[name];
}

// 指定の方向に歩くコマンド
// direction: 数値
// 0: Down 1: Left 2: Right 3: Up
addCommand('walk',{
  /*
   * 0: Down 1: Left 2: Right 3: Up
   */
  initialize: function(owner,properties){
   Command.call(this,owner,properties);
   this.preAction=true;
   this.walk=1;
   if( !(properties!=undefined && properties.direction!=undefined)){
    throw(new Error("missing property: direction"));
   }
   this.direction=properties.direction;
   this.isMoving=true;
   // 方向から速度指定
   this.vx=0;
   this.vy=0;
   switch (properties.direction) {
   case 1:
    this.vx=-this.owner.baseVelocity;
    break;
   case 2:
    this.vx=this.owner.baseVelocity;
    break;
   case 3:
    this.vy=-this.owner.baseVelocity;
    break;
   case 0:
    this.vy=this.owner.baseVelocity;
    break;
   default:
    throw new Error("Invalid value: properties.direction");
   }
   // TODO: なんとかする
   // this.owner.frame=this.direction*3+this.walk;
  },
  action: function(){
   // 行動前
   if(this.preAction){
    this.owner.direction=this.direction;
    this.owner.state_frame=this.walk;
    if(!this.checkValid()){
     this.isMoving=false;
    }
   }
   this.preAction=false;
   if(!this.isMoving){
    return;
   }
   this.owner.moveBy(this.vx,this.vy);
   if( game.frame%3 == 0){
    this.walk++;
    this.walk%=3;
   }
   if( (this.vx&&(this.owner.x - this.owner.offsetX)%16 == 0)||(this.vy && (this.owner.y-this.owner.offsetY) % 16 == 0)){
    this.isMoving=false;
    this.walk=1;
   }
   this.owner.state_frame=this.walk;
  },
  // 移動先が壁じゃないかどうかなど
  // 無効な移動は拒否する
  checkValid: function(){
   var map_scene=this.owner.parentNode.parentNode;
   var characterList=map_scene.characterList;
   var map=map_scene.bgMap;
   var x=this.owner.x + (this.vx ? this.vx/Math.abs(this.vx)*16: 0) + this.owner.offsetX;
   var y=this.owner.y + (this.vy ? this.vy/Math.abs(this.vy)*16: 0) + this.owner.offsetY;
   var opts={x:x-this.owner.offsetX,y:y-this.owner.offsetY};
   return (0<=x && x< map.width && 0<=y && y<map.height && !map.hitTest(x,y) && characterList.checkHit(this.owner,{maxLength:1},opts).length==0);
  },
  popFlag: function(){
   return !this.isMoving;
  },
  toString: function(){
   return this.cmdName+" direction is "+(["down","left","right","up"])[this.direction];
  }
});

// 向きを変えるコマンド
// direction: 数値
// 0: Down 1: Left 2: Right 3: Up
addCommand('turn',{
  /*
   * 0: Down 1: Left 2: Right 3: Up
   */
  initialize: function(owner,properties){
   Command.call(this,owner,properties);
   if( !(properties!=undefined && properties.direction!=undefined)){
    throw(new Error("missing property: direction"));
   }
   this.direction=properties.direction;
  },
  action: function(){
   this.owner.direction=this.direction;
   this.owner.state_frame=1;
  },
  popFlag: function(){
   return true;
  },
  toString: function(){
   return this.cmdName+" direction is "+(["down","left","right","up"])[this.direction];
  }
});

// その場で待機するコマンド
// count: 待つフレーム数
addCommand('wait',{
  initialize:function(owner,properties){
   Command.call(this,owner,properties);
   this.count=this.properties.count || 0;
  },
  action:function(){
   this.count--;
  },
  popFlag:function(){
   return !(this.count>0);
  }
});

// thinkingRoutineを呼び出すコマンド
addCommand('think',{
  initialize:function(owner,properties){
   Command.call(this,owner,properties);
   this.executed=false;
  },
  action:function(){
   this.owner.thinkingRoutine();
   this.executed=true;
  },
  popFlag:function(){
   return this.executed;
  }
});

addCommand('watch',{
  initialize: function(owner,properties){
   Command.call(this,owner,properties);
   this.flag=false;
   this.spike=undefined;
  },
  action: function(){
   // var res=this.owner.parentNode.checkHit(this.owner);
   if(!this.spike){
    var dir=this.owner.direction;
    var x=0;
    var y=0;
    switch(dir){
    case 0:
     y=1;
     break;
    case 1:
     x=-1;
     break;
    case 2:
     x=1;
     break;
    case 3:
     y=-1;
     break;
    }
    var dummy=new Character(0,0,0,0,16,16);
    dummy.move_map(this.owner.mapX+x,this.owner.mapY+y);
    var res=this.owner.parentNode.checkHit(dummy,{},{ignoreCollision: true});
    var target=res[0];
    if(target instanceof Spike){
     this.spike=target;
    }else{
     console.log(target);
     this.flag=true;
    }
   }
   if(this.spike && this.spike.queue[0] instanceof this.spike.toggle_on_off && this.spike.state){
    this.flag=true;
   }
  },
  popFlag:function(){
   return this.flag;
  }
});

// Knight用コマンド
// 今のところ剣を振るモーションを行うのみ
addCommand('attack',{
  initialize: function(owner,properties){
   Command.call(this,owner,properties);
   if(owner instanceof Knight){
    this.change_state=true;
   }
   this.state_interval=30;
   this.count=0;
   this.endFlag=false;
  },
  action: function(){
   if(this.change_state){
    this.owner.state=2;
    this.change_state=false;
   }
   this.owner.state_frame=Math.floor(this.count/this.state_interval);
   this.count++;
   if(this.count==this.state_interval*3){
    this.owner.state=0;
    this.owner.state_frame=1;
    this.endFlag=true;
   }
  },
  popFlag: function(){
   return this.endFlag;
  }
});

// 今のところプレイヤー用コマンド
// 向いている方向のCharacterを調べる
// 即ち、向いている方向のCharacterにcheckイベントを発火
addCommand('check',{
  action:function(){
   // var res=this.owner.parentNode.checkHit(this.owner);
   var dir=this.owner.direction;
   var x=0;
   var y=0;
   switch(dir){
   case 0:
    y=1;
    break;
   case 1:
    x=-1;
    break;
   case 2:
    x=1;
    break;
   case 3:
    y=-1;
    break;
   }
   var dummy=new Character(0,0,0,0,16,16);
   dummy.move_map(this.owner.mapX+x,this.owner.mapY+y);
   var res=this.owner.parentNode.checkHit(dummy);
   if(res.length>0){
    var e=new enchant.Event("check");
    e.checker=this.owner;
    res.forEach(function(val){
     val.dispatchEvent(e);
    });
   }
  }
});

// 危ない
addCommand('func',{
  initialize:function(owner,properties){
   Command.call(this,owner,properties);
   if(typeof properties.popFlag ==="undefined"){
    throw new Error("popFlag is undefined");
   }else if(!(properties.popFlag instanceof Function)){
    throw new Error("popFlag is Not Function");
   }
   if(properties.initialize instanceof Function){
    properties.initialize.call(this);
   }
  },
  action:function(){
   if(this.properties.action instanceof Function){
    this.properties.action.call(this);
   }
  },
  popFlag:function(){
   return this.properties.popFlag();
  }
});
<commit_msg>wait#toString追加<commit_after>// ゲーム用コマンド

commands={};
function addCommand(name,definition){
 if(commands[name]){
  throw new Error('commands['+name+'] is already exist.');
 }
 definition.cmdName=name;
 commands[name]=enchant.Class.create(Command,definition);
 return commands[name];
}

// 指定の方向に歩くコマンド
// direction: 数値
// 0: Down 1: Left 2: Right 3: Up
addCommand('walk',{
  /*
   * 0: Down 1: Left 2: Right 3: Up
   */
  initialize: function(owner,properties){
   Command.call(this,owner,properties);
   this.preAction=true;
   this.walk=1;
   if( !(properties!=undefined && properties.direction!=undefined)){
    throw(new Error("missing property: direction"));
   }
   this.direction=properties.direction;
   this.isMoving=true;
   // 方向から速度指定
   this.vx=0;
   this.vy=0;
   switch (properties.direction) {
   case 1:
    this.vx=-this.owner.baseVelocity;
    break;
   case 2:
    this.vx=this.owner.baseVelocity;
    break;
   case 3:
    this.vy=-this.owner.baseVelocity;
    break;
   case 0:
    this.vy=this.owner.baseVelocity;
    break;
   default:
    throw new Error("Invalid value: properties.direction");
   }
   // TODO: なんとかする
   // this.owner.frame=this.direction*3+this.walk;
  },
  action: function(){
   // 行動前
   if(this.preAction){
    this.owner.direction=this.direction;
    this.owner.state_frame=this.walk;
    if(!this.checkValid()){
     this.isMoving=false;
    }
   }
   this.preAction=false;
   if(!this.isMoving){
    return;
   }
   this.owner.moveBy(this.vx,this.vy);
   if( game.frame%3 == 0){
    this.walk++;
    this.walk%=3;
   }
   if( (this.vx&&(this.owner.x - this.owner.offsetX)%16 == 0)||(this.vy && (this.owner.y-this.owner.offsetY) % 16 == 0)){
    this.isMoving=false;
    this.walk=1;
   }
   this.owner.state_frame=this.walk;
  },
  // 移動先が壁じゃないかどうかなど
  // 無効な移動は拒否する
  checkValid: function(){
   var map_scene=this.owner.parentNode.parentNode;
   var characterList=map_scene.characterList;
   var map=map_scene.bgMap;
   var x=this.owner.x + (this.vx ? this.vx/Math.abs(this.vx)*16: 0) + this.owner.offsetX;
   var y=this.owner.y + (this.vy ? this.vy/Math.abs(this.vy)*16: 0) + this.owner.offsetY;
   var opts={x:x-this.owner.offsetX,y:y-this.owner.offsetY};
   return (0<=x && x< map.width && 0<=y && y<map.height && !map.hitTest(x,y) && characterList.checkHit(this.owner,{maxLength:1},opts).length==0);
  },
  popFlag: function(){
   return !this.isMoving;
  },
  toString: function(){
   return this.cmdName+" direction is "+(["down","left","right","up"])[this.direction];
  }
});

// 向きを変えるコマンド
// direction: 数値
// 0: Down 1: Left 2: Right 3: Up
addCommand('turn',{
  /*
   * 0: Down 1: Left 2: Right 3: Up
   */
  initialize: function(owner,properties){
   Command.call(this,owner,properties);
   if( !(properties!=undefined && properties.direction!=undefined)){
    throw(new Error("missing property: direction"));
   }
   this.direction=properties.direction;
  },
  action: function(){
   this.owner.direction=this.direction;
   this.owner.state_frame=1;
  },
  popFlag: function(){
   return true;
  },
  toString: function(){
   return this.cmdName+" direction is "+(["down","left","right","up"])[this.direction];
  }
});

// その場で待機するコマンド
// count: 待つフレーム数
addCommand('wait',{
  initialize:function(owner,properties){
   Command.call(this,owner,properties);
   this.count=this.properties.count || 0;
  },
  action:function(){
   this.count--;
  },
  popFlag:function(){
   return !(this.count>0);
  },
  toString: function(){
   return this.cmdName+" "+this.count;
  }
});

// thinkingRoutineを呼び出すコマンド
addCommand('think',{
  initialize:function(owner,properties){
   Command.call(this,owner,properties);
   this.executed=false;
  },
  action:function(){
   this.owner.thinkingRoutine();
   this.executed=true;
  },
  popFlag:function(){
   return this.executed;
  }
});

addCommand('watch',{
  initialize: function(owner,properties){
   Command.call(this,owner,properties);
   this.flag=false;
   this.spike=undefined;
  },
  action: function(){
   // var res=this.owner.parentNode.checkHit(this.owner);
   if(!this.spike){
    var dir=this.owner.direction;
    var x=0;
    var y=0;
    switch(dir){
    case 0:
     y=1;
     break;
    case 1:
     x=-1;
     break;
    case 2:
     x=1;
     break;
    case 3:
     y=-1;
     break;
    }
    var dummy=new Character(0,0,0,0,16,16);
    dummy.move_map(this.owner.mapX+x,this.owner.mapY+y);
    var res=this.owner.parentNode.checkHit(dummy,{},{ignoreCollision: true});
    var target=res[0];
    if(target instanceof Spike){
     this.spike=target;
    }else{
     console.log(target);
     this.flag=true;
    }
   }
   if(this.spike && this.spike.queue[0] instanceof this.spike.toggle_on_off && this.spike.state){
    this.flag=true;
   }
  },
  popFlag:function(){
   return this.flag;
  }
});

// Knight用コマンド
// 今のところ剣を振るモーションを行うのみ
addCommand('attack',{
  initialize: function(owner,properties){
   Command.call(this,owner,properties);
   if(owner instanceof Knight){
    this.change_state=true;
   }
   this.state_interval=30;
   this.count=0;
   this.endFlag=false;
  },
  action: function(){
   if(this.change_state){
    this.owner.state=2;
    this.change_state=false;
   }
   this.owner.state_frame=Math.floor(this.count/this.state_interval);
   this.count++;
   if(this.count==this.state_interval*3){
    this.owner.state=0;
    this.owner.state_frame=1;
    this.endFlag=true;
   }
  },
  popFlag: function(){
   return this.endFlag;
  }
});

// 今のところプレイヤー用コマンド
// 向いている方向のCharacterを調べる
// 即ち、向いている方向のCharacterにcheckイベントを発火
addCommand('check',{
  action:function(){
   // var res=this.owner.parentNode.checkHit(this.owner);
   var dir=this.owner.direction;
   var x=0;
   var y=0;
   switch(dir){
   case 0:
    y=1;
    break;
   case 1:
    x=-1;
    break;
   case 2:
    x=1;
    break;
   case 3:
    y=-1;
    break;
   }
   var dummy=new Character(0,0,0,0,16,16);
   dummy.move_map(this.owner.mapX+x,this.owner.mapY+y);
   var res=this.owner.parentNode.checkHit(dummy);
   if(res.length>0){
    var e=new enchant.Event("check");
    e.checker=this.owner;
    res.forEach(function(val){
     val.dispatchEvent(e);
    });
   }
  }
});

// 危ない
addCommand('func',{
  initialize:function(owner,properties){
   Command.call(this,owner,properties);
   if(typeof properties.popFlag ==="undefined"){
    throw new Error("popFlag is undefined");
   }else if(!(properties.popFlag instanceof Function)){
    throw new Error("popFlag is Not Function");
   }
   if(properties.initialize instanceof Function){
    properties.initialize.call(this);
   }
  },
  action:function(){
   if(this.properties.action instanceof Function){
    this.properties.action.call(this);
   }
  },
  popFlag:function(){
   return this.properties.popFlag();
  }
});
<|endoftext|>