<commit_before>'use strict';

var net = require('net');
var url = require('url');
var http2 = require('http2');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var reconnect = require('reconnect-net');

class Proxy {
    constructor(options, dns) {
        this.options = options;
        this.dns = dns;
        this.connections = new Map();

        this.server = net.createServer((socket) => {
            let requestData = '';
            let heartbeatInterval = undefined;
            let myDomain = undefined;

            socket.on('data', (data) => {
                requestData += data.toString('utf-8');

                try {
                    var result = JSON.parse(requestData);
                } catch (err) {
                    return;
                }

                if (result.domain) {
                    socket.removeAllListeners('data');

                    this.dns.kvPut(result.domain, this.localAddress, (err, key, n) => {
                        if (err) {
                            console.log('store dns failed:', err);
                            socket.write(JSON.stringify({ code: 2 }), 'utf-8');
                            socket.destroy();
                            return;
                        }

                        myDomain = result.domain;
                        this.connections.set(myDomain, socket);

                        heartbeatInterval =
                            setInterval(() => {
                                this.dns.kvPut(myDomain, this.localAddress, (err, key, n) => {
                                    if (err) {
                                        console.log('keep heartbeat interval failed:', err);
                                    }
                                });
                            }, this.options.heartbeatInterval);

                        socket.write(JSON.stringify({ code: 0 }), 'utf-8');

                        console.log('new proxy connection:', myDomain);
                    });
                } else {
                    socket.write(JSON.stringify({ code: 1 }), 'utf-8');
                    socket.destroy();
                }
            });

            socket.on('error', (error) => {
                if (heartbeatInterval) clearInterval(heartbeatInterval);
                if (myDomain) this.connections.delete(myDomain);
            });

            socket.on('close', () => {
                if (heartbeatInterval) clearInterval(heartbeatInterval);
                if (myDomain) this.connections.delete(myDomain);

                console.log('proxy connection closed:', myDomain);
            });
        });

        if (options.entryNode && options.entryNode.proxyPort) {
            this.reconnectInstance =
                reconnect((stream) => {
                    let signin = { domain: options.domain };
                    stream.write(JSON.stringify(signin), 'utf-8');

                    let resultData = '';
                    stream.on('data', (data) => {
                        resultData += data.toString('utf-8');

                        try {
                            var result = JSON.parse(resultData);
                        } catch (err) {
                            return;
                        }

                        if (result.code === 0) {
                            stream.removeAllListeners('data');

                            http2.raw.createServer({
                                plain: true,
                                createServer: (start) => {
                                    start(stream);
                                    return stream;
                                }
                            }, (request, response) => {
                                this.emit('request', request, response);
                            });

                            this.emit('connected');
                        } else {
                            this.emit('error', { errno: 'entry node error', code: result.code });
                            stream.destroy();
                        }
                    });
                })
                    .on('error', (err) => {
                        this.emit('error', err);
                    })
                    .connect(options.entryNode.proxyPort, options.entryNode.host);
        }
    }

    listen(port, cb) {
        this.server.listen(port, cb);
    }

    destroy(cb) {
        if (this.reconnectInstance) {
            this.reconnectInstance.disconnect();
        }

        this.server.close(cb);
    }

    handleRequest(hostname, request, response) {
        if (hostname === this.options.domain) {
            this.emit('request', request, response);
        } else if (this.connections.has(hostname)) {
            let connection = this.connections.get(hostname);

            console.log('reverse request from', hostname);

            let reqUrl = url.parse(request.url);

			let reverseRequest = http2.raw.request({
				plain: true,
				socket: connection,
				path: reqUrl.path,
				method: request.method
			}, (resp) => {
				resp.pipe(response);
            });

			reverseRequest.on('error', (error) => {
				console.log('reverse request error:', error);

				response.statusCode = 500;
				response.end('internal error');
            });

			request.pipe(reverseRequest);
        } else {
            response.statusCode = 404;
            response.end(hostname + ' not found');
        }
    }
}

util.inherits(Proxy, EventEmitter);

module.exports = Proxy;<commit_msg>lib http2 need host<commit_after>'use strict';

var net = require('net');
var url = require('url');
var http2 = require('http2');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var reconnect = require('reconnect-net');

class Proxy {
    constructor(options, dns) {
        this.options = options;
        this.dns = dns;
        this.connections = new Map();

        this.server = net.createServer((socket) => {
            let requestData = '';
            let heartbeatInterval = undefined;
            let myDomain = undefined;

            socket.on('data', (data) => {
                requestData += data.toString('utf-8');

                try {
                    var result = JSON.parse(requestData);
                } catch (err) {
                    return;
                }

                if (result.domain) {
                    socket.removeAllListeners('data');

                    this.dns.kvPut(result.domain, this.localAddress, (err, key, n) => {
                        if (err) {
                            console.log('store dns failed:', err);
                            socket.write(JSON.stringify({ code: 2 }), 'utf-8');
                            socket.destroy();
                            return;
                        }

                        myDomain = result.domain;
                        this.connections.set(myDomain, socket);

                        heartbeatInterval =
                            setInterval(() => {
                                this.dns.kvPut(myDomain, this.localAddress, (err, key, n) => {
                                    if (err) {
                                        console.log('keep heartbeat interval failed:', err);
                                    }
                                });
                            }, this.options.heartbeatInterval);

                        socket.write(JSON.stringify({ code: 0 }), 'utf-8');

                        console.log('new proxy connection:', myDomain);
                    });
                } else {
                    socket.write(JSON.stringify({ code: 1 }), 'utf-8');
                    socket.destroy();
                }
            });

            socket.on('error', (error) => {
                if (heartbeatInterval) clearInterval(heartbeatInterval);
                if (myDomain) this.connections.delete(myDomain);
            });

            socket.on('close', () => {
                if (heartbeatInterval) clearInterval(heartbeatInterval);
                if (myDomain) this.connections.delete(myDomain);

                console.log('proxy connection closed:', myDomain);
            });
        });

        if (options.entryNode && options.entryNode.proxyPort) {
            this.reconnectInstance =
                reconnect((stream) => {
                    let signin = { domain: options.domain };
                    stream.write(JSON.stringify(signin), 'utf-8');

                    let resultData = '';
                    stream.on('data', (data) => {
                        resultData += data.toString('utf-8');

                        try {
                            var result = JSON.parse(resultData);
                        } catch (err) {
                            return;
                        }

                        if (result.code === 0) {
                            stream.removeAllListeners('data');

                            http2.raw.createServer({
                                plain: true,
                                createServer: (start) => {
                                    start(stream);
                                    return stream;
                                }
                            }, (request, response) => {
                                this.emit('request', request, response);
                            });

                            this.emit('connected');
                        } else {
                            this.emit('error', { errno: 'entry node error', code: result.code });
                            stream.destroy();
                        }
                    });
                })
                    .on('error', (err) => {
                        this.emit('error', err);
                    })
                    .connect(options.entryNode.proxyPort, options.entryNode.host);
        }
    }

    listen(port, cb) {
        this.server.listen(port, cb);
    }

    destroy(cb) {
        if (this.reconnectInstance) {
            this.reconnectInstance.disconnect();
        }

        this.server.close(cb);
    }

    handleRequest(hostname, request, response) {
        if (hostname === this.options.domain) {
            this.emit('request', request, response);
        } else if (this.connections.has(hostname)) {
            let connection = this.connections.get(hostname);

            console.log('reverse request from', hostname);

            let reqUrl = url.parse(request.url);

			let reverseRequest = http2.raw.request({
                host: hostname,
				plain: true,
				socket: connection,
				path: reqUrl.path,
				method: request.method
			}, (resp) => {
				resp.pipe(response);
            });

			reverseRequest.on('error', (error) => {
				console.log('reverse request error:', error);

				response.statusCode = 500;
				response.end('internal error');
            });

			request.pipe(reverseRequest);
        } else {
            response.statusCode = 404;
            response.end(hostname + ' not found');
        }
    }
}

util.inherits(Proxy, EventEmitter);

module.exports = Proxy;<|endoftext|>


<commit_before>var deps = {
	Core: {
		src: ['RaphaelLayer.js'],
		desc: 'The core of the Raphael Leaflet layer.'
	},

	Layer: {
		src: ['layer/vector/Layer.Raphael.js'],
		desc: 'Vector rendering core (Raphael-powered), enables overlaying the map with SVG paths and animation.',
		heading: 'Vector layers'
	},

	Marker: {
		src: ['layer/vector/Marker.js'],
		deps: ['Layer'],
		desc: 'Marker overlay with a standard SVG icon'
	},

	Pulse: {
		src: ['layer/vector/Pulse.js'],
		deps: ['Layer'],
		desc: 'Animated pulse marker overlay'
	},

	Polyline: {
		src: ['layer/vector/Polyline.js'],
		deps: ['Layer'],
		desc: 'Straight lines connecting n latlngs.'
	},

	Polygon: {
		src: ['layer/vector/Polygon.js'],
		deps: ['Layer'],
		desc: 'Straight lines connecting n latlngs and closing the last latlng with the first.'
	},

	PolygonGlow: {
		src: ['layer/vector/PolygonGlow.js'],
		deps: ['Layer'],
		desc: 'Straight lines connecting n latlngs and closing the last latlng with the first with \'glowing\' animation.'
	},

	Bezier: {
		src: ['layer/vector/Bezier.js'],
		deps: ['Layer'],
		desc: 'Quadratic bezier line.'
	},

	BezierAnim: {
		src: ['layer/vector/BezierAnim.js'],
		deps: ['Layer'],
		desc: 'Quadratic bezier line animated.'
	}
};

if (typeof exports !== 'undefined') {
	exports.deps = deps;
}<commit_msg>Added MultiPoly and GeoJSON to build files<commit_after>var deps = {
	Core: {
		src: ['RaphaelLayer.js'],
		desc: 'The core of the Raphael Leaflet layer.'
	},

	Layer: {
		src: ['layer/vector/Layer.Raphael.js'],
		desc: 'Vector rendering core (Raphael-powered), enables overlaying the map with SVG paths and animation.',
		heading: 'Vector layers'
	},

	Marker: {
		src: ['layer/vector/Marker.js'],
		deps: ['Layer'],
		desc: 'Marker overlay with a standard SVG icon'
	},

	Pulse: {
		src: ['layer/vector/Pulse.js'],
		deps: ['Layer'],
		desc: 'Animated pulse marker overlay'
	},

	Polyline: {
		src: ['layer/vector/Polyline.js'],
		deps: ['Layer'],
		desc: 'Straight lines connecting n latlngs.'
	},

	Polygon: {
		src: ['layer/vector/Polygon.js'],
		deps: ['Layer'],
		desc: 'Straight lines connecting n latlngs and closing the last latlng with the first.'
	},

	PolygonGlow: {
		src: ['layer/vector/PolygonGlow.js'],
		deps: ['Layer'],
		desc: 'Straight lines connecting n latlngs and closing the last latlng with the first with \'glowing\' animation.'
	},

	Bezier: {
		src: ['layer/vector/Bezier.js'],
		deps: ['Layer'],
		desc: 'Quadratic bezier line.'
	},

	BezierAnim: {
		src: ['layer/vector/BezierAnim.js'],
		deps: ['Layer'],
		desc: 'Quadratic bezier line animated.'
	},

	MultiPoly: {
		src: ['layer/vector/MultiPoly.js'],
		deps: ['Layer', 'PolyLine', 'Polygon'],
		desc: 'Groups for GeoJSON objects.'
	},

	GeoJSON: {
		src: ['layer/vector/GeoJSON.js'],
		deps: ['MultiPoly'],
		desc: 'GeoJSON parser to layer groups.'
	}
};

if (typeof exports !== 'undefined') {
	exports.deps = deps;
}<|endoftext|>


<commit_before>var db_helper = require('./connection');

var Queriable = function () {

  this.onDocLoad = function (fn) {
    this.onDocLoadFn = fn;
  };

  this.find = function (id, cb) {
    var db = db_helper.connection(),
        self = this;

    db.get(id, function (err, doc) {
      if (err) {
        return cb(err, null);
      }

      if(doc) {
        try {
          var loaded_doc = self.onDocLoadFn(doc);
        } catch(ex) {
          //dumpError(ex);
          return cb(ex,null);
        }
        return cb(null, loaded_doc);
      } else {
        return cb("item does not exist", null);
      }
    });
  };

  this._view = function (view_name, options, cb) {
    var db = db_helper.connection(),
        view_name = view_name.split("/")
        self = this;
    db.view(view_name[0],view_name[1], options, function (err, docs) {
      if (err) {
        return cb(err, null);
      }

      var model_collection = [];

      docs.rows.forEach(function (doc,index) {
        model_collection.push(self.onDocLoadFn(doc.doc));
      });

      return cb(null, model_collection);
    });
  };

  this.all = function (cb) {

    this._view(this.model_type + '/all', {}, cb);

  };

  this.whereFirst = function (property, key, cb) {

    this._view(this.model_type + '/'+property,{key: key}, function(err,results) {

      if(err != null) {

        return cb(err, null);

      } else {

        if( results && results.length ) {

          return cb(err, results[0] );

        } else {

          return cb("item does not exist", null);

        } //results && results.length

      } //err != null

    }); //this._view

  }; //whereFirst

  this.where = function (property, key,cb) {
    this._view(this.model_type + '/'+property,{key: key}, cb);
  };
};

module.exports = Queriable;

function dumpError(err) {
  if (typeof err === 'object') {
    if (err.message) {
      console.dir('\nMessage: ' + err.message)
    }
    if (err.stack) {
      console.dir('\nStacktrace:')
        console.dir('====================')
        console.dir(err.stack);
    }

    if (err.error) {
      //console.dir(err);
    }
  } else {
    console.dir('dumpError :: argument is not an object');
  }
}

<commit_msg>find by property<commit_after>var db_helper = require('./connection');

var Queriable = function () {

  this.onDocLoad = function (fn) {
    this.onDocLoadFn = fn;
  };

  this.find = function (id, cb) {
    var db = db_helper.connection(),
        self = this;

    db.get(id, function (err, doc) {
      if (err) {
        return cb(err, null);
      }

      if(doc) {
        try {
          var loaded_doc = self.onDocLoadFn(doc);
        } catch(ex) {
          //dumpError(ex);
          return cb(ex,null);
        }
        return cb(null, loaded_doc);
      } else {
        return cb("item does not exist", null);
      }
    });
  };

  this._view = function (view_name, options, cb) {
    var db = db_helper.connection(),
        view_name = view_name.split("/")
        self = this;
    db.view(view_name[0],view_name[1], options, function (err, docs) {

      if (err) {
        return cb(err, null);
      }

      var model_collection = [];

      docs.rows.forEach(function (doc,index) {
        var place = docs.rows.length>1?"doc":"value";
        model_collection.push(self.onDocLoadFn(doc[place]));
      });

      return cb(null, model_collection);
    });
  };

  this.all = function (cb) {

    this._view(this.model_type + '/all', {}, cb);

  };

  this.whereFirst = function (property, key, cb) {

    this._view(this.model_type + '/'+property,{key: key}, function(err,results) {

      if(err != null) {

        return cb(err, null);

      } else {

        if( results && results.length ) {

          return cb(err, results[0] );

        } else {

          return cb("item does not exist", null);

        } //results && results.length

      } //err != null

    }); //this._view

  }; //whereFirst

  this.where = function (property, key,cb) {
    this._view(this.model_type + '/'+property,{key: key}, cb);
  };
};

module.exports = Queriable;

function dumpError(err) {
  if (typeof err === 'object') {
    if (err.message) {
      console.dir('\nMessage: ' + err.message)
    }
    if (err.stack) {
      console.dir('\nStacktrace:')
        console.dir('====================')
        console.dir(err.stack);
    }

    if (err.error) {
      //console.dir(err);
    }
  } else {
    console.dir('dumpError :: argument is not an object');
  }
}

<|endoftext|>


<commit_before>var Promise = require('bluebird');

function Query(model, query, type) {
    this._model = model; // constructor
    this._r = model._getModel()._thinky.r;

    if (query != null) {
        this._query = query;
        this._type = type || 'value'
    }
    else {
        this._query = this._r.table(model.getName());
        this._type = type || 'sequence'
    }
}

Query.prototype.setType = function(type) {
    //TODO Test
    this._type = type;
}

//TODO refactor run and execute
//TODO pass the groupFormat 'raw'
Query.prototype.run = function() {
    var self = this;
    var p;
    if (self._model._error !== null) {
        p = new Promise(function(resolve, reject) {
            reject(self._model._error);
        })
    }
    else if (self._model._getModel()._tableReady === true) {
        p = new Promise(function(resolve, reject) {
            self._query.run().then(function(result) {
                 self._model._parse(result).then(resolve).error(reject);
            }).error(reject)
        })
    }
    else {
        p = new Promise(function(resolve, reject) {
            self._model.on('ready', function() {
                self._query.run().then(function(result) {
                     self._model._parse(result).then(resolve).error(reject);
                }).error(reject)
            });
        })
    }
    return p;
}
Query.prototype.execute = function() {
    var self = this;
    var p;
    if (self._model._error !== null) {
        p = new Promise(function(resolve, reject) {
            reject(self._model._error);
        })
    }
    else if (self._model._tableReady === true) {
        p = new Promise(function(resolve, reject) {
            self._query.run().then(function(result) {
                 self._model._parse(result, false).then(resolve).error(reject);
            }).error(reject)
        })
    }
    else {
        p = new Promise(function(resolve, reject) {
            self._model.on('ready', function() {
                self._query.execute().then(function(result) {
                    resolve(self._model._parse(result, false))
                }).error(reject);
            });
        })
    }
    return p;
}

Query.prototype.getJoin = function(modelToGet) {
    var self = this;
    var r = self._model._getModel()._thinky.r;

    var getAll = (modelToGet === undefined) ? true: false;
    modelToGet = modelToGet || {};
    var model = this._model;
    var joins = this._model._getModel()._joins;

    for(var key in joins) {
        if (((joins[key].model.getName() in modelToGet) || (getAll === true)) && (joins[key].type === 'hasOne')) {
            self._query = self._query.merge(function(doc) {
                return r.table(joins[key].model.getName()).getAll(doc(joins[key].leftKey), {index: joins[key].rightKey}).coerceTo("ARRAY").do(function(result) {
                    return r.branch(
                        result.count().eq(1),
                        r.object(key, result.nth(0)),
                        r.branch(
                            result.count().eq(0),
                            {},
                            r.error(r.expr("More than one element found for ").add(doc.coerceTo("STRING")).add(r.expr("for the field ").add(key)))
                        )
                    )
                })
            });
        }

        if (((joins[key].model.getName() in modelToGet) || (getAll === true)) && (joins[key].type === 'belongsTo')) {
            self._query = self._query.merge(function(doc) {
                return r.table(joins[key].model.getName()).getAll(doc(joins[key].leftKey), {index: joins[key].rightKey}).coerceTo("ARRAY").do(function(result) {
                    return r.branch(
                        result.count().eq(1),
                        r.object(key, result.nth(0)),
                        r.branch(
                            result.count().eq(0),
                            {},
                            r.error(r.expr("More than one element found for ").add(doc.coerceTo("STRING")).add(r.expr("for the field ").add(key)))
                        )
                    )
                })
            });
        }
        if (((joins[key].model.getName() in modelToGet) || (getAll === true)) && (joins[key].type === 'hasMany')) {
            self._query = self._query.merge(function(doc) {
                return r.object(key, r.table(joins[key].model.getName()).getAll(doc(joins[key].leftKey), {index: joins[key].rightKey}).coerceTo("ARRAY"))
            });
        }

        if (((joins[key].model.getName() in modelToGet) || (getAll === true)) && (joins[key].type === 'hasAndBelongsToMany')) {
            self._query = self._query.merge(function(doc) {
                return r.object(key, r.table(joins[key].link).getAll(doc(joins[key].leftKey), {index: model.getName()+"_"+joins[key].leftKey}).concatMap(function(link) {
                    //TODO Check the length of the array?
                    return r.table(joins[key].model.getName()).getAll(link(joins[key].model.getName()+"_"+joins[key].rightKey), {index: joins[key].rightKey})
                }).coerceTo("ARRAY"))

            });
        }

    }

    //hasOne
    //belongsTo
    //hasMany
    //hasAndBelongsToMany

    return self;
}

// Import rethinkdbdash methods
var Term = require('rethinkdbdash')({pool: false}).expr(1).__proto__;
for(var key in Term) {
    if ((Term.hasOwnProperty(key)) && (key !== 'run') && (key[0] !== '_')) {
        (function(key) {
            Query.prototype[key] = function() {
                this._query = this._query[key].apply(this._query, arguments);
                return this;
            }
        })(key);
    }
}

module.exports = Query;
<commit_msg>Remove internal type<commit_after>var Promise = require('bluebird');

function Query(model, query, type) {
    this._model = model; // constructor
    this._r = model._getModel()._thinky.r;

    if (query != null) {
        this._query = query;
    }
    else {
        this._query = this._r.table(model.getName());
    }
}

//TODO refactor run and execute
//TODO pass the groupFormat 'raw'
Query.prototype.run = function() {
    var self = this;
    var p;
    if (self._model._error !== null) {
        p = new Promise(function(resolve, reject) {
            reject(self._model._error);
        })
    }
    else if (self._model._getModel()._tableReady === true) {
        p = new Promise(function(resolve, reject) {
            self._query.run().then(function(result) {
                 self._model._parse(result).then(resolve).error(reject);
            }).error(reject)
        })
    }
    else {
        p = new Promise(function(resolve, reject) {
            self._model.on('ready', function() {
                self._query.run().then(function(result) {
                     self._model._parse(result).then(resolve).error(reject);
                }).error(reject)
            });
        })
    }
    return p;
}
Query.prototype.execute = function() {
    var self = this;
    var p;
    if (self._model._error !== null) {
        p = new Promise(function(resolve, reject) {
            reject(self._model._error);
        })
    }
    else if (self._model._tableReady === true) {
        p = new Promise(function(resolve, reject) {
            self._query.run().then(function(result) {
                 self._model._parse(result, false).then(resolve).error(reject);
            }).error(reject)
        })
    }
    else {
        p = new Promise(function(resolve, reject) {
            self._model.on('ready', function() {
                self._query.execute().then(function(result) {
                    resolve(self._model._parse(result, false))
                }).error(reject);
            });
        })
    }
    return p;
}

Query.prototype.getJoin = function(modelToGet) {
    var self = this;
    var r = self._model._getModel()._thinky.r;

    var getAll = (modelToGet === undefined) ? true: false;
    modelToGet = modelToGet || {};
    var model = this._model;
    var joins = this._model._getModel()._joins;

    for(var key in joins) {
        if (((joins[key].model.getName() in modelToGet) || (getAll === true)) && (joins[key].type === 'hasOne')) {
            self._query = self._query.merge(function(doc) {
                return r.table(joins[key].model.getName()).getAll(doc(joins[key].leftKey), {index: joins[key].rightKey}).coerceTo("ARRAY").do(function(result) {
                    return r.branch(
                        result.count().eq(1),
                        r.object(key, result.nth(0)),
                        r.branch(
                            result.count().eq(0),
                            {},
                            r.error(r.expr("More than one element found for ").add(doc.coerceTo("STRING")).add(r.expr("for the field ").add(key)))
                        )
                    )
                })
            });
        }

        if (((joins[key].model.getName() in modelToGet) || (getAll === true)) && (joins[key].type === 'belongsTo')) {
            self._query = self._query.merge(function(doc) {
                return r.table(joins[key].model.getName()).getAll(doc(joins[key].leftKey), {index: joins[key].rightKey}).coerceTo("ARRAY").do(function(result) {
                    return r.branch(
                        result.count().eq(1),
                        r.object(key, result.nth(0)),
                        r.branch(
                            result.count().eq(0),
                            {},
                            r.error(r.expr("More than one element found for ").add(doc.coerceTo("STRING")).add(r.expr("for the field ").add(key)))
                        )
                    )
                })
            });
        }
        if (((joins[key].model.getName() in modelToGet) || (getAll === true)) && (joins[key].type === 'hasMany')) {
            self._query = self._query.merge(function(doc) {
                return r.object(key, r.table(joins[key].model.getName()).getAll(doc(joins[key].leftKey), {index: joins[key].rightKey}).coerceTo("ARRAY"))
            });
        }

        if (((joins[key].model.getName() in modelToGet) || (getAll === true)) && (joins[key].type === 'hasAndBelongsToMany')) {
            self._query = self._query.merge(function(doc) {
                return r.object(key, r.table(joins[key].link).getAll(doc(joins[key].leftKey), {index: model.getName()+"_"+joins[key].leftKey}).concatMap(function(link) {
                    //TODO Check the length of the array?
                    return r.table(joins[key].model.getName()).getAll(link(joins[key].model.getName()+"_"+joins[key].rightKey), {index: joins[key].rightKey})
                }).coerceTo("ARRAY"))

            });
        }

    }

    //hasOne
    //belongsTo
    //hasMany
    //hasAndBelongsToMany

    return self;
}

// Import rethinkdbdash methods
var Term = require('rethinkdbdash')({pool: false}).expr(1).__proto__;
for(var key in Term) {
    if ((Term.hasOwnProperty(key)) && (key !== 'run') && (key[0] !== '_')) {
        (function(key) {
            Query.prototype[key] = function() {
                this._query = this._query[key].apply(this._query, arguments);
                return this;
            }
        })(key);
    }
}

module.exports = Query;
<|endoftext|>


<commit_before>/**
 * The reveal.js markdown plugin. Handles parsing of
 * markdown inside of presentations as well as loading
 * of external markdown documents.
 */
(function( root, factory ) {
	if( typeof exports === 'object' ) {
		module.exports = factory( require( './marked' ) );
	}
	else {
		// Browser globals (root is window)
		root.RevealMarkdown = factory( root.marked );
		root.RevealMarkdown.initialize();
	}
}( this, function( marked ) {

	if( typeof marked === 'undefined' ) {
		throw 'The reveal.js Markdown plugin requires marked to be loaded';
	}

	if( typeof hljs !== 'undefined' ) {
		marked.setOptions({
			highlight: function( lang, code ) {
				return hljs.highlightAuto( lang, code ).value;
			}
		});
	}

	var DEFAULT_SLIDE_SEPARATOR = '^\n---\n$',
		DEFAULT_NOTES_SEPARATOR = 'note:',
		DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$',
		DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$';

	/**
	 * Retrieves the markdown contents of a slide section
	 * element. Normalizes leading tabs/whitespace.
	 */
	function getMarkdownFromSlide( section ) {

		var template = section.querySelector( 'script' );

		// strip leading whitespace so it isn't evaluated as code
		var text = ( template || section ).textContent;

		var leadingWs = text.match( /^\n?(\s*)/ )[1].length,
			leadingTabs = text.match( /^\n?(\t*)/ )[1].length;

		if( leadingTabs > 0 ) {
			text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
		}
		else if( leadingWs > 1 ) {
			text = text.replace( new RegExp('\\n? {' + leadingWs + '}'), '\n' );
		}

		return text;

	}

	/**
	 * Given a markdown slide section element, this will
	 * return all arguments that aren't related to markdown
	 * parsing. Used to forward any other user-defined arguments
	 * to the output markdown slide.
	 */
	function getForwardedAttributes( section ) {

		var attributes = section.attributes;
		var result = [];

		for( var i = 0, len = attributes.length; i < len; i++ ) {
			var name = attributes[i].name,
				value = attributes[i].value;

			// disregard attributes that are used for markdown loading/parsing
			if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;

			if( value ) {
				result.push( name + '=' + value );
			}
			else {
				result.push( name );
			}
		}

		return result.join( ' ' );

	}

	/**
	 * Inspects the given options and fills out default
	 * values for what's not defined.
	 */
	function getSlidifyOptions( options ) {

		options = options || {};
		options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
		options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
		options.attributes = options.attributes || '';

		return options;

	}

	/**
	 * Helper function for constructing a markdown slide.
	 */
	function createMarkdownSlide( content, options ) {

		options = getSlidifyOptions( options );

		var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );

		if( notesMatch.length === 2 ) {
			content = notesMatch[0] + '' + notesMatch[1].trim() + '';
		}

		return '';

	}

	/**
	 * Parses a data string into multiple slides based
	 * on the passed in separator arguments.
	 */
	function slidify( markdown, options ) {

		options = getSlidifyOptions( options );

		var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
			horizontalSeparatorRegex = new RegExp( options.separator );

		var matches,
			lastIndex = 0,
			isHorizontal,
			wasHorizontal = true,
			content,
			sectionStack = [];

		// iterate until all blocks between separators are stacked up
		while( matches = separatorRegex.exec( markdown ) ) {
			notes = null;

			// determine direction (horizontal by default)
			isHorizontal = horizontalSeparatorRegex.test( matches[0] );

			if( !isHorizontal && wasHorizontal ) {
				// create vertical stack
				sectionStack.push( [] );
			}

			// pluck slide content from markdown input
			content = markdown.substring( lastIndex, matches.index );

			if( isHorizontal && wasHorizontal ) {
				// add to horizontal stack
				sectionStack.push( content );
			}
			else {
				// add to vertical stack
				sectionStack[sectionStack.length-1].push( content );
			}

			lastIndex = separatorRegex.lastIndex;
			wasHorizontal = isHorizontal;
		}

		// add the remaining slide
		( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );

		var markdownSections = '';

		// flatten the hierarchical stack, and insert
 tags
		for( var i = 0, len = sectionStack.length; i < len; i++ ) {
			// vertical
			if( sectionStack[i] instanceof Array ) {
				markdownSections += '
';

				sectionStack[i].forEach( function( child ) {
					markdownSections += '
' +  createMarkdownSlide( child, options ) + '
';
				} );

				markdownSections += '
';
			}
			else {
				markdownSections += '
' + createMarkdownSlide( sectionStack[i], options ) + '
';
			}
		}

		return markdownSections;

	}

	/**
	 * Parses any current data-markdown slides, splits
	 * multi-slide markdown into separate sections and
	 * handles loading of external markdown.
	 */
	function processSlides() {

		var sections = document.querySelectorAll( '[data-markdown]'),
			section;

		for( var i = 0, len = sections.length; i < len; i++ ) {

			section = sections[i];

			if( section.getAttribute( 'data-markdown' ).length ) {

				var xhr = new XMLHttpRequest(),
					url = section.getAttribute( 'data-markdown' );

				datacharset = section.getAttribute( 'data-charset' );

				// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
				if( datacharset != null && datacharset != '' ) {
					xhr.overrideMimeType( 'text/html; charset=' + datacharset );
				}

				xhr.onreadystatechange = function() {
					if( xhr.readyState === 4 ) {
						// file protocol yields status code 0 (useful for local debug, mobile applications etc.)
						if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) {

							section.outerHTML = slidify( xhr.responseText, {
								separator: section.getAttribute( 'data-separator' ),
								verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
								notesSeparator: section.getAttribute( 'data-separator-notes' ),
								attributes: getForwardedAttributes( section )
							});

						}
						else {

							section.outerHTML = '
' +
								'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
								'Check your browser\'s JavaScript console for more details.' +
								'
Remember that you need to serve the presentation HTML from a HTTP server.
' +
								'
';

						}
					}
				};

				xhr.open( 'GET', url, false );

				try {
					xhr.send();
				}
				catch ( e ) {
					alert( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e );
				}

			}
			else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-separator-vertical' ) || section.getAttribute( 'data-separator-notes' ) ) {

				section.outerHTML = slidify( getMarkdownFromSlide( section ), {
					separator: section.getAttribute( 'data-separator' ),
					verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
					notesSeparator: section.getAttribute( 'data-separator-notes' ),
					attributes: getForwardedAttributes( section )
				});

			}
			else {
				section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
			}
		}

	}

	/**
	 * Check if a node value has the attributes pattern.
	 * If yes, extract it and add that value as one or several attributes
	 * the the terget element.
	 *
	 * You need Cache Killer on Chrome to see the effect on any FOM transformation
	 * directly on refresh (F5)
	 * http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277
	 */
	function addAttributeInElement( node, elementTarget, separator ) {

		var mardownClassesInElementsRegex = new RegExp( separator, 'mg' );
		var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' );
		var nodeValue = node.nodeValue;
		if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {

			var classes = matches[1];
			nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex );
			node.nodeValue = nodeValue;
			while( matchesClass = mardownClassRegex.exec( classes ) ) {
				elementTarget.setAttribute( matchesClass[1], matchesClass[2] );
			}
			return true;
		}
		return false;
	}

	/**
	 * Add attributes to the parent element of a text node,
	 * or the element of an attribute node.
	 */
	function addAttributes( section, element, previousElement, separatorElementAttributes, separatorSectionAttributes ) {

		if ( element != null && element.childNodes != undefined && element.childNodes.length > 0 ) {
			previousParentElement = element;
			for( var i = 0; i < element.childNodes.length; i++ ) {
				childElement = element.childNodes[i];
				if ( i > 0 ) {
					j = i - 1;
					while ( j >= 0 ) {
						aPreviousChildElement = element.childNodes[j];
						if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) {
							previousParentElement = aPreviousChildElement;
							break;
						}
						j = j - 1;
					}
				}
				parentSection = section;
				if( childElement.nodeName ==  "section" ) {
					parentSection = childElement ;
					previousParentElement = childElement ;
				}
				if ( typeof childElement.setAttribute == 'function' || childElement.nodeType == Node.COMMENT_NODE ) {
					addAttributes( parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes );
				}
			}
		}

		if ( element.nodeType == Node.COMMENT_NODE ) {
			if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) == false ) {
				addAttributeInElement( element, section, separatorSectionAttributes );
			}
		}
	}

	/**
	 * Converts any current data-markdown slides in the
	 * DOM to HTML.
	 */
	function convertSlides() {

		var sections = document.querySelectorAll( '[data-markdown]');

		for( var i = 0, len = sections.length; i < len; i++ ) {

			var section = sections[i];

			// Only parse the same slide once
			if( !section.getAttribute( 'data-markdown-parsed' ) ) {

				section.setAttribute( 'data-markdown-parsed', true )

				var notes = section.querySelector( 'aside.notes' );
				var markdown = getMarkdownFromSlide( section );

				section.innerHTML = marked( markdown );
				addAttributes( 	section, section, null, section.getAttribute( 'data-element-attributes' ) ||
								section.parentNode.getAttribute( 'data-element-attributes' ) ||
								DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,
								section.getAttribute( 'data-attributes' ) ||
								section.parentNode.getAttribute( 'data-attributes' ) ||
								DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR);

				// If there were notes, we need to re-add them after
				// having overwritten the section's HTML
				if( notes ) {
					section.appendChild( notes );
				}

			}

		}

	}

	// API
	return {

		initialize: function() {
			processSlides();
			convertSlides();
		},

		// TODO: Do these belong in the API?
		processSlides: processSlides,
		convertSlides: convertSlides,
		slidify: slidify

	};

}));
<commit_msg>handle the </script> end bug inside code markdown<commit_after>/**
 * The reveal.js markdown plugin. Handles parsing of
 * markdown inside of presentations as well as loading
 * of external markdown documents.
 */
(function( root, factory ) {
	if( typeof exports === 'object' ) {
		module.exports = factory( require( './marked' ) );
	}
	else {
		// Browser globals (root is window)
		root.RevealMarkdown = factory( root.marked );
		root.RevealMarkdown.initialize();
	}
}( this, function( marked ) {

	if( typeof marked === 'undefined' ) {
		throw 'The reveal.js Markdown plugin requires marked to be loaded';
	}

	if( typeof hljs !== 'undefined' ) {
		marked.setOptions({
			highlight: function( lang, code ) {
				return hljs.highlightAuto( lang, code ).value;
			}
		});
	}

	var DEFAULT_SLIDE_SEPARATOR = '^\n---\n$',
		DEFAULT_NOTES_SEPARATOR = 'note:',
		DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$',
		DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$';

	/**
	 * Retrieves the markdown contents of a slide section
	 * element. Normalizes leading tabs/whitespace.
	 */
	function getMarkdownFromSlide( section ) {

		var template = section.querySelector( 'script' );

		// strip leading whitespace so it isn't evaluated as code
		var text = ( template || section ).textContent;
		// restore script end tag
		text = text.replace(/__SCRIPT_END__/g, '</script>');
		var leadingWs = text.match( /^\n?(\s*)/ )[1].length,
			leadingTabs = text.match( /^\n?(\t*)/ )[1].length;

		if( leadingTabs > 0 ) {
			text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
		}
		else if( leadingWs > 1 ) {
			text = text.replace( new RegExp('\\n? {' + leadingWs + '}'), '\n' );
		}

		return text;

	}

	/**
	 * Given a markdown slide section element, this will
	 * return all arguments that aren't related to markdown
	 * parsing. Used to forward any other user-defined arguments
	 * to the output markdown slide.
	 */
	function getForwardedAttributes( section ) {

		var attributes = section.attributes;
		var result = [];

		for( var i = 0, len = attributes.length; i < len; i++ ) {
			var name = attributes[i].name,
				value = attributes[i].value;

			// disregard attributes that are used for markdown loading/parsing
			if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;

			if( value ) {
				result.push( name + '=' + value );
			}
			else {
				result.push( name );
			}
		}

		return result.join( ' ' );

	}

	/**
	 * Inspects the given options and fills out default
	 * values for what's not defined.
	 */
	function getSlidifyOptions( options ) {

		options = options || {};
		options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
		options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
		options.attributes = options.attributes || '';

		return options;

	}

	/**
	 * Helper function for constructing a markdown slide.
	 */
	function createMarkdownSlide( content, options ) {

		options = getSlidifyOptions( options );

		var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );

		if( notesMatch.length === 2 ) {
			content = notesMatch[0] + '' + notesMatch[1].trim() + '';
		}
		//handle script end tag bug
		content = content.replace(/<\/script>/g, '__SCRIPT_END__');
		return '';

	}

	/**
	 * Parses a data string into multiple slides based
	 * on the passed in separator arguments.
	 */
	function slidify( markdown, options ) {

		options = getSlidifyOptions( options );

		var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
			horizontalSeparatorRegex = new RegExp( options.separator );

		var matches,
			lastIndex = 0,
			isHorizontal,
			wasHorizontal = true,
			content,
			sectionStack = [];

		// iterate until all blocks between separators are stacked up
		while( matches = separatorRegex.exec( markdown ) ) {
			notes = null;

			// determine direction (horizontal by default)
			isHorizontal = horizontalSeparatorRegex.test( matches[0] );

			if( !isHorizontal && wasHorizontal ) {
				// create vertical stack
				sectionStack.push( [] );
			}

			// pluck slide content from markdown input
			content = markdown.substring( lastIndex, matches.index );

			if( isHorizontal && wasHorizontal ) {
				// add to horizontal stack
				sectionStack.push( content );
			}
			else {
				// add to vertical stack
				sectionStack[sectionStack.length-1].push( content );
			}

			lastIndex = separatorRegex.lastIndex;
			wasHorizontal = isHorizontal;
		}

		// add the remaining slide
		( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );

		var markdownSections = '';

		// flatten the hierarchical stack, and insert
 tags
		for( var i = 0, len = sectionStack.length; i < len; i++ ) {
			// vertical
			if( sectionStack[i] instanceof Array ) {
				markdownSections += '
';

				sectionStack[i].forEach( function( child ) {
					markdownSections += '
' +  createMarkdownSlide( child, options ) + '
';
				} );

				markdownSections += '
';
			}
			else {
				markdownSections += '
' + createMarkdownSlide( sectionStack[i], options ) + '
';
			}
		}

		return markdownSections;

	}

	/**
	 * Parses any current data-markdown slides, splits
	 * multi-slide markdown into separate sections and
	 * handles loading of external markdown.
	 */
	function processSlides() {

		var sections = document.querySelectorAll( '[data-markdown]'),
			section;

		for( var i = 0, len = sections.length; i < len; i++ ) {

			section = sections[i];

			if( section.getAttribute( 'data-markdown' ).length ) {

				var xhr = new XMLHttpRequest(),
					url = section.getAttribute( 'data-markdown' );

				datacharset = section.getAttribute( 'data-charset' );

				// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
				if( datacharset != null && datacharset != '' ) {
					xhr.overrideMimeType( 'text/html; charset=' + datacharset );
				}

				xhr.onreadystatechange = function() {
					if( xhr.readyState === 4 ) {
						// file protocol yields status code 0 (useful for local debug, mobile applications etc.)
						if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) {

							section.outerHTML = slidify( xhr.responseText, {
								separator: section.getAttribute( 'data-separator' ),
								verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
								notesSeparator: section.getAttribute( 'data-separator-notes' ),
								attributes: getForwardedAttributes( section )
							});

						}
						else {

							section.outerHTML = '
' +
								'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
								'Check your browser\'s JavaScript console for more details.' +
								'
Remember that you need to serve the presentation HTML from a HTTP server.
' +
								'
';

						}
					}
				};

				xhr.open( 'GET', url, false );

				try {
					xhr.send();
				}
				catch ( e ) {
					alert( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e );
				}

			}
			else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-separator-vertical' ) || section.getAttribute( 'data-separator-notes' ) ) {

				section.outerHTML = slidify( getMarkdownFromSlide( section ), {
					separator: section.getAttribute( 'data-separator' ),
					verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
					notesSeparator: section.getAttribute( 'data-separator-notes' ),
					attributes: getForwardedAttributes( section )
				});

			}
			else {
				section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
			}
		}

	}

	/**
	 * Check if a node value has the attributes pattern.
	 * If yes, extract it and add that value as one or several attributes
	 * the the terget element.
	 *
	 * You need Cache Killer on Chrome to see the effect on any FOM transformation
	 * directly on refresh (F5)
	 * http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277
	 */
	function addAttributeInElement( node, elementTarget, separator ) {

		var mardownClassesInElementsRegex = new RegExp( separator, 'mg' );
		var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' );
		var nodeValue = node.nodeValue;
		if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {

			var classes = matches[1];
			nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex );
			node.nodeValue = nodeValue;
			while( matchesClass = mardownClassRegex.exec( classes ) ) {
				elementTarget.setAttribute( matchesClass[1], matchesClass[2] );
			}
			return true;
		}
		return false;
	}

	/**
	 * Add attributes to the parent element of a text node,
	 * or the element of an attribute node.
	 */
	function addAttributes( section, element, previousElement, separatorElementAttributes, separatorSectionAttributes ) {

		if ( element != null && element.childNodes != undefined && element.childNodes.length > 0 ) {
			previousParentElement = element;
			for( var i = 0; i < element.childNodes.length; i++ ) {
				childElement = element.childNodes[i];
				if ( i > 0 ) {
					j = i - 1;
					while ( j >= 0 ) {
						aPreviousChildElement = element.childNodes[j];
						if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) {
							previousParentElement = aPreviousChildElement;
							break;
						}
						j = j - 1;
					}
				}
				parentSection = section;
				if( childElement.nodeName ==  "section" ) {
					parentSection = childElement ;
					previousParentElement = childElement ;
				}
				if ( typeof childElement.setAttribute == 'function' || childElement.nodeType == Node.COMMENT_NODE ) {
					addAttributes( parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes );
				}
			}
		}

		if ( element.nodeType == Node.COMMENT_NODE ) {
			if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) == false ) {
				addAttributeInElement( element, section, separatorSectionAttributes );
			}
		}
	}

	/**
	 * Converts any current data-markdown slides in the
	 * DOM to HTML.
	 */
	function convertSlides() {

		var sections = document.querySelectorAll( '[data-markdown]');

		for( var i = 0, len = sections.length; i < len; i++ ) {

			var section = sections[i];

			// Only parse the same slide once
			if( !section.getAttribute( 'data-markdown-parsed' ) ) {

				section.setAttribute( 'data-markdown-parsed', true )

				var notes = section.querySelector( 'aside.notes' );
				var markdown = getMarkdownFromSlide( section );

				section.innerHTML = marked( markdown );
				addAttributes( 	section, section, null, section.getAttribute( 'data-element-attributes' ) ||
								section.parentNode.getAttribute( 'data-element-attributes' ) ||
								DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,
								section.getAttribute( 'data-attributes' ) ||
								section.parentNode.getAttribute( 'data-attributes' ) ||
								DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR);

				// If there were notes, we need to re-add them after
				// having overwritten the section's HTML
				if( notes ) {
					section.appendChild( notes );
				}

			}

		}

	}

	// API
	return {

		initialize: function() {
			processSlides();
			convertSlides();
		},

		// TODO: Do these belong in the API?
		processSlides: processSlides,
		convertSlides: convertSlides,
		slidify: slidify

	};

}));
<|endoftext|>


<commit_before>/**
 * #Query
 * This is the controller of our geolocalisation service.
 *
 * @author Olivier Evalet <evaleto@gmail.com>
 * @license GPL3 (see LICENSE)
 */

var config = require('./config');
var debug = config.debug;
var _=require('underscore');

var geo = exports;

/**
 * ## geo.Query(opts)
 * @param {Object} Query constructor options:
 *	- driver: mongo, ...
 *  - X: ...
 *  - Y: ...
 * @constructor
 */
function Query(opts) {
  var self = this;
}

/**
 * ## geo.Query.isValid()
 * Validate the engine
 * @returns {Boolean} Validation result
 */
Query.prototype.isValid = function() {
};

/**
 * ## geo.Query.nearbySearch(request)
 * request bestresource near a position
 * @param {request}
 * @return promise
 */
Query.prototype.nearbySearch = function(request) {
  var self = this,promise;
  //
  //validate request params

  // promise=query_drv.r(request);
  // promise.then(function (result) {
  //   _.extend(self,result);
  // });
  return promise;
};

geo.Query = Query;
<commit_msg>initial import<commit_after>/**
 * #Query
 * This is the controller of our geolocalisation service.
 *
 * @author Olivier Evalet <evaleto@gmail.com>
 * @license GPL3 (see LICENSE)
 */

var config = require('./config');
var debug = config.debug;
var _=require('underscore');

var geo = exports;

/**
 * ## geo.Query(opts)
 * @param {Object} Query constructor options:
 *	- driver: mongo, ...
 *  - X: ...
 *  - Y: ...
 * @constructor
 */
function Query(opts) {
  var self = this;
}

/**
 * ## geo.Query.isValid()
 * Validate the engine
 * @returns {Boolean} Validation result
 */
Query.prototype.isValid = function() {
};

/**
 * ## geo.Query.nearbySearch(request)
 * request bestresource near a position
 * @param {request}
 * @return promise
 */
Query.prototype.nearbySearch = function(request) {
  var self = this,promise;
  //
  //validate request params

  // apply api implementation
  // promise=query_drv.r(request);
  // promise.then(function (result) {
  //   _.extend(self,result);
  // });
  return promise;
};

geo.Query = Query;
<|endoftext|>


<commit_before>/**
 * The reveal.js markdown plugin. Handles parsing of
 * markdown inside of presentations as well as loading
 * of external markdown documents.
 */
(function( root, factory ) {
	if( typeof exports === 'object' ) {
		module.exports = factory( require( './marked' ) );
	}
	else {
		// Browser globals (root is window)
		root.RevealMarkdown = factory( root.marked );
		root.RevealMarkdown.initialize();
	}
}( this, function( marked ) {

	if( typeof marked === 'undefined' ) {
		throw 'The reveal.js Markdown plugin requires marked to be loaded';
	}

	if( typeof hljs !== 'undefined' ) {
		marked.setOptions({
			highlight: function( lang, code ) {
				return hljs.highlightAuto( lang, code ).value;
			}
		});
	}

	var DEFAULT_SLIDE_SEPARATOR = '^\n---\n$',
		DEFAULT_NOTES_SEPARATOR = 'note:';

	/**
	 * Retrieves the markdown contents of a slide section
	 * element. Normalizes leading tabs/whitespace.
	 */
	function getMarkdownFromSlide( section ) {

		var template = section.querySelector( 'script' );

		// strip leading whitespace so it isn't evaluated as code
		var text = ( template || section ).textContent;

		var leadingWs = text.match( /^\n?(\s*)/ )[1].length,
			leadingTabs = text.match( /^\n?(\t*)/ )[1].length;

		if( leadingTabs > 0 ) {
			text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
		}
		else if( leadingWs > 1 ) {
			text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
		}

		return text;

	}

	/**
	 * Given a markdown slide section element, this will
	 * return all arguments that aren't related to markdown
	 * parsing. Used to forward any other user-defined arguments
	 * to the output markdown slide.
	 */
	function getForwardedAttributes( section ) {

		var attributes = section.attributes;
		var result = [];

		for( var i = 0, len = attributes.length; i < len; i++ ) {
			var name = attributes[i].name,
				value = attributes[i].value;

			// disregard attributes that are used for markdown loading/parsing
			if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;

			if( value ) {
				result.push( name + '=' + value );
			}
			else {
				result.push( name );
			}
		}

		return result.join( ' ' );

	}

	/**
	 * Inspects the given options and fills out default
	 * values for what's not defined.
	 */
	function getSlidifyOptions( options ) {

		options = options || {};
		options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
		options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
		options.attributes = options.attributes || '';

		return options;

	}

	/**
	 * Helper function for constructing a markdown slide.
	 */
	function createMarkdownSlide( content, options ) {

		options = getSlidifyOptions( options );

		var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );

		if( notesMatch.length === 2 ) {
			content = notesMatch[0] + '' + notesMatch[1].trim() + '';
		}

		return '';

	}

	/**
	 * Parses a data string into multiple slides based
	 * on the passed in separator arguments.
	 */
	function slidify( markdown, options ) {

		options = getSlidifyOptions( options );

		var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
			horizontalSeparatorRegex = new RegExp( options.separator );

		var matches,
			lastIndex = 0,
			isHorizontal,
			wasHorizontal = true,
			content,
			sectionStack = [];

		// iterate until all blocks between separators are stacked up
		while( matches = separatorRegex.exec( markdown ) ) {
			notes = null;

			// determine direction (horizontal by default)
			isHorizontal = horizontalSeparatorRegex.test( matches[0] );

			if( !isHorizontal && wasHorizontal ) {
				// create vertical stack
				sectionStack.push( [] );
			}

			// pluck slide content from markdown input
			content = markdown.substring( lastIndex, matches.index );

			if( isHorizontal && wasHorizontal ) {
				// add to horizontal stack
				sectionStack.push( content );
			}
			else {
				// add to vertical stack
				sectionStack[sectionStack.length-1].push( content );
			}

			lastIndex = separatorRegex.lastIndex;
			wasHorizontal = isHorizontal;
		}

		// add the remaining slide
		( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );

		var markdownSections = '';

		// flatten the hierarchical stack, and insert
 tags
		for( var i = 0, len = sectionStack.length; i < len; i++ ) {
			// vertical
			if( sectionStack[i] instanceof Array ) {
				markdownSections += '
';

				sectionStack[i].forEach( function( child ) {
					markdownSections += '
' +  createMarkdownSlide( child, options ) + '
';
				} );

				markdownSections += '
';
			}
			else {
				markdownSections += '
' + createMarkdownSlide( sectionStack[i], options ) + '
';
			}
		}

		return markdownSections;

	}

	/**
	 * Parses any current data-markdown slides, splits
	 * multi-slide markdown into separate sections and
	 * handles loading of external markdown.
	 */
	function processSlides() {

		var sections = document.querySelectorAll( '[data-markdown]'),
			section;

		for( var i = 0, len = sections.length; i < len; i++ ) {

			section = sections[i];

			if( section.getAttribute( 'data-markdown' ).length ) {

				var xhr = new XMLHttpRequest(),
					url = section.getAttribute( 'data-markdown' );

				datacharset = section.getAttribute( 'data-charset' );

				// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
				if( datacharset != null && datacharset != '' ) {
					xhr.overrideMimeType( 'text/html; charset=' + datacharset );
				}

				xhr.onreadystatechange = function() {
					if( xhr.readyState === 4 ) {
						if ( xhr.status >= 200 && xhr.status < 300 ) {

							section.outerHTML = slidify( xhr.responseText, {
								separator: section.getAttribute( 'data-separator' ),
								verticalSeparator: section.getAttribute( 'data-vertical' ),
								notesSeparator: section.getAttribute( 'data-notes' ),
								attributes: getForwardedAttributes( section )
							});

						}
						else {

							section.outerHTML = '
' +
								'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
								'Check your browser\'s JavaScript console for more details.' +
								'
Remember that you need to serve the presentation HTML from a HTTP server.
' +
								'
';

						}
					}
				};

				xhr.open( 'GET', url, false );

				try {
					xhr.send();
				}
				catch ( e ) {
					alert( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e );
				}

			}
			else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-vertical' ) || section.getAttribute( 'data-notes' ) ) {

				section.outerHTML = slidify( getMarkdownFromSlide( section ), {
					separator: section.getAttribute( 'data-separator' ),
					verticalSeparator: section.getAttribute( 'data-vertical' ),
					notesSeparator: section.getAttribute( 'data-notes' ),
					attributes: getForwardedAttributes( section )
				});

			}
			else {

				section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );

			}
		}

	}

	/**
	 * Add classes to the parent element of a text node
	 * From http://stackoverflow.com/questions/9178174/find-all-text-nodes
	 */
	function addClasses(element)
	{
		var mardownClassesInElementsRegex = new RegExp( "{\\\.\s*?([^}]+?)}", 'mg' );
		var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' );
		if ( element.childNodes.length > 0 ) {

			for (var i = 0; i < element.childNodes.length; i++) {
				addClasses(element.childNodes[i]);
			}
		}

		if (element.nodeType == Node.TEXT_NODE && /\S/.test(element.nodeValue)) {

			var nodeValue = element.nodeValue;
			if ( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {

				var classes = matches[1];
				console.log("'" + classes + "'");
				nodeValue = nodeValue.substring(0,matches.index) + nodeValue.substring(mardownClassesInElementsRegex.lastIndex) + "ee";
				console.log("'" + nodeValue + "'");
				element.nodeValue = nodeValue;
				console.log("'" + element.parentNode.tagName + "'");

				while( matchesClass = mardownClassRegex.exec( classes ) ) {
					console.log("attr='" + matchesClass[1] + "'='" + matchesClass[2] + "'");
					element.parentNode.attributes[matchesClass[1]] = matchesClass[2];
					console.log("=>'" + element.parentNode.attributes[matchesClass[1]] + "'");
				}
			}
		}
	}

	/**
	 * Converts any current data-markdown slides in the
	 * DOM to HTML.
	 */
	function convertSlides() {

		var sections = document.querySelectorAll( '[data-markdown]');

		for( var i = 0, len = sections.length; i < len; i++ ) {

			var section = sections[i];

			// Only parse the same slide once
			if( !section.getAttribute( 'data-markdown-parsed' ) ) {

				section.setAttribute( 'data-markdown-parsed', true )

				var notes = section.querySelector( 'aside.notes' );
				var markdown = getMarkdownFromSlide( section );

				section.innerHTML = marked( markdown );
				addClasses(section);

				// If there were notes, we need to re-add them after
				// having overwritten the section's HTML
				if( notes ) {
					section.appendChild( notes );
				}

			}

		}

	}

	// API
	return {

		initialize: function() {
			processSlides();
			convertSlides();
		},

		// TODO: Do these belong in the API?
		processSlides: processSlides,
		convertSlides: convertSlides,
		slidify: slidify

	};

}));
<commit_msg>Uses the right method setAttribute.<commit_after>/**
 * The reveal.js markdown plugin. Handles parsing of
 * markdown inside of presentations as well as loading
 * of external markdown documents.
 */
(function( root, factory ) {
	if( typeof exports === 'object' ) {
		module.exports = factory( require( './marked' ) );
	}
	else {
		// Browser globals (root is window)
		root.RevealMarkdown = factory( root.marked );
		root.RevealMarkdown.initialize();
	}
}( this, function( marked ) {

	if( typeof marked === 'undefined' ) {
		throw 'The reveal.js Markdown plugin requires marked to be loaded';
	}

	if( typeof hljs !== 'undefined' ) {
		marked.setOptions({
			highlight: function( lang, code ) {
				return hljs.highlightAuto( lang, code ).value;
			}
		});
	}

	var DEFAULT_SLIDE_SEPARATOR = '^\n---\n$',
		DEFAULT_NOTES_SEPARATOR = 'note:';

	/**
	 * Retrieves the markdown contents of a slide section
	 * element. Normalizes leading tabs/whitespace.
	 */
	function getMarkdownFromSlide( section ) {

		var template = section.querySelector( 'script' );

		// strip leading whitespace so it isn't evaluated as code
		var text = ( template || section ).textContent;

		var leadingWs = text.match( /^\n?(\s*)/ )[1].length,
			leadingTabs = text.match( /^\n?(\t*)/ )[1].length;

		if( leadingTabs > 0 ) {
			text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
		}
		else if( leadingWs > 1 ) {
			text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
		}

		return text;

	}

	/**
	 * Given a markdown slide section element, this will
	 * return all arguments that aren't related to markdown
	 * parsing. Used to forward any other user-defined arguments
	 * to the output markdown slide.
	 */
	function getForwardedAttributes( section ) {

		var attributes = section.attributes;
		var result = [];

		for( var i = 0, len = attributes.length; i < len; i++ ) {
			var name = attributes[i].name,
				value = attributes[i].value;

			// disregard attributes that are used for markdown loading/parsing
			if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;

			if( value ) {
				result.push( name + '=' + value );
			}
			else {
				result.push( name );
			}
		}

		return result.join( ' ' );

	}

	/**
	 * Inspects the given options and fills out default
	 * values for what's not defined.
	 */
	function getSlidifyOptions( options ) {

		options = options || {};
		options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
		options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
		options.attributes = options.attributes || '';

		return options;

	}

	/**
	 * Helper function for constructing a markdown slide.
	 */
	function createMarkdownSlide( content, options ) {

		options = getSlidifyOptions( options );

		var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );

		if( notesMatch.length === 2 ) {
			content = notesMatch[0] + '' + notesMatch[1].trim() + '';
		}

		return '';

	}

	/**
	 * Parses a data string into multiple slides based
	 * on the passed in separator arguments.
	 */
	function slidify( markdown, options ) {

		options = getSlidifyOptions( options );

		var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
			horizontalSeparatorRegex = new RegExp( options.separator );

		var matches,
			lastIndex = 0,
			isHorizontal,
			wasHorizontal = true,
			content,
			sectionStack = [];

		// iterate until all blocks between separators are stacked up
		while( matches = separatorRegex.exec( markdown ) ) {
			notes = null;

			// determine direction (horizontal by default)
			isHorizontal = horizontalSeparatorRegex.test( matches[0] );

			if( !isHorizontal && wasHorizontal ) {
				// create vertical stack
				sectionStack.push( [] );
			}

			// pluck slide content from markdown input
			content = markdown.substring( lastIndex, matches.index );

			if( isHorizontal && wasHorizontal ) {
				// add to horizontal stack
				sectionStack.push( content );
			}
			else {
				// add to vertical stack
				sectionStack[sectionStack.length-1].push( content );
			}

			lastIndex = separatorRegex.lastIndex;
			wasHorizontal = isHorizontal;
		}

		// add the remaining slide
		( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );

		var markdownSections = '';

		// flatten the hierarchical stack, and insert
 tags
		for( var i = 0, len = sectionStack.length; i < len; i++ ) {
			// vertical
			if( sectionStack[i] instanceof Array ) {
				markdownSections += '
';

				sectionStack[i].forEach( function( child ) {
					markdownSections += '
' +  createMarkdownSlide( child, options ) + '
';
				} );

				markdownSections += '
';
			}
			else {
				markdownSections += '
' + createMarkdownSlide( sectionStack[i], options ) + '
';
			}
		}

		return markdownSections;

	}

	/**
	 * Parses any current data-markdown slides, splits
	 * multi-slide markdown into separate sections and
	 * handles loading of external markdown.
	 */
	function processSlides() {

		var sections = document.querySelectorAll( '[data-markdown]'),
			section;

		for( var i = 0, len = sections.length; i < len; i++ ) {

			section = sections[i];

			if( section.getAttribute( 'data-markdown' ).length ) {

				var xhr = new XMLHttpRequest(),
					url = section.getAttribute( 'data-markdown' );

				datacharset = section.getAttribute( 'data-charset' );

				// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
				if( datacharset != null && datacharset != '' ) {
					xhr.overrideMimeType( 'text/html; charset=' + datacharset );
				}

				xhr.onreadystatechange = function() {
					if( xhr.readyState === 4 ) {
						if ( xhr.status >= 200 && xhr.status < 300 ) {

							section.outerHTML = slidify( xhr.responseText, {
								separator: section.getAttribute( 'data-separator' ),
								verticalSeparator: section.getAttribute( 'data-vertical' ),
								notesSeparator: section.getAttribute( 'data-notes' ),
								attributes: getForwardedAttributes( section )
							});

						}
						else {

							section.outerHTML = '
' +
								'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
								'Check your browser\'s JavaScript console for more details.' +
								'
Remember that you need to serve the presentation HTML from a HTTP server.
' +
								'
';

						}
					}
				};

				xhr.open( 'GET', url, false );

				try {
					xhr.send();
				}
				catch ( e ) {
					alert( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e );
				}

			}
			else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-vertical' ) || section.getAttribute( 'data-notes' ) ) {

				section.outerHTML = slidify( getMarkdownFromSlide( section ), {
					separator: section.getAttribute( 'data-separator' ),
					verticalSeparator: section.getAttribute( 'data-vertical' ),
					notesSeparator: section.getAttribute( 'data-notes' ),
					attributes: getForwardedAttributes( section )
				});

			}
			else {

				section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );

			}
		}

	}

	/**
	 * Add classes to the parent element of a text node
	 * From http://stackoverflow.com/questions/9178174/find-all-text-nodes
	 */
	function addClasses(element)
	{
		var mardownClassesInElementsRegex = new RegExp( "{\\\.\s*?([^}]+?)}", 'mg' );
		var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' );
		if ( element.childNodes.length > 0 ) {

			for (var i = 0; i < element.childNodes.length; i++) {
				addClasses(element.childNodes[i]);
			}
		}

		if (element.nodeType == Node.TEXT_NODE && /\S/.test(element.nodeValue)) {

			var nodeValue = element.nodeValue;
			if ( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {

				var classes = matches[1];
				console.log("'" + classes + "'");
				nodeValue = nodeValue.substring(0,matches.index) + nodeValue.substring(mardownClassesInElementsRegex.lastIndex) + "ee";
				console.log("'" + nodeValue + "'");
				element.nodeValue = nodeValue;
				console.log("'" + element.parentNode.tagName + "'");

				while( matchesClass = mardownClassRegex.exec( classes ) ) {
					console.log("attr='" + matchesClass[1] + "'='" + matchesClass[2] + "'");
					element.parentNode.setAttribute(matchesClass[1], matchesClass[2]);
					console.log("=>'" + element.parentNode.attributes[matchesClass[1]].nodeValue + "'");
				}
			}
		}
	}

	/**
	 * Converts any current data-markdown slides in the
	 * DOM to HTML.
	 */
	function convertSlides() {

		var sections = document.querySelectorAll( '[data-markdown]');

		for( var i = 0, len = sections.length; i < len; i++ ) {

			var section = sections[i];

			// Only parse the same slide once
			if( !section.getAttribute( 'data-markdown-parsed' ) ) {

				section.setAttribute( 'data-markdown-parsed', true )

				var notes = section.querySelector( 'aside.notes' );
				var markdown = getMarkdownFromSlide( section );

				section.innerHTML = marked( markdown );
				addClasses(section);

				// If there were notes, we need to re-add them after
				// having overwritten the section's HTML
				if( notes ) {
					section.appendChild( notes );
				}

			}

		}

	}

	// API
	return {

		initialize: function() {
			processSlides();
			convertSlides();
		},

		// TODO: Do these belong in the API?
		processSlides: processSlides,
		convertSlides: convertSlides,
		slidify: slidify

	};

}));
<|endoftext|>


<commit_before>Ractive.decorators.autoNumeric = function (node, relativeKeypath, boundValue) {
    var self = this,
        $el = $(node),
        context = self.getContext(node),
        updateModel = function () {
            context.set(relativeKeypath, $el.autoNumeric('getNumber'));
        };

    if (typeof relativeKeypath !== 'string') {
        throw new Error('The binding name is required.');
    }

    if (arguments.length !== 3) {
        throw new Error('Invalid number of arguments specified. Correct usage: as-autoNumeric="\'relativeKeypath\', relativeKeypath"');
    }

    if (context.isBound()) {
        throw new Error('You cannot use two-way binding for the "autoNumeric" decorator.');
    }

    $el.autoNumeric('init')
       .autoNumeric('set', boundValue)
       .on('input', updateModel);

    return {
        update: function (newRelativeKeypath, newValue) {
            if (newRelativeKeypath !== relativeKeypath) {
                relativeKeypath = newRelativeKeypath;
            }

            if ($el.autoNumeric('getNumber') !== newValue) {
                $el.autoNumeric('set', newValue);
            }
        },

        teardown: function () {
            $el.off('input', updateModel)
               .autoNumeric('destroy');
        }
    };
};
<commit_msg>Add ability to pass autoNumeric config object to the decorator function<commit_after>Ractive.decorators.autoNumeric = function (node, relativeKeypath, boundValue, autoNumericCfg) {
    var self = this,
        $el = $(node),
        context = self.getContext(node),
        updateModel = function () {
            context.set(relativeKeypath, $el.autoNumeric('getNumber'));
        };

    if (typeof relativeKeypath !== 'string') {
        throw new Error('The binding name is required.');
    }

    if (arguments.length !== 3) {
        throw new Error('Invalid number of arguments specified. Correct usage: as-autoNumeric="\'relativeKeypath\', relativeKeypath"');
    }

    if (context.isBound()) {
        throw new Error('You cannot use two-way binding for the "autoNumeric" decorator.');
    }

    $el.autoNumeric('init', autoNumericCfg)
       .autoNumeric('set', boundValue)
       .on('input', updateModel);

    return {
        update: function (newRelativeKeypath, newValue) {
            if (newRelativeKeypath !== relativeKeypath) {
                relativeKeypath = newRelativeKeypath;
            }

            if ($el.autoNumeric('getNumber') !== newValue) {
                $el.autoNumeric('set', newValue);
            }
        },

        teardown: function () {
            $el.off('input', updateModel)
               .autoNumeric('destroy');
        }
    };
};
<|endoftext|>